From caa9d00ac4d54047a3e4dc06555cfba443c84605 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Jan 2023 10:39:37 +0000 Subject: [PATCH 001/423] chore(deps): update dependency prettier to v2.8.2 Signed-off-by: Renovate Bot --- microsite-next/yarn.lock | 6 +++--- microsite/yarn.lock | 6 +++--- yarn.lock | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index 3a632b3079..54b353b415 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -8361,11 +8361,11 @@ __metadata: linkType: hard "prettier@npm:^2.6.2": - version: 2.8.1 - resolution: "prettier@npm:2.8.1" + version: 2.8.2 + resolution: "prettier@npm:2.8.2" bin: prettier: bin-prettier.js - checksum: 4f21a0f1269f76fb36f54e9a8a1ea4c11e27478958bf860661fb4b6d7ac69aac1581f8724fa98ea3585e56d42a2ea317a17ff6e3324f40cb11ff9e20b73785cc + checksum: 740c56c2128d587d656ea1dde9bc9c3503dfc94db4f3ac387259215eeb2e216680bdad9d18a0c9feecc6b42cfa188d6fa777df4c36c1d00cedd4199074fbfbd2 languageName: node linkType: hard diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 3bc81619e3..34ed76e9e4 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -7369,11 +7369,11 @@ __metadata: linkType: hard "prettier@npm:^2.6.2": - version: 2.8.1 - resolution: "prettier@npm:2.8.1" + version: 2.8.2 + resolution: "prettier@npm:2.8.2" bin: prettier: bin-prettier.js - checksum: 4f21a0f1269f76fb36f54e9a8a1ea4c11e27478958bf860661fb4b6d7ac69aac1581f8724fa98ea3585e56d42a2ea317a17ff6e3324f40cb11ff9e20b73785cc + checksum: 740c56c2128d587d656ea1dde9bc9c3503dfc94db4f3ac387259215eeb2e216680bdad9d18a0c9feecc6b42cfa188d6fa777df4c36c1d00cedd4199074fbfbd2 languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index 56fa82473c..fc273856e1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32407,11 +32407,11 @@ __metadata: linkType: hard "prettier@npm:^2.2.1, prettier@npm:^2.7.1": - version: 2.8.1 - resolution: "prettier@npm:2.8.1" + version: 2.8.2 + resolution: "prettier@npm:2.8.2" bin: prettier: bin-prettier.js - checksum: 4f21a0f1269f76fb36f54e9a8a1ea4c11e27478958bf860661fb4b6d7ac69aac1581f8724fa98ea3585e56d42a2ea317a17ff6e3324f40cb11ff9e20b73785cc + checksum: 740c56c2128d587d656ea1dde9bc9c3503dfc94db4f3ac387259215eeb2e216680bdad9d18a0c9feecc6b42cfa188d6fa777df4c36c1d00cedd4199074fbfbd2 languageName: node linkType: hard From 7d4ca3514709133c9e713d42e63d81deccfb7a5b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Jan 2023 14:31:47 +0000 Subject: [PATCH 002/423] fix(deps): update dependency postcss to v8.4.21 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index a549cab5a9..4315beb6a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32367,13 +32367,13 @@ __metadata: linkType: hard "postcss@npm:^8.1.0, postcss@npm:^8.4.19": - version: 8.4.20 - resolution: "postcss@npm:8.4.20" + version: 8.4.21 + resolution: "postcss@npm:8.4.21" dependencies: nanoid: ^3.3.4 picocolors: ^1.0.0 source-map-js: ^1.0.2 - checksum: 1a5609ea1c1b204f9c2974a0019ae9eef2d99bf645c2c9aac675166c4cb1005be7b5e2ba196160bc771f5d9ac896ed883f236f888c891e835e59d28fff6651aa + checksum: e39ac60ccd1542d4f9d93d894048aac0d686b3bb38e927d8386005718e6793dbbb46930f0a523fe382f1bbd843c6d980aaea791252bf5e176180e5a4336d9679 languageName: node linkType: hard From 78bd3b80e2ef9fe0be4705a4e8fc10a3f21cba87 Mon Sep 17 00:00:00 2001 From: Kiss Miklos Date: Wed, 11 Jan 2023 16:00:59 +0100 Subject: [PATCH 003/423] add filter to sentry table Signed-off-by: Kiss Miklos --- .../src/components/Select/Select.tsx | 6 ++- .../SentryIssuesTable/SentryIssuesTable.tsx | 54 +++++++++++++++---- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/packages/core-components/src/components/Select/Select.tsx b/packages/core-components/src/components/Select/Select.tsx index 9cb8822a05..f0f65d2fac 100644 --- a/packages/core-components/src/components/Select/Select.tsx +++ b/packages/core-components/src/components/Select/Select.tsx @@ -128,7 +128,7 @@ export type SelectedItems = string | string[] | number | number[]; export type SelectProps = { multiple?: boolean; items: SelectItem[]; - label: string; + label?: string; placeholder?: string; selected?: SelectedItems; onChange: (arg: SelectedItems) => void; @@ -200,7 +200,9 @@ export function SelectComponent(props: SelectProps) { - {label} + {label && ( + {label} + )} + + ); }; From 6a8d6b9a0c4865d7def0b99829b894b9ad101d7a Mon Sep 17 00:00:00 2001 From: Kiss Miklos Date: Thu, 12 Jan 2023 12:31:17 +0100 Subject: [PATCH 004/423] add changesets Signed-off-by: Kiss Miklos --- .changeset/beige-cobras-leave.md | 5 +++++ .changeset/silver-wolves-breathe.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/beige-cobras-leave.md create mode 100644 .changeset/silver-wolves-breathe.md diff --git a/.changeset/beige-cobras-leave.md b/.changeset/beige-cobras-leave.md new file mode 100644 index 0000000000..fccefe616b --- /dev/null +++ b/.changeset/beige-cobras-leave.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': minor +--- + +Make the
+ Sentry Issues + + + + + + + } + subtitle={statsFor ? `Stats for ${statsFor}` : undefined} data={filteredIssues} /> From d12d1d95bb7635a6654a1bbfded479a054968b41 Mon Sep 17 00:00:00 2001 From: Kiss Miklos Date: Thu, 12 Jan 2023 17:45:56 +0100 Subject: [PATCH 006/423] remove changeset Signed-off-by: Kiss Miklos --- .changeset/beige-cobras-leave.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changeset/beige-cobras-leave.md diff --git a/.changeset/beige-cobras-leave.md b/.changeset/beige-cobras-leave.md deleted file mode 100644 index fccefe616b..0000000000 --- a/.changeset/beige-cobras-leave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': minor ---- - -Make the Date: Mon, 16 Jan 2023 14:34:09 -0500 Subject: [PATCH 008/423] Feature: Make workflow a link in CircleCI plugin Signed-off-by: Mark Anderson-Trocme --- .../src/components/BuildsPage/lib/CITable/CITable.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx b/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx index adc8a569bb..8f99f1f69c 100644 --- a/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx +++ b/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx @@ -212,6 +212,10 @@ const generatedColumns: TableColumn[] = [ { title: 'Workflow', field: 'workflow.name', + highlight: true, + render: (row: Partial) => ( + {row?.workflow?.name} + ), }, { title: 'Actions', From 1616e06047ebd78e2904e93cfaf9264a6479a3c2 Mon Sep 17 00:00:00 2001 From: Mark Anderson-Trocme Date: Mon, 16 Jan 2023 14:52:47 -0500 Subject: [PATCH 009/423] add changeset Signed-off-by: Mark Anderson-Trocme --- .changeset/slow-moles-sin.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/slow-moles-sin.md diff --git a/.changeset/slow-moles-sin.md b/.changeset/slow-moles-sin.md new file mode 100644 index 0000000000..13527b509e --- /dev/null +++ b/.changeset/slow-moles-sin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-circleci': minor +--- + +Making workflow a link From 5523f06afc08ad6637ded3aa48340a08060fa74f Mon Sep 17 00:00:00 2001 From: Kiss Miklos Date: Tue, 17 Jan 2023 02:28:52 +0100 Subject: [PATCH 010/423] fix tests Signed-off-by: Kiss Miklos --- .../components/SentryIssuesTable/SentryIssuesTable.test.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.test.tsx b/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.test.tsx index 647208f141..5bf6b1e92b 100644 --- a/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.test.tsx +++ b/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.test.tsx @@ -19,6 +19,7 @@ import SentryIssuesTable from './SentryIssuesTable'; import { SentryIssue } from '../../api'; import mockIssue from '../../api/mock/sentry-issue-mock.json'; import { renderInTestApp } from '@backstage/test-utils'; +import { DateTime } from 'luxon'; describe('SentryIssuesTable', () => { it('should render headers in a table', async () => { @@ -62,6 +63,7 @@ describe('SentryIssuesTable', () => { }, count: '101', userCount: 202, + lastSeen: DateTime.now().toISO(), }, ]; const table = await renderInTestApp( @@ -105,6 +107,6 @@ describe('SentryIssuesTable', () => { }} />, ); - expect(await table.findByText('Last 24h')).toBeInTheDocument(); + expect(await table.findByText('Stats for 24h')).toBeInTheDocument(); }); }); From 58d9145eef563e72685bbc5fa04fd5c64de5c6f6 Mon Sep 17 00:00:00 2001 From: Alex Crome Date: Sun, 22 Jan 2023 21:05:12 +0000 Subject: [PATCH 011/423] Added page size support to MSGraph client Signed-off-by: Alex Crome --- .../src/microsoftGraph/client.test.ts | 5 +++-- .../src/microsoftGraph/client.ts | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts index 05693149d8..783c16fe6f 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts @@ -70,7 +70,7 @@ describe('MicrosoftGraphClient', () => { expect(await response.json()).toEqual({ value: 'example' }); }); - it('should perform api request with filter, select and expand', async () => { + it('should perform api request with filter, select, expand and top', async () => { worker.use( rest.get('https://example.com/users', (req, res, ctx) => res(ctx.status(200), ctx.json({ queryString: req.url.search })), @@ -81,12 +81,13 @@ describe('MicrosoftGraphClient', () => { filter: 'test eq true', expand: 'children', select: ['id', 'children'], + top: 471, }); expect(response.status).toBe(200); expect(await response.json()).toEqual({ queryString: - '?$filter=test%20eq%20true&$select=id,children&$expand=children', + '?$filter=test%20eq%20true&$select=id,children&$expand=children&$top=471', }); }); diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts index 26da0cb64b..a1fc77b4fd 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts @@ -52,6 +52,10 @@ export type ODataQuery = { * Retrieves the total count of matching resources. */ count?: boolean; + /** + * Maximum number of records to receive in one batch. + */ + top?: number; }; /** @@ -188,6 +192,7 @@ export class MicrosoftGraphClient { $select: query?.select?.join(','), $expand: query?.expand, $count: query?.count, + $top: query?.top, }, { addQueryPrefix: true, From c5b119ad9cbb1d35e5357a6319237320cda0637d Mon Sep 17 00:00:00 2001 From: Alex Crome Date: Sun, 22 Jan 2023 21:56:39 +0000 Subject: [PATCH 012/423] Updated MS Graph plugin to use larger page sizes Signed-off-by: Alex Crome --- .changeset/young-points-drop.md | 5 +++ .../src/microsoftGraph/client.ts | 12 ++++- .../src/microsoftGraph/read.test.ts | 45 ++++++++++++++++--- .../src/microsoftGraph/read.ts | 13 +++++- 4 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 .changeset/young-points-drop.md diff --git a/.changeset/young-points-drop.md b/.changeset/young-points-drop.md new file mode 100644 index 0000000000..4309d54c2c --- /dev/null +++ b/.changeset/young-points-drop.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-msgraph': patch +--- + +Increased default page size to 999 (from 100) to reduce the number of calls made to the Microsoft Graph API. diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts index a1fc77b4fd..fd640e70ba 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts @@ -348,8 +348,16 @@ export class MicrosoftGraphClient { * @param groupId - The unique identifier for the `Group` resource * */ - async *getGroupMembers(groupId: string): AsyncIterable { - yield* this.requestCollection(`groups/${groupId}/members`); + async *getGroupMembers( + groupId: string, + query?: ODataQuery, + queryMode?: 'basic' | 'advanced', + ): AsyncIterable { + yield* this.requestCollection( + `groups/${groupId}/members`, + query, + queryMode, + ); } /** diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts index bafb2ecaad..0f9ddb0c13 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts @@ -140,6 +140,7 @@ describe('read microsoft graph', () => { expect(client.getUsers).toHaveBeenCalledWith( { filter: 'accountEnabled eq true', + top: 999, }, undefined, ); @@ -186,6 +187,7 @@ describe('read microsoft graph', () => { expect(client.getUsers).toHaveBeenCalledWith( { filter: 'accountEnabled eq true', + top: 999, }, 'advanced', ); @@ -228,6 +230,7 @@ describe('read microsoft graph', () => { { expand: 'manager', filter: 'accountEnabled eq true', + top: 999, }, undefined, ); @@ -278,11 +281,14 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq true', + top: 999, }, undefined, ); expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); + expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { + top: 999, + }); expect(client.getUserProfile).toHaveBeenCalledTimes(1); expect(client.getUserProfile).toHaveBeenCalledWith('userid', { @@ -338,11 +344,14 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq true', + top: 999, }, 'advanced', ); expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); + expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { + top: 999, + }); expect(client.getUserProfile).toHaveBeenCalledTimes(1); expect(client.getUserProfile).toHaveBeenCalledWith('userid', { @@ -390,11 +399,14 @@ describe('read microsoft graph', () => { { expand: 'member', filter: 'securityEnabled eq true', + top: 999, }, undefined, ); expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); + expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { + top: 999, + }); expect(client.getUserProfile).toHaveBeenCalledTimes(1); expect(client.getUserProfile).toHaveBeenCalledWith('userid', { @@ -527,11 +539,14 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq false', + top: 999, }, undefined, ); expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); + expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { + top: 999, + }); // TODO: Loading groups photos doesn't work right now as Microsoft Graph // doesn't allows this yet // expect(client.getGroupPhotoWithSizeLimit).toBeCalledTimes(1); @@ -603,11 +618,14 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq false', + top: 999, }, 'advanced', ); expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); + expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { + top: 999, + }); // TODO: Loading groups photos doesn't work right now as Microsoft Graph // doesn't allows this yet // expect(client.getGroupPhotoWithSizeLimit).toBeCalledTimes(1); @@ -680,11 +698,14 @@ describe('read microsoft graph', () => { { expand: 'member', filter: 'securityEnabled eq false', + top: 999, }, undefined, ); expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); + expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { + top: 999, + }); // TODO: Loading groups photos doesn't work right now as Microsoft Graph // doesn't allows this yet // expect(client.getGroupPhotoWithSizeLimit).toBeCalledTimes(1); @@ -750,11 +771,14 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq true', + top: 999, }, undefined, ); expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); + expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { + top: 999, + }); }); }); @@ -887,6 +911,7 @@ describe('read microsoft graph', () => { expect(client.getUsers).toHaveBeenCalledWith( { filter: undefined, + top: 999, }, undefined, ); @@ -894,6 +919,7 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq false', + top: 999, }, undefined, ); @@ -925,6 +951,7 @@ describe('read microsoft graph', () => { { expand: 'manager', filter: 'accountEnabled eq true', + top: 999, }, undefined, ); @@ -932,6 +959,7 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq false', + top: 999, }, undefined, ); @@ -960,6 +988,7 @@ describe('read microsoft graph', () => { expect(client.getUsers).toHaveBeenCalledWith( { select: ['mail'], + top: 999, }, undefined, ); @@ -994,12 +1023,14 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'name eq backstage-group', + top: 999, }, undefined, ); expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq false', + top: 999, }, undefined, ); diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts index 0ed411bfea..2541416777 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts @@ -37,6 +37,8 @@ import { UserTransformer, } from './types'; +const PAGE_SIZE = 999; + /** * The default implementation of the transformation from a graph user entry to * a User entity. @@ -107,6 +109,7 @@ export async function readMicrosoftGraphUsers( filter: options.userFilter, expand: options.userExpand, select: options.userSelect, + top: PAGE_SIZE, }, options.queryMode, )) { @@ -172,13 +175,16 @@ export async function readMicrosoftGraphUsersInGroups( expand: options.groupExpand, search: options.userGroupMemberSearch, filter: options.userGroupMemberFilter, + top: PAGE_SIZE, }, options.queryMode, )) { // Process all groups in parallel, otherwise it can take quite some time userGroupMemberPromises.push( limiter(async () => { - for await (const member of client.getGroupMembers(group.id!)) { + for await (const member of client.getGroupMembers(group.id!, { + top: PAGE_SIZE, + })) { if (!member.id) { continue; } @@ -380,6 +386,7 @@ export async function readMicrosoftGraphGroups( search: options?.groupSearch, filter: options?.groupFilter, select: options?.groupSelect, + top: PAGE_SIZE, }, options?.queryMode, )) { @@ -401,7 +408,9 @@ export async function readMicrosoftGraphGroups( return; } - for await (const member of client.getGroupMembers(group.id!)) { + for await (const member of client.getGroupMembers(group.id!, { + top: PAGE_SIZE, + })) { if (!member.id) { continue; } From fb568e2683697a64aef7c9ffe1d140d6ed2eb314 Mon Sep 17 00:00:00 2001 From: Alex Crome Date: Sun, 22 Jan 2023 23:23:26 +0000 Subject: [PATCH 013/423] Optimised loading of users via group membership Signed-off-by: Alex Crome --- .changeset/slow-carrots-sniff.md | 8 + .../api-report.md | 16 +- .../src/microsoftGraph/client.test.ts | 48 ++--- .../src/microsoftGraph/client.ts | 43 ++-- .../src/microsoftGraph/read.test.ts | 78 ++++---- .../src/microsoftGraph/read.ts | 183 +++++++++--------- 6 files changed, 185 insertions(+), 191 deletions(-) create mode 100644 .changeset/slow-carrots-sniff.md diff --git a/.changeset/slow-carrots-sniff.md b/.changeset/slow-carrots-sniff.md new file mode 100644 index 0000000000..d32c2a281e --- /dev/null +++ b/.changeset/slow-carrots-sniff.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-catalog-backend-module-msgraph': minor +--- + +Improve performance when loading users via group membership. +Users data is now loaded from a paged query, rather than having to make an extra call per user to load each user's profiles. + +Note, there are still additional per user calls made to load user avatars diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md index a5abdc17c6..09770614b4 100644 --- a/plugins/catalog-backend-module-msgraph/api-report.md +++ b/plugins/catalog-backend-module-msgraph/api-report.md @@ -70,7 +70,11 @@ export const MICROSOFT_GRAPH_USER_ID_ANNOTATION = 'graph.microsoft.com/user-id'; export class MicrosoftGraphClient { constructor(baseUrl: string, tokenCredential: TokenCredential); static create(config: MicrosoftGraphProviderConfig): MicrosoftGraphClient; - getGroupMembers(groupId: string): AsyncIterable; + getGroupMembers( + groupId: string, + query?: ODataQuery, + queryMode?: 'basic' | 'advanced', + ): AsyncIterable; // (undocumented) getGroupPhoto(groupId: string, sizeId?: string): Promise; getGroupPhotoWithSizeLimit( @@ -81,6 +85,11 @@ export class MicrosoftGraphClient { query?: ODataQuery, queryMode?: 'basic' | 'advanced', ): AsyncIterable; + getGroupUserMembers( + groupId: string, + query?: ODataQuery, + queryMode?: 'basic' | 'advanced', + ): AsyncIterable; getOrganization(tenantId: string): Promise; // (undocumented) getUserPhoto(userId: string, sizeId?: string): Promise; @@ -88,10 +97,6 @@ export class MicrosoftGraphClient { userId: string, maxSize: number, ): Promise; - getUserProfile( - userId: string, - query?: ODataQuery, - ): Promise; getUsers( query?: ODataQuery, queryMode?: 'basic' | 'advanced', @@ -231,6 +236,7 @@ export type ODataQuery = { expand?: string; select?: string[]; count?: boolean; + top?: number; }; // @public diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts index 783c16fe6f..f621b4d924 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts @@ -135,33 +135,6 @@ describe('MicrosoftGraphClient', () => { expect(values).toEqual(['first', 'second']); }); - it('should load user profile', async () => { - worker.use( - rest.get('https://example.com/users/user-id', (_, res, ctx) => - res( - ctx.status(200), - ctx.json({ - surname: 'Example', - }), - ), - ), - ); - - const userProfile = await client.getUserProfile('user-id'); - - expect(userProfile).toEqual({ surname: 'Example' }); - }); - - it('should throw exception if load user profile fails', async () => { - worker.use( - rest.get('https://example.com/users/user-id', (_, res, ctx) => - res(ctx.status(404)), - ), - ); - - await expect(() => client.getUserProfile('user-id')).rejects.toThrow(); - }); - it('should load user profile photo with max size of 120', async () => { worker.use( rest.get('https://example.com/users/user-id/photos', (_, res, ctx) => @@ -330,6 +303,27 @@ describe('MicrosoftGraphClient', () => { ]); }); + it('should load user group members', async () => { + worker.use( + rest.get( + 'https://example.com/groups/group-id/members/microsoft.graph.user', + (_, res, ctx) => + res( + ctx.status(200), + ctx.json({ + value: [{ id: '12345' }, { id: '67890' }], + }), + ), + ), + ); + + const values = await collectAsyncIterable( + client.getGroupUserMembers('group-id'), + ); + + expect(values).toEqual([{ id: '12345' }, { id: '67890' }]); + }); + it('should load organization', async () => { worker.use( rest.get('https://example.com/organization/tentant-id', (_, res, ctx) => diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts index fd640e70ba..c644e545d6 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts @@ -234,28 +234,6 @@ export class MicrosoftGraphClient { }); } - /** - * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User} - * from Graph API - * - * @public - * @param userId - The unique identifier for the `User` resource - * @param query - OData Query {@link ODataQuery} - * - */ - async getUserProfile( - userId: string, - query?: ODataQuery, - ): Promise { - const response = await this.requestApi(`users/${userId}`, query); - - if (response.status !== 200) { - await this.handleError('user profile', response); - } - - return await response.json(); - } - /** * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto} * of `User` from Graph API with size limit @@ -360,6 +338,27 @@ export class MicrosoftGraphClient { ); } + /** + * Get a collection of + * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User} + * belonging to a `Group` from Graph API and return as `AsyncIterable` + * @public + * @param groupId - The unique identifier for the `Group` resource + * @param query - OData Query {@link ODataQuery} + * @param queryMode - Mode to use while querying. Some features are only available at "advanced". + */ + async *getGroupUserMembers( + groupId: string, + query?: ODataQuery, + queryMode?: 'basic' | 'advanced', + ): AsyncIterable { + yield* this.requestCollection( + `groups/${groupId}/members/microsoft.graph.user/`, + query, + queryMode, + ); + } + /** * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/organization | Organization} * from Graph API diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts index 0f9ddb0c13..b1dfc5a148 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts @@ -61,9 +61,9 @@ function group(data: Partial): GroupEntity { describe('read microsoft graph', () => { const client: jest.Mocked = { getUsers: jest.fn(), - getUserProfile: jest.fn(), getGroups: jest.fn(), getGroupMembers: jest.fn(), + getGroupUserMembers: jest.fn(), getUserPhotoWithSizeLimit: jest.fn(), getGroupPhotoWithSizeLimit: jest.fn(), getOrganization: jest.fn(), @@ -78,13 +78,6 @@ describe('read microsoft graph', () => { mail: 'user.name@example.com', }; } - async function getExampleUserProfile() { - return { - id: 'userid', - displayName: 'User Name', - mail: 'user.name@example.com', - }; - } async function* getExampleGroups() { yield { id: 'groupid', @@ -245,9 +238,8 @@ describe('read microsoft graph', () => { describe('readMicrosoftGraphUsersInGroups', () => { it('should read users from Groups', async () => { client.getGroups.mockImplementation(getExampleGroups); - client.getGroupMembers.mockImplementation(getExampleGroupMembers); + client.getGroupUserMembers.mockImplementation(getExampleUsers); - client.getUserProfile.mockResolvedValue(getExampleUserProfile()); client.getUserPhotoWithSizeLimit.mockResolvedValue( 'data:image/jpeg;base64,...', ); @@ -281,19 +273,19 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq true', + select: ['id', 'displayName'], top: 999, }, undefined, ); - expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { - top: 999, - }); - expect(client.getUserProfile).toHaveBeenCalledTimes(1); - expect(client.getUserProfile).toHaveBeenCalledWith('userid', { - expand: undefined, - }); + expect(client.getGroupUserMembers).toHaveBeenCalledTimes(1); + expect(client.getGroupUserMembers).toHaveBeenCalledWith( + 'groupid', + { top: 999 }, + undefined, + ); + expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledTimes(1); expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledWith( 'userid', @@ -303,13 +295,8 @@ describe('read microsoft graph', () => { it('should read users from Groups with advanced query mode', async () => { client.getGroups.mockImplementation(getExampleGroups); - client.getGroupMembers.mockImplementation(getExampleGroupMembers); + client.getGroupUserMembers.mockImplementation(getExampleUsers); - client.getUserProfile.mockResolvedValue({ - id: 'userid', - displayName: 'User Name', - mail: 'user.name@example.com', - }); client.getUserPhotoWithSizeLimit.mockResolvedValue( 'data:image/jpeg;base64,...', ); @@ -344,19 +331,19 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq true', + select: ['id', 'displayName'], top: 999, }, 'advanced', ); - expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { - top: 999, - }); - expect(client.getUserProfile).toHaveBeenCalledTimes(1); - expect(client.getUserProfile).toHaveBeenCalledWith('userid', { - expand: undefined, - }); + expect(client.getGroupUserMembers).toHaveBeenCalledTimes(1); + expect(client.getGroupUserMembers).toHaveBeenCalledWith( + 'groupid', + { top: 999 }, + 'advanced', + ); + expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledTimes(1); expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledWith( 'userid', @@ -366,8 +353,8 @@ describe('read microsoft graph', () => { it('should read users with userExpand, groupExpand and custom transformer', async () => { client.getGroups.mockImplementation(getExampleGroups); - client.getGroupMembers.mockImplementation(getExampleGroupMembers); - client.getUserProfile.mockResolvedValue(getExampleUserProfile()); + client.getGroupUserMembers.mockImplementation(getExampleUsers); + client.getUserPhotoWithSizeLimit.mockResolvedValue( 'data:image/jpeg;base64,...', ); @@ -399,19 +386,22 @@ describe('read microsoft graph', () => { { expand: 'member', filter: 'securityEnabled eq true', + select: ['id', 'displayName'], + top: 999, + }, + undefined, + ); + + expect(client.getGroupUserMembers).toHaveBeenCalledTimes(1); + expect(client.getGroupUserMembers).toHaveBeenCalledWith( + 'groupid', + { + expand: 'manager', top: 999, }, undefined, ); - expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { - top: 999, - }); - expect(client.getUserProfile).toHaveBeenCalledTimes(1); - expect(client.getUserProfile).toHaveBeenCalledWith('userid', { - expand: 'manager', - }); expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledTimes(1); expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledWith( 'userid', @@ -1001,13 +991,13 @@ describe('read microsoft graph', () => { }); client.getUsers.mockImplementation(getExampleUsers); - client.getUserProfile.mockImplementation(getExampleUserProfile); client.getUserPhotoWithSizeLimit.mockResolvedValue( 'data:image/jpeg;base64,...', ); client.getGroups.mockImplementation(getExampleGroups); client.getGroupMembers.mockImplementation(getExampleGroupMembers); + client.getGroupUserMembers.mockImplementation(getExampleUsers); client.getGroupPhotoWithSizeLimit.mockResolvedValue( 'data:image/jpeg;base64,...', ); @@ -1023,6 +1013,7 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'name eq backstage-group', + select: ['id', 'displayName'], top: 999, }, undefined, @@ -1034,7 +1025,6 @@ describe('read microsoft graph', () => { }, undefined, ); - expect(client.getUserProfile).toHaveBeenCalledTimes(1); expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledTimes(1); }); }); diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts index 2541416777..d0c09d6267 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts @@ -98,13 +98,7 @@ export async function readMicrosoftGraphUsers( ): Promise<{ users: UserEntity[]; // With all relations empty }> { - const users: UserEntity[] = []; - const limiter = limiterFactory(10); - - const transformer = options.transformer ?? defaultUserTransformer; - const promises: Promise[] = []; - - for await (const user of client.getUsers( + const users = client.getUsers( { filter: options.userFilter, expand: options.userExpand, @@ -112,37 +106,16 @@ export async function readMicrosoftGraphUsers( top: PAGE_SIZE, }, options.queryMode, - )) { - // Process all users in parallel, otherwise it can take quite some time - promises.push( - limiter(async () => { - let userPhoto; - try { - userPhoto = await client.getUserPhotoWithSizeLimit( - user.id!, - // We are limiting the photo size, as users with full resolution photos - // can make the Backstage API slow - 120, - ); - } catch (e) { - options.logger.warn(`Unable to load photo for ${user.id}, ${e}`); - } + ); - const entity = await transformer(user, userPhoto); - - if (!entity) { - return; - } - - users.push(entity); - }), - ); - } - - // Wait for all users and photos to be downloaded - await Promise.all(promises); - - return { users }; + return { + users: await transformUsers( + client, + users, + options.logger, + options.transformer, + ), + }; } export async function readMicrosoftGraphUsersInGroups( @@ -160,21 +133,17 @@ export async function readMicrosoftGraphUsersInGroups( ): Promise<{ users: UserEntity[]; // With all relations empty }> { - const users: UserEntity[] = []; - const limiter = limiterFactory(10); - const transformer = options.transformer ?? defaultUserTransformer; const userGroupMemberPromises: Promise[] = []; - const userPromises: Promise[] = []; - - const groupMemberUsers: Set = new Set(); + const userGroupMembers = new Map(); for await (const group of client.getGroups( { expand: options.groupExpand, search: options.userGroupMemberSearch, filter: options.userGroupMemberFilter, + select: ['id', 'displayName'], top: PAGE_SIZE, }, options.queryMode, @@ -182,17 +151,23 @@ export async function readMicrosoftGraphUsersInGroups( // Process all groups in parallel, otherwise it can take quite some time userGroupMemberPromises.push( limiter(async () => { - for await (const member of client.getGroupMembers(group.id!, { - top: PAGE_SIZE, - })) { - if (!member.id) { - continue; - } - - if (member['@odata.type'] === '#microsoft.graph.user') { - groupMemberUsers.add(member.id); - } + let groupMemberCount = 0; + for await (const user of client.getGroupUserMembers( + group.id!, + { + expand: options.userExpand, + top: PAGE_SIZE, + }, + options.queryMode, + )) { + userGroupMembers.set(user.id!, user); + groupMemberCount++; } + options.logger.debug('Read users from group', { + groupId: group.id, + groupName: group.displayName, + memberCount: groupMemberCount, + }); }), ); } @@ -200,47 +175,19 @@ export async function readMicrosoftGraphUsersInGroups( // Wait for all group members await Promise.all(userGroupMemberPromises); - options.logger.info(`groupMemberUsers ${groupMemberUsers.size}`); - for (const userId of groupMemberUsers) { - // Process all users in parallel, otherwise it can take quite some time - userPromises.push( - limiter(async () => { - let user; - let userPhoto; - try { - user = await client.getUserProfile(userId, { - expand: options.userExpand, - }); - } catch (e) { - options.logger.warn(`Unable to load user for ${userId}, ${e}`); - } - if (user) { - try { - userPhoto = await client.getUserPhotoWithSizeLimit( - user.id!, - // We are limiting the photo size, as users with full resolution photos - // can make the Backstage API slow - 120, - ); - } catch (e) { - options.logger.warn(`Unable to load userphoto for ${userId}, ${e}`); - } + options.logger.info('Read users from group membership', { + groupCount: userGroupMemberPromises.length, + userCount: userGroupMembers.size, + }); - const entity = await transformer(user, userPhoto); - - if (!entity) { - return; - } - users.push(entity); - } - }), - ); - } - - // Wait for all users and photos to be downloaded - await Promise.all(userPromises); - - return { users }; + return { + users: await transformUsers( + client, + userGroupMembers.values(), + options.logger, + options.transformer, + ), + }; } /** @@ -602,6 +549,56 @@ export async function readMicrosoftGraphOrg( return { users, groups }; } +async function transformUsers( + client: MicrosoftGraphClient, + users: Iterable | AsyncIterable, + logger: Logger, + transformer?: UserTransformer, +) { + const limiter = limiterFactory(10); + + const resolvedTransformer = transformer ?? defaultUserTransformer; + const promises: Promise[] = []; + const entities: UserEntity[] = []; + + // Process all users in parallel, otherwise it can take quite some time + for await (const user of users) { + promises.push( + limiter(async () => { + let userPhoto; + try { + userPhoto = await client.getUserPhotoWithSizeLimit( + user.id!, + // We are limiting the photo size, as users with full resolution photos + // can make the Backstage API slow + 120, + ); + } catch (e) { + logger.warn(`Unable to load user photo for`, { + user: user.id, + error: e, + }); + } + + const entity = await resolvedTransformer(user, userPhoto); + + if (entity) { + entities.push(entity); + } + }), + ); + } + + // Wait for all users and photos to be downloaded + await Promise.all(promises); + + logger.debug('Finished transforming users', { + microsoftUserCount: promises.length, + backstageUserCount: entities.length, + }); + return entities; +} + function ensureItem( target: Map>, key: string, From 98a00a09d5db54a7d815b1fa2479585ce3ba9121 Mon Sep 17 00:00:00 2001 From: Deepankumar Loganathan Date: Tue, 24 Jan 2023 12:12:38 +0100 Subject: [PATCH 014/423] fixed AzureSite plugin UI load and action issue Signed-off-by: Deepankumar Loganathan --- .changeset/thin-scissors-press.md | 6 ++++++ plugins/azure-sites/src/api/AzureSitesApiBackendClient.ts | 4 ++-- .../AzureSitesOverviewTable.tsx | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 .changeset/thin-scissors-press.md diff --git a/.changeset/thin-scissors-press.md b/.changeset/thin-scissors-press.md new file mode 100644 index 0000000000..2891d4ca66 --- /dev/null +++ b/.changeset/thin-scissors-press.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-azure-sites': patch +--- + +Fixed `AzureSites` plugin start and stop issue #15904 +Fixed `AzureSites` UI load issue #15907 diff --git a/plugins/azure-sites/src/api/AzureSitesApiBackendClient.ts b/plugins/azure-sites/src/api/AzureSitesApiBackendClient.ts index fc622e786b..b66a3cbb3f 100644 --- a/plugins/azure-sites/src/api/AzureSitesApiBackendClient.ts +++ b/plugins/azure-sites/src/api/AzureSitesApiBackendClient.ts @@ -35,7 +35,7 @@ export class AzureSitesApiBackendClient implements AzureSitesApi { } async stop(request: AzureSiteStartStopRequest): Promise { - const url = `${await this.discoveryApi.getBaseUrl('azure-functions')}/${ + const url = `${await this.discoveryApi.getBaseUrl('azure-sites')}/${ request.subscription }/${request.resourceGroup}/${request.name}/stop`; const { token: accessToken } = await this.identityApi.getCredentials(); @@ -48,7 +48,7 @@ export class AzureSitesApiBackendClient implements AzureSitesApi { }); } async start(request: AzureSiteStartStopRequest): Promise { - const url = `${await this.discoveryApi.getBaseUrl('azure-functions')}/${ + const url = `${await this.discoveryApi.getBaseUrl('azure-sites')}/${ request.subscription }/${request.resourceGroup}/${request.name}/start`; const { token: accessToken } = await this.identityApi.getCredentials(); diff --git a/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx b/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx index a25d186a48..dc059b2f15 100644 --- a/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx +++ b/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx @@ -73,9 +73,11 @@ const Kind = ({ value }: { value: Kinds }) => { app: , functionapp: , }; + const kindArray = value.split(','); + const iconValue: Kinds = kindArray.includes('app') ? 'app' : 'functionapp'; return ( - {iconMap[value]} + {iconMap[iconValue]} ); }; From cbe69fa263663b93276e0f17b140208093a66732 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 27 Jan 2023 12:05:53 +0100 Subject: [PATCH 015/423] fix formatting Signed-off-by: Patrik Oldsberg --- packages/backend-common/src/scm/git.test.ts | 6 +++--- .../src/layout/InfoCard/InfoCard.tsx | 4 ++-- packages/techdocs-cli/src/lib/PublisherConfig.ts | 4 ++-- plugins/badges-backend/src/types.ts | 2 +- plugins/bitbucket-cloud-common/src/models/index.ts | 14 +++++++------- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/backend-common/src/scm/git.test.ts b/packages/backend-common/src/scm/git.test.ts index fdd3c7dbc8..629173f96e 100644 --- a/packages/backend-common/src/scm/git.test.ts +++ b/packages/backend-common/src/scm/git.test.ts @@ -202,7 +202,7 @@ describe('Git', () => { await git.clone({ url, dir }); const { onAuth } = ( - isomorphic.clone as unknown as jest.Mock + isomorphic.clone as unknown as jest.Mock<(typeof isomorphic)['clone']> ).mock.calls[0][0]!; expect(onAuth()).toEqual(auth); @@ -315,7 +315,7 @@ describe('Git', () => { await git.fetch({ remote, dir }); const { onAuth } = ( - isomorphic.fetch as unknown as jest.Mock + isomorphic.fetch as unknown as jest.Mock<(typeof isomorphic)['fetch']> ).mock.calls[0][0]!; expect(onAuth()).toEqual(auth); @@ -486,7 +486,7 @@ describe('Git', () => { await git.push({ remote, dir, remoteRef, force }); const { onAuth } = ( - isomorphic.push as unknown as jest.Mock + isomorphic.push as unknown as jest.Mock<(typeof isomorphic)['push']> ).mock.calls[0][0]!; expect(onAuth()).toEqual(auth); diff --git a/packages/core-components/src/layout/InfoCard/InfoCard.tsx b/packages/core-components/src/layout/InfoCard/InfoCard.tsx index 95d474aae4..3d8d0f3bb0 100644 --- a/packages/core-components/src/layout/InfoCard/InfoCard.tsx +++ b/packages/core-components/src/layout/InfoCard/InfoCard.tsx @@ -188,12 +188,12 @@ export function InfoCard(props: Props): JSX.Element { variants.forEach(name => { calculatedStyle = { ...calculatedStyle, - ...VARIANT_STYLES.card[name as keyof typeof VARIANT_STYLES['card']], + ...VARIANT_STYLES.card[name as keyof (typeof VARIANT_STYLES)['card']], }; calculatedCardStyle = { ...calculatedCardStyle, ...VARIANT_STYLES.cardContent[ - name as keyof typeof VARIANT_STYLES['cardContent'] + name as keyof (typeof VARIANT_STYLES)['cardContent'] ], }; }); diff --git a/packages/techdocs-cli/src/lib/PublisherConfig.ts b/packages/techdocs-cli/src/lib/PublisherConfig.ts index 0d1c8fc8a9..0ef6b66eaf 100644 --- a/packages/techdocs-cli/src/lib/PublisherConfig.ts +++ b/packages/techdocs-cli/src/lib/PublisherConfig.ts @@ -17,7 +17,7 @@ import { ConfigReader } from '@backstage/config'; import { OptionValues } from 'commander'; -type Publisher = keyof typeof PublisherConfig['configFactories']; +type Publisher = keyof (typeof PublisherConfig)['configFactories']; type PublisherConfiguration = { [p in Publisher]?: any; } & { @@ -73,7 +73,7 @@ export class PublisherConfig { */ private static isKnownPublisher( type: string, - ): type is keyof typeof PublisherConfig['configFactories'] { + ): type is keyof (typeof PublisherConfig)['configFactories'] { return PublisherConfig.configFactories.hasOwnProperty(type); } diff --git a/plugins/badges-backend/src/types.ts b/plugins/badges-backend/src/types.ts index eec7063f88..0d778289f9 100644 --- a/plugins/badges-backend/src/types.ts +++ b/plugins/badges-backend/src/types.ts @@ -27,7 +27,7 @@ export const BADGE_STYLES = [ ] as const; /** @public */ -export type BadgeStyle = typeof BADGE_STYLES[number]; +export type BadgeStyle = (typeof BADGE_STYLES)[number]; /** @public */ export interface Badge { diff --git a/plugins/bitbucket-cloud-common/src/models/index.ts b/plugins/bitbucket-cloud-common/src/models/index.ts index 9d25bbb873..d868e2926c 100644 --- a/plugins/bitbucket-cloud-common/src/models/index.ts +++ b/plugins/bitbucket-cloud-common/src/models/index.ts @@ -107,7 +107,7 @@ export namespace Models { * @public */ export type BaseCommitSummaryMarkupEnum = - typeof BaseCommitSummaryMarkupEnum[keyof typeof BaseCommitSummaryMarkupEnum]; + (typeof BaseCommitSummaryMarkupEnum)[keyof typeof BaseCommitSummaryMarkupEnum]; /** * A branch object, representing a branch in a repository. @@ -146,7 +146,7 @@ export namespace Models { * @public */ export type BranchMergeStrategiesEnum = - typeof BranchMergeStrategiesEnum[keyof typeof BranchMergeStrategiesEnum]; + (typeof BranchMergeStrategiesEnum)[keyof typeof BranchMergeStrategiesEnum]; /** * A repository commit object. @@ -191,7 +191,7 @@ export namespace Models { * @public */ export type CommitFileAttributesEnum = - typeof CommitFileAttributesEnum[keyof typeof CommitFileAttributesEnum]; + (typeof CommitFileAttributesEnum)[keyof typeof CommitFileAttributesEnum]; /** * A link to a resource related to this object. @@ -280,7 +280,7 @@ export namespace Models { * @public */ export type ParticipantRoleEnum = - typeof ParticipantRoleEnum[keyof typeof ParticipantRoleEnum]; + (typeof ParticipantRoleEnum)[keyof typeof ParticipantRoleEnum]; /** * @public @@ -295,7 +295,7 @@ export namespace Models { * @public */ export type ParticipantStateEnum = - typeof ParticipantStateEnum[keyof typeof ParticipantStateEnum]; + (typeof ParticipantStateEnum)[keyof typeof ParticipantStateEnum]; /** * A Bitbucket project. @@ -423,7 +423,7 @@ export namespace Models { * @public */ export type RepositoryForkPolicyEnum = - typeof RepositoryForkPolicyEnum[keyof typeof RepositoryForkPolicyEnum]; + (typeof RepositoryForkPolicyEnum)[keyof typeof RepositoryForkPolicyEnum]; /** * @public @@ -436,7 +436,7 @@ export namespace Models { * @public */ export type RepositoryScmEnum = - typeof RepositoryScmEnum[keyof typeof RepositoryScmEnum]; + (typeof RepositoryScmEnum)[keyof typeof RepositoryScmEnum]; /** * @public From fcbd3d72fb353150013e21868e01e59ccd5b6ef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=82=98=EC=83=81=EC=9A=B0=28Roy=29?= Date: Mon, 30 Jan 2023 10:47:43 +0900 Subject: [PATCH 016/423] Speficy RUN location for installing mkdocs dependencies. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 나상우(Roy) --- docs/features/techdocs/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md index c2070e7840..e91a3e5c11 100644 --- a/docs/features/techdocs/getting-started.md +++ b/docs/features/techdocs/getting-started.md @@ -262,7 +262,7 @@ You will have to install the `mkdocs` and `mkdocs-techdocs-core` package from pip, as well as `graphviz` and `plantuml` from your OS package manager (e.g. apt). -You can do so by including the following lines in the last step of your +You can do so by including the following lines right above `USER node` of your `Dockerfile`: ```Dockerfile From db77ab2869023c5e78403616ab7b8b9d6661913a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=82=98=EC=83=81=EC=9A=B0=28Roy=29?= Date: Mon, 30 Jan 2023 10:58:18 +0900 Subject: [PATCH 017/423] Update version of mkdocs-techdocs-core to most recent version. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 나상우(Roy) --- docs/features/techdocs/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md index e91a3e5c11..578a631798 100644 --- a/docs/features/techdocs/getting-started.md +++ b/docs/features/techdocs/getting-started.md @@ -267,7 +267,7 @@ You can do so by including the following lines right above `USER node` of your ```Dockerfile RUN apt-get update && apt-get install -y python3 python3-pip -RUN pip3 install mkdocs-techdocs-core==1.0.1 +RUN pip3 install mkdocs-techdocs-core==1.1.7 ``` Please be aware that the version requirement could change, you need to check our From 49948f644f1276f19020171a223fa74fbde6d1fd Mon Sep 17 00:00:00 2001 From: Jamie Klassen Date: Sat, 28 Jan 2023 01:49:58 -0500 Subject: [PATCH 018/423] Standardize term 'gitlab instance' In other places in the docs the term 'instance' is used to refer to a single GitLab API host. The use of 'project' in these cases is particularly troublesome because that term already has a well-defined meaning in GitLab: a single codebase with associated issues, MRs, and automation. Signed-off-by: Jamie Klassen --- .changeset/breezy-ears-rule.md | 5 +++++ docs/integrations/gitlab/discovery.md | 2 +- plugins/catalog-backend-module-gitlab/config.d.ts | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/breezy-ears-rule.md diff --git a/.changeset/breezy-ears-rule.md b/.changeset/breezy-ears-rule.md new file mode 100644 index 0000000000..753554187d --- /dev/null +++ b/.changeset/breezy-ears-rule.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-gitlab': patch +--- + +The config now consistently uses the term 'instance' to refer to a single GitLab API host. diff --git a/docs/integrations/gitlab/discovery.md b/docs/integrations/gitlab/discovery.md index dc0b911b3d..51c34b67ac 100644 --- a/docs/integrations/gitlab/discovery.md +++ b/docs/integrations/gitlab/discovery.md @@ -22,7 +22,7 @@ catalog: yourProviderId: host: gitlab-host # Identifies one of the hosts set up in the integrations branch: main # Optional. Uses `master` as default - group: example-group # Optional. Group and subgroup (if needed) to look for repositories. If not present the whole project will be scanned + group: example-group # Optional. Group and subgroup (if needed) to look for repositories. If not present the whole instance will be scanned entityFilename: catalog-info.yaml # Optional. Defaults to `catalog-info.yaml` projectPattern: /[\s\S]*/ # Optional. Filters found projects based on provided patter. Defaults to `/[\s\S]*/`, what means to not filter anything schedule: # optional; same options as in TaskScheduleDefinition diff --git a/plugins/catalog-backend-module-gitlab/config.d.ts b/plugins/catalog-backend-module-gitlab/config.d.ts index 4f51867efc..00ad0ef032 100644 --- a/plugins/catalog-backend-module-gitlab/config.d.ts +++ b/plugins/catalog-backend-module-gitlab/config.d.ts @@ -31,7 +31,7 @@ export interface Config { host: string; /** * (Optional) Gitlab's group[/subgroup] where the discovery is done. - * If not defined the whole project will be scanned. + * If not defined the whole instance will be scanned. */ group?: string; /** From c5957024a3dc0ced76a9c2c98ed31136f0ca35c8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 16:41:23 +0000 Subject: [PATCH 019/423] chore(deps): update backstage/actions action to v0.6.0 Signed-off-by: Renovate Bot --- .github/workflows/automate_changeset_feedback.yml | 2 +- .github/workflows/ci.yml | 6 +++--- .github/workflows/cron.yml | 2 +- .github/workflows/deploy_docker-image.yml | 2 +- .github/workflows/deploy_nightly.yml | 2 +- .github/workflows/deploy_packages.yml | 4 ++-- .github/workflows/issue.yaml | 2 +- .github/workflows/pr-review-comment.yaml | 2 +- .github/workflows/pr.yaml | 2 +- .github/workflows/sync_code-formatting.yml | 2 +- .github/workflows/sync_snyk-github-issues.yml | 2 +- .github/workflows/uffizzi-build.yml | 2 +- .github/workflows/verify_e2e-linux.yml | 2 +- .github/workflows/verify_kubernetes.yml | 2 +- .github/workflows/verify_storybook.yml | 2 +- 15 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index e18aa9d428..11fef75b9b 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -28,7 +28,7 @@ jobs: ref: 'refs/pull/${{ github.event.pull_request.number }}/merge' - name: fetch base run: git fetch --depth 1 origin ${{ github.base_ref }} - - uses: backstage/actions/changeset-feedback@v0.5.13 + - uses: backstage/actions/changeset-feedback@v0.6.0 name: Generate feedback with: diffRef: 'origin/master' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10db591f4c..16573cf5b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -63,7 +63,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -181,7 +181,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index dc221c1a1e..2e6573ede8 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -8,7 +8,7 @@ jobs: cron: runs-on: ubuntu-latest steps: - - uses: backstage/actions/cron@v0.5.13 + - uses: backstage/actions/cron@v0.6.0 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index d8470d4124..909a36199c 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -26,7 +26,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index 5f337ace3e..c9cd22640c 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -26,7 +26,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index c05b850883..fa43271a96 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -68,7 +68,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -145,7 +145,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index d16d0b55d7..9f2e5827be 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -10,4 +10,4 @@ jobs: if: github.repository == 'backstage/backstage' steps: - name: Issue sync - uses: backstage/actions/issue-sync@v0.5.13 + uses: backstage/actions/issue-sync@v0.6.0 diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index 11b590809a..261ce56177 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -35,7 +35,7 @@ jobs: const prNumber = artifact.name.slice('pr_number-'.length) core.setOutput('pr-number', prNumber); - - uses: backstage/actions/re-review@v0.5.13 + - uses: backstage/actions/re-review@v0.6.0 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index acbd11aece..1cde52bfbb 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -18,7 +18,7 @@ jobs: if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) steps: - name: PR sync - uses: backstage/actions/pr-sync@v0.5.13 + uses: backstage/actions/pr-sync@v0.6.0 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index 19cc5f8045..b84fe5c2e6 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -20,7 +20,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index 9dcc9f63ef..dfd114c66a 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -23,7 +23,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index a23216a9cb..968bc859d6 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -27,7 +27,7 @@ jobs: registry-url: https://registry.npmjs.org/ - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: linux-v16 diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index f687e4f5a4..16ddb04086 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -52,7 +52,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_kubernetes.yml b/.github/workflows/verify_kubernetes.yml index 7fbcf9fa3f..6d8a7682b5 100644 --- a/.github/workflows/verify_kubernetes.yml +++ b/.github/workflows/verify_kubernetes.yml @@ -28,7 +28,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index 0e63393af8..38b685c539 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -35,7 +35,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: storybook yarn install From d34b3267f9628b1ec7678083e40b0e885c714d4b Mon Sep 17 00:00:00 2001 From: ivgo Date: Mon, 30 Jan 2023 16:13:35 +0100 Subject: [PATCH 020/423] Entity Validation UI Signed-off-by: ivgo --- .changeset/silly-socks-lie.md | 5 + plugins/entity-validation/.eslintrc.js | 1 + plugins/entity-validation/README.md | 51 ++++++ plugins/entity-validation/api-report.md | 30 ++++ plugins/entity-validation/dev/index.tsx | 27 +++ plugins/entity-validation/package.json | 63 +++++++ .../EntityTextArea/EntityTextArea.tsx | 97 +++++++++++ .../src/components/EntityTextArea/index.ts | 16 ++ .../EntityValidationOutput/EntityResult.tsx | 107 ++++++++++++ .../EntityValidationOutput.tsx | 162 ++++++++++++++++++ .../EntityValidationOutput/index.ts | 17 ++ .../EntityValidationPage.tsx | 117 +++++++++++++ .../components/EntityValidationPage/index.ts | 16 ++ plugins/entity-validation/src/index.ts | 16 ++ plugins/entity-validation/src/plugin.test.ts | 22 +++ plugins/entity-validation/src/plugin.ts | 42 +++++ plugins/entity-validation/src/routes.ts | 20 +++ plugins/entity-validation/src/setupTests.ts | 17 ++ plugins/entity-validation/src/types.ts | 30 ++++ plugins/entity-validation/src/utils/index.ts | 16 ++ plugins/entity-validation/src/utils/utils.ts | 58 +++++++ yarn.lock | 38 ++++ 22 files changed, 968 insertions(+) create mode 100644 .changeset/silly-socks-lie.md create mode 100644 plugins/entity-validation/.eslintrc.js create mode 100644 plugins/entity-validation/README.md create mode 100644 plugins/entity-validation/api-report.md create mode 100644 plugins/entity-validation/dev/index.tsx create mode 100644 plugins/entity-validation/package.json create mode 100644 plugins/entity-validation/src/components/EntityTextArea/EntityTextArea.tsx create mode 100644 plugins/entity-validation/src/components/EntityTextArea/index.ts create mode 100644 plugins/entity-validation/src/components/EntityValidationOutput/EntityResult.tsx create mode 100644 plugins/entity-validation/src/components/EntityValidationOutput/EntityValidationOutput.tsx create mode 100644 plugins/entity-validation/src/components/EntityValidationOutput/index.ts create mode 100644 plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx create mode 100644 plugins/entity-validation/src/components/EntityValidationPage/index.ts create mode 100644 plugins/entity-validation/src/index.ts create mode 100644 plugins/entity-validation/src/plugin.test.ts create mode 100644 plugins/entity-validation/src/plugin.ts create mode 100644 plugins/entity-validation/src/routes.ts create mode 100644 plugins/entity-validation/src/setupTests.ts create mode 100644 plugins/entity-validation/src/types.ts create mode 100644 plugins/entity-validation/src/utils/index.ts create mode 100644 plugins/entity-validation/src/utils/utils.ts diff --git a/.changeset/silly-socks-lie.md b/.changeset/silly-socks-lie.md new file mode 100644 index 0000000000..ae7e1c0b2a --- /dev/null +++ b/.changeset/silly-socks-lie.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-entity-validation': minor +--- + +First implementation for the entity validation UI. For more information refer to its `README.md`. diff --git a/plugins/entity-validation/.eslintrc.js b/plugins/entity-validation/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/entity-validation/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/entity-validation/README.md b/plugins/entity-validation/README.md new file mode 100644 index 0000000000..0e80ebd29b --- /dev/null +++ b/plugins/entity-validation/README.md @@ -0,0 +1,51 @@ +# entity-validation + +This plugin creates a new page in Backstage where the user can validate the entities. + +## Getting started + +First of all, install the package in the `app` package by running the following command: + +```bash +yarn add --cwd packages/app @backstage/plugin-entity-validation +``` + +Add the new route to the app by adding the following line: + +```typescript +// In packages/app/src/App.tsx +import { EntityValidationPage } from '@backstage/plugin-entity-validation'; + +const routes = ( + + {/* ...other routes */} + } /> + +); +``` + +To add the new page to your sidebar, you must include these lines in your `Root.tsx` file: + +```typescript + // In packages/app/src/components/Root/Root.tsx + import BuildIcon from '@material-ui/icons/Build'; + + ... + + export const Root = ({ children }: PropsWithChildren<{}>) => ( + + + {/* ...other elements */} + }> + {/* Global nav, not org-specific */} + {/* ...other sidebars */} + + {/* End global nav */} + + + {/* ...other elements */} + + {children} + + ); +``` diff --git a/plugins/entity-validation/api-report.md b/plugins/entity-validation/api-report.md new file mode 100644 index 0000000000..1a3b92a7c1 --- /dev/null +++ b/plugins/entity-validation/api-report.md @@ -0,0 +1,30 @@ +## API Report File for "@backstage/plugin-entity-validation" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { RouteRef } from '@backstage/core-plugin-api'; + +// @public (undocumented) +export const EntityValidationPage: ({ + defaultPreviewCatalog, + locationPlaceholder, +}: { + defaultPreviewCatalog?: string | undefined; + locationPlaceholder?: string | undefined; +}) => JSX.Element; + +// @public (undocumented) +export const entityValidationPlugin: BackstagePlugin< + { + root: RouteRef; + }, + {}, + {} +>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/entity-validation/dev/index.tsx b/plugins/entity-validation/dev/index.tsx new file mode 100644 index 0000000000..1e1dfa760c --- /dev/null +++ b/plugins/entity-validation/dev/index.tsx @@ -0,0 +1,27 @@ +/* + * Copyright 2023 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 { createDevApp } from '@backstage/dev-utils'; +import { entityValidationPlugin, EntityValidationPage } from '../src/plugin'; + +createDevApp() + .registerPlugin(entityValidationPlugin) + .addPage({ + element: , + title: 'Root Page', + path: '/entity-validation', + }) + .render(); diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json new file mode 100644 index 0000000000..fa0c132e67 --- /dev/null +++ b/plugins/entity-validation/package.json @@ -0,0 +1,63 @@ +{ + "name": "@backstage/plugin-entity-validation", + "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-client": "workspace:^", + "@backstage/catalog-model": "workspace:^", + "@backstage/core-components": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/plugin-catalog-common": "workspace:^", + "@backstage/plugin-catalog-node": "workspace:^", + "@backstage/plugin-catalog-react": "workspace:^", + "@backstage/theme": "workspace:^", + "@codemirror/language": "^6.0.0", + "@codemirror/legacy-modes": "^6.1.0", + "@codemirror/view": "^6.0.0", + "@material-ui/core": "^4.12.2", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "^4.0.0-alpha.57", + "@react-hookz/web": "^20.0.0", + "@uiw/react-codemirror": "^4.9.3", + "lodash": "^4.17.21", + "react-use": "^17.2.4", + "yaml": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/dev-utils": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^14.0.0", + "@types/node": "*", + "cross-fetch": "^3.1.5", + "msw": "^0.49.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/entity-validation/src/components/EntityTextArea/EntityTextArea.tsx b/plugins/entity-validation/src/components/EntityTextArea/EntityTextArea.tsx new file mode 100644 index 0000000000..c39f8d5ed7 --- /dev/null +++ b/plugins/entity-validation/src/components/EntityTextArea/EntityTextArea.tsx @@ -0,0 +1,97 @@ +/* + * Copyright 2023 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, { useMemo, useState } from 'react'; +import { Box, makeStyles } from '@material-ui/core'; +import CodeMirror from '@uiw/react-codemirror'; +import { showPanel } from '@codemirror/view'; +import { StreamLanguage } from '@codemirror/language'; +import { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml'; +import { useKeyboardEvent } from '@react-hookz/web'; + +const useStyles = makeStyles(theme => ({ + container: { + position: 'relative', + width: '100%', + height: '100%', + minHeight: '400px', + }, + codeMirror: { + position: 'absolute', + top: 0, + bottom: 0, + left: 0, + right: 0, + }, + infoPanel: { + color: theme.palette.info.main, + lineHeight: 2, + margin: theme.spacing(0, 1), + }, +})); + +type TemplateTextAreaProps = { + catalogYaml: string; + onChange: (value: string) => void; + onValidate: () => void; +}; + +export const EntityTextArea = ({ + catalogYaml, + onChange, + onValidate, +}: TemplateTextAreaProps) => { + const classes = useStyles(); + const [close, setClose] = useState(false); + + const panelExtension = useMemo(() => { + if (close) { + return showPanel.of(null); + } + + const dom = document.createElement('div'); + dom.classList.add(classes.infoPanel); + dom.textContent = + 'To validate your catalog-info.yaml click on the "Validate" button or use "Ctrl + S" or "Ctrl + Enter"'; + dom.onclick = () => setClose(true); + return showPanel.of(() => ({ dom, top: true })); + }, [classes, close]); + + // Triggers a validation when Ctrl+S or Ctrl+Enter instead of default behavior + useKeyboardEvent( + e => (e.key === 's' || e.key === 'Enter') && (e.ctrlKey || e.metaKey), + e => { + e.preventDefault(); + onValidate(); + }, + ); + + return ( + + { + // Prevent new line if Ctrl + Enter was clicked + if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) e.preventDefault(); + }} + /> + + ); +}; diff --git a/plugins/entity-validation/src/components/EntityTextArea/index.ts b/plugins/entity-validation/src/components/EntityTextArea/index.ts new file mode 100644 index 0000000000..d2a5e41d0f --- /dev/null +++ b/plugins/entity-validation/src/components/EntityTextArea/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './EntityTextArea'; diff --git a/plugins/entity-validation/src/components/EntityValidationOutput/EntityResult.tsx b/plugins/entity-validation/src/components/EntityValidationOutput/EntityResult.tsx new file mode 100644 index 0000000000..85d47fa2c2 --- /dev/null +++ b/plugins/entity-validation/src/components/EntityValidationOutput/EntityResult.tsx @@ -0,0 +1,107 @@ +/* + * Copyright 2023 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, { useState } from 'react'; +import { ValidateEntityResponse } from '@backstage/catalog-client'; +import { useApp } from '@backstage/core-plugin-api'; +import { + Collapse, + IconButton, + ListItem, + ListItemIcon, + ListItemSecondaryAction, + ListItemText, + makeStyles, + Paper, +} from '@material-ui/core'; +import { humanizeEntityRef } from '@backstage/plugin-catalog-react'; +import WorkIcon from '@material-ui/icons/Work'; +import ExpandLessIcon from '@material-ui/icons/ExpandLess'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import { MarkdownContent } from '@backstage/core-components'; +import { ValidationOutputOk } from '../../types'; + +const useStyles = makeStyles(theme => ({ + validationOk: { + color: theme.palette.success.main, + }, + validationNotOk: { + color: theme.palette.error.main, + }, + errorContainer: { + color: theme.palette.error.main, + background: theme.palette.background.paper, + padding: theme.spacing(2), + }, +})); + +type EntityResultProps = { + isFirstError?: boolean; + item: ValidationOutputOk; +}; + +export const EntityResult = ({ + isFirstError = false, + item, +}: EntityResultProps) => { + const classes = useStyles(); + const app = useApp(); + const [expanded, setExpanded] = useState(isFirstError); + + const Icon = + app.getSystemIcon(`kind:${item.entity.kind.toLocaleLowerCase('en-US')}`) ?? + WorkIcon; + + const fetchErrorMessages = (response: ValidateEntityResponse) => { + if (!response.valid) { + return response.errors.map(err => err.message).join('\n\n'); + } + return ''; + }; + + return ( + <> + + + + + setExpanded(!expanded)} + /> + {!item.response.valid && ( + + setExpanded(!expanded)}> + {expanded ? : } + + + )} + + {!item.response.valid && ( + + + + + + )} + + ); +}; diff --git a/plugins/entity-validation/src/components/EntityValidationOutput/EntityValidationOutput.tsx b/plugins/entity-validation/src/components/EntityValidationOutput/EntityValidationOutput.tsx new file mode 100644 index 0000000000..f58fc90559 --- /dev/null +++ b/plugins/entity-validation/src/components/EntityValidationOutput/EntityValidationOutput.tsx @@ -0,0 +1,162 @@ +/* + * Copyright 2023 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 { identityApiRef, useApi } from '@backstage/core-plugin-api'; +import { CatalogProcessorResult } from '@backstage/plugin-catalog-node'; +import { + catalogApiRef, + humanizeEntityRef, +} from '@backstage/plugin-catalog-react'; +import { List, makeStyles, Typography } from '@material-ui/core'; +import useAsync from 'react-use/lib/useAsync'; +import { InfoCard, Progress } from '@backstage/core-components'; +import Alert from '@material-ui/lab/Alert'; +import { + ValidationOutput, + ValidationOutputError, + ValidationOutputOk, +} from '../../types'; +import { EntityResult } from './EntityResult'; + +const useStyles = makeStyles(theme => ({ + validationOk: { + color: theme.palette.success.main, + }, + validationNotOk: { + color: theme.palette.error.main, + }, +})); + +function sortResults(items: Array) { + return items.sort((a, b) => + humanizeEntityRef(a.entity).localeCompare(humanizeEntityRef(b.entity)), + ); +} + +type EntityValidationOutputProps = { + processorResults?: CatalogProcessorResult[]; + locationUrl: string; +}; + +export const EntityValidationOutput = ({ + processorResults, + locationUrl, +}: EntityValidationOutputProps) => { + const classes = useStyles(); + const catalogApi = useApi(catalogApiRef); + const identityApi = useApi(identityApiRef); + + const { value = [], loading } = useAsync(async (): Promise< + ValidationOutput[] | undefined + > => { + if (!processorResults) { + return undefined; + } + + const location = locationUrl + ? `url:${locationUrl}` + : 'url:http://localhost'; + + return await Promise.all( + processorResults.map(async item => { + if (item.type === 'entity') { + const { token } = await identityApi.getCredentials(); + + const validateResult = await catalogApi.validateEntity( + item.entity, + location, + { + token, + }, + ); + return { + type: 'valid', + entity: item.entity, + response: validateResult, + }; + } else if (item.type === 'error') { + return { + type: 'error', + processingError: `Malformed entity YAML, ${item.error}`, + }; + } + return { + type: 'error', + processingError: `Internal error, failed to parse entity`, + }; + }), + ); + }, [processorResults]); + + if (loading) { + return ; + } + + const errors = value.filter( + v => v.type === 'error', + ) as ValidationOutputError[]; + + const results = sortResults( + value.filter(v => v.type === 'valid') as ValidationOutputOk[], + ); + // If there are any errors, only the first one will be expanded + const firstErrorIndex = results.findIndex(r => !r.response.valid); + + if (errors.length !== 0) { + return ( + <> + {errors.map(err => ( + {err.processingError} + ))} + + ); + } + + return ( + + {results.length === 0 ? ( +
+ + No entity definitions found or validated yet + +
+ ) : ( + <> + + {results.map((item, key) => ( + + ))} + +
+ {results.every(r => r.response.valid) ? ( + + All the entities are valid! + + ) : ( + + One or more entities have validation errors + + )} +
+ + )} +
+ ); +}; diff --git a/plugins/entity-validation/src/components/EntityValidationOutput/index.ts b/plugins/entity-validation/src/components/EntityValidationOutput/index.ts new file mode 100644 index 0000000000..8d327581c6 --- /dev/null +++ b/plugins/entity-validation/src/components/EntityValidationOutput/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './EntityValidationOutput'; +export * from './EntityResult'; diff --git a/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx b/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx new file mode 100644 index 0000000000..d39b234342 --- /dev/null +++ b/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx @@ -0,0 +1,117 @@ +/* + * Copyright 2023 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, { useState } from 'react'; +import { Button, Content, Header, Page } from '@backstage/core-components'; +import { EntityTextArea } from '../EntityTextArea'; +import { Grid, TextField } from '@material-ui/core'; +import { CatalogProcessorResult } from '@backstage/plugin-catalog-node'; +import { parseEntityYaml } from '../../utils'; +import { EntityValidationOutput } from '../EntityValidationOutput'; + +const EXAMPLE_CATALOG_INFO_YAML = `# Put your catalog-info.yaml below and validate it +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: test + description: Component description + links: [] + tags: [] + annotations: {} +spec: + type: service + lifecycle: experimental + owner: owner +`; + +export const EntityValidationPage = ({ + defaultPreviewCatalog = EXAMPLE_CATALOG_INFO_YAML, + locationPlaceholder = 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', +}: { + defaultPreviewCatalog?: string; + locationPlaceholder?: string; +}) => { + const [catalogYaml, setCatalogYaml] = useState(defaultPreviewCatalog); + const [yamlFiles, setYamlFiles] = useState(); + const [locationUrl, setLocationUrl] = useState(''); + + const parseYaml = () => { + const parsedFiles = [ + ...parseEntityYaml(Buffer.from(catalogYaml), { + type: 'url', + target: locationUrl ? locationUrl : 'http://localhost', + }), + ]; + setYamlFiles(parsedFiles); + }; + + return ( + +
+ + + + setLocationUrl(e.target.value)} + /> + + + + + + + + + + + + setCatalogYaml(value)} + catalogYaml={catalogYaml} + /> + + + + + + + + + + + + ); +}; diff --git a/plugins/entity-validation/src/components/EntityValidationPage/index.ts b/plugins/entity-validation/src/components/EntityValidationPage/index.ts new file mode 100644 index 0000000000..24149a9387 --- /dev/null +++ b/plugins/entity-validation/src/components/EntityValidationPage/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './EntityValidationPage'; diff --git a/plugins/entity-validation/src/index.ts b/plugins/entity-validation/src/index.ts new file mode 100644 index 0000000000..33ae575dfe --- /dev/null +++ b/plugins/entity-validation/src/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 { entityValidationPlugin, EntityValidationPage } from './plugin'; diff --git a/plugins/entity-validation/src/plugin.test.ts b/plugins/entity-validation/src/plugin.test.ts new file mode 100644 index 0000000000..eae69e8d3a --- /dev/null +++ b/plugins/entity-validation/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2023 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 { entityValidationPlugin } from './plugin'; + +describe('entity-validation', () => { + it('should export plugin', () => { + expect(entityValidationPlugin).toBeDefined(); + }); +}); diff --git a/plugins/entity-validation/src/plugin.ts b/plugins/entity-validation/src/plugin.ts new file mode 100644 index 0000000000..9a3014da28 --- /dev/null +++ b/plugins/entity-validation/src/plugin.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2023 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 { + createComponentExtension, + createPlugin, +} from '@backstage/core-plugin-api'; + +import { rootRouteRef } from './routes'; + +/** @public */ +export const entityValidationPlugin = createPlugin({ + id: 'entity-validation', + routes: { + root: rootRouteRef, + }, +}); + +/** @public */ +export const EntityValidationPage = entityValidationPlugin.provide( + createComponentExtension({ + name: 'EntityValidationPage', + component: { + lazy: () => + import('./components/EntityValidationPage').then( + m => m.EntityValidationPage, + ), + }, + }), +); diff --git a/plugins/entity-validation/src/routes.ts b/plugins/entity-validation/src/routes.ts new file mode 100644 index 0000000000..8cdc138782 --- /dev/null +++ b/plugins/entity-validation/src/routes.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2023 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 } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + id: 'entity-validation', +}); diff --git a/plugins/entity-validation/src/setupTests.ts b/plugins/entity-validation/src/setupTests.ts new file mode 100644 index 0000000000..73dd8dce47 --- /dev/null +++ b/plugins/entity-validation/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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/entity-validation/src/types.ts b/plugins/entity-validation/src/types.ts new file mode 100644 index 0000000000..69caf79e33 --- /dev/null +++ b/plugins/entity-validation/src/types.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2023 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 { ValidateEntityResponse } from '@backstage/catalog-client'; + +export type ValidationOutputError = { + type: 'error'; + processingError: string; +}; + +export type ValidationOutputOk = { + type: 'valid'; + entity: Entity; + response: ValidateEntityResponse; +}; + +export type ValidationOutput = ValidationOutputOk | ValidationOutputError; diff --git a/plugins/entity-validation/src/utils/index.ts b/plugins/entity-validation/src/utils/index.ts new file mode 100644 index 0000000000..8d45a67a36 --- /dev/null +++ b/plugins/entity-validation/src/utils/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './utils'; diff --git a/plugins/entity-validation/src/utils/utils.ts b/plugins/entity-validation/src/utils/utils.ts new file mode 100644 index 0000000000..dde50d2f9c --- /dev/null +++ b/plugins/entity-validation/src/utils/utils.ts @@ -0,0 +1,58 @@ +/* + * Copyright 2023 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, stringifyLocationRef } from '@backstage/catalog-model'; +import lodash from 'lodash'; +import yaml from 'yaml'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; +import { + CatalogProcessorResult, + processingResult, +} from '@backstage/plugin-catalog-node'; + +// Copy from: https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/modules/util/parse.ts +export function* parseEntityYaml( + data: Buffer, + location: LocationSpec, +): Iterable { + let documents: yaml.Document.Parsed[]; + try { + documents = yaml.parseAllDocuments(data.toString('utf8')).filter(d => d); + } catch (e) { + const loc = stringifyLocationRef(location); + const message = `Failed to parse YAML at ${loc}, ${e}`; + yield processingResult.generalError(location, message); + return; + } + + for (const document of documents) { + if (document.errors?.length) { + const loc = stringifyLocationRef(location); + const message = `YAML error at ${loc}, ${document.errors[0]}`; + yield processingResult.generalError(location, message); + } else { + const json = document.toJSON(); + if (lodash.isPlainObject(json)) { + yield processingResult.entity(location, json as Entity); + } else if (json === null) { + // Ignore null values, these happen if there is an empty document in the + // YAML file, for example if --- is added to the end of the file. + } else { + const message = `Expected object at root, got ${typeof json}`; + yield processingResult.generalError(location, message); + } + } + } +} diff --git a/yarn.lock b/yarn.lock index f68a2d20d0..a3e9612ca6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5759,6 +5759,44 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-entity-validation@workspace:plugins/entity-validation": + version: 0.0.0-use.local + resolution: "@backstage/plugin-entity-validation@workspace:plugins/entity-validation" + dependencies: + "@backstage/catalog-client": "workspace:^" + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/plugin-catalog-common": "workspace:^" + "@backstage/plugin-catalog-node": "workspace:^" + "@backstage/plugin-catalog-react": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@codemirror/language": ^6.0.0 + "@codemirror/legacy-modes": ^6.1.0 + "@codemirror/view": ^6.0.0 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": ^4.0.0-alpha.57 + "@react-hookz/web": ^20.0.0 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/user-event": ^14.0.0 + "@types/node": "*" + "@uiw/react-codemirror": ^4.9.3 + cross-fetch: ^3.1.5 + lodash: ^4.17.21 + msw: ^0.49.0 + react-use: ^17.2.4 + yaml: ^2.0.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + languageName: unknown + linkType: soft + "@backstage/plugin-events-backend-module-aws-sqs@workspace:plugins/events-backend-module-aws-sqs": version: 0.0.0-use.local resolution: "@backstage/plugin-events-backend-module-aws-sqs@workspace:plugins/events-backend-module-aws-sqs" From 690905b78b723c8ad884855d1c26dfe05e210966 Mon Sep 17 00:00:00 2001 From: bogdannechyporenko Date: Tue, 31 Jan 2023 12:50:46 +0100 Subject: [PATCH 021/423] Described how to configure jest tests in IntelliJ Signed-off-by: bogdannechyporenko --- docs/local-dev/cli-build-system.md | 13 +++++++++++++ docs/plugins/testing.md | 12 +----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index cc364d0ca5..ba65bedb9f 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -595,6 +595,19 @@ If you also want to enable source maps when debugging tests, you can do so by se } ``` +### Debugging Jest Tests + +To configure the debugging of your tests in IntelliJ, you have to: + +1. Update Jest configuration template by: + +- Click on "Edit Configurations" on top panel +- In the modal dialog click on link "Edit configuration templates..." located in the bottom left corner. +- In "Jest package" you have to point to relative path of jest module (it will be suggested by IntelliJ), i.e. ~/proj/backstage/node_modules/jest +- In "Jest config" point to your jest configuration file, use absolute path for that, i.e. `--config /Users/user/proj/backstage/packages/cli/config/jest.js --runInBand` + +2. Now you can run any tests by clicking on green arrow located on `describe` or `it`. + ## Publishing Package publishing is an optional part of the Backstage build system and not diff --git a/docs/plugins/testing.md b/docs/plugins/testing.md index baee47c695..2fa086c444 100644 --- a/docs/plugins/testing.md +++ b/docs/plugins/testing.md @@ -371,14 +371,4 @@ Note: wrapping in the test application **requires** you to do a `find()` or # Debugging Jest Tests -Currently, debugging Jest tests using IntelliJ or `node-debugger` is possible -but can be -[problematic to set up.](https://intellij-support.jetbrains.com/hc/en-us/community/posts/115000634564-Debugging-Jest-unit-tests) - -It is possible, but you might spend a decent amount of time configuring your -IDE. - -In most cases, we have found that using `console.log` works well. - -Note: if your console.logs are not being displayed, focus your specific unit -test from the command line by running them like so `yarn test MyTest`. +You can find it [here](https://backstage.io/docs/local-dev/cli-build-system#debugging-jest-tests) From 6197146926d9aa7a39eb7173fb5f71b5d292529a Mon Sep 17 00:00:00 2001 From: Alex Crome Date: Tue, 31 Jan 2023 18:56:20 +0000 Subject: [PATCH 022/423] Fix bad merge Signed-off-by: Alex Crome --- .../catalog-backend-module-msgraph/src/microsoftGraph/read.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts index a060df5ea3..003448a3e8 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts @@ -38,6 +38,7 @@ import { defaultOrganizationTransformer, defaultUserTransformer, } from './defaultTransformers'; +import * as MicrosoftGraph from '@microsoft/microsoft-graph-types'; const PAGE_SIZE = 999; From 77c41b69241da6c266c9f51e67c755ebe45df756 Mon Sep 17 00:00:00 2001 From: Damon Kaswell Date: Tue, 31 Jan 2023 11:13:06 -0800 Subject: [PATCH 023/423] Added changeset Signed-off-by: Damon Kaswell --- .changeset/tall-tables-hide.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tall-tables-hide.md diff --git a/.changeset/tall-tables-hide.md b/.changeset/tall-tables-hide.md new file mode 100644 index 0000000000..3e8011aff2 --- /dev/null +++ b/.changeset/tall-tables-hide.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +--- + +Updated README to include newer API options for incremental entity providers From 72a06103d01cc0d16b2ca87664624f9f17ede9de Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Tue, 31 Jan 2023 16:09:35 -0500 Subject: [PATCH 024/423] add trpc widget Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- .../ApiDefinitionCard/ApiDefinitionWidget.tsx | 8 ++++ .../GraphQlDefinition.tsx | 2 +- .../TrpcApiDefinitionWidget.test.tsx | 32 +++++++++++++++ .../TrpcApiDefinitionWidget.tsx | 40 +++++++++++++++++++ .../components/TrpcDefinitionWidget/index.ts | 19 +++++++++ plugins/api-docs/src/components/index.ts | 1 + 6 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.test.tsx create mode 100644 plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx create mode 100644 plugins/api-docs/src/components/TrpcDefinitionWidget/index.ts diff --git a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionWidget.tsx b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionWidget.tsx index 03a56eaa78..8d7d7a7729 100644 --- a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionWidget.tsx @@ -18,6 +18,7 @@ import { AsyncApiDefinitionWidget } from '../AsyncApiDefinitionWidget'; import { GraphQlDefinitionWidget } from '../GraphQlDefinitionWidget'; import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget'; import { GrpcApiDefinitionWidget } from '../GrpcApiDefinitionWidget'; +import { TrpcApiDefinitionWidget } from '../TrpcDefinitionWidget'; /** @public */ export type ApiDefinitionWidget = { @@ -61,5 +62,12 @@ export function defaultDefinitionWidgets(): ApiDefinitionWidget[] { ), }, + { + type: 'trpc', + title: 'tRPC', + component: definition => ( + + ), + }, ]; } diff --git a/plugins/api-docs/src/components/GraphQlDefinitionWidget/GraphQlDefinition.tsx b/plugins/api-docs/src/components/GraphQlDefinitionWidget/GraphQlDefinition.tsx index d3fddf70cf..3dbe941be3 100644 --- a/plugins/api-docs/src/components/GraphQlDefinitionWidget/GraphQlDefinition.tsx +++ b/plugins/api-docs/src/components/GraphQlDefinitionWidget/GraphQlDefinition.tsx @@ -44,7 +44,7 @@ type Props = { definition: string; }; -export const GraphQlDefinition = ({ definition }: Props) => { +export const GraphQlDefinition: React.FC = ({ definition }: Props) => { const classes = useStyles(); const schema = buildSchema(definition); diff --git a/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.test.tsx b/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.test.tsx new file mode 100644 index 0000000000..d7e6951e2e --- /dev/null +++ b/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.test.tsx @@ -0,0 +1,32 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { renderInTestApp } from '@backstage/test-utils'; +import React from 'react'; +import { TrpcApiDefinitionWidget } from './TrpcApiDefinitionWidget'; + +describe('', () => { + it('renders plain text', async () => { + const { getAllByText } = await renderInTestApp( + , + ); + + expect( + getAllByText((_text, element) => element?.textContent === 'Hello World') + .length, + ).toBeGreaterThan(0); + }); +}); diff --git a/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx b/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx new file mode 100644 index 0000000000..c4cf56bedb --- /dev/null +++ b/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx @@ -0,0 +1,40 @@ +/* + * Copyright 2023 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 { CodeSnippet } from '@backstage/core-components'; +import { useTheme } from '@material-ui/core/styles'; +import { BackstageTheme } from '@backstage/theme'; + +/** @public */ +export type TrpcApiDefinitionWidgetProps = { + definition: string; +}; + +/** @public */ +export const TrpcApiDefinitionWidget: React.FC = ( + props: TrpcApiDefinitionWidgetProps, +) => { + const { definition } = props; + const theme = useTheme(); + return ( + + ); +}; diff --git a/plugins/api-docs/src/components/TrpcDefinitionWidget/index.ts b/plugins/api-docs/src/components/TrpcDefinitionWidget/index.ts new file mode 100644 index 0000000000..604adb06f3 --- /dev/null +++ b/plugins/api-docs/src/components/TrpcDefinitionWidget/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2023 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 { + TrpcApiDefinitionWidget, + type TrpcApiDefinitionWidgetProps, +} from './TrpcApiDefinitionWidget'; diff --git a/plugins/api-docs/src/components/index.ts b/plugins/api-docs/src/components/index.ts index ea40076af4..7e7b206c54 100644 --- a/plugins/api-docs/src/components/index.ts +++ b/plugins/api-docs/src/components/index.ts @@ -22,3 +22,4 @@ export * from './ComponentsCards'; export * from './GraphQlDefinitionWidget'; export * from './OpenApiDefinitionWidget'; export * from './PlainApiDefinitionWidget'; +export * from './TrpcDefinitionWidget'; From 9ed53218a5395667523e2ed9dfd50d5ab655b767 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Tue, 31 Jan 2023 16:21:13 -0500 Subject: [PATCH 025/423] add changeset for api-docs plugins Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- .changeset/great-goats-talk.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/great-goats-talk.md diff --git a/.changeset/great-goats-talk.md b/.changeset/great-goats-talk.md new file mode 100644 index 0000000000..92a1cd59ee --- /dev/null +++ b/.changeset/great-goats-talk.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': minor +--- + +Adds a new tRPC API definition widget which users can utilize to integrate their tRPC API definitions into Backstage. From ed40fbbe7e48eb3a6d51ec6da436eefd5ee37c40 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Tue, 31 Jan 2023 16:42:05 -0500 Subject: [PATCH 026/423] add tRPC to dev app Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- plugins/api-docs/dev/index.tsx | 15 +++++++++++++ plugins/api-docs/dev/trpc-example-api.yaml | 25 ++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 plugins/api-docs/dev/trpc-example-api.yaml diff --git a/plugins/api-docs/dev/index.tsx b/plugins/api-docs/dev/index.tsx index 9975e91e98..995aa9c2fb 100644 --- a/plugins/api-docs/dev/index.tsx +++ b/plugins/api-docs/dev/index.tsx @@ -32,6 +32,7 @@ import graphqlApiEntity from './graphql-example-api.yaml'; import invalidLanguageApiEntity from './invalid-language-example-api.yaml'; import openapiApiEntity from './openapi-example-api.yaml'; import otherApiEntity from './other-example-api.yaml'; +import trpcApiEntity from './trpc-example-api.yaml'; const mockEntities = [ openapiApiEntity, @@ -39,6 +40,7 @@ const mockEntities = [ graphqlApiEntity, invalidLanguageApiEntity, otherApiEntity, + trpcApiEntity, ] as unknown as Entity[]; createDevApp() @@ -137,4 +139,17 @@ createDevApp() ), }) + .addPage({ + title: 'tRPC', + element: ( + +
+ + + + + + + ), + }) .render(); diff --git a/plugins/api-docs/dev/trpc-example-api.yaml b/plugins/api-docs/dev/trpc-example-api.yaml new file mode 100644 index 0000000000..4adf78835c --- /dev/null +++ b/plugins/api-docs/dev/trpc-example-api.yaml @@ -0,0 +1,25 @@ +apiVersion: backstage.io/v1alpha1 +kind: API +metadata: + name: hello-world + description: Hello World example for tRPC +spec: + type: trpc + lifecycle: experimental + owner: team-c + definition: | + import { z } from 'zod'; + import { publicProcedure, router } from '../trpc'; + + export const apiRouter = router({ + version: publicProcedure.query(() => { + return { version: '0.42.0' }; + }), + hello: publicProcedure + .input(z.object({ username: z.string().nullish() }).nullish()) + .query(({ input, ctx }) => { + return { + text: `hello ${input?.username ?? ctx.user?.name ?? 'world'}`, + }; + }), + }); From a2194b2a4d0415b27d49dcaac5b916462d6dcc79 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Tue, 31 Jan 2023 16:47:51 -0500 Subject: [PATCH 027/423] rename trpc-sample api Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- plugins/api-docs/dev/trpc-example-api.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/api-docs/dev/trpc-example-api.yaml b/plugins/api-docs/dev/trpc-example-api.yaml index 4adf78835c..eff7efa8f1 100644 --- a/plugins/api-docs/dev/trpc-example-api.yaml +++ b/plugins/api-docs/dev/trpc-example-api.yaml @@ -1,7 +1,7 @@ apiVersion: backstage.io/v1alpha1 kind: API metadata: - name: hello-world + name: hello-world-trpc description: Hello World example for tRPC spec: type: trpc From a16f81df082b8e89b323c71d6d70c80e3e788c52 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Tue, 31 Jan 2023 17:06:16 -0500 Subject: [PATCH 028/423] add the tRPC hello world example Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- .../examples/apis/hello-world-trpc-api.yaml | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 packages/catalog-model/examples/apis/hello-world-trpc-api.yaml diff --git a/packages/catalog-model/examples/apis/hello-world-trpc-api.yaml b/packages/catalog-model/examples/apis/hello-world-trpc-api.yaml new file mode 100644 index 0000000000..eff7efa8f1 --- /dev/null +++ b/packages/catalog-model/examples/apis/hello-world-trpc-api.yaml @@ -0,0 +1,25 @@ +apiVersion: backstage.io/v1alpha1 +kind: API +metadata: + name: hello-world-trpc + description: Hello World example for tRPC +spec: + type: trpc + lifecycle: experimental + owner: team-c + definition: | + import { z } from 'zod'; + import { publicProcedure, router } from '../trpc'; + + export const apiRouter = router({ + version: publicProcedure.query(() => { + return { version: '0.42.0' }; + }), + hello: publicProcedure + .input(z.object({ username: z.string().nullish() }).nullish()) + .query(({ input, ctx }) => { + return { + text: `hello ${input?.username ?? ctx.user?.name ?? 'world'}`, + }; + }), + }); From 4205d9eec177ffe4f1863951eb727e289af9056f Mon Sep 17 00:00:00 2001 From: MitchWijt Date: Fri, 27 Jan 2023 16:25:35 +0100 Subject: [PATCH 029/423] feat(plugin): Add graphql-voyager as new backstage plugin Signed-off-by: MitchWijt --- microsite/data/plugins/graphql-voyager.yaml | 13 ++ plugins/graphql-voyager/.eslintrc.js | 1 + plugins/graphql-voyager/README.md | 75 ++++++++++ plugins/graphql-voyager/api-report.md | 64 ++++++++ plugins/graphql-voyager/package.json | 53 +++++++ .../GraphQLVoyagerBrowser.test.tsx | 94 ++++++++++++ .../GraphQLVoyagerBrowser.tsx | 131 ++++++++++++++++ .../components/GraphQLVoyagerBrowser/index.ts | 16 ++ .../GraphQLVoyagerPage.test.tsx | 64 ++++++++ .../GraphQLVoyagerPage/GraphQLVoyagerPage.tsx | 62 ++++++++ .../components/GraphQLVoyagerPage/index.ts | 16 ++ .../graphql-voyager/src/components/index.ts | 17 +++ plugins/graphql-voyager/src/index.ts | 18 +++ .../src/lib/api/GraphQLVoyagerEndpoints.ts | 29 ++++ plugins/graphql-voyager/src/lib/api/index.ts | 17 +++ plugins/graphql-voyager/src/lib/api/types.ts | 141 ++++++++++++++++++ plugins/graphql-voyager/src/plugin.test.ts | 22 +++ plugins/graphql-voyager/src/plugin.ts | 38 +++++ plugins/graphql-voyager/src/routes.ts | 20 +++ plugins/graphql-voyager/src/setupTests.ts | 17 +++ 20 files changed, 908 insertions(+) create mode 100644 microsite/data/plugins/graphql-voyager.yaml create mode 100644 plugins/graphql-voyager/.eslintrc.js create mode 100644 plugins/graphql-voyager/README.md create mode 100644 plugins/graphql-voyager/api-report.md create mode 100644 plugins/graphql-voyager/package.json create mode 100644 plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.test.tsx create mode 100644 plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx create mode 100644 plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/index.ts create mode 100644 plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx create mode 100644 plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx create mode 100644 plugins/graphql-voyager/src/components/GraphQLVoyagerPage/index.ts create mode 100644 plugins/graphql-voyager/src/components/index.ts create mode 100644 plugins/graphql-voyager/src/index.ts create mode 100644 plugins/graphql-voyager/src/lib/api/GraphQLVoyagerEndpoints.ts create mode 100644 plugins/graphql-voyager/src/lib/api/index.ts create mode 100644 plugins/graphql-voyager/src/lib/api/types.ts create mode 100644 plugins/graphql-voyager/src/plugin.test.ts create mode 100644 plugins/graphql-voyager/src/plugin.ts create mode 100644 plugins/graphql-voyager/src/routes.ts create mode 100644 plugins/graphql-voyager/src/setupTests.ts diff --git a/microsite/data/plugins/graphql-voyager.yaml b/microsite/data/plugins/graphql-voyager.yaml new file mode 100644 index 0000000000..0bb56fb469 --- /dev/null +++ b/microsite/data/plugins/graphql-voyager.yaml @@ -0,0 +1,13 @@ +--- +title: GraphQL Voyager +author: PostNL +authorUrl: https://github.com/postnl +category: Debugging +description: Integrates the GraphQL Voyager tool inside Backstage. +documentation: https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager +iconUrl: https://res.cloudinary.com/apideck/image/upload/v1612724234/icons/graphql-voyager.png +npmPackageName: '@backstage/plugin-graphql-voyager' +tags: + - graphql + - graphql-voyager +addedDate: '2023-01-27' diff --git a/plugins/graphql-voyager/.eslintrc.js b/plugins/graphql-voyager/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/graphql-voyager/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/graphql-voyager/README.md b/plugins/graphql-voyager/README.md new file mode 100644 index 0000000000..f2f5265e2f --- /dev/null +++ b/plugins/graphql-voyager/README.md @@ -0,0 +1,75 @@ +# graphql-voyager + +Welcome to the graphql-voyager plugin! + +_This plugin was created through the Backstage CLI_ + +## Getting started + +### Installing + +To get started, first install the plugin with the following command: + +```bash +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-graphql-voyager +``` + +### Adding the page + +In order to be able to navigate to the graphQL voyager page, a new route needs to be added to the app. This can be done in the following way: + +```tsx +// packages/app/App.tsx + + import { GraphQLVoyagerPage } from "@backstage/plugin-graphql-voyager"; + + const routes = ( + + }/> +``` + +### Configuration + +In order for the plugin to function correctly. GraphQL endpoints need to be added / configured through the GraphQLVoyager API. This can be done by implementing the `graphQlVoyagerApiRef` exported by this plugin. + +Add your own configuration to the `packages/app/src/apis.ts` file the following way: + +```ts +import { identityApiRef } from './IdentityApi'; +import { GraphQLVoyagerEndpoints } from './GraphQLVoyagerEndpoints'; + +export const apis: AnyApiFactory[] = [ + createApiFactory({ + api: graphQlVoyagerApiRef, + deps: { identityApi: identityApiRef }, + factory: ({ identityApiRef }) => { + GraphQLVoyagerEndpoints.from([ + { + id: `graphql-voyager-endpoint-id`, + title: 'endpoint-title', + introspectionErrorMessage: + 'Unable to perform introspection, make sure you are on the correct environment.', + introspection: async (query: any) => { + const token = 'someSecretJWTComingFromIdentityApiRef'; + + const res = await fetch('graphQLEndpoint', { + method: 'POST', + body: JSON.stringify({ query }), + headers: { + 'Content-Type': 'application/json', + Authorization: token, + }, + }); + + return res.json(); + }, + voyagerProps: { + hideDocs: true, + }, + }, + ]); + }, + }), +]; +``` diff --git a/plugins/graphql-voyager/api-report.md b/plugins/graphql-voyager/api-report.md new file mode 100644 index 0000000000..21423a8c30 --- /dev/null +++ b/plugins/graphql-voyager/api-report.md @@ -0,0 +1,64 @@ +## API Report File for "@backstage/plugin-graphql-voyager" + +> 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 { RouteRef } from '@backstage/core-plugin-api'; +import { VoyagerDisplayOptions } from 'graphql-voyager/typings/components/Voyager'; +import { WorkerCallback } from 'graphql-voyager/typings/utils/types'; + +// @public (undocumented) +export type GraphQLVoyagerApi = { + getEndpoints(): Promise; +}; + +// @public (undocumented) +export const graphQlVoyagerApiRef: ApiRef; + +// @public (undocumented) +export type GraphQLVoyagerEndpoint = { + id: string; + title: string; + introspection: (body: any) => Promise; + introspectionErrorMessage: string; + voyagerProps?: { + displayOptions?: VoyagerDisplayOptions; + hideDocs?: boolean; + hideSettings?: boolean; + workerURI?: string; + loadWorker?: WorkerCallback; + }; +}; + +// @public (undocumented) +export class GraphQLVoyagerEndpoints implements GraphQLVoyagerApi { + // (undocumented) + static from(endpoints: GraphQLVoyagerEndpoint[]): GraphQLVoyagerEndpoints; + // (undocumented) + getEndpoints(): Promise; +} + +// @public (undocumented) +export const GraphqlVoyagerPage: () => JSX.Element; + +// @public (undocumented) +export const graphqlVoyagerPlugin: BackstagePlugin< + { + root: RouteRef; + }, + {}, + {} +>; + +// @public (undocumented) +export const introspectionQuery: string; + +// @public (undocumented) +export const Router: () => JSX.Element; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json new file mode 100644 index 0000000000..1cc7bb19e6 --- /dev/null +++ b/plugins/graphql-voyager/package.json @@ -0,0 +1,53 @@ +{ + "name": "@backstage/plugin-graphql-voyager", + "description": "Backstage plugin for GraphQL Voyager", + "version": "0.1.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/core-components": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/theme": "workspace:^", + "@material-ui/core": "^4.9.13", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "4.0.0-alpha.57", + "graphql-voyager": "^1.0.0-rc.31", + "react-use": "^17.2.4" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/dev-utils": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^14.0.0", + "@types/node": "*", + "cross-fetch": "^3.1.5", + "msw": "^0.47.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.test.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.test.tsx new file mode 100644 index 0000000000..76ccbd9965 --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.test.tsx @@ -0,0 +1,94 @@ +/* + * Copyright 2023 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 { renderInTestApp } from '@backstage/test-utils'; +import { GraphQLVoyagerBrowser } from './GraphQLVoyagerBrowser'; + +jest.mock('graphql-voyager', () => ({ Voyager: () => '' })); + +describe('GraphQLVoyagerBrowser', () => { + it('should render error text if there are no endpoints', async () => { + const rendered = await renderInTestApp( + , + ); + + expect(rendered.getByText('No endpoints available')).toBeInTheDocument(); + }); + + it('should render endpoint tabs', async () => { + const rendered = await renderInTestApp( + , + ); + + expect(rendered.getByText('Endpoint A')).toBeInTheDocument(); + expect(rendered.getByText('Endpoint B')).toBeInTheDocument(); + }); + + it('Should render the introspection error message when introspection fails', async () => { + const rendered = await renderInTestApp( + , + ); + + expect(rendered.getByText('Failed to introspect A')).toBeInTheDocument(); + }); +}); diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx new file mode 100644 index 0000000000..a4a5533642 --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx @@ -0,0 +1,131 @@ +/* + * Copyright 2023 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 { + GraphQLVoyagerEndpoint, + introspectionQuery, +} from '../../lib/api/types'; +import { Dispatch, SetStateAction, useEffect, useState } from 'react'; +import { Divider, makeStyles, Tab, Tabs, Typography } from '@material-ui/core'; +import React, { Suspense } from 'react'; +import { BackstageTheme } from '@backstage/theme'; +import { Content, Progress } from '@backstage/core-components'; +import { Voyager } from 'graphql-voyager'; + +const useStyles = makeStyles(theme => ({ + root: { + height: '100%', + display: 'flex', + flexFlow: 'column nowrap', + }, + tabs: { + background: theme.palette.background.paper, + }, +})); + +type GraphQLVoyagerBrowserProps = { + endpoints: GraphQLVoyagerEndpoint[]; +}; + +type IntrospectionResult = { + data?: Object; +}; + +const NoEndpoints = () => { + return No endpoints available; +}; + +const VoyagerBrowser = (props: GraphQLVoyagerBrowserProps) => { + const { endpoints } = props; + const [tabIndex, setTabIndex] = useState(0); + const [isLoading, setIsLoading] = useState(true); + const [introspectionResult, setIntrospectionResult]: [ + IntrospectionResult, + Dispatch>, + ] = useState({}); + const classes = useStyles(); + + const { + voyagerProps = {}, + introspectionErrorMessage, + introspection, + } = endpoints[tabIndex]; + + useEffect(() => { + const fetchIntrospection = async () => { + setIsLoading(true); + + const data = await introspection(introspectionQuery); + setIntrospectionResult(data); + + setIsLoading(false); + }; + + fetchIntrospection(); + }, [tabIndex, introspection]); + + let voyagerContent: JSX.Element; + + if (isLoading) { + voyagerContent = Loading...; + } else if (!introspectionResult.data) { + voyagerContent = ( + + {introspectionErrorMessage} + + ); + } else { + voyagerContent = ( + + ); + } + + return ( +
+ }> + setTabIndex(value)} + indicatorColor="primary" + > + {endpoints.map(({ title }, index) => ( + + ))} + + + {voyagerContent} + +
+ ); +}; + +/** @public */ +export const GraphQLVoyagerBrowser = (props: GraphQLVoyagerBrowserProps) => { + const hasEndpoints = checkEndpoints(props); + + if (!hasEndpoints) { + return ; + } + return ; +}; + +function checkEndpoints(props: GraphQLVoyagerBrowserProps) { + return props.endpoints.length; +} diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/index.ts b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/index.ts new file mode 100644 index 0000000000..3beb0ccd95 --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './GraphQLVoyagerBrowser'; diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx new file mode 100644 index 0000000000..e40e81d7a6 --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx @@ -0,0 +1,64 @@ +/* + * Copyright 2023 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 { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; + +import { GraphQLVoyagerPage } from './GraphQLVoyagerPage'; +import { GraphQLVoyagerApi, graphQlVoyagerApiRef } from '../../lib/api'; + +jest.mock('../GraphQLVoyagerBrowser', () => ({ + GraphQLVoyagerBrowser: () => '', +})); + +describe('GraphQLVoyagerPage', () => { + it('should show error when no endpoints are loaded', async () => { + const loadingApi: GraphQLVoyagerApi = { + async getEndpoints() { + throw new Error('No endpoints'); + }, + }; + + const rendered = await renderInTestApp( + + + , + ); + + expect(rendered.getByText('Welcome to Voyager!')).toBeInTheDocument(); + expect( + rendered.getByText( + 'Failed to load GraphQL endpoints, Error: No endpoints', + ), + ).toBeInTheDocument(); + }); + + it('should show GraphQLVoyagerBrowser', async () => { + const loadingApi: GraphQLVoyagerApi = { + async getEndpoints() { + return []; + }, + }; + + const rendered = await renderInTestApp( + + + , + ); + + expect(rendered.getByText('Welcome to Voyager!')).toBeInTheDocument(); + expect(rendered.getByText('')).toBeInTheDocument(); + }); +}); diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx new file mode 100644 index 0000000000..fa15eae86f --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx @@ -0,0 +1,62 @@ +/* + * Copyright 2023 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 { Header, Page, Content, Progress } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; +import 'graphql-voyager/dist/voyager.css'; +import { graphQlVoyagerApiRef } from '../../lib/api'; +import useAsync from 'react-use/lib/useAsync'; +import { Typography } from '@material-ui/core'; +import { GraphQLVoyagerBrowser } from '../GraphQLVoyagerBrowser'; + +/** @public */ +export const GraphQLVoyagerPage = () => { + const graphQLVoyagerApi = useApi(graphQlVoyagerApiRef); + const { value, loading, error } = useAsync(() => + graphQLVoyagerApi.getEndpoints(), + ); + + let content: JSX.Element; + + if (loading) { + content = ( + + + + ); + } else if (error) { + content = ( + + + Failed to load GraphQL endpoints, {String(error)} + + + ); + } else { + content = ( + + + + ); + } + + return ( + +
+ {content} + + ); +}; diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/index.ts b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/index.ts new file mode 100644 index 0000000000..5ee042fd5f --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './GraphQLVoyagerPage'; diff --git a/plugins/graphql-voyager/src/components/index.ts b/plugins/graphql-voyager/src/components/index.ts new file mode 100644 index 0000000000..76c4229839 --- /dev/null +++ b/plugins/graphql-voyager/src/components/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './GraphQLVoyagerPage'; +export * from './GraphQLVoyagerBrowser'; diff --git a/plugins/graphql-voyager/src/index.ts b/plugins/graphql-voyager/src/index.ts new file mode 100644 index 0000000000..2e7852bc51 --- /dev/null +++ b/plugins/graphql-voyager/src/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 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 { graphqlVoyagerPlugin, GraphqlVoyagerPage } from './plugin'; +export { GraphQLVoyagerPage as Router } from './components'; +export * from './lib/api'; diff --git a/plugins/graphql-voyager/src/lib/api/GraphQLVoyagerEndpoints.ts b/plugins/graphql-voyager/src/lib/api/GraphQLVoyagerEndpoints.ts new file mode 100644 index 0000000000..4d08ffbce3 --- /dev/null +++ b/plugins/graphql-voyager/src/lib/api/GraphQLVoyagerEndpoints.ts @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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 { GraphQLVoyagerApi, GraphQLVoyagerEndpoint } from './types'; + +/** @public */ +export class GraphQLVoyagerEndpoints implements GraphQLVoyagerApi { + private constructor(private readonly endpoints: GraphQLVoyagerEndpoint[]) {} + + static from(endpoints: GraphQLVoyagerEndpoint[]) { + return new GraphQLVoyagerEndpoints(endpoints); + } + + async getEndpoints() { + return this.endpoints; + } +} diff --git a/plugins/graphql-voyager/src/lib/api/index.ts b/plugins/graphql-voyager/src/lib/api/index.ts new file mode 100644 index 0000000000..c52eedafb7 --- /dev/null +++ b/plugins/graphql-voyager/src/lib/api/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './GraphQLVoyagerEndpoints'; +export * from './types'; diff --git a/plugins/graphql-voyager/src/lib/api/types.ts b/plugins/graphql-voyager/src/lib/api/types.ts new file mode 100644 index 0000000000..08e6f13923 --- /dev/null +++ b/plugins/graphql-voyager/src/lib/api/types.ts @@ -0,0 +1,141 @@ +/* + * Copyright 2023 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 { VoyagerDisplayOptions } from 'graphql-voyager/typings/components/Voyager'; +import { WorkerCallback } from 'graphql-voyager/typings/utils/types'; + +/** @public */ +export type GraphQLVoyagerEndpoint = { + id: string; + title: string; + introspection: (body: any) => Promise; + introspectionErrorMessage: string; + voyagerProps?: { + displayOptions?: VoyagerDisplayOptions; + hideDocs?: boolean; + hideSettings?: boolean; + workerURI?: string; + loadWorker?: WorkerCallback; + }; +}; + +/** @public */ +export type GraphQLVoyagerApi = { + getEndpoints(): Promise; +}; + +/** @public */ +export const graphQlVoyagerApiRef = createApiRef({ + id: 'plugin.graphqlvoyager.api', +}); + +/** @public */ +export const introspectionQuery: string = `query IntrospectionQuery { + __schema { + + queryType { name } + mutationType { name } + subscriptionType { name } + types { + ...FullType + } + directives { + name + description + + locations + args { + ...InputValue + } + } + } + } + + fragment FullType on __Type { + kind + name + description + + fields(includeDeprecated: true) { + name + description + args { + ...InputValue + } + type { + ...TypeRef + } + isDeprecated + deprecationReason + } + inputFields { + ...InputValue + } + interfaces { + ...TypeRef + } + enumValues(includeDeprecated: true) { + name + description + isDeprecated + deprecationReason + } + possibleTypes { + ...TypeRef + } + } + + fragment InputValue on __InputValue { + name + description + type { ...TypeRef } + defaultValue + + + } + + fragment TypeRef on __Type { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + } + } + } + } + } + } + } + }`; diff --git a/plugins/graphql-voyager/src/plugin.test.ts b/plugins/graphql-voyager/src/plugin.test.ts new file mode 100644 index 0000000000..df7acc7143 --- /dev/null +++ b/plugins/graphql-voyager/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2023 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 { graphqlVoyagerPlugin } from './plugin'; + +describe('graphql-voyager', () => { + it('should export plugin', () => { + expect(graphqlVoyagerPlugin).toBeDefined(); + }); +}); diff --git a/plugins/graphql-voyager/src/plugin.ts b/plugins/graphql-voyager/src/plugin.ts new file mode 100644 index 0000000000..bd33209a1d --- /dev/null +++ b/plugins/graphql-voyager/src/plugin.ts @@ -0,0 +1,38 @@ +/* + * Copyright 2023 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 { + createPlugin, + createRoutableExtension, +} from '@backstage/core-plugin-api'; + +import { rootRouteRef } from './routes'; + +/** @public */ +export const graphqlVoyagerPlugin = createPlugin({ + id: 'graphql-voyager', + routes: { + root: rootRouteRef, + }, +}); + +/** @public */ +export const GraphqlVoyagerPage = graphqlVoyagerPlugin.provide( + createRoutableExtension({ + name: 'GraphqlVoyagerPage', + component: () => import('./components').then(m => m.GraphQLVoyagerPage), + mountPoint: rootRouteRef, + }), +); diff --git a/plugins/graphql-voyager/src/routes.ts b/plugins/graphql-voyager/src/routes.ts new file mode 100644 index 0000000000..12f06c1cb5 --- /dev/null +++ b/plugins/graphql-voyager/src/routes.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2023 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 } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + id: 'graphql-voyager', +}); diff --git a/plugins/graphql-voyager/src/setupTests.ts b/plugins/graphql-voyager/src/setupTests.ts new file mode 100644 index 0000000000..73dd8dce47 --- /dev/null +++ b/plugins/graphql-voyager/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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'; From de146444f97e4b413e670e1ddc44982299c0a4e2 Mon Sep 17 00:00:00 2001 From: MitchWijt Date: Tue, 31 Jan 2023 16:15:44 +0100 Subject: [PATCH 030/423] feat(plugin): resolve remarks of review Signed-off-by: MitchWijt --- .changeset/tasty-jobs-help.md | 5 + plugins/graphql-voyager/README.md | 10 +- plugins/graphql-voyager/package.json | 6 +- .../GraphQLVoyagerBrowser.tsx | 96 ++-- .../GraphQLVoyagerPage.test.tsx | 6 +- .../GraphQLVoyagerPage/GraphQLVoyagerPage.tsx | 51 +- yarn.lock | 542 +++++++++++++++++- 7 files changed, 593 insertions(+), 123 deletions(-) create mode 100644 .changeset/tasty-jobs-help.md diff --git a/.changeset/tasty-jobs-help.md b/.changeset/tasty-jobs-help.md new file mode 100644 index 0000000000..02afa71656 --- /dev/null +++ b/.changeset/tasty-jobs-help.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-graphql-voyager': minor +--- + +Add the new GraphQL Voyager tool as a plugin for backstage, expose necessary API and components needed for it. diff --git a/plugins/graphql-voyager/README.md b/plugins/graphql-voyager/README.md index f2f5265e2f..fe87e1d843 100644 --- a/plugins/graphql-voyager/README.md +++ b/plugins/graphql-voyager/README.md @@ -22,11 +22,11 @@ In order to be able to navigate to the graphQL voyager page, a new route needs t ```tsx // packages/app/App.tsx - import { GraphQLVoyagerPage } from "@backstage/plugin-graphql-voyager"; + import { GraphQLVoyagerPage } from '@backstage/plugin-graphql-voyager'; const routes = ( - }/> + }/> ``` ### Configuration @@ -36,15 +36,15 @@ In order for the plugin to function correctly. GraphQL endpoints need to be adde Add your own configuration to the `packages/app/src/apis.ts` file the following way: ```ts -import { identityApiRef } from './IdentityApi'; -import { GraphQLVoyagerEndpoints } from './GraphQLVoyagerEndpoints'; +import { identityApiRef } from '@backstage/core-plugin-api'; +import { GraphQLVoyagerEndpoints } from '@backstage/plugin-graphql-voyager'; export const apis: AnyApiFactory[] = [ createApiFactory({ api: graphQlVoyagerApiRef, deps: { identityApi: identityApiRef }, factory: ({ identityApiRef }) => { - GraphQLVoyagerEndpoints.from([ + return GraphQLVoyagerEndpoints.from([ { id: `graphql-voyager-endpoint-id`, title: 'endpoint-title', diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index 1cc7bb19e6..02e8ec95ca 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-voyager", "description": "Backstage plugin for GraphQL Voyager", - "version": "0.1.0", + "version": "0.0.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -26,7 +26,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/theme": "workspace:^", - "@material-ui/core": "^4.9.13", + "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "graphql-voyager": "^1.0.0-rc.31", @@ -45,7 +45,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.47.0" + "msw": "^0.49.0" }, "files": [ "dist" diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx index a4a5533642..d2f9262983 100644 --- a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx @@ -17,100 +17,76 @@ import { GraphQLVoyagerEndpoint, introspectionQuery, } from '../../lib/api/types'; -import { Dispatch, SetStateAction, useEffect, useState } from 'react'; -import { Divider, makeStyles, Tab, Tabs, Typography } from '@material-ui/core'; +import { useState } from 'react'; +import { makeStyles, Tab, Tabs, Typography } from '@material-ui/core'; import React, { Suspense } from 'react'; import { BackstageTheme } from '@backstage/theme'; -import { Content, Progress } from '@backstage/core-components'; +import { Content, ErrorPanel, Progress } from '@backstage/core-components'; import { Voyager } from 'graphql-voyager'; +import useAsync from 'react-use/lib/useAsync'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(() => ({ root: { height: '100%', display: 'flex', flexFlow: 'column nowrap', }, - tabs: { - background: theme.palette.background.paper, - }, })); type GraphQLVoyagerBrowserProps = { endpoints: GraphQLVoyagerEndpoint[]; }; -type IntrospectionResult = { - data?: Object; -}; - const NoEndpoints = () => { return No endpoints available; }; +const VoyagerBrowserContent = ({ + endpoint, +}: { + endpoint: GraphQLVoyagerEndpoint; +}) => { + const { id, introspection, introspectionErrorMessage, voyagerProps } = + endpoint; + const { value, loading, error } = useAsync( + () => introspection(introspectionQuery), + [endpoint], + ); + + if (loading) { + return ; + } else if (error) { + return ; + } + return value.data ? ( + + ) : ( + + {introspectionErrorMessage} + + ); +}; + const VoyagerBrowser = (props: GraphQLVoyagerBrowserProps) => { const { endpoints } = props; const [tabIndex, setTabIndex] = useState(0); - const [isLoading, setIsLoading] = useState(true); - const [introspectionResult, setIntrospectionResult]: [ - IntrospectionResult, - Dispatch>, - ] = useState({}); const classes = useStyles(); - const { - voyagerProps = {}, - introspectionErrorMessage, - introspection, - } = endpoints[tabIndex]; - - useEffect(() => { - const fetchIntrospection = async () => { - setIsLoading(true); - - const data = await introspection(introspectionQuery); - setIntrospectionResult(data); - - setIsLoading(false); - }; - - fetchIntrospection(); - }, [tabIndex, introspection]); - - let voyagerContent: JSX.Element; - - if (isLoading) { - voyagerContent = Loading...; - } else if (!introspectionResult.data) { - voyagerContent = ( - - {introspectionErrorMessage} - - ); - } else { - voyagerContent = ( - - ); - } - return (
}> setTabIndex(value)} indicatorColor="primary" > - {endpoints.map(({ title }, index) => ( - + {endpoints.map(({ title, id }, index) => ( + ))} - - {voyagerContent} + + +
); diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx index e40e81d7a6..67c257be2b 100644 --- a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx @@ -38,11 +38,7 @@ describe('GraphQLVoyagerPage', () => { ); expect(rendered.getByText('Welcome to Voyager!')).toBeInTheDocument(); - expect( - rendered.getByText( - 'Failed to load GraphQL endpoints, Error: No endpoints', - ), - ).toBeInTheDocument(); + expect(rendered.getByText('Error: No endpoints')).toBeInTheDocument(); }); it('should show GraphQLVoyagerBrowser', async () => { diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx index fa15eae86f..8b32a25f87 100644 --- a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx @@ -14,49 +14,48 @@ * limitations under the License. */ import React from 'react'; -import { Header, Page, Content, Progress } from '@backstage/core-components'; +import { + Header, + Page, + Content, + Progress, + ErrorPanel, +} from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; import 'graphql-voyager/dist/voyager.css'; import { graphQlVoyagerApiRef } from '../../lib/api'; import useAsync from 'react-use/lib/useAsync'; -import { Typography } from '@material-ui/core'; import { GraphQLVoyagerBrowser } from '../GraphQLVoyagerBrowser'; -/** @public */ -export const GraphQLVoyagerPage = () => { +type GraphQLVoyagerPageProps = { + title?: string; +}; + +const VoyagerContent = () => { const graphQLVoyagerApi = useApi(graphQlVoyagerApiRef); + const { value, loading, error } = useAsync(() => graphQLVoyagerApi.getEndpoints(), ); - let content: JSX.Element; - if (loading) { - content = ( - - - - ); + return ; } else if (error) { - content = ( - - - Failed to load GraphQL endpoints, {String(error)} - - - ); - } else { - content = ( - - - - ); + return ; } + return ; +}; + +/** @public */ +export const GraphQLVoyagerPage = (props: GraphQLVoyagerPageProps) => { + const { title = 'Welcome to Voyager!' } = props; return ( -
- {content} +
+ + + ); }; diff --git a/yarn.lock b/yarn.lock index 9a7492289e..d0f4833c0c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3295,12 +3295,12 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.20.7 - resolution: "@babel/runtime@npm:7.20.7" +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": + version: 7.20.13 + resolution: "@babel/runtime@npm:7.20.13" dependencies: regenerator-runtime: ^0.13.11 - checksum: 4629ce5c46f06cca9cfb9b7fc00d48003335a809888e2b91ec2069a2dcfbfef738480cff32ba81e0b7c290f8918e5c22ddcf2b710001464ee84ba62c7e32a3a3 + checksum: 09b7a97a05c80540db6c9e4ddf8c5d2ebb06cae5caf3a87e33c33f27f8c4d49d9c67a2d72f1570e796045288fad569f98a26ceba0c4f5fad2af84b6ad855c4fb languageName: node linkType: hard @@ -6439,6 +6439,33 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-graphql-voyager@workspace:plugins/graphql-voyager": + version: 0.0.0-use.local + resolution: "@backstage/plugin-graphql-voyager@workspace:plugins/graphql-voyager" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@material-ui/core": ^4.12.2 + "@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/user-event": ^14.0.0 + "@types/node": "*" + cross-fetch: ^3.1.5 + graphql-voyager: ^1.0.0-rc.31 + msw: ^0.49.0 + react-use: ^17.2.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + languageName: unknown + linkType: soft + "@backstage/plugin-home@npm:^0.4.30": version: 0.4.30 resolution: "@backstage/plugin-home@npm:0.4.30" @@ -9311,6 +9338,56 @@ __metadata: languageName: node linkType: hard +"@f/animate@npm:^1.0.1": + version: 1.0.1 + resolution: "@f/animate@npm:1.0.1" + dependencies: + "@f/elapsed-time": ^1.0.0 + "@f/raf": ^1.0.0 + "@f/tween": ^1.0.0 + checksum: 660b44d297b1a6e5e28c48438633e00ded40f8e51adb4bfb26fc809b60c8c056f567f2e61f4f842c8fd2cf8a85dffaa1c2502bd0963eb926135f2d66d9f997db + languageName: node + linkType: hard + +"@f/elapsed-time@npm:^1.0.0": + version: 1.0.0 + resolution: "@f/elapsed-time@npm:1.0.0" + dependencies: + "@f/timestamp": ^1.0.0 + checksum: 5934d24a667bae4e0089408aa362c0ee1503945adf73ca0ff0d09fed33d62d070f0323eb9a54f42c37bd0545330a0f63da13319f66cc89fef59b8917a3278b5f + languageName: node + linkType: hard + +"@f/map-obj@npm:^1.2.2": + version: 1.2.2 + resolution: "@f/map-obj@npm:1.2.2" + checksum: d67db6074e1daa7a3c0f8c2e54094bff48b54d11817fddc886631dd8a17586d0040e7116282a374cc1d3d643d05862d49a1062ea5b2d03b9069507c09ae888a4 + languageName: node + linkType: hard + +"@f/raf@npm:^1.0.0": + version: 1.0.3 + resolution: "@f/raf@npm:1.0.3" + checksum: 800344caf4c649c0bcdefd4febbf3f0eed96bb9b7e54b5bc6eebd7d781c9e6d98ba22fb39da41474080d97ac21916bd1e82051558b43dabcbbf410d2dd0899c1 + languageName: node + linkType: hard + +"@f/timestamp@npm:^1.0.0": + version: 1.0.0 + resolution: "@f/timestamp@npm:1.0.0" + checksum: 8c37acb40cf67952309a214be2ddfd5c4f6634a414efc47406e8d1c1624e74662f584f6b48f3382c742f256aea1537e730e74c6078e52be3a28d0624cc7306a0 + languageName: node + linkType: hard + +"@f/tween@npm:^1.0.0": + version: 1.0.1 + resolution: "@f/tween@npm:1.0.1" + dependencies: + "@f/map-obj": ^1.2.2 + checksum: e37155c43875becc9eca8425b8dc83e64a78fa327738b33fcb3946418369568aa77007ade39591991379187381da829702e5cb84729dd2a0bc3bb4b7c94e4f2b + languageName: node + linkType: hard + "@fmvilas/pseudo-yaml-ast@npm:^0.3.1": version: 0.3.1 resolution: "@fmvilas/pseudo-yaml-ast@npm:0.3.1" @@ -11370,6 +11447,44 @@ __metadata: languageName: node linkType: hard +"@material-ui/core@npm:^3.9.3": + version: 3.9.4 + resolution: "@material-ui/core@npm:3.9.4" + dependencies: + "@babel/runtime": ^7.2.0 + "@material-ui/system": ^3.0.0-alpha.0 + "@material-ui/utils": ^3.0.0-alpha.2 + "@types/jss": ^9.5.6 + "@types/react-transition-group": ^2.0.8 + brcast: ^3.0.1 + classnames: ^2.2.5 + csstype: ^2.5.2 + debounce: ^1.1.0 + deepmerge: ^3.0.0 + dom-helpers: ^3.2.1 + hoist-non-react-statics: ^3.2.1 + is-plain-object: ^2.0.4 + jss: ^9.8.7 + jss-camel-case: ^6.0.0 + jss-default-unit: ^8.0.2 + jss-global: ^3.0.0 + jss-nested: ^6.0.1 + jss-props-sort: ^6.0.0 + jss-vendor-prefixer: ^7.0.0 + normalize-scroll-left: ^0.1.2 + popper.js: ^1.14.1 + prop-types: ^15.6.0 + react-event-listener: ^0.6.2 + react-transition-group: ^2.2.1 + recompose: 0.28.0 - 0.30.0 + warning: ^4.0.1 + peerDependencies: + react: ^16.3.0 + react-dom: ^16.3.0 + checksum: c3923bfba4ef4449fbdcd37712ec0d11393ffa396c575a05b5f9530ca1e714028882d39402eb6918dad49f2eb1c53b261cfd0f2dfed494c2dfd96ee335336b44 + languageName: node + linkType: hard + "@material-ui/core@npm:^4.11.0, @material-ui/core@npm:^4.11.3, @material-ui/core@npm:^4.12.1, @material-ui/core@npm:^4.12.2, @material-ui/core@npm:^4.12.4": version: 4.12.4 resolution: "@material-ui/core@npm:4.12.4" @@ -11528,6 +11643,21 @@ __metadata: languageName: node linkType: hard +"@material-ui/system@npm:^3.0.0-alpha.0": + version: 3.0.0-alpha.2 + resolution: "@material-ui/system@npm:3.0.0-alpha.2" + dependencies: + "@babel/runtime": ^7.2.0 + deepmerge: ^3.0.0 + prop-types: ^15.6.0 + warning: ^4.0.1 + peerDependencies: + react: ^16.3.0 + react-dom: ^16.3.0 + checksum: 3aacb8b4afe2a820844b90905cfcd86ab934108cd719f11713ee46f8a4da30cb8c50e86219e1440b3c6dd333a09d4123cd1990d9c51862c1d56ec2b36e4d7ded + languageName: node + linkType: hard + "@material-ui/system@npm:^4.12.2": version: 4.12.2 resolution: "@material-ui/system@npm:4.12.2" @@ -11571,6 +11701,20 @@ __metadata: languageName: node linkType: hard +"@material-ui/utils@npm:^3.0.0-alpha.2": + version: 3.0.0-alpha.3 + resolution: "@material-ui/utils@npm:3.0.0-alpha.3" + dependencies: + "@babel/runtime": ^7.2.0 + prop-types: ^15.6.0 + react-is: ^16.6.3 + peerDependencies: + react: ^16.3.0 + react-dom: ^16.3.0 + checksum: 589a16245338c374b604a793d9f7a05bd932c9710f78261e46176b74a61d5d308b3e36dab688988ee5177d689c53d9e9da4649eca009ea11d8aac948db27af50 + languageName: node + linkType: hard + "@material-ui/utils@npm:^4.11.2, @material-ui/utils@npm:^4.11.3, @material-ui/utils@npm:^4.7.1": version: 4.11.3 resolution: "@material-ui/utils@npm:4.11.3" @@ -14758,6 +14902,16 @@ __metadata: languageName: node linkType: hard +"@types/jss@npm:^9.5.6": + version: 9.5.8 + resolution: "@types/jss@npm:9.5.8" + dependencies: + csstype: ^2.0.0 + indefinite-observable: ^1.0.1 + checksum: 6e51707529a15f2f5ff94555ecb555d29427fd10c4f3d2d29474934292e365c2dfaa4ad30b2ab46946201cbca7f6e8df56513a22fc6ceca10a979db8338935c5 + languageName: node + linkType: hard + "@types/jwt-decode@npm:^3.1.0": version: 3.1.0 resolution: "@types/jwt-decode@npm:3.1.0" @@ -15217,6 +15371,15 @@ __metadata: languageName: node linkType: hard +"@types/react-transition-group@npm:^2.0.8": + version: 2.9.2 + resolution: "@types/react-transition-group@npm:2.9.2" + dependencies: + "@types/react": "*" + checksum: 6f30fffc221339de90bd3e999f32328618cfaedfcaa501603f5ddc5bed1c2dbaa0d51347c3a25e5f8fd3041c671aabd2b7bfbcad611a7636adcd9da4e0666fa5 + languageName: node + linkType: hard + "@types/react-transition-group@npm:^4.2.0": version: 4.2.4 resolution: "@types/react-transition-group@npm:4.2.4" @@ -17864,6 +18027,13 @@ __metadata: languageName: node linkType: hard +"brcast@npm:^3.0.1": + version: 3.0.2 + resolution: "brcast@npm:3.0.2" + checksum: 7abae42088c6ffad9ff9e0fc756607a1764e299d737b3007fa49a73a38b3fda1e51362713f645db7991878ca388de94942011188450324c3debd08509315fa94 + languageName: node + linkType: hard + "breakword@npm:^1.0.5": version: 1.0.5 resolution: "breakword@npm:1.0.5" @@ -18446,6 +18616,13 @@ __metadata: languageName: node linkType: hard +"change-emitter@npm:^0.1.2": + version: 0.1.6 + resolution: "change-emitter@npm:0.1.6" + checksum: 0ed494ba9901ca56ea6f942668fd294465c334a9a0981dca96da5aea5e387c0023a630d7c658c1b532d203db54c928ddca2564e434b4a8b7f6d39155d09db255 + languageName: node + linkType: hard + "char-regex@npm:^1.0.2": version: 1.0.2 resolution: "char-regex@npm:1.0.2" @@ -18702,6 +18879,17 @@ __metadata: languageName: node linkType: hard +"clipboard@npm:^2.0.4": + version: 2.0.11 + resolution: "clipboard@npm:2.0.11" + dependencies: + good-listener: ^1.2.2 + select: ^1.1.2 + tiny-emitter: ^2.0.0 + checksum: 413055a6038e43898e0e895216b58ed54fbf386f091cb00188875ef35b186cefbd258acdf4cb4b0ac87cbc00de936f41b45dde9fe1fd1a57f7babb28363b8748 + languageName: node + linkType: hard + "cliui@npm:^3.2.0": version: 3.2.0 resolution: "cliui@npm:3.2.0" @@ -19136,6 +19324,20 @@ __metadata: languageName: node linkType: hard +"commonmark@npm:^0.29.0": + version: 0.29.3 + resolution: "commonmark@npm:0.29.3" + dependencies: + entities: ~2.0 + mdurl: ~1.0.1 + minimist: ">=1.2.2" + string.prototype.repeat: ^0.2.0 + bin: + commonmark: bin/commonmark + checksum: 892b603aeffea6a04770ce24979fc4024d2d92ca6d5146353398faab15be980af6802f3d7b35357400b870e752a9f80b766fed5c09ca063a2951c8c26013876c + languageName: node + linkType: hard + "compare-versions@npm:4.1.3": version: 4.1.3 resolution: "compare-versions@npm:4.1.3" @@ -19461,6 +19663,13 @@ __metadata: languageName: node linkType: hard +"core-js@npm:^1.0.0": + version: 1.2.7 + resolution: "core-js@npm:1.2.7" + checksum: 0b76371bfa98708351cde580f9287e2360d2209920e738ae950ae74ad08639a2e063541020bf666c28778956fc356ed9fe56d962129c88a87a6a4a0612526c75 + languageName: node + linkType: hard + "core-js@npm:^2.4.0, core-js@npm:^2.5.0": version: 2.6.12 resolution: "core-js@npm:2.6.12" @@ -19825,6 +20034,15 @@ __metadata: languageName: node linkType: hard +"css-vendor@npm:^0.3.8": + version: 0.3.8 + resolution: "css-vendor@npm:0.3.8" + dependencies: + is-in-browser: ^1.0.2 + checksum: 0a2e0cd0d4adbfdb6236950e7f9697b8a9b294eb2ae7c95996a95d273d2a63316ce793cb4654ae048aa3c129327124d2a29aada9935a0c284f9cc341c2768c8a + languageName: node + linkType: hard + "css-vendor@npm:^2.0.8": version: 2.0.8 resolution: "css-vendor@npm:2.0.8" @@ -19966,10 +20184,10 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^2.5.2, csstype@npm:^2.6.7": - version: 2.6.17 - resolution: "csstype@npm:2.6.17" - checksum: 6eee5cf81a4b1b2f0e8707b4accd7504f7cceb4b5a496d58c6e4fcea1a70c1443a975e45d722c892d372ffe788fa278ddfe4d70c5f881375f34e48bb99c70ecc +"csstype@npm:^2.0.0, csstype@npm:^2.5.2, csstype@npm:^2.6.7": + version: 2.6.21 + resolution: "csstype@npm:2.6.21" + checksum: 2ce8bc832375146eccdf6115a1f8565a27015b74cce197c35103b4494955e9516b246140425ad24103864076aa3e1257ac9bab25a06c8d931dd87a6428c9dccf languageName: node linkType: hard @@ -20368,10 +20586,10 @@ __metadata: languageName: node linkType: hard -"debounce@npm:^1.2.0": - version: 1.2.0 - resolution: "debounce@npm:1.2.0" - checksum: e39cb593ae26344921f5a2681b40b703bdd22bc43b179f0e7515176c790997932b3a0ee6ea9864f384c6ac58cecc08158fb102c3632d5d88ab621f8230ee39ff +"debounce@npm:^1.1.0, debounce@npm:^1.2.0": + version: 1.2.1 + resolution: "debounce@npm:1.2.1" + checksum: 682a89506d9e54fb109526f4da255c5546102fbb8e3ae75eef3b04effaf5d4853756aee97475cd4650641869794e44f410eeb20ace2b18ea592287ab2038519e languageName: node linkType: hard @@ -20541,6 +20759,13 @@ __metadata: languageName: node linkType: hard +"deepmerge@npm:^3.0.0": + version: 3.3.0 + resolution: "deepmerge@npm:3.3.0" + checksum: 4322195389e0170a0443c07b36add19b90249802c4b47b96265fdc5f5d8beddf491d5e50cbc5bfd65f85ccf76598173083863c202f5463b3b667aca8be75d5ac + languageName: node + linkType: hard + "deepmerge@npm:^4.2.2, deepmerge@npm:~4.2.2": version: 4.2.2 resolution: "deepmerge@npm:4.2.2" @@ -20620,6 +20845,13 @@ __metadata: languageName: node linkType: hard +"delegate@npm:^3.1.2": + version: 3.2.0 + resolution: "delegate@npm:3.2.0" + checksum: d943058fe05897228b158cbd1bab05164df28c8f54127873231d6b03b0a5acc1b3ee1f98ac70ccc9b79cd84aa47118a7de111fee2923753491583905069da27d + languageName: node + linkType: hard + "delegates@npm:^1.0.0": version: 1.0.0 resolution: "delegates@npm:1.0.0" @@ -20918,7 +21150,7 @@ __metadata: languageName: node linkType: hard -"dom-helpers@npm:^3.4.0": +"dom-helpers@npm:^3.2.1, dom-helpers@npm:^3.4.0": version: 3.4.0 resolution: "dom-helpers@npm:3.4.0" dependencies: @@ -21272,7 +21504,7 @@ __metadata: languageName: node linkType: hard -"encoding@npm:^0.1.12, encoding@npm:^0.1.13": +"encoding@npm:^0.1.11, encoding@npm:^0.1.12, encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" dependencies: @@ -21376,6 +21608,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:~2.0": + version: 2.0.3 + resolution: "entities@npm:2.0.3" + checksum: 5a7899fcc622e0d76afdeafe4c58a6b40ae3a8ee4772e5825a648c11a2ca324a9a02515386f512e466baac4aeb551f3d3b79eaece5cd98369b9f8601be336b1a + languageName: node + linkType: hard + "entities@npm:~2.1.0": version: 2.1.0 resolution: "entities@npm:2.1.0" @@ -23013,6 +23252,21 @@ __metadata: languageName: node linkType: hard +"fbjs@npm:^0.8.1": + version: 0.8.18 + resolution: "fbjs@npm:0.8.18" + dependencies: + core-js: ^1.0.0 + isomorphic-fetch: ^2.1.1 + loose-envify: ^1.0.0 + object-assign: ^4.1.0 + promise: ^7.1.1 + setimmediate: ^1.0.5 + ua-parser-js: ^0.7.30 + checksum: 668731b946a765908c9cbe51d5160f973abb78004b3d122587c3e930e3e1ddcc0ce2b17f2a8637dc9d733e149aa580f8d3035a35cc2d3bc78b78f1b19aab90e2 + languageName: node + linkType: hard + "fbjs@npm:^3.0.0": version: 3.0.0 resolution: "fbjs@npm:3.0.0" @@ -24050,6 +24304,15 @@ __metadata: languageName: node linkType: hard +"good-listener@npm:^1.2.2": + version: 1.2.2 + resolution: "good-listener@npm:1.2.2" + dependencies: + delegate: ^3.1.2 + checksum: f39fb82c4e41524f56104cfd2d7aef1a88e72f3f75139115fbdf98cc7d844e0c1b39218b2e83438c6188727bf904ed78c7f0f2feff67b32833bc3af7f0202b33 + languageName: node + linkType: hard + "google-auth-library@npm:^8.0.0, google-auth-library@npm:^8.0.1, google-auth-library@npm:^8.0.2": version: 8.7.0 resolution: "google-auth-library@npm:8.7.0" @@ -24262,6 +24525,27 @@ __metadata: languageName: node linkType: hard +"graphql-voyager@npm:^1.0.0-rc.31": + version: 1.0.0-rc.31 + resolution: "graphql-voyager@npm:1.0.0-rc.31" + dependencies: + "@f/animate": ^1.0.1 + "@material-ui/core": ^3.9.3 + classnames: ^2.2.6 + clipboard: ^2.0.4 + commonmark: ^0.29.0 + lodash: ^4.17.10 + prop-types: ^15.7.2 + svg-pan-zoom: ^3.6.0 + viz.js: 2.1.2 + peerDependencies: + graphql: ">=14.0.0" + react: ">=15.4.2" + react-dom: ">=15.4.2" + checksum: 80e826eeb42d286540447723ea35a463a3a155287914a45e24b69f31617d8ca74c0c43bdaa64123bf4ed046e68f7e31feca7661c06288551040f3e5b96c48fed + languageName: node + linkType: hard + "graphql-ws@npm:5.11.2, graphql-ws@npm:^5.4.1, graphql-ws@npm:^5.9.0": version: 5.11.2 resolution: "graphql-ws@npm:5.11.2" @@ -24596,7 +24880,14 @@ __metadata: languageName: node linkType: hard -"hoist-non-react-statics@npm:^3.0.0, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.2": +"hoist-non-react-statics@npm:^2.3.1": + version: 2.5.5 + resolution: "hoist-non-react-statics@npm:2.5.5" + checksum: ee2d05e5c7e1398ad84a15b0327f66bd78f38a8e0015e852f954b36434e32eb7e942d5357505020a3a1147f247b165bf1e69d72393e3accab67cafdafeb86230 + languageName: node + linkType: hard + +"hoist-non-react-statics@npm:^3.0.0, hoist-non-react-statics@npm:^3.2.1, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.2": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" dependencies: @@ -25142,6 +25433,15 @@ __metadata: languageName: node linkType: hard +"indefinite-observable@npm:^1.0.1": + version: 1.0.2 + resolution: "indefinite-observable@npm:1.0.2" + dependencies: + symbol-observable: 1.2.0 + checksum: 69a337967f48fca18989f9d68ad98c7220ed9b499bf00330ff72669a9583cb7f8e82f801da10720f720edf1313f427c77ce793350bdc413c952cec8ce112fc12 + languageName: node + linkType: hard + "indefinite-observable@npm:^2.0.1": version: 2.0.1 resolution: "indefinite-observable@npm:2.0.1" @@ -25908,6 +26208,13 @@ __metadata: languageName: node linkType: hard +"is-stream@npm:^1.0.1": + version: 1.1.0 + resolution: "is-stream@npm:1.1.0" + checksum: 063c6bec9d5647aa6d42108d4c59723d2bd4ae42135a2d4db6eadbd49b7ea05b750fd69d279e5c7c45cf9da753ad2c00d8978be354d65aa9f6bb434969c6a2ae + languageName: node + linkType: hard + "is-stream@npm:^2.0.0": version: 2.0.1 resolution: "is-stream@npm:2.0.1" @@ -26110,6 +26417,16 @@ __metadata: languageName: node linkType: hard +"isomorphic-fetch@npm:^2.1.1": + version: 2.2.1 + resolution: "isomorphic-fetch@npm:2.2.1" + dependencies: + node-fetch: ^1.0.1 + whatwg-fetch: ">=0.10.0" + checksum: bb5daa7c3785d6742f4379a81e55b549a469503f7c9bf9411b48592e86632cf5e8fe8ea878dba185c0f33eb7c510c23abdeb55aebfdf5d3c70f031ced68c5424 + languageName: node + linkType: hard + "isomorphic-fetch@npm:^3.0.0": version: 3.0.0 resolution: "isomorphic-fetch@npm:3.0.0" @@ -27468,6 +27785,46 @@ __metadata: languageName: node linkType: hard +"jss-camel-case@npm:^6.0.0": + version: 6.1.0 + resolution: "jss-camel-case@npm:6.1.0" + dependencies: + hyphenate-style-name: ^1.0.2 + peerDependencies: + jss: ^9.7.0 + checksum: f20ad892cddc30241b5127d648233b513ce57b2a6ed2f710cd995510f8d06e1418cd8f6e8e50dc6bd60b2e8a35159bfdeb40143938e0f2cdc19fd39279953789 + languageName: node + linkType: hard + +"jss-default-unit@npm:^8.0.2": + version: 8.0.2 + resolution: "jss-default-unit@npm:8.0.2" + peerDependencies: + jss: ^9.4.0 + checksum: 5277c5ccc3d56f5c137d6d65f0fc36d15eb22ef08b5949e887ee75e9f4f25197e25f2a99706b70a2828cee010fd8ed7484fb1bb2086fe327f2b24b1bdcc22abb + languageName: node + linkType: hard + +"jss-global@npm:^3.0.0": + version: 3.0.0 + resolution: "jss-global@npm:3.0.0" + peerDependencies: + jss: ^9.0.0 + checksum: e3fa80d8251ba5f183d9b0b4416d64e8f5d285cfdb595cc600daf1a1366b67bca573939bb71d98b6596bf4d6f2c95711cf53a358af3d63cd7945dbb434c6547b + languageName: node + linkType: hard + +"jss-nested@npm:^6.0.1": + version: 6.0.1 + resolution: "jss-nested@npm:6.0.1" + dependencies: + warning: ^3.0.0 + peerDependencies: + jss: ^9.0.0 + checksum: 437bdacc559be0b4b5bc1faa2bc77b5c6cf14733fefbf73a34bb7335786b9f08e4e79b3d73cf83b386959adcd8fa9d725877912e96d9a0921ed38baa1a69b8d9 + languageName: node + linkType: hard + "jss-plugin-camel-case@npm:^10.5.1": version: 10.6.0 resolution: "jss-plugin-camel-case@npm:10.6.0" @@ -27542,6 +27899,26 @@ __metadata: languageName: node linkType: hard +"jss-props-sort@npm:^6.0.0": + version: 6.0.0 + resolution: "jss-props-sort@npm:6.0.0" + peerDependencies: + jss: ^9.0.0 + checksum: 82a04f625a2f2b3a71b2fcb00b1ed0478137c83dc47c323d24c7ea88d08c9ea295b061f99cf264db133fef3435366d6da594724f7713e0415dc50b4eff2aeb53 + languageName: node + linkType: hard + +"jss-vendor-prefixer@npm:^7.0.0": + version: 7.0.0 + resolution: "jss-vendor-prefixer@npm:7.0.0" + dependencies: + css-vendor: ^0.3.8 + peerDependencies: + jss: ^9.0.0 + checksum: 8ec3608711833e79da7ccfffd8177e752f16093589fa28d3a24ec19e6588fbc6a07cc5cacf59ef4c111ab1d0fb72e07b88cb3444eb8c0c6ed4cc8107da984633 + languageName: node + linkType: hard + "jss@npm:10.6.0": version: 10.6.0 resolution: "jss@npm:10.6.0" @@ -27567,6 +27944,17 @@ __metadata: languageName: node linkType: hard +"jss@npm:^9.8.7": + version: 9.8.7 + resolution: "jss@npm:9.8.7" + dependencies: + is-in-browser: ^1.1.3 + symbol-observable: ^1.1.0 + warning: ^3.0.0 + checksum: ebb264cc893fb8c17a0277875947f8f72e01f5be991bf7f61a39abb861e1276e75ee402fdd2be9ce827af839a1a08bd81ad86a4e108d57fd7d7ebb2361837a53 + languageName: node + linkType: hard + "jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.3": version: 3.3.3 resolution: "jsx-ast-utils@npm:3.3.3" @@ -28880,7 +29268,7 @@ __metadata: languageName: node linkType: hard -"mdurl@npm:^1.0.0, mdurl@npm:^1.0.1": +"mdurl@npm:^1.0.0, mdurl@npm:^1.0.1, mdurl@npm:~1.0.1": version: 1.0.1 resolution: "mdurl@npm:1.0.1" checksum: 71731ecba943926bfbf9f9b51e28b5945f9411c4eda80894221b47cc105afa43ba2da820732b436f0798fd3edbbffcd1fc1415843c41a87fea08a41cc1e3d02b @@ -29541,7 +29929,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.7": +"minimist@npm:>=1.2.2, minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.7": version: 1.2.7 resolution: "minimist@npm:1.2.7" checksum: 7346574a1038ca23c32e02252f603801f09384dd1d78b69a943a4e8c2c28730b80e96193882d3d3b22a063445f460e48316b29b8a25addca2d7e5e8f75478bec @@ -30085,6 +30473,16 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^1.0.1": + version: 1.7.3 + resolution: "node-fetch@npm:1.7.3" + dependencies: + encoding: ^0.1.11 + is-stream: ^1.0.1 + checksum: 3bb0528c05d541316ebe52770d71ee25a6dce334df4231fd55df41a644143e07f068637488c18a5b0c43f05041dbd3346752f9e19b50df50569a802484544d5b + languageName: node + linkType: hard + "node-forge@npm:^1, node-forge@npm:^1.3.1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -30278,6 +30676,13 @@ __metadata: languageName: node linkType: hard +"normalize-scroll-left@npm:^0.1.2": + version: 0.1.2 + resolution: "normalize-scroll-left@npm:0.1.2" + checksum: 817d5a659ba6f14f458cd03a5a0f98ec2a9d7e6c63c160f2db164827b87bb77c0237752890a18d11054fe628907493c5f4d8914907585ec9fbba3de26d2a6815 + languageName: node + linkType: hard + "normalize-url@npm:^6.0.1": version: 6.1.0 resolution: "normalize-url@npm:6.1.0" @@ -31960,6 +32365,13 @@ __metadata: languageName: node linkType: hard +"popper.js@npm:^1.14.1": + version: 1.16.1 + resolution: "popper.js@npm:1.16.1" + checksum: c56ae5001ec50a77ee297a8061a0221d99d25c7348d2e6bcd3e45a0d0f32a1fd81bca29d46cb0d4bdf13efb77685bd6a0ce93f9eb3c608311a461f945fffedbe + languageName: node + linkType: hard + "postcss-calc@npm:^8.0.0": version: 8.0.0 resolution: "postcss-calc@npm:8.0.0" @@ -32644,7 +33056,7 @@ __metadata: languageName: node linkType: hard -"prop-types@npm:^15.0.0, prop-types@npm:^15.5.10, prop-types@npm:^15.5.7, prop-types@npm:^15.5.8, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": +"prop-types@npm:^15.0.0, prop-types@npm:^15.5.10, prop-types@npm:^15.5.7, prop-types@npm:^15.5.8, prop-types@npm:^15.6.0, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": version: 15.8.1 resolution: "prop-types@npm:15.8.1" dependencies: @@ -33222,6 +33634,19 @@ __metadata: languageName: node linkType: hard +"react-event-listener@npm:^0.6.2": + version: 0.6.6 + resolution: "react-event-listener@npm:0.6.6" + dependencies: + "@babel/runtime": ^7.2.0 + prop-types: ^15.6.0 + warning: ^4.0.1 + peerDependencies: + react: ^16.3.0 + checksum: 0287e0ae8cbf0a4c03889ffc2b745f5494b3edea0f4667357d709f5646dd78c7289ce305b6f473ec6ac5789f8a937c86b7e543d0249f0bf787bccdb1eab7ecd0 + languageName: node + linkType: hard + "react-fast-compare@npm:^3.1.1": version: 3.2.0 resolution: "react-fast-compare@npm:3.2.0" @@ -33302,7 +33727,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^16.10.2, react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.7.0, react-is@npm:^16.8.0, react-is@npm:^16.8.6, react-is@npm:^16.9.0": +"react-is@npm:^16.10.2, react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.6.3, react-is@npm:^16.7.0, react-is@npm:^16.8.0, react-is@npm:^16.8.6, react-is@npm:^16.9.0": version: 16.13.1 resolution: "react-is@npm:16.13.1" checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f @@ -33323,7 +33748,7 @@ __metadata: languageName: node linkType: hard -"react-lifecycles-compat@npm:^3.0.4": +"react-lifecycles-compat@npm:^3.0.2, react-lifecycles-compat@npm:^3.0.4": version: 3.0.4 resolution: "react-lifecycles-compat@npm:3.0.4" checksum: a904b0fc0a8eeb15a148c9feb7bc17cec7ef96e71188280061fc340043fd6d8ee3ff233381f0e8f95c1cf926210b2c4a31f38182c8f35ac55057e453d6df204f @@ -33524,7 +33949,7 @@ __metadata: languageName: node linkType: hard -"react-transition-group@npm:2.9.0": +"react-transition-group@npm:2.9.0, react-transition-group@npm:^2.2.1": version: 2.9.0 resolution: "react-transition-group@npm:2.9.0" dependencies: @@ -33836,6 +34261,22 @@ __metadata: languageName: node linkType: hard +"recompose@npm:0.28.0 - 0.30.0": + version: 0.30.0 + resolution: "recompose@npm:0.30.0" + dependencies: + "@babel/runtime": ^7.0.0 + change-emitter: ^0.1.2 + fbjs: ^0.8.1 + hoist-non-react-statics: ^2.3.1 + react-lifecycles-compat: ^3.0.2 + symbol-observable: ^1.0.4 + peerDependencies: + react: ^0.14.0 || ^15.0.0 || ^16.0.0 + checksum: 18e58252336d0628b22db1e38407d32e836648e6d5c9453ba37c9f8030138b3429ee3952b053a13b60311f8b60893b207a761466bb293083542db0cf317b7a41 + languageName: node + linkType: hard + "recursive-readdir@npm:^2.2.2": version: 2.2.3 resolution: "recursive-readdir@npm:2.2.3" @@ -34915,6 +35356,13 @@ __metadata: languageName: node linkType: hard +"select@npm:^1.1.2": + version: 1.1.2 + resolution: "select@npm:1.1.2" + checksum: 4346151e94f226ea6131e44e68e6d837f3fdee64831b756dd657cc0b02f4cb5107f867cb34a1d1216ab7737d0bf0645d44546afb030bbd8d64e891f5e4c4814e + languageName: node + linkType: hard + "selfsigned@npm:^2.0.0, selfsigned@npm:^2.1.1": version: 2.1.1 resolution: "selfsigned@npm:2.1.1" @@ -36106,6 +36554,13 @@ __metadata: languageName: node linkType: hard +"string.prototype.repeat@npm:^0.2.0": + version: 0.2.0 + resolution: "string.prototype.repeat@npm:0.2.0" + checksum: 5127ce1b5bce45258905877048ac28bae71be18f1c3421011bd3979cfbcacf9c16f6b7f42daa3b999c9d90f5da39bd7136982c8e64439f02666dd6c0778ed262 + languageName: node + linkType: hard + "string.prototype.trimend@npm:^1.0.5": version: 1.0.5 resolution: "string.prototype.trimend@npm:1.0.5" @@ -36453,6 +36908,13 @@ __metadata: languageName: node linkType: hard +"svg-pan-zoom@npm:^3.6.0": + version: 3.6.1 + resolution: "svg-pan-zoom@npm:3.6.1" + checksum: 500b99378d321315e1668067ef6a73af3f61f9adfab75a575b21d2d216cb446def61d60ad12265203463cca9bef56b090f00e48118fa9b7f0ffa1c691e4c1621 + languageName: node + linkType: hard + "svg-parser@npm:^2.0.4": version: 2.0.4 resolution: "svg-parser@npm:2.0.4" @@ -36573,7 +37035,7 @@ __metadata: languageName: node linkType: hard -"symbol-observable@npm:1.2.0, symbol-observable@npm:^1.0.4": +"symbol-observable@npm:1.2.0, symbol-observable@npm:^1.0.4, symbol-observable@npm:^1.1.0": version: 1.2.0 resolution: "symbol-observable@npm:1.2.0" checksum: 48ffbc22e3d75f9853b3ff2ae94a44d84f386415110aea5effc24d84c502e03a4a6b7a8f75ebaf7b585780bda34eb5d6da3121f826a6f93398429d30032971b6 @@ -36926,6 +37388,13 @@ __metadata: languageName: node linkType: hard +"tiny-emitter@npm:^2.0.0": + version: 2.1.0 + resolution: "tiny-emitter@npm:2.1.0" + checksum: fbcfb5145751a0e3b109507a828eb6d6d4501352ab7bb33eccef46e22e9d9ad3953158870a6966a59e57ab7c3f9cfac7cab8521db4de6a5e757012f4677df2dd + languageName: node + linkType: hard + "tiny-invariant@npm:^1.0.6": version: 1.1.0 resolution: "tiny-invariant@npm:1.1.0" @@ -37520,7 +37989,7 @@ __metadata: languageName: node linkType: hard -"ua-parser-js@npm:^0.7.18": +"ua-parser-js@npm:^0.7.18, ua-parser-js@npm:^0.7.30": version: 0.7.33 resolution: "ua-parser-js@npm:0.7.33" checksum: 1510e9ec26fcaf0d8c6ae8f1078a8230e8816f083e1b5f453ea19d06b8ef2b8a596601c92148fd41899e8b3e5f83fa69c42332bd5729b931a721040339831696 @@ -38264,6 +38733,13 @@ __metadata: languageName: node linkType: hard +"viz.js@npm:2.1.2": + version: 2.1.2 + resolution: "viz.js@npm:2.1.2" + checksum: 299e5a8519a472e0e98197c5f39c0ca6f3f6c4642b6ae007ed888fea998d82455c7ae0118d09cb888bfd2c46ebe3b03d7ce321a4eef1c822a5f5719d3a6ef3bb + languageName: node + linkType: hard + "vm-browserify@npm:^1.0.1": version: 1.1.2 resolution: "vm-browserify@npm:1.1.2" @@ -38362,6 +38838,24 @@ __metadata: languageName: node linkType: hard +"warning@npm:^3.0.0": + version: 3.0.0 + resolution: "warning@npm:3.0.0" + dependencies: + loose-envify: ^1.0.0 + checksum: c9f99a12803aab81b29858e7dc3415bf98b41baee3a4c3acdeb680d98c47b6e17490f1087dccc54432deed5711a5ce0ebcda2b27e9b5eb054c32ae50acb4419c + languageName: node + linkType: hard + +"warning@npm:^4.0.1": + version: 4.0.3 + resolution: "warning@npm:4.0.3" + dependencies: + loose-envify: ^1.0.0 + checksum: 4f2cb6a9575e4faf71ddad9ad1ae7a00d0a75d24521c193fa464f30e6b04027bd97aa5d9546b0e13d3a150ab402eda216d59c1d0f2d6ca60124d96cd40dfa35c + languageName: node + linkType: hard + "watchpack@npm:^2.0.0-beta.10, watchpack@npm:^2.4.0": version: 2.4.0 resolution: "watchpack@npm:2.4.0" @@ -38614,7 +39108,7 @@ __metadata: languageName: node linkType: hard -"whatwg-fetch@npm:^3.0.0, whatwg-fetch@npm:^3.4.1": +"whatwg-fetch@npm:>=0.10.0, whatwg-fetch@npm:^3.0.0, whatwg-fetch@npm:^3.4.1": version: 3.6.2 resolution: "whatwg-fetch@npm:3.6.2" checksum: ee976b7249e7791edb0d0a62cd806b29006ad7ec3a3d89145921ad8c00a3a67e4be8f3fb3ec6bc7b58498724fd568d11aeeeea1f7827e7e1e5eae6c8a275afed From e06bfd085144774b9cb84c659233f3d9f8c39ca8 Mon Sep 17 00:00:00 2001 From: MitchWijt Date: Wed, 1 Feb 2023 08:06:49 +0100 Subject: [PATCH 031/423] chore: export added page props Signed-off-by: MitchWijt --- plugins/graphql-voyager/api-report.md | 11 +++++++++-- .../GraphQLVoyagerPage/GraphQLVoyagerPage.tsx | 3 ++- plugins/graphql-voyager/src/index.ts | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/plugins/graphql-voyager/api-report.md b/plugins/graphql-voyager/api-report.md index 21423a8c30..9b488f9356 100644 --- a/plugins/graphql-voyager/api-report.md +++ b/plugins/graphql-voyager/api-report.md @@ -43,7 +43,14 @@ export class GraphQLVoyagerEndpoints implements GraphQLVoyagerApi { } // @public (undocumented) -export const GraphqlVoyagerPage: () => JSX.Element; +export const GraphqlVoyagerPage: ( + props: GraphQLVoyagerPageProps, +) => JSX.Element; + +// @public (undocumented) +export type GraphQLVoyagerPageProps = { + title?: string; +}; // @public (undocumented) export const graphqlVoyagerPlugin: BackstagePlugin< @@ -58,7 +65,7 @@ export const graphqlVoyagerPlugin: BackstagePlugin< export const introspectionQuery: string; // @public (undocumented) -export const Router: () => JSX.Element; +export const Router: (props: GraphQLVoyagerPageProps) => JSX.Element; // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx index 8b32a25f87..f3c4f70b4f 100644 --- a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx @@ -27,7 +27,8 @@ import { graphQlVoyagerApiRef } from '../../lib/api'; import useAsync from 'react-use/lib/useAsync'; import { GraphQLVoyagerBrowser } from '../GraphQLVoyagerBrowser'; -type GraphQLVoyagerPageProps = { +/** @public */ +export type GraphQLVoyagerPageProps = { title?: string; }; diff --git a/plugins/graphql-voyager/src/index.ts b/plugins/graphql-voyager/src/index.ts index 2e7852bc51..9e314c2eef 100644 --- a/plugins/graphql-voyager/src/index.ts +++ b/plugins/graphql-voyager/src/index.ts @@ -15,4 +15,5 @@ */ export { graphqlVoyagerPlugin, GraphqlVoyagerPage } from './plugin'; export { GraphQLVoyagerPage as Router } from './components'; +export type { GraphQLVoyagerPageProps } from './components'; export * from './lib/api'; From 4a6f38a53513b6cc90062cfba13f3940cdb94f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 1 Feb 2023 11:35:52 +0100 Subject: [PATCH 032/423] implement some of the trivial backend plugins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/stale-experts-punch.md | 9 ++++ plugins/bazaar-backend/api-report.md | 4 ++ plugins/bazaar-backend/package.json | 9 ++-- plugins/bazaar-backend/src/index.ts | 1 + plugins/bazaar-backend/src/plugin.ts | 52 ++++++++++++++++++ .../example-todo-list-backend/api-report.md | 4 ++ .../example-todo-list-backend/package.json | 9 ++-- .../example-todo-list-backend/src/index.ts | 1 + .../example-todo-list-backend/src/plugin.ts | 48 +++++++++++++++++ plugins/kafka-backend/api-report.md | 4 ++ plugins/kafka-backend/package.json | 9 ++-- plugins/kafka-backend/src/index.ts | 1 + plugins/kafka-backend/src/plugin.ts | 45 ++++++++++++++++ plugins/periskop-backend/api-report.md | 4 ++ plugins/periskop-backend/package.json | 9 ++-- plugins/periskop-backend/src/index.ts | 1 + plugins/periskop-backend/src/plugin.ts | 45 ++++++++++++++++ plugins/proxy-backend/api-report.md | 10 ++++ plugins/proxy-backend/package.json | 9 ++-- plugins/proxy-backend/src/index.ts | 1 + plugins/proxy-backend/src/plugin.ts | 53 +++++++++++++++++++ plugins/user-settings-backend/api-report.md | 4 ++ plugins/user-settings-backend/package.json | 9 ++-- plugins/user-settings-backend/src/index.ts | 1 + plugins/user-settings-backend/src/plugin.ts | 42 +++++++++++++++ yarn.lock | 6 +++ 26 files changed, 372 insertions(+), 18 deletions(-) create mode 100644 .changeset/stale-experts-punch.md create mode 100644 plugins/bazaar-backend/src/plugin.ts create mode 100644 plugins/example-todo-list-backend/src/plugin.ts create mode 100644 plugins/kafka-backend/src/plugin.ts create mode 100644 plugins/periskop-backend/src/plugin.ts create mode 100644 plugins/proxy-backend/src/plugin.ts create mode 100644 plugins/user-settings-backend/src/plugin.ts diff --git a/.changeset/stale-experts-punch.md b/.changeset/stale-experts-punch.md new file mode 100644 index 0000000000..85872bfffe --- /dev/null +++ b/.changeset/stale-experts-punch.md @@ -0,0 +1,9 @@ +--- +'@backstage/plugin-user-settings-backend': patch +'@backstage/plugin-periskop-backend': patch +'@backstage/plugin-bazaar-backend': patch +'@backstage/plugin-kafka-backend': patch +'@backstage/plugin-proxy-backend': patch +--- + +Added a Backend System plugin feature diff --git a/plugins/bazaar-backend/api-report.md b/plugins/bazaar-backend/api-report.md index 1ee889c04a..6281530851 100644 --- a/plugins/bazaar-backend/api-report.md +++ b/plugins/bazaar-backend/api-report.md @@ -3,12 +3,16 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { Logger } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; +// @alpha +export const bazaarPlugin: () => BackendFeature; + // @public (undocumented) export function createRouter(options: RouterOptions): Promise; diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 166aca7c44..0d21223078 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -7,14 +7,15 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "backstage": { "role": "backend-plugin" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -23,6 +24,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", @@ -39,6 +41,7 @@ }, "files": [ "dist", - "migrations/**/*.{js,d.ts}" + "migrations/**/*.{js,d.ts}", + "alpha" ] } diff --git a/plugins/bazaar-backend/src/index.ts b/plugins/bazaar-backend/src/index.ts index ca73cb27ba..dd0cdbb750 100644 --- a/plugins/bazaar-backend/src/index.ts +++ b/plugins/bazaar-backend/src/index.ts @@ -15,3 +15,4 @@ */ export * from './service/router'; +export { bazaarPlugin } from './plugin'; diff --git a/plugins/bazaar-backend/src/plugin.ts b/plugins/bazaar-backend/src/plugin.ts new file mode 100644 index 0000000000..03491950e8 --- /dev/null +++ b/plugins/bazaar-backend/src/plugin.ts @@ -0,0 +1,52 @@ +/* + * Copyright 2023 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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * The Bazaar backend plugin. + * + * @alpha + */ +export const bazaarPlugin = createBackendPlugin({ + id: 'bazaar', + register(env) { + env.registerInit({ + deps: { + config: coreServices.config, + database: coreServices.database, + identity: coreServices.identity, + logger: coreServices.logger, + httpRouter: coreServices.httpRouter, + }, + async init({ database, config, identity, logger, httpRouter }) { + httpRouter.use( + await createRouter({ + database, + config, + identity, + logger: loggerToWinstonLogger(logger), + }), + ); + }, + }); + }, +}); diff --git a/plugins/example-todo-list-backend/api-report.md b/plugins/example-todo-list-backend/api-report.md index c4f8665a70..319fbbf226 100644 --- a/plugins/example-todo-list-backend/api-report.md +++ b/plugins/example-todo-list-backend/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; import express from 'express'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { Logger } from 'winston'; @@ -10,6 +11,9 @@ import { Logger } from 'winston'; // @public export function createRouter(options: RouterOptions): Promise; +// @alpha +export const exampleTodoListPlugin: () => BackendFeature; + // @public export interface RouterOptions { // (undocumented) diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index eec3b47b67..11973d8f2a 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -11,11 +11,12 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -24,6 +25,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", @@ -42,6 +44,7 @@ "supertest": "^6.1.6" }, "files": [ - "dist" + "dist", + "alpha" ] } diff --git a/plugins/example-todo-list-backend/src/index.ts b/plugins/example-todo-list-backend/src/index.ts index ca73cb27ba..6917307db6 100644 --- a/plugins/example-todo-list-backend/src/index.ts +++ b/plugins/example-todo-list-backend/src/index.ts @@ -15,3 +15,4 @@ */ export * from './service/router'; +export { exampleTodoListPlugin } from './plugin'; diff --git a/plugins/example-todo-list-backend/src/plugin.ts b/plugins/example-todo-list-backend/src/plugin.ts new file mode 100644 index 0000000000..ba25ed7218 --- /dev/null +++ b/plugins/example-todo-list-backend/src/plugin.ts @@ -0,0 +1,48 @@ +/* + * Copyright 2023 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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * The example TODO list backend plugin. + * + * @alpha + */ +export const exampleTodoListPlugin = createBackendPlugin({ + id: 'exampleTodoList', + register(env) { + env.registerInit({ + deps: { + identity: coreServices.identity, + logger: coreServices.logger, + httpRouter: coreServices.httpRouter, + }, + async init({ identity, logger, httpRouter }) { + httpRouter.use( + await createRouter({ + identity, + logger: loggerToWinstonLogger(logger), + }), + ); + }, + }); + }, +}); diff --git a/plugins/kafka-backend/api-report.md b/plugins/kafka-backend/api-report.md index 20c8260b52..a748a543d9 100644 --- a/plugins/kafka-backend/api-report.md +++ b/plugins/kafka-backend/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { Logger } from 'winston'; @@ -10,6 +11,9 @@ import { Logger } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; +// @alpha +export const kafkaPlugin: () => BackendFeature; + // @public (undocumented) export interface RouterOptions { // (undocumented) diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 93377dd9eb..623764c147 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -8,7 +8,8 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "backstage": { "role": "backend-plugin" @@ -26,7 +27,7 @@ "configSchema": "config.d.ts", "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -35,6 +36,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", @@ -54,6 +56,7 @@ }, "files": [ "dist", - "config.d.ts" + "config.d.ts", + "alpha" ] } diff --git a/plugins/kafka-backend/src/index.ts b/plugins/kafka-backend/src/index.ts index 70b7fb45a4..2000c8b89a 100644 --- a/plugins/kafka-backend/src/index.ts +++ b/plugins/kafka-backend/src/index.ts @@ -22,3 +22,4 @@ export type { RouterOptions } from './service/router'; export { createRouter } from './service/router'; +export { kafkaPlugin } from './plugin'; diff --git a/plugins/kafka-backend/src/plugin.ts b/plugins/kafka-backend/src/plugin.ts new file mode 100644 index 0000000000..f627e5a0bd --- /dev/null +++ b/plugins/kafka-backend/src/plugin.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2023 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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * The Kafka backend plugin. + * + * @alpha + */ +export const kafkaPlugin = createBackendPlugin({ + id: 'kafka', + register(env) { + env.registerInit({ + deps: { + config: coreServices.config, + logger: coreServices.logger, + httpRouter: coreServices.httpRouter, + }, + async init({ config, logger, httpRouter }) { + httpRouter.use( + await createRouter({ config, logger: loggerToWinstonLogger(logger) }), + ); + }, + }); + }, +}); diff --git a/plugins/periskop-backend/api-report.md b/plugins/periskop-backend/api-report.md index caaed109f9..7906bc4785 100644 --- a/plugins/periskop-backend/api-report.md +++ b/plugins/periskop-backend/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { Logger } from 'winston'; @@ -10,6 +11,9 @@ import { Logger } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; +// @alpha +export const periskopPlugin: () => BackendFeature; + // @public (undocumented) export interface RouterOptions { // (undocumented) diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index aa6d8daec3..dc29122b8e 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -11,11 +11,12 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -24,6 +25,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@types/express": "*", "express": "^4.17.1", @@ -39,6 +41,7 @@ "supertest": "^6.1.6" }, "files": [ - "dist" + "dist", + "alpha" ] } diff --git a/plugins/periskop-backend/src/index.ts b/plugins/periskop-backend/src/index.ts index ca73cb27ba..a053633745 100644 --- a/plugins/periskop-backend/src/index.ts +++ b/plugins/periskop-backend/src/index.ts @@ -15,3 +15,4 @@ */ export * from './service/router'; +export { periskopPlugin } from './plugin'; diff --git a/plugins/periskop-backend/src/plugin.ts b/plugins/periskop-backend/src/plugin.ts new file mode 100644 index 0000000000..b5dcfb1425 --- /dev/null +++ b/plugins/periskop-backend/src/plugin.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2023 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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * The Periskop backend plugin. + * + * @alpha + */ +export const periskopPlugin = createBackendPlugin({ + id: 'periskop', + register(env) { + env.registerInit({ + deps: { + config: coreServices.config, + logger: coreServices.logger, + httpRouter: coreServices.httpRouter, + }, + async init({ config, logger, httpRouter }) { + httpRouter.use( + await createRouter({ config, logger: loggerToWinstonLogger(logger) }), + ); + }, + }); + }, +}); diff --git a/plugins/proxy-backend/api-report.md b/plugins/proxy-backend/api-report.md index 581e7a904c..741f7c3b54 100644 --- a/plugins/proxy-backend/api-report.md +++ b/plugins/proxy-backend/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { Logger } from 'winston'; @@ -11,6 +12,15 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; // @public export function createRouter(options: RouterOptions): Promise; +// @alpha +export const proxyPlugin: ( + options?: + | { + skipInvalidProxies?: boolean | undefined; + } + | undefined, +) => BackendFeature; + // @public (undocumented) export interface RouterOptions { // (undocumented) diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index d145d91454..1d93d0eb4f 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -8,7 +8,8 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "backstage": { "role": "backend-plugin" @@ -24,7 +25,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -33,6 +34,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -56,7 +58,8 @@ }, "files": [ "dist", - "config.d.ts" + "config.d.ts", + "alpha" ], "configSchema": "config.d.ts" } diff --git a/plugins/proxy-backend/src/index.ts b/plugins/proxy-backend/src/index.ts index 8f5d5c79dc..2658a557b7 100644 --- a/plugins/proxy-backend/src/index.ts +++ b/plugins/proxy-backend/src/index.ts @@ -21,3 +21,4 @@ */ export * from './service'; +export { proxyPlugin } from './plugin'; diff --git a/plugins/proxy-backend/src/plugin.ts b/plugins/proxy-backend/src/plugin.ts new file mode 100644 index 0000000000..e9d6d515c1 --- /dev/null +++ b/plugins/proxy-backend/src/plugin.ts @@ -0,0 +1,53 @@ +/* + * Copyright 2023 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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + createBackendPlugin, + coreServices, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * The proxy backend plugin. + * + * @alpha + */ +export const proxyPlugin = createBackendPlugin( + (options?: { skipInvalidProxies?: boolean }) => ({ + id: 'proxy', + register(env) { + env.registerInit({ + deps: { + config: coreServices.config, + discovery: coreServices.discovery, + logger: coreServices.logger, + httpRouter: coreServices.httpRouter, + }, + async init({ config, discovery, logger, httpRouter }) { + httpRouter.use( + await createRouter({ + config, + discovery, + logger: loggerToWinstonLogger(logger), + skipInvalidProxies: options?.skipInvalidProxies, + }), + ); + }, + }); + }, + }), +); diff --git a/plugins/user-settings-backend/api-report.md b/plugins/user-settings-backend/api-report.md index 1bc37bbec7..b015915723 100644 --- a/plugins/user-settings-backend/api-report.md +++ b/plugins/user-settings-backend/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; import express from 'express'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { PluginDatabaseManager } from '@backstage/backend-common'; @@ -18,5 +19,8 @@ export interface RouterOptions { identity: IdentityApi; } +// @alpha +export const userSettingsPlugin: () => BackendFeature; + // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index 8197078d74..97570989f6 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -11,7 +11,8 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "repository": { "type": "git", @@ -20,7 +21,7 @@ }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -29,6 +30,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", @@ -48,6 +50,7 @@ }, "files": [ "dist", - "migrations" + "migrations", + "alpha" ] } diff --git a/plugins/user-settings-backend/src/index.ts b/plugins/user-settings-backend/src/index.ts index 04d8accdaf..5504aaa564 100644 --- a/plugins/user-settings-backend/src/index.ts +++ b/plugins/user-settings-backend/src/index.ts @@ -16,3 +16,4 @@ export * from './service'; export * from './database'; +export { userSettingsPlugin } from './plugin'; diff --git a/plugins/user-settings-backend/src/plugin.ts b/plugins/user-settings-backend/src/plugin.ts new file mode 100644 index 0000000000..83120cc180 --- /dev/null +++ b/plugins/user-settings-backend/src/plugin.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2023 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 { + createBackendPlugin, + coreServices, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * The user settings backend plugin. + * + * @alpha + */ +export const userSettingsPlugin = createBackendPlugin({ + id: 'userSettings', + register(env) { + env.registerInit({ + deps: { + database: coreServices.database, + identity: coreServices.identity, + httpRouter: coreServices.httpRouter, + }, + async init({ database, identity, httpRouter }) { + httpRouter.use(await createRouter({ database, identity })); + }, + }); + }, +}); diff --git a/yarn.lock b/yarn.lock index 9a7492289e..fe295228dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4758,6 +4758,7 @@ __metadata: resolution: "@backstage/plugin-bazaar-backend@workspace:plugins/bazaar-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" @@ -6602,6 +6603,7 @@ __metadata: resolution: "@backstage/plugin-kafka-backend@workspace:plugins/kafka-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" @@ -6924,6 +6926,7 @@ __metadata: resolution: "@backstage/plugin-periskop-backend@workspace:plugins/periskop-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@types/express": "*" @@ -7139,6 +7142,7 @@ __metadata: resolution: "@backstage/plugin-proxy-backend@workspace:plugins/proxy-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@types/express": ^4.17.6 @@ -8349,6 +8353,7 @@ __metadata: resolution: "@backstage/plugin-user-settings-backend@workspace:plugins/user-settings-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" @@ -10302,6 +10307,7 @@ __metadata: resolution: "@internal/plugin-todo-list-backend@workspace:plugins/example-todo-list-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" From 94f4b4be384ee16698cbcb6b8f6ddeb49e75d982 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 11:49:34 +0000 Subject: [PATCH 033/423] fix(deps): update dependency eslint-plugin-import to v2.27.5 Signed-off-by: Renovate Bot --- yarn.lock | 123 +++++++++++++++++++----------------------------------- 1 file changed, 42 insertions(+), 81 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7adadefb11..e8a7f4ca63 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16918,7 +16918,7 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.4, array-includes@npm:^3.1.5, array-includes@npm:^3.1.6": +"array-includes@npm:^3.1.5, array-includes@npm:^3.1.6": version: 3.1.6 resolution: "array-includes@npm:3.1.6" dependencies: @@ -16954,15 +16954,15 @@ __metadata: languageName: node linkType: hard -"array.prototype.flat@npm:^1.2.3, array.prototype.flat@npm:^1.2.5": - version: 1.3.0 - resolution: "array.prototype.flat@npm:1.3.0" +"array.prototype.flat@npm:^1.2.3, array.prototype.flat@npm:^1.3.1": + version: 1.3.1 + resolution: "array.prototype.flat@npm:1.3.1" dependencies: call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 es-shim-unscopables: ^1.0.0 - checksum: 2a652b3e8dc0bebb6117e42a5ab5738af0203a14c27341d7bb2431467bdb4b348e2c5dc555dfcda8af0a5e4075c400b85311ded73861c87290a71a17c3e0a257 + checksum: 5a8415949df79bf6e01afd7e8839bbde5a3581300e8ad5d8449dea52639e9e59b26a467665622783697917b43bf39940a6e621877c7dd9b3d1c1f97484b9b88b languageName: node linkType: hard @@ -20401,7 +20401,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:2.6.9, debug@npm:^2.6.0, debug@npm:^2.6.9": +"debug@npm:2.6.9, debug@npm:^2.6.0": version: 2.6.9 resolution: "debug@npm:2.6.9" dependencies: @@ -21455,7 +21455,7 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.19.0, es-abstract@npm:^1.19.2, es-abstract@npm:^1.19.5, es-abstract@npm:^1.20.4": +"es-abstract@npm:^1.19.0, es-abstract@npm:^1.19.5, es-abstract@npm:^1.20.4": version: 1.20.4 resolution: "es-abstract@npm:1.20.4" dependencies: @@ -21951,23 +21951,26 @@ __metadata: languageName: node linkType: hard -"eslint-import-resolver-node@npm:^0.3.6": - version: 0.3.6 - resolution: "eslint-import-resolver-node@npm:0.3.6" +"eslint-import-resolver-node@npm:^0.3.7": + version: 0.3.7 + resolution: "eslint-import-resolver-node@npm:0.3.7" dependencies: debug: ^3.2.7 - resolve: ^1.20.0 - checksum: 6266733af1e112970e855a5bcc2d2058fb5ae16ad2a6d400705a86b29552b36131ffc5581b744c23d550de844206fb55e9193691619ee4dbf225c4bde526b1c8 + is-core-module: ^2.11.0 + resolve: ^1.22.1 + checksum: 3379aacf1d2c6952c1b9666c6fa5982c3023df695430b0d391c0029f6403a7775414873d90f397e98ba6245372b6c8960e16e74d9e4a3b0c0a4582f3bdbe3d6e languageName: node linkType: hard -"eslint-module-utils@npm:^2.1.1, eslint-module-utils@npm:^2.7.3": - version: 2.7.3 - resolution: "eslint-module-utils@npm:2.7.3" +"eslint-module-utils@npm:^2.1.1, eslint-module-utils@npm:^2.7.4": + version: 2.7.4 + resolution: "eslint-module-utils@npm:2.7.4" dependencies: debug: ^3.2.7 - find-up: ^2.1.0 - checksum: 77048263f309167a1e6a1e1b896bfb5ddd1d3859b2e2abbd9c32c432aee13d610d46e6820b1ca81b37fba437cf423a404bc6649be64ace9148a3062d1886a678 + peerDependenciesMeta: + eslint: + optional: true + checksum: 5da13645daff145a5c922896b258f8bba560722c3767254e458d894ff5fbb505d6dfd945bffa932a5b0ae06714da2379bd41011c4c20d2d59cc83e23895360f7 languageName: node linkType: hard @@ -21997,25 +22000,27 @@ __metadata: linkType: hard "eslint-plugin-import@npm:^2.25.4": - version: 2.26.0 - resolution: "eslint-plugin-import@npm:2.26.0" + version: 2.27.5 + resolution: "eslint-plugin-import@npm:2.27.5" dependencies: - array-includes: ^3.1.4 - array.prototype.flat: ^1.2.5 - debug: ^2.6.9 + array-includes: ^3.1.6 + array.prototype.flat: ^1.3.1 + array.prototype.flatmap: ^1.3.1 + debug: ^3.2.7 doctrine: ^2.1.0 - eslint-import-resolver-node: ^0.3.6 - eslint-module-utils: ^2.7.3 + eslint-import-resolver-node: ^0.3.7 + eslint-module-utils: ^2.7.4 has: ^1.0.3 - is-core-module: ^2.8.1 + is-core-module: ^2.11.0 is-glob: ^4.0.3 minimatch: ^3.1.2 - object.values: ^1.1.5 - resolve: ^1.22.0 + object.values: ^1.1.6 + resolve: ^1.22.1 + semver: ^6.3.0 tsconfig-paths: ^3.14.1 peerDependencies: eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 0bf77ad80339554481eafa2b1967449e1f816b94c7a6f9614ce33fb4083c4e6c050f10d241dd50b4975d47922880a34de1e42ea9d8e6fd663ebb768baa67e655 + checksum: f500571a380167e25d72a4d925ef9a7aae8899eada57653e5f3051ec3d3c16d08271fcefe41a30a9a2f4fefc232f066253673ee4ea77b30dba65ae173dade85d languageName: node linkType: hard @@ -23214,15 +23219,6 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^2.1.0": - version: 2.1.0 - resolution: "find-up@npm:2.1.0" - dependencies: - locate-path: ^2.0.0 - checksum: 43284fe4da09f89011f08e3c32cd38401e786b19226ea440b75386c1b12a4cb738c94969808d53a84f564ede22f732c8409e3cfc3f7fb5b5c32378ad0bbf28bd - languageName: node - linkType: hard - "find-up@npm:^3.0.0": version: 3.0.0 resolution: "find-up@npm:3.0.0" @@ -25567,12 +25563,12 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.1.0, is-core-module@npm:^2.8.1, is-core-module@npm:^2.9.0": - version: 2.10.0 - resolution: "is-core-module@npm:2.10.0" +"is-core-module@npm:^2.1.0, is-core-module@npm:^2.11.0, is-core-module@npm:^2.9.0": + version: 2.11.0 + resolution: "is-core-module@npm:2.11.0" dependencies: has: ^1.0.3 - checksum: 0f3f77811f430af3256fa7bbc806f9639534b140f8ee69476f632c3e1eb4e28a38be0b9d1b8ecf596179c841b53576129279df95e7051d694dac4ceb6f967593 + checksum: f96fd490c6b48eb4f6d10ba815c6ef13f410b0ba6f7eb8577af51697de523e5f2cd9de1c441b51d27251bf0e4aebc936545e33a5d26d5d51f28d25698d4a8bab languageName: node linkType: hard @@ -28109,16 +28105,6 @@ __metadata: languageName: node linkType: hard -"locate-path@npm:^2.0.0": - version: 2.0.0 - resolution: "locate-path@npm:2.0.0" - dependencies: - p-locate: ^2.0.0 - path-exists: ^3.0.0 - checksum: 02d581edbbbb0fa292e28d96b7de36b5b62c2fa8b5a7e82638ebb33afa74284acf022d3b1e9ae10e3ffb7658fbc49163fcd5e76e7d1baaa7801c3e05a81da755 - languageName: node - linkType: hard - "locate-path@npm:^3.0.0": version: 3.0.0 resolution: "locate-path@npm:3.0.0" @@ -30637,7 +30623,7 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.5, object.values@npm:^1.1.6": +"object.values@npm:^1.1.6": version: 1.1.6 resolution: "object.values@npm:1.1.6" dependencies: @@ -30933,15 +30919,6 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^1.1.0": - version: 1.3.0 - resolution: "p-limit@npm:1.3.0" - dependencies: - p-try: ^1.0.0 - checksum: 281c1c0b8c82e1ac9f81acd72a2e35d402bf572e09721ce5520164e9de07d8274451378a3470707179ad13240535558f4b277f02405ad752e08c7d5b0d54fbfd - languageName: node - linkType: hard - "p-limit@npm:^2.0.0, p-limit@npm:^2.2.0": version: 2.3.0 resolution: "p-limit@npm:2.3.0" @@ -30960,15 +30937,6 @@ __metadata: languageName: node linkType: hard -"p-locate@npm:^2.0.0": - version: 2.0.0 - resolution: "p-locate@npm:2.0.0" - dependencies: - p-limit: ^1.1.0 - checksum: e2dceb9b49b96d5513d90f715780f6f4972f46987dc32a0e18bc6c3fc74a1a5d73ec5f81b1398af5e58b99ea1ad03fd41e9181c01fa81b4af2833958696e3081 - languageName: node - linkType: hard - "p-locate@npm:^3.0.0": version: 3.0.0 resolution: "p-locate@npm:3.0.0" @@ -31051,13 +31019,6 @@ __metadata: languageName: node linkType: hard -"p-try@npm:^1.0.0": - version: 1.0.0 - resolution: "p-try@npm:1.0.0" - checksum: 3b5303f77eb7722144154288bfd96f799f8ff3e2b2b39330efe38db5dd359e4fb27012464cd85cb0a76e9b7edd1b443568cb3192c22e7cffc34989df0bafd605 - languageName: node - linkType: hard - "p-try@npm:^2.0.0": version: 2.2.0 resolution: "p-try@npm:2.2.0" @@ -34319,7 +34280,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.0, resolve@npm:~1.22.1": +"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:~1.22.1": version: 1.22.1 resolution: "resolve@npm:1.22.1" dependencies: @@ -34364,7 +34325,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.0#~builtin, resolve@patch:resolve@~1.22.1#~builtin": +"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin, resolve@patch:resolve@~1.22.1#~builtin": version: 1.22.1 resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin::version=1.22.1&hash=07638b" dependencies: From 95d052f829ae31d0907a15a57204eb33fc5b49c6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 1 Feb 2023 13:16:26 +0100 Subject: [PATCH 034/423] docs: make backend-system docs available with disclaimer Signed-off-by: Patrik Oldsberg --- docs/backend-system/architecture/01-index.md | 2 + .../architecture/02-backends.md | 2 + .../architecture/03-services.md | 2 + .../backend-system/architecture/04-plugins.md | 2 + .../architecture/05-extension-points.md | 2 + .../backend-system/architecture/06-modules.md | 2 + .../architecture/07-naming-patterns.md | 2 + .../building-backends/01-index.md | 2 + .../building-backends/08-migrating.md | 2 + .../building-plugins-and-modules/01-index.md | 2 + .../02-testing.md | 2 + .../08-migrating.md | 2 + docs/backend-system/core-services/01-index.md | 2 + microsite/sidebars.json | 68 +++++++++---------- 14 files changed, 58 insertions(+), 36 deletions(-) diff --git a/docs/backend-system/architecture/01-index.md b/docs/backend-system/architecture/01-index.md index 88ba3262df..a9f08c7907 100644 --- a/docs/backend-system/architecture/01-index.md +++ b/docs/backend-system/architecture/01-index.md @@ -6,6 +6,8 @@ sidebar_label: System Architecture description: The structure and architecture of the new Backend System and its component parts --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + ## Building Blocks This section introduces the high-level building blocks upon which this new diff --git a/docs/backend-system/architecture/02-backends.md b/docs/backend-system/architecture/02-backends.md index 69b74e7dd3..53670aba12 100644 --- a/docs/backend-system/architecture/02-backends.md +++ b/docs/backend-system/architecture/02-backends.md @@ -6,6 +6,8 @@ sidebar_label: Backend description: Backend instances --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + ## The Backend Instance This is the main entry point for creating a backend. It does not have any functionality in and of itself, but is simply responsible for wiring things together. diff --git a/docs/backend-system/architecture/03-services.md b/docs/backend-system/architecture/03-services.md index 96b82d7e95..d202c21740 100644 --- a/docs/backend-system/architecture/03-services.md +++ b/docs/backend-system/architecture/03-services.md @@ -6,6 +6,8 @@ sidebar_label: Services description: Services for backend plugins --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + Backend services provide shared functionality available to all backend plugins and modules. They are made available through service references that embed a type that represents the service interface, similar to how [Utility APIs](../../api/utility-apis.md) work in the Backstage frontend system. To use a service in your plugin or module you request an implementation of that service using the service reference. The system surrounding services exists to provide a level of indirection between the service interfaces and their implementation. It is an implementation of dependency injection, where each backend instance is the dependency injection container. The implementation for each service is provided by a service factory, which encapsulates the logic for how each service instance is created. diff --git a/docs/backend-system/architecture/04-plugins.md b/docs/backend-system/architecture/04-plugins.md index f535268b2a..7721b1c9f7 100644 --- a/docs/backend-system/architecture/04-plugins.md +++ b/docs/backend-system/architecture/04-plugins.md @@ -6,6 +6,8 @@ sidebar_label: Plugins description: Backend plugins --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + Plugins provide the actual base features of a Backstage backend. Each plugin operates completely independently of all other plugins and they only communicate with each other through network calls. This means that there is a strong degree of isolation between plugins, and that each plugin can be considered a separate microservice. While a default Backstage project has all plugins installed within a single backend, it is also possible to split this setup into multiple backends, with each backend housing one or more plugins. ## Defining a Plugin diff --git a/docs/backend-system/architecture/05-extension-points.md b/docs/backend-system/architecture/05-extension-points.md index f82fde3561..d16a773c0c 100644 --- a/docs/backend-system/architecture/05-extension-points.md +++ b/docs/backend-system/architecture/05-extension-points.md @@ -6,6 +6,8 @@ sidebar_label: Extension Points description: Extension points of backend plugins --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + While plugins are able to accept options for lightweight forms of customization and extension, you quickly hit a limit where you need something more powerful to allow users to extend your plugin. For this purpose, the backend system provides a mechanism for plugins to provide extension points, which can be used to expose deeper customizations for your plugin. Extension points are used by modules, which are installed in the backend adjacent to plugins. Modules are covered more in-depth in the [next section](./06-modules.md). Extension points are quite similar to services, in that they both encapsulate an interface in a reference object. The key difference is that extension points are registered and provided by plugins themselves, and do not have any factory associated with them. Extension points for a given plugin are also only accessible to modules that extend that same plugin. diff --git a/docs/backend-system/architecture/06-modules.md b/docs/backend-system/architecture/06-modules.md index 83428c7a26..2f359eaa75 100644 --- a/docs/backend-system/architecture/06-modules.md +++ b/docs/backend-system/architecture/06-modules.md @@ -6,6 +6,8 @@ sidebar_label: Modules description: Modules for backend plugins --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + Backend modules are used to extend [plugins](./04-plugins.md) with additional features or change existing behavior. They must always be installed in the same backend instance as the plugin that they extend, and may only extend a single plugin. Modules interact with their target plugin using the [extension points](./05-extension-points.md) registered by the plugin, while also being able to depend on the [services](./03-services.md) of that plugin. Both modules and plugins register an `init` method that is called during startup. In order to ensure that modules have registered all their extensions before the plugin starts up, all modules for each plugin are completely initialized before the plugin itself is initialized. In practice this means that all promises returned by each `init` method of the modules need to resolve before the plugin `init` method is called. This also means that it is not possible to further interact with the extension points once the `init` method has resolved. diff --git a/docs/backend-system/architecture/07-naming-patterns.md b/docs/backend-system/architecture/07-naming-patterns.md index 6bd7c412c3..dc781a61ac 100644 --- a/docs/backend-system/architecture/07-naming-patterns.md +++ b/docs/backend-system/architecture/07-naming-patterns.md @@ -6,6 +6,8 @@ sidebar_label: Naming Patterns description: Naming patterns in the backend system --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + These are the naming patterns to adhere to within the backend system. They help us keep exports consistent across packages and make it easier to understand the usage and intent of exports. ### Plugins diff --git a/docs/backend-system/building-backends/01-index.md b/docs/backend-system/building-backends/01-index.md index f810417ed7..de01c6d39c 100644 --- a/docs/backend-system/building-backends/01-index.md +++ b/docs/backend-system/building-backends/01-index.md @@ -6,6 +6,8 @@ sidebar_label: Overview description: Building backends using the new backend system --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + > NOTE: If you have an existing backend that is not yet using the new backend > system, see [migrating](./08-migrating.md). diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index 6e0b84b10f..e503d627ef 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -6,6 +6,8 @@ sidebar_label: Migration Guide description: How to migrate existing backends to the new backend system --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + ## Overview This section describes how to migrate an existing Backstage backend service diff --git a/docs/backend-system/building-plugins-and-modules/01-index.md b/docs/backend-system/building-plugins-and-modules/01-index.md index 01e35036aa..5fefb3ff16 100644 --- a/docs/backend-system/building-plugins-and-modules/01-index.md +++ b/docs/backend-system/building-plugins-and-modules/01-index.md @@ -6,6 +6,8 @@ sidebar_label: Overview description: Building backend plugins and modules using the new backend system --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + > NOTE: If you have an existing backend and/or backend plugins that are not yet > using the new backend system, see [migrating](./08-migrating.md). diff --git a/docs/backend-system/building-plugins-and-modules/02-testing.md b/docs/backend-system/building-plugins-and-modules/02-testing.md index 20bef6fec4..37c5698512 100644 --- a/docs/backend-system/building-plugins-and-modules/02-testing.md +++ b/docs/backend-system/building-plugins-and-modules/02-testing.md @@ -6,6 +6,8 @@ sidebar_label: Testing description: Learn how to test your backend plugins and modules --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + Utilities for testing backend plugins and modules are available in `@backstage/backend-test-utils`. This section describes those facilities. diff --git a/docs/backend-system/building-plugins-and-modules/08-migrating.md b/docs/backend-system/building-plugins-and-modules/08-migrating.md index ec003a6fec..ec5836a126 100644 --- a/docs/backend-system/building-plugins-and-modules/08-migrating.md +++ b/docs/backend-system/building-plugins-and-modules/08-migrating.md @@ -6,6 +6,8 @@ sidebar_label: Migration Guide description: How to migrate existing backend plugins to the new backend system --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + Migrating an existing backend plugin to the new backend system is fairly straightforward. The process is similar across the majority of plugins which just return a `Router` that is then wired up in the `index.ts` file of your backend. The primary thing that we need to do is to make sure that the dependencies that are required by the plugin are available, and then registering the router with the HTTP router service. Let's look at an example of migrating the Kubernetes backend plugin. In the existing (old) system, the kubernetes backend is structured like this: diff --git a/docs/backend-system/core-services/01-index.md b/docs/backend-system/core-services/01-index.md index 4ef9d75bde..b394391480 100644 --- a/docs/backend-system/core-services/01-index.md +++ b/docs/backend-system/core-services/01-index.md @@ -6,6 +6,8 @@ sidebar_label: Core Services description: Core backend service APIs --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + The default backend provides several [core services](https://github.com/backstage/backstage/blob/master/packages/backend-plugin-api/src/services/definitions/coreServices.ts) out of the box which includes access to configuration, logging, URL Readers, databases and more. All core services are available through the `coreServices` namespace in the `@backstage/backend-plugin-api` package. diff --git a/microsite/sidebars.json b/microsite/sidebars.json index fcded5ebfb..f051d3c70b 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -365,44 +365,40 @@ ], "FAQ": ["FAQ"], "Experimental Backend System": [ + "backend-system/index", { - "_hidden_": [ - "backend-system/index", - { - "type": "subcategory", - "label": "Architecture", - "ids": [ - "backend-system/architecture/index", - "backend-system/architecture/services", - "backend-system/architecture/plugins", - "backend-system/architecture/extension-points", - "backend-system/architecture/modules", - "backend-system/architecture/naming-patterns" - ] - }, - { - "type": "subcategory", - "label": "Building Backends", - "ids": [ - "backend-system/building-backends/index", - "backend-system/building-backends/migrating" - ] - }, - { - "type": "subcategory", - "label": "Building Plugins & Modules", - "ids": [ - "backend-system/building-plugins-and-modules/index", - "backend-system/building-plugins-and-modules/testing", - "backend-system/building-plugins-and-modules/migrating" - ] - }, - { - "type": "subcategory", - "label": "Core Services", - "ids": ["backend-system/core-services/index"] - } + "type": "subcategory", + "label": "Architecture", + "ids": [ + "backend-system/architecture/index", + "backend-system/architecture/services", + "backend-system/architecture/plugins", + "backend-system/architecture/extension-points", + "backend-system/architecture/modules", + "backend-system/architecture/naming-patterns" ] + }, + { + "type": "subcategory", + "label": "Building Backends", + "ids": [ + "backend-system/building-backends/index", + "backend-system/building-backends/migrating" + ] + }, + { + "type": "subcategory", + "label": "Building Plugins & Modules", + "ids": [ + "backend-system/building-plugins-and-modules/index", + "backend-system/building-plugins-and-modules/testing", + "backend-system/building-plugins-and-modules/migrating" + ] + }, + { + "type": "subcategory", + "label": "Core Services", + "ids": ["backend-system/core-services/index"] } ] } From 69d4fd3bae2c9ddc148d554e8521f383423ed2e2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 1 Feb 2023 13:21:43 +0100 Subject: [PATCH 035/423] changeset tweak Signed-off-by: Patrik Oldsberg --- .changeset/tall-years-relate.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/tall-years-relate.md b/.changeset/tall-years-relate.md index 10198992ea..73a0e875b0 100644 --- a/.changeset/tall-years-relate.md +++ b/.changeset/tall-years-relate.md @@ -2,4 +2,4 @@ '@backstage/plugin-airbrake': patch --- -Adds a boolean helper function to airbrake plugin for use on the EntityPage to show/hide airbrake tab depending on whether the entity's catalog-info.yml has an airbrake id set in the metadata +Adds a boolean helper function to airbrake plugin for use on the EntityPage to show/hide airbrake tab depending on whether the entity's `catalog-info.yaml` has an airbrake id set in the metadata From 89d02916c9b2bb6b2198e37412de574b171e8e33 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 12:35:02 +0000 Subject: [PATCH 036/423] fix(deps): update dependency glob to v8.1.0 Signed-off-by: Renovate Bot --- yarn.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index e8a7f4ca63..de18b87b69 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3725,7 +3725,7 @@ __metadata: express: ^4.17.1 fork-ts-checker-webpack-plugin: ^7.0.0-alpha.8 fs-extra: 10.1.0 - glob: ^7.1.7 + glob: ^8.0.3 global-agent: ^3.0.0 handlebars: ^4.7.3 html-webpack-plugin: ^5.3.1 @@ -5191,7 +5191,7 @@ __metadata: fast-json-stable-stringify: ^2.1.0 fs-extra: 10.1.0 git-url-parse: ^13.0.0 - glob: ^7.1.6 + glob: ^8.0.3 knex: ^2.0.0 lodash: ^4.17.21 luxon: ^3.0.0 @@ -23955,15 +23955,15 @@ __metadata: linkType: hard "glob@npm:^8.0.0, glob@npm:^8.0.1, glob@npm:^8.0.3": - version: 8.0.3 - resolution: "glob@npm:8.0.3" + version: 8.1.0 + resolution: "glob@npm:8.1.0" dependencies: fs.realpath: ^1.0.0 inflight: ^1.0.4 inherits: 2 minimatch: ^5.0.1 once: ^1.3.0 - checksum: 50bcdea19d8e79d8de5f460b1939ffc2b3299eac28deb502093fdca22a78efebc03e66bf54f0abc3d3d07d8134d19a32850288b7440d77e072aa55f9d33b18c5 + checksum: 92fbea3221a7d12075f26f0227abac435de868dd0736a17170663783296d0dd8d3d532a5672b4488a439bf5d7fb85cdd07c11185d6cd39184f0385cbdfb86a47 languageName: node linkType: hard From fba5b7439efed4d74ef70894860bc1a79f4fe3b9 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 1 Feb 2023 13:40:41 +0100 Subject: [PATCH 037/423] updating lock Signed-off-by: blam --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index de18b87b69..c5c424e4d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3725,7 +3725,7 @@ __metadata: express: ^4.17.1 fork-ts-checker-webpack-plugin: ^7.0.0-alpha.8 fs-extra: 10.1.0 - glob: ^8.0.3 + glob: ^7.1.7 global-agent: ^3.0.0 handlebars: ^4.7.3 html-webpack-plugin: ^5.3.1 @@ -5191,7 +5191,7 @@ __metadata: fast-json-stable-stringify: ^2.1.0 fs-extra: 10.1.0 git-url-parse: ^13.0.0 - glob: ^8.0.3 + glob: ^7.1.6 knex: ^2.0.0 lodash: ^4.17.21 luxon: ^3.0.0 From d9c8720dd48fa42c6e753f3b7c8549cfc84aef85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 1 Feb 2023 13:48:51 +0100 Subject: [PATCH 038/423] just some comment cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../software-catalog/external-integrations.md | 12 ++++++------ .../implementations/lifecycle/lifecycleFactory.ts | 3 ++- .../rootLifecycle/rootLifecycleFactory.ts | 4 +++- .../src/services/definitions/LifecycleService.ts | 4 ++-- .../core-components/src/layout/Sidebar/config.ts | 4 ++-- .../test-utils/src/testUtils/TestApiProvider.tsx | 2 +- .../src/processors/AzureDevOpsDiscoveryProcessor.ts | 4 ++-- .../src/processors/GithubDiscoveryProcessor.ts | 2 +- .../src/components/SearchModal/SearchModal.tsx | 4 ++-- .../stack-overflow/src/api/StackOverflowClient.ts | 5 ++--- plugins/tech-insights-node/src/facts.ts | 4 ++-- 11 files changed, 25 insertions(+), 23 deletions(-) diff --git a/docs/features/software-catalog/external-integrations.md b/docs/features/software-catalog/external-integrations.md index da4eb3d229..5fc2537712 100644 --- a/docs/features/software-catalog/external-integrations.md +++ b/docs/features/software-catalog/external-integrations.md @@ -89,23 +89,23 @@ export class FrobsProvider implements EntityProvider { private readonly reader: UrlReader; private connection?: EntityProviderConnection; - /** [1] **/ + /** [1] */ constructor(env: string, reader: UrlReader) { this.env = env; this.reader = reader; } - /** [2] **/ + /** [2] */ getProviderName(): string { return `frobs-${this.env}`; } - /** [3] **/ + /** [3] */ async connect(connection: EntityProviderConnection): Promise { this.connection = connection; } - /** [4] **/ + /** [4] */ async run(): Promise { if (!this.connection) { throw new Error('Not initialized'); @@ -116,10 +116,10 @@ export class FrobsProvider implements EntityProvider { ); const data = JSON.parse(await response.buffer()).toString(); - /** [5] **/ + /** [5] */ const entities: Entity[] = frobsToEntities(data); - /** [6] **/ + /** [6] */ await this.connection.applyMutation({ type: 'full', entities: entities.map(entity => ({ diff --git a/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts b/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts index b2f3a9f70b..299022079b 100644 --- a/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts +++ b/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts @@ -21,7 +21,8 @@ import { /** * Allows plugins to register shutdown hooks that are run when the process is about to exit. - * @public */ + * @public + */ export const lifecycleFactory = createServiceFactory({ service: coreServices.lifecycle, deps: { diff --git a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts index f451c38f20..71ab76ae92 100644 --- a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts @@ -58,7 +58,9 @@ export class BackendLifecycleImpl implements RootLifecycleService { /** * Allows plugins to register shutdown hooks that are run when the process is about to exit. - * @public */ + * + * @public + */ export const rootLifecycleFactory = createServiceFactory({ service: coreServices.rootLifecycle, deps: { diff --git a/packages/backend-plugin-api/src/services/definitions/LifecycleService.ts b/packages/backend-plugin-api/src/services/definitions/LifecycleService.ts index 25cc47270e..59d14aa61d 100644 --- a/packages/backend-plugin-api/src/services/definitions/LifecycleService.ts +++ b/packages/backend-plugin-api/src/services/definitions/LifecycleService.ts @@ -18,7 +18,7 @@ import { LoggerService } from './LoggerService'; /** * @public - **/ + */ export type LifecycleServiceShutdownHook = { fn: () => void | Promise; @@ -30,7 +30,7 @@ export type LifecycleServiceShutdownHook = { /** * @public - **/ + */ export interface LifecycleService { /** * Register a function to be called when the backend is shutting down. diff --git a/packages/core-components/src/layout/Sidebar/config.ts b/packages/core-components/src/layout/Sidebar/config.ts index dacf4bd0a5..e3d126a86f 100644 --- a/packages/core-components/src/layout/Sidebar/config.ts +++ b/packages/core-components/src/layout/Sidebar/config.ts @@ -32,7 +32,7 @@ export type SubmenuOptions = { drawerWidthOpen?: number; }; -/** @internal **/ +/** @internal */ export type SidebarConfig = { drawerWidthClosed: number; drawerWidthOpen: number; @@ -78,7 +78,7 @@ export const makeSidebarConfig = ( sidebarConfig.drawerWidthClosed - sidebarConfig.userBadgePadding * 2, }); -/** @internal **/ +/** @internal */ export type SubmenuConfig = { drawerWidthClosed: number; drawerWidthOpen: number; diff --git a/packages/test-utils/src/testUtils/TestApiProvider.tsx b/packages/test-utils/src/testUtils/TestApiProvider.tsx index 51edf77cba..35fa302415 100644 --- a/packages/test-utils/src/testUtils/TestApiProvider.tsx +++ b/packages/test-utils/src/testUtils/TestApiProvider.tsx @@ -119,7 +119,7 @@ export class TestApiRegistry implements ApiHolder { * implements a subset of the `IdentityApi`. * * @public - **/ + */ export const TestApiProvider = ( props: TestApiProviderProps, ) => { diff --git a/plugins/catalog-backend-module-azure/src/processors/AzureDevOpsDiscoveryProcessor.ts b/plugins/catalog-backend-module-azure/src/processors/AzureDevOpsDiscoveryProcessor.ts index 4852edbb03..8893d5d42d 100644 --- a/plugins/catalog-backend-module-azure/src/processors/AzureDevOpsDiscoveryProcessor.ts +++ b/plugins/catalog-backend-module-azure/src/processors/AzureDevOpsDiscoveryProcessor.ts @@ -43,7 +43,7 @@ import { codeSearch } from '../lib'; * target: https://dev.azure.com/org/project/_git/repo * * @public - **/ + */ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { private readonly integrations: ScmIntegrationRegistry; private readonly logger: Logger; @@ -123,7 +123,7 @@ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { /** * parseUrl extracts segments from the Azure DevOps URL. - **/ + */ export function parseUrl(urlString: string): { baseUrl: string; org: string; diff --git a/plugins/catalog-backend-module-github/src/processors/GithubDiscoveryProcessor.ts b/plugins/catalog-backend-module-github/src/processors/GithubDiscoveryProcessor.ts index 3fec87d0b2..c6733df13b 100644 --- a/plugins/catalog-backend-module-github/src/processors/GithubDiscoveryProcessor.ts +++ b/plugins/catalog-backend-module-github/src/processors/GithubDiscoveryProcessor.ts @@ -46,7 +46,7 @@ import { getOrganizationRepositories } from '../lib'; * target: https://github.com/backstage/*\/blob/main/catalog-info.yaml * * @public - **/ + */ export class GithubDiscoveryProcessor implements CatalogProcessor { private readonly integrations: ScmIntegrationRegistry; private readonly logger: Logger; diff --git a/plugins/search/src/components/SearchModal/SearchModal.tsx b/plugins/search/src/components/SearchModal/SearchModal.tsx index d17cf0f6ba..c9621c5940 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.tsx @@ -42,7 +42,7 @@ import { rootRouteRef } from '../../plugin'; /** * @public - **/ + */ export interface SearchModalChildrenProps { /** * A function that should be invoked when navigating away from the modal. @@ -52,7 +52,7 @@ export interface SearchModalChildrenProps { /** * @public - **/ + */ export interface SearchModalProps { /** * If true, it renders the modal. diff --git a/plugins/stack-overflow/src/api/StackOverflowClient.ts b/plugins/stack-overflow/src/api/StackOverflowClient.ts index f4ff5bf190..f598f912bd 100644 --- a/plugins/stack-overflow/src/api/StackOverflowClient.ts +++ b/plugins/stack-overflow/src/api/StackOverflowClient.ts @@ -39,9 +39,8 @@ export class StackOverflowClient implements StackOverflowApi { } /** - * List Questions in the StackOverflow instance - * - * */ + * List questions in the StackOverflow instance + */ async listQuestions(options: { requestParams: StackOverflowQuestionsRequestParams; }): Promise { diff --git a/plugins/tech-insights-node/src/facts.ts b/plugins/tech-insights-node/src/facts.ts index 3619f8b66f..b35ad756ed 100644 --- a/plugins/tech-insights-node/src/facts.ts +++ b/plugins/tech-insights-node/src/facts.ts @@ -162,7 +162,7 @@ export interface FactRetriever { * \{ timeToLive: 1209600000 \} * \{ timeToLive: \{ weeks: 4 \} \} * - **/ + */ export type TTL = { timeToLive: DurationLike }; /** @@ -172,7 +172,7 @@ export type TTL = { timeToLive: DurationLike }; * @example * \{ maxItems: 10 \} * - **/ + */ export type MaxItems = { maxItems: number }; /** From e0d354b4542af105d8a2a3f779447afc3935f43b Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 1 Feb 2023 15:28:47 +0100 Subject: [PATCH 039/423] docs: fix permissions tutorial setup script Signed-off-by: Vincenzo Scamporlino --- docs/permissions/plugin-authors/01-setup.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/permissions/plugin-authors/01-setup.md b/docs/permissions/plugin-authors/01-setup.md index 18de410612..04e31b859e 100644 --- a/docs/permissions/plugin-authors/01-setup.md +++ b/docs/permissions/plugin-authors/01-setup.md @@ -26,6 +26,9 @@ The source code is available here: git checkout master -- plugins/example-todo-list/ git checkout master -- plugins/example-todo-list-backend/ git checkout master -- plugins/example-todo-list-common/ + sed -i '' 's/workspace:\^/\*/g' plugins/example-todo-list/package.json + sed -i '' 's/workspace:\^/\*/g' plugins/example-todo-list-backend/package.json + sed -i '' 's/workspace:\^/\*/g' plugins/example-todo-list-common/package.json for file in plugins/*; do mv "$file" "$OLDPWD/${file/example-todo/todo}"; done cd - ``` @@ -37,8 +40,8 @@ The source code is available here: 2. Add these packages as dependencies for your Backstage app: ``` - $ yarn workspace backend add @internal/plugin-todo-list-backend@^1.0.0 @internal/plugin-todo-list-common@^1.0.0 - $ yarn workspace app add @internal/plugin-todo-list@^1.0.0 + $ yarn workspace backend add @internal/plugin-todo-list-backend @internal/plugin-todo-list-common + $ yarn workspace app add @internal/plugin-todo-list ``` 3. Include the backend and frontend plugin in your application: From 4c6950b5d8c222b274f8b31908aa2f804d07939a Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Fri, 20 Jan 2023 10:36:00 +0100 Subject: [PATCH 040/423] add aria labels to mobile navbar actions Signed-off-by: Emma Indal --- packages/core-components/src/layout/Sidebar/SidebarGroup.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx b/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx index 5254199563..15d22599b5 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx @@ -100,6 +100,7 @@ const MobileSidebarGroup = (props: SidebarGroupProps) => { return ( // Material UI issue: https://github.com/mui-org/material-ui/issues/27820 Date: Fri, 20 Jan 2023 10:40:59 +0100 Subject: [PATCH 041/423] user primary color from palette to improve color contrast of tabs in Search modal Signed-off-by: Emma Indal --- plugins/search/src/components/SearchType/SearchType.Tabs.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/search/src/components/SearchType/SearchType.Tabs.tsx b/plugins/search/src/components/SearchType/SearchType.Tabs.tsx index fc0380e23a..b686e2e1f1 100644 --- a/plugins/search/src/components/SearchType/SearchType.Tabs.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Tabs.tsx @@ -28,7 +28,7 @@ const useStyles = makeStyles((theme: BackstageTheme) => ({ height: '50px', fontWeight: theme.typography.fontWeightBold, fontSize: theme.typography.pxToRem(13), - color: theme.palette.textSubtle, + color: theme.palette.text.primary, minWidth: '130px', }, })); From a0619a5b492ff9f9050f334391a024b37bac1371 Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Fri, 20 Jan 2023 16:23:23 +0100 Subject: [PATCH 042/423] make sure result list is structured with list elements only Signed-off-by: Emma Indal --- .../app/src/components/search/SearchModal.tsx | 14 +-- .../CatalogSearchResultListItem.tsx | 75 +++++++-------- .../ToolSearchResultListItem.tsx | 71 +++++++------- .../DefaultResultListItem.tsx | 94 +++++++++---------- .../TechDocsSearchResultListItem.tsx | 12 +-- 5 files changed, 119 insertions(+), 147 deletions(-) diff --git a/packages/app/src/components/search/SearchModal.tsx b/packages/app/src/components/search/SearchModal.tsx index 4694d56390..e994262e66 100644 --- a/packages/app/src/components/search/SearchModal.tsx +++ b/packages/app/src/components/search/SearchModal.tsx @@ -23,17 +23,11 @@ import { Grid, makeStyles, Paper, - useTheme, } from '@material-ui/core'; import Typography from '@material-ui/core/Typography'; import BuildIcon from '@material-ui/icons/Build'; import LaunchIcon from '@material-ui/icons/Launch'; -import { - CatalogIcon, - DocsIcon, - Link, - useContent, -} from '@backstage/core-components'; +import { CatalogIcon, DocsIcon, Link } from '@backstage/core-components'; import { useApi, useRouteRef } from '@backstage/core-plugin-api'; import { CatalogSearchResultListItem } from '@internal/plugin-catalog-customized'; import { @@ -78,9 +72,6 @@ const rootRouteRef = searchPlugin.routes.root; export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => { const classes = useStyles(); const navigate = useNavigate(); - const { transitions } = useTheme(); - const { focusContent } = useContent(); - const catalogApi = useApi(catalogApiRef); const { term, types } = useSearch(); @@ -91,11 +82,14 @@ export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => { searchBarRef?.current?.focus(); }); +<<<<<<< HEAD const handleSearchResultClick = useCallback(() => { toggleModal(); setTimeout(focusContent, transitions.duration.leavingScreen); }, [toggleModal, focusContent, transitions]); +======= +>>>>>>> c224202137 (make sure result list is structured with list elements only) const handleSearchBarKeyDown = useCallback( (e: KeyboardEvent) => { if (e.key === 'Enter') { diff --git a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx index cf60138d99..2a4ec300cd 100644 --- a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx +++ b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx @@ -18,7 +18,6 @@ import React, { ReactNode } from 'react'; import { Box, Chip, - Divider, ListItem, ListItemIcon, ListItemText, @@ -52,6 +51,7 @@ export interface CatalogSearchResultListItemProps { result?: IndexableDocument; highlight?: ResultHighlight; rank?: number; + toggleModal?: () => void; } /** @public */ @@ -66,49 +66,44 @@ export function CatalogSearchResultListItem( if (!result) return null; return ( - <> - - {props.icon && {props.icon}} -
- - {highlight?.fields.title ? ( - - ) : ( - result.title - )} - - } - secondary={ - highlight?.fields.text ? ( + + {props.icon && {props.icon}} +
+ + {highlight?.fields.title ? ( ) : ( - result.text - ) - } - /> - - {result.kind && ( - - )} - {result.lifecycle && ( - - )} - -
-
- - + result.title + )} + + } + secondary={ + highlight?.fields.text ? ( + + ) : ( + result.title + ) + } + /> + + {result.kind && } + {result.lifecycle && ( + + )} + +
+
); } diff --git a/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx b/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx index c9e8946f26..fa57b93822 100644 --- a/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx +++ b/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx @@ -18,7 +18,6 @@ import React, { ReactNode } from 'react'; import { Box, Chip, - Divider, ListItem, ListItemIcon, ListItemText, @@ -52,6 +51,7 @@ export interface ToolSearchResultListItemProps { result?: IndexableDocument; highlight?: ResultHighlight; rank?: number; + toggleModal?: () => void; } /** @public */ @@ -63,47 +63,42 @@ export function ToolSearchResultListItem(props: ToolSearchResultListItemProps) { if (!result) return null; return ( - <> - - {props.icon && {props.icon}} -
- - {props.highlight?.fields.title ? ( - - ) : ( - result.title - )} - - } - secondary={ - props.highlight?.fields.text ? ( + + {props.icon && {props.icon}} +
+ + {props.highlight?.fields.title ? ( ) : ( - result.text - ) - } - /> - - {result.tags && - result.tags.map((tag: string) => ( - - ))} - -
-
- - + result.title + )} + + } + secondary={ + props.highlight?.fields.text ? ( + + ) : ( + result.text + ) + } + /> + + {result.tags && + result.tags.map((tag: string) => )} + +
+
); } diff --git a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx index 6ea5e4d1a2..bb43db352c 100644 --- a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx +++ b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx @@ -21,13 +21,7 @@ import { SearchDocument, } from '@backstage/plugin-search-common'; import { HighlightedSearchResultText } from '../HighlightedSearchResultText'; -import { - ListItem, - ListItemIcon, - ListItemText, - Box, - Divider, -} from '@material-ui/core'; +import { ListItem, ListItemIcon, ListItemText, Box } from '@material-ui/core'; import Typography from '@material-ui/core/Typography'; import { Link } from '@backstage/core-components'; @@ -43,6 +37,7 @@ export type DefaultResultListItemProps = { highlight?: ResultHighlight; rank?: number; lineClamp?: number; + toggleModal?: () => void; }; /** @@ -60,50 +55,47 @@ export const DefaultResultListItemComponent = ({ if (!result) return null; return ( - <> - - {icon && {icon}} - - {highlight?.fields.title ? ( - - ) : ( - result.title - )} - - } - secondary={ - - {highlight?.fields.text ? ( - - ) : ( - result.text - )} - - } - /> - {secondaryAction && {secondaryAction}} - - - + + {icon && {icon}} + + {highlight?.fields.title ? ( + + ) : ( + result.title + )} + + } + secondary={ + + {highlight?.fields.text ? ( + + ) : ( + result.text + )} + + } + /> + {secondaryAction && {secondaryAction}} + ); }; diff --git a/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx b/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx index f058fd0a9e..50a4695b96 100644 --- a/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx +++ b/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx @@ -16,7 +16,6 @@ import React, { PropsWithChildren, ReactNode } from 'react'; import { - Divider, ListItem, ListItemIcon, ListItemText, @@ -156,13 +155,10 @@ export const TechDocsSearchResultListItem = ( const ListItemWrapper = ({ children }: PropsWithChildren<{}>) => asListItem ? ( - <> - - {icon && {icon}} -
{children}
-
- - + + {icon && {icon}} +
{children}
+
) : ( <>{children} ); From 77c85b4467efeeb7a456d8a555bae33f403c72e4 Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Fri, 20 Jan 2023 16:23:51 +0100 Subject: [PATCH 043/423] add aria label to tabs, remove disableRipple prop to indicate focus on tab when navigating through keyboard Signed-off-by: Emma Indal --- plugins/search/src/components/SearchType/SearchType.Tabs.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/search/src/components/SearchType/SearchType.Tabs.tsx b/plugins/search/src/components/SearchType/SearchType.Tabs.tsx index b686e2e1f1..9c741004e6 100644 --- a/plugins/search/src/components/SearchType/SearchType.Tabs.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Tabs.tsx @@ -72,6 +72,7 @@ export const SearchTypeTabs = (props: SearchTypeTabsProps) => { return ( { From 8ce32c1ab8210855bec409ebfb88a2182693c0ec Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Fri, 20 Jan 2023 16:24:01 +0100 Subject: [PATCH 044/423] remove tabs padding Signed-off-by: Emma Indal --- plugins/search/src/components/SearchType/SearchType.Tabs.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/search/src/components/SearchType/SearchType.Tabs.tsx b/plugins/search/src/components/SearchType/SearchType.Tabs.tsx index 9c741004e6..57a311b00c 100644 --- a/plugins/search/src/components/SearchType/SearchType.Tabs.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Tabs.tsx @@ -22,7 +22,6 @@ import { makeStyles, Tab, Tabs } from '@material-ui/core'; const useStyles = makeStyles((theme: BackstageTheme) => ({ tabs: { borderBottom: `1px solid ${theme.palette.textVerySubtle}`, - padding: theme.spacing(0, 4), }, tab: { height: '50px', From 66e2aab4c44fc36f7144501b5aa2b7fab62e5beb Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Mon, 23 Jan 2023 10:21:13 +0100 Subject: [PATCH 045/423] add changesets Signed-off-by: Emma Indal --- .changeset/serious-pigs-watch.md | 8 ++++++++ .changeset/tall-falcons-teach.md | 5 +++++ .changeset/violet-tips-rhyme.md | 5 +++++ 3 files changed, 18 insertions(+) create mode 100644 .changeset/serious-pigs-watch.md create mode 100644 .changeset/tall-falcons-teach.md create mode 100644 .changeset/violet-tips-rhyme.md diff --git a/.changeset/serious-pigs-watch.md b/.changeset/serious-pigs-watch.md new file mode 100644 index 0000000000..3deb3724b4 --- /dev/null +++ b/.changeset/serious-pigs-watch.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-techdocs': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-explore': patch +'@backstage/plugin-search-react': patch +--- + +`*SearchResultListItems` now accept optional ´toggleModal´ prop that is used to toggle the search modal on result click. diff --git a/.changeset/tall-falcons-teach.md b/.changeset/tall-falcons-teach.md new file mode 100644 index 0000000000..d6608a6597 --- /dev/null +++ b/.changeset/tall-falcons-teach.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Navigation items in mobile sidebar now have aria label. diff --git a/.changeset/violet-tips-rhyme.md b/.changeset/violet-tips-rhyme.md new file mode 100644 index 0000000000..c2d95cfbf9 --- /dev/null +++ b/.changeset/violet-tips-rhyme.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Updated colors for each tab used on search modal, to improve color contrast. Aria label added to tabs wrapper component. `disableRipple` property on the `Tab` component removed to improve keyboard navigation indicator. From f7e698636a208f8a19909616561c395dcec044df Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Tue, 31 Jan 2023 15:43:57 +0100 Subject: [PATCH 046/423] updates based on result list items extension changes Signed-off-by: Emma Indal --- .../app/src/components/search/SearchModal.tsx | 19 +--- .../CatalogSearchResultListItem.tsx | 10 +-- .../ToolSearchResultListItem.tsx | 5 +- .../DefaultResultListItem.test.tsx | 7 +- .../DefaultResultListItem.tsx | 8 +- .../SearchResult/SearchResult.test.tsx | 5 +- .../SearchResultGroup.test.tsx | 5 +- .../SearchResultList.test.tsx | 3 +- plugins/search-react/src/extensions.test.tsx | 16 ++-- plugins/search-react/src/extensions.tsx | 10 ++- .../StackOverflowSearchResultListItem.tsx | 86 ++++++++----------- .../TechDocsSearchResultListItem.tsx | 11 +-- 12 files changed, 77 insertions(+), 108 deletions(-) diff --git a/packages/app/src/components/search/SearchModal.tsx b/packages/app/src/components/search/SearchModal.tsx index e994262e66..ea5a156c55 100644 --- a/packages/app/src/components/search/SearchModal.tsx +++ b/packages/app/src/components/search/SearchModal.tsx @@ -82,22 +82,14 @@ export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => { searchBarRef?.current?.focus(); }); -<<<<<<< HEAD - const handleSearchResultClick = useCallback(() => { - toggleModal(); - setTimeout(focusContent, transitions.duration.leavingScreen); - }, [toggleModal, focusContent, transitions]); - -======= ->>>>>>> c224202137 (make sure result list is structured with list elements only) const handleSearchBarKeyDown = useCallback( (e: KeyboardEvent) => { if (e.key === 'Enter') { - handleSearchResultClick(); + toggleModal(); navigate(searchPagePath); } }, - [navigate, searchPagePath, handleSearchResultClick], + [navigate, searchPagePath, toggleModal], ); return ( @@ -181,7 +173,7 @@ export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => { alignItems="center" > - + void }) => { - + } /> } /> } /> diff --git a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx index 2a4ec300cd..541d7c7d3a 100644 --- a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx +++ b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx @@ -18,7 +18,6 @@ import React, { ReactNode } from 'react'; import { Box, Chip, - ListItem, ListItemIcon, ListItemText, makeStyles, @@ -51,7 +50,6 @@ export interface CatalogSearchResultListItemProps { result?: IndexableDocument; highlight?: ResultHighlight; rank?: number; - toggleModal?: () => void; } /** @public */ @@ -66,7 +64,7 @@ export function CatalogSearchResultListItem( if (!result) return null; return ( - + <> {props.icon && {props.icon}}
) : ( - result.title + result.text ) } /> @@ -104,6 +102,6 @@ export function CatalogSearchResultListItem( )}
-
+ ); } diff --git a/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx b/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx index fa57b93822..f3573007fc 100644 --- a/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx +++ b/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx @@ -18,7 +18,6 @@ import React, { ReactNode } from 'react'; import { Box, Chip, - ListItem, ListItemIcon, ListItemText, makeStyles, @@ -63,7 +62,7 @@ export function ToolSearchResultListItem(props: ToolSearchResultListItemProps) { if (!result) return null; return ( - + <> {props.icon && {props.icon}}
)}
-
+ ); } diff --git a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.test.tsx b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.test.tsx index e94d394639..aab105df48 100644 --- a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.test.tsx +++ b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.test.tsx @@ -35,9 +35,10 @@ describe('DefaultResultListItem', () => { it('Includes primary/secondary text (title / text)', async () => { await renderInTestApp(); - expect(screen.getByRole('listitem')).toHaveTextContent( - result.title + result.text, - ); + expect( + screen.getByRole('link', { name: result.title }), + ).toBeInTheDocument(); + expect(screen.getByText(result.text)).toBeInTheDocument(); }); it('should render icon if prop is specified', async () => { diff --git a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx index bb43db352c..eef7f799a6 100644 --- a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx +++ b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx @@ -21,12 +21,12 @@ import { SearchDocument, } from '@backstage/plugin-search-common'; import { HighlightedSearchResultText } from '../HighlightedSearchResultText'; -import { ListItem, ListItemIcon, ListItemText, Box } from '@material-ui/core'; +import { ListItemIcon, ListItemText, Box } from '@material-ui/core'; import Typography from '@material-ui/core/Typography'; import { Link } from '@backstage/core-components'; /** - * Props for {@link DefaultResultListItem} + * Props for {@link DefaultResultListItemComponent} * * @public */ @@ -55,7 +55,7 @@ export const DefaultResultListItemComponent = ({ if (!result) return null; return ( - + <> {icon && {icon}} {secondaryAction && {secondaryAction}} - + ); }; diff --git a/plugins/search-react/src/components/SearchResult/SearchResult.test.tsx b/plugins/search-react/src/components/SearchResult/SearchResult.test.tsx index 6a5a683295..4b8caa2780 100644 --- a/plugins/search-react/src/components/SearchResult/SearchResult.test.tsx +++ b/plugins/search-react/src/components/SearchResult/SearchResult.test.tsx @@ -16,8 +16,6 @@ import React from 'react'; import { waitFor } from '@testing-library/react'; - -import { ListItem } from '@material-ui/core'; import { wrapInTestApp, renderInTestApp, @@ -217,8 +215,7 @@ describe('SearchResult', () => { }).provide( createSearchResultListItemExtension({ name: 'SearchResultExtension', - component: async () => props => - Result: {props.result?.title}, + component: async () => props => <>Result: {props.result?.title}, }), ); diff --git a/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx b/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx index 728bd9113a..8a9e8986b8 100644 --- a/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx +++ b/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { ListItem, MenuItem } from '@material-ui/core'; +import { MenuItem } from '@material-ui/core'; import DocsIcon from '@material-ui/icons/InsertDriveFile'; import { @@ -143,8 +143,7 @@ describe('SearchResultGroup', () => { }).provide( createSearchResultListItemExtension({ name: 'SearchResultGroupItemExtension', - component: async () => props => - Result: {props.result?.title}, + component: async () => props => <>Result: {props.result?.title}, }), ); diff --git a/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx b/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx index 7e8aa7bb33..941493aea1 100644 --- a/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx +++ b/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx @@ -226,8 +226,7 @@ describe('SearchResultList', () => { }).provide( createSearchResultListItemExtension({ name: 'SearchResultListItemExtension', - component: async () => props => - Result: {props.result?.title}, + component: async () => props => <>Result: {props.result?.title}, }), ); diff --git a/plugins/search-react/src/extensions.test.tsx b/plugins/search-react/src/extensions.test.tsx index 24c115e572..7e5070c738 100644 --- a/plugins/search-react/src/extensions.test.tsx +++ b/plugins/search-react/src/extensions.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { ListItem, ListItemText } from '@material-ui/core'; +import { ListItemText } from '@material-ui/core'; import { wrapInTestApp, @@ -75,9 +75,9 @@ const createExtension = ( predicate, component = async () => (props: { result?: SearchDocument }) => ( - + <> - + ), } = options; return plugin.provide( @@ -120,7 +120,7 @@ describe('extensions', () => { ); await userEvent.click( - screen.getByRole('button', { name: /Search Result 1/ }), + screen.getByRole('link', { name: /Search Result 1/ }), ); expect(analyticsApiMock.getEvents()[0]).toMatchObject({ @@ -146,9 +146,7 @@ describe('extensions', () => { expect(screen.getByText('Default')).toBeInTheDocument(); expect(screen.getByText('Search Result 1')).toBeInTheDocument(); - await userEvent.click( - screen.getByRole('button', { name: /Search Result 1/ }), - ); + await userEvent.click(screen.getByRole('listitem')); expect(analyticsApiMock.getEvents()[0]).toMatchObject({ action: 'discover', @@ -184,9 +182,9 @@ describe('extensions', () => { predicate: (result: SearchResult) => result.type === 'explore', component: async () => (props: { result?: SearchDocument }) => ( - + <> - + ), }); diff --git a/plugins/search-react/src/extensions.tsx b/plugins/search-react/src/extensions.tsx index 1e0619b14c..30611b0879 100644 --- a/plugins/search-react/src/extensions.tsx +++ b/plugins/search-react/src/extensions.tsx @@ -33,7 +33,7 @@ import { } from '@backstage/core-plugin-api'; import { SearchDocument, SearchResult } from '@backstage/plugin-search-common'; -import { Box, List, ListProps } from '@material-ui/core'; +import { ListItem, List, ListProps } from '@material-ui/core'; import { DefaultResultListItem } from './components'; @@ -105,9 +105,13 @@ const SearchResultListItemExtension = ({ }, [rank, result, noTrack, analytics]); return ( - + {children} - + ); }; diff --git a/plugins/stack-overflow/src/search/StackOverflowSearchResultListItem/StackOverflowSearchResultListItem.tsx b/plugins/stack-overflow/src/search/StackOverflowSearchResultListItem/StackOverflowSearchResultListItem.tsx index 9971b0e7e5..932995b895 100644 --- a/plugins/stack-overflow/src/search/StackOverflowSearchResultListItem/StackOverflowSearchResultListItem.tsx +++ b/plugins/stack-overflow/src/search/StackOverflowSearchResultListItem/StackOverflowSearchResultListItem.tsx @@ -17,14 +17,7 @@ import React from 'react'; import _unescape from 'lodash/unescape'; import { Link } from '@backstage/core-components'; -import { - Divider, - ListItem, - ListItemText, - ListItemIcon, - Box, - Chip, -} from '@material-ui/core'; +import { ListItemText, ListItemIcon, Box, Chip } from '@material-ui/core'; import { useAnalytics } from '@backstage/core-plugin-api'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { HighlightedSearchResultText } from '@backstage/plugin-search-react'; @@ -52,47 +45,44 @@ export const StackOverflowSearchResultListItem = ( return ( <> - - {props.icon && {props.icon}} - - - {highlight?.fields?.title ? ( - - ) : ( - _unescape(title) - )} - - } - secondary={ - highlight?.fields?.text ? ( - <> - Author:{' '} - - + {props.icon && {props.icon}} + + + {highlight?.fields?.title ? ( + ) : ( - `Author: ${text}` - ) - } - /> - - {tags && - tags.map((tag: string) => ( - - ))} - - - + _unescape(title) + )} + + } + secondary={ + highlight?.fields?.text ? ( + <> + Author:{' '} + + + ) : ( + `Author: ${text}` + ) + } + /> + + {tags && + tags.map((tag: string) => ( + + ))} + ); }; diff --git a/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx b/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx index 50a4695b96..9bf8b76092 100644 --- a/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx +++ b/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx @@ -15,12 +15,7 @@ */ import React, { PropsWithChildren, ReactNode } from 'react'; -import { - ListItem, - ListItemIcon, - ListItemText, - makeStyles, -} from '@material-ui/core'; +import { ListItemIcon, ListItemText, makeStyles } from '@material-ui/core'; import Typography from '@material-ui/core/Typography'; import { Link } from '@backstage/core-components'; import { ResultHighlight } from '@backstage/plugin-search-common'; @@ -155,10 +150,10 @@ export const TechDocsSearchResultListItem = ( const ListItemWrapper = ({ children }: PropsWithChildren<{}>) => asListItem ? ( - + <> {icon && {icon}}
{children}
-
+ ) : ( <>{children} ); From 37e9ba8a7da8a7afe33c06ad7b22554a17253d65 Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Tue, 31 Jan 2023 15:44:28 +0100 Subject: [PATCH 047/423] adjust changeset for list items Signed-off-by: Emma Indal --- .changeset/serious-pigs-watch.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.changeset/serious-pigs-watch.md b/.changeset/serious-pigs-watch.md index 3deb3724b4..6736c64557 100644 --- a/.changeset/serious-pigs-watch.md +++ b/.changeset/serious-pigs-watch.md @@ -5,4 +5,6 @@ '@backstage/plugin-search-react': patch --- -`*SearchResultListItems` now accept optional ´toggleModal´ prop that is used to toggle the search modal on result click. +`ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems`. This is to make sure the list only contains list elements. + +Note: If you have implemented a custom result list item, you can remove the list item wrapper to avoid duplicated `
  • ` elements. From c3798fd6bdfcc89ebdac5d61a61db0f0efdfc7ae Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Wed, 1 Feb 2023 09:17:32 +0100 Subject: [PATCH 048/423] update api reports Signed-off-by: Emma Indal --- plugins/explore/api-report.md | 2 ++ plugins/search-react/api-report.md | 1 + .../components/DefaultResultListItem/DefaultResultListItem.tsx | 2 +- .../src/components/SearchResultList/SearchResultList.test.tsx | 1 - 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/explore/api-report.md b/plugins/explore/api-report.md index e7adde4b77..02b917b9ed 100644 --- a/plugins/explore/api-report.md +++ b/plugins/explore/api-report.md @@ -139,5 +139,7 @@ export interface ToolSearchResultListItemProps { rank?: number; // (undocumented) result?: IndexableDocument; + // (undocumented) + toggleModal?: () => void; } ``` diff --git a/plugins/search-react/api-report.md b/plugins/search-react/api-report.md index ccf7a72e33..0d6598feca 100644 --- a/plugins/search-react/api-report.md +++ b/plugins/search-react/api-report.md @@ -55,6 +55,7 @@ export type DefaultResultListItemProps = { highlight?: ResultHighlight; rank?: number; lineClamp?: number; + toggleModal?: () => void; }; // @public (undocumented) diff --git a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx index eef7f799a6..cf89b6a9cd 100644 --- a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx +++ b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx @@ -26,7 +26,7 @@ import Typography from '@material-ui/core/Typography'; import { Link } from '@backstage/core-components'; /** - * Props for {@link DefaultResultListItemComponent} + * Props for {@link DefaultResultListItem} * * @public */ diff --git a/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx b/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx index 941493aea1..a0f5bc7830 100644 --- a/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx +++ b/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx @@ -17,7 +17,6 @@ import React from 'react'; import { screen, waitFor } from '@testing-library/react'; -import { ListItem } from '@material-ui/core'; import { TestApiProvider, renderWithEffects, From b031b821d509d5df7ecdac824191c4800fda6ab8 Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Wed, 1 Feb 2023 12:58:54 +0100 Subject: [PATCH 049/423] Apply suggestions from code review Co-authored-by: Camila Belo Signed-off-by: Emma Indal --- .changeset/serious-pigs-watch.md | 4 +- plugins/explore/api-report.md | 2 - .../ToolSearchResultListItem.tsx | 6 +- .../StackOverflowSearchResultListItem.tsx | 86 +++++++++++-------- 4 files changed, 53 insertions(+), 45 deletions(-) diff --git a/.changeset/serious-pigs-watch.md b/.changeset/serious-pigs-watch.md index 6736c64557..2efd8697f3 100644 --- a/.changeset/serious-pigs-watch.md +++ b/.changeset/serious-pigs-watch.md @@ -5,6 +5,6 @@ '@backstage/plugin-search-react': patch --- -`ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems`. This is to make sure the list only contains list elements. +`ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. -Note: If you have implemented a custom result list item, you can remove the list item wrapper to avoid duplicated `
  • ` elements. +Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. diff --git a/plugins/explore/api-report.md b/plugins/explore/api-report.md index 02b917b9ed..e7adde4b77 100644 --- a/plugins/explore/api-report.md +++ b/plugins/explore/api-report.md @@ -139,7 +139,5 @@ export interface ToolSearchResultListItemProps { rank?: number; // (undocumented) result?: IndexableDocument; - // (undocumented) - toggleModal?: () => void; } ``` diff --git a/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx b/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx index f3573007fc..eb12ba45d8 100644 --- a/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx +++ b/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx @@ -50,7 +50,6 @@ export interface ToolSearchResultListItemProps { result?: IndexableDocument; highlight?: ResultHighlight; rank?: number; - toggleModal?: () => void; } /** @public */ @@ -94,8 +93,9 @@ export function ToolSearchResultListItem(props: ToolSearchResultListItemProps) { } /> - {result.tags && - result.tags.map((tag: string) => )} + {result.tags?.map((tag: string) => ( + + ))} diff --git a/plugins/stack-overflow/src/search/StackOverflowSearchResultListItem/StackOverflowSearchResultListItem.tsx b/plugins/stack-overflow/src/search/StackOverflowSearchResultListItem/StackOverflowSearchResultListItem.tsx index 932995b895..9971b0e7e5 100644 --- a/plugins/stack-overflow/src/search/StackOverflowSearchResultListItem/StackOverflowSearchResultListItem.tsx +++ b/plugins/stack-overflow/src/search/StackOverflowSearchResultListItem/StackOverflowSearchResultListItem.tsx @@ -17,7 +17,14 @@ import React from 'react'; import _unescape from 'lodash/unescape'; import { Link } from '@backstage/core-components'; -import { ListItemText, ListItemIcon, Box, Chip } from '@material-ui/core'; +import { + Divider, + ListItem, + ListItemText, + ListItemIcon, + Box, + Chip, +} from '@material-ui/core'; import { useAnalytics } from '@backstage/core-plugin-api'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { HighlightedSearchResultText } from '@backstage/plugin-search-react'; @@ -45,44 +52,47 @@ export const StackOverflowSearchResultListItem = ( return ( <> - {props.icon && {props.icon}} - - - {highlight?.fields?.title ? ( - + + {props.icon && {props.icon}} + + + {highlight?.fields?.title ? ( + + ) : ( + _unescape(title) + )} + + } + secondary={ + highlight?.fields?.text ? ( + <> + Author:{' '} + + ) : ( - _unescape(title) - )} - - } - secondary={ - highlight?.fields?.text ? ( - <> - Author:{' '} - - - ) : ( - `Author: ${text}` - ) - } - /> - - {tags && - tags.map((tag: string) => ( - - ))} - + `Author: ${text}` + ) + } + /> + + {tags && + tags.map((tag: string) => ( + + ))} + + + ); }; From 6f097023fc9c5a1258f0697ea26435d468cb3a59 Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Wed, 1 Feb 2023 15:05:48 +0000 Subject: [PATCH 050/423] keep event stream alive even if its taking a while Signed-off-by: Brian Fletcher --- .changeset/hungry-stingrays-type.md | 5 +++++ plugins/techdocs-backend/src/service/DocsSynchronizer.ts | 6 ++++++ 2 files changed, 11 insertions(+) create mode 100644 .changeset/hungry-stingrays-type.md diff --git a/.changeset/hungry-stingrays-type.md b/.changeset/hungry-stingrays-type.md new file mode 100644 index 0000000000..8cb11f67a5 --- /dev/null +++ b/.changeset/hungry-stingrays-type.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-backend': patch +--- + +Keep the tech docs sync event stream alive even if it is taking a while to build. diff --git a/plugins/techdocs-backend/src/service/DocsSynchronizer.ts b/plugins/techdocs-backend/src/service/DocsSynchronizer.ts index 647447a612..3d89d1647f 100644 --- a/plugins/techdocs-backend/src/service/DocsSynchronizer.ts +++ b/plugins/techdocs-backend/src/service/DocsSynchronizer.ts @@ -128,7 +128,13 @@ export class DocsSynchronizer { cache: this.cache, }); + const interval = setInterval(() => { + taskLogger.info( + 'The docs building process is taking a little bit longer to process this entity. Please bear with us.', + ); + }, 10000); const updated = await this.buildLimiter(() => docsBuilder.build()); + clearInterval(interval); if (!updated) { finish({ updated: false }); From 314c463c4e44583c1657b8bcc706db25a2cd4876 Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Wed, 1 Feb 2023 17:20:32 +0000 Subject: [PATCH 051/423] fix image paths in scaling incremental ingestion post Signed-off-by: Paul Cowan --- microsite/blog/2023-01-31-incremental-entity-provider.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/microsite/blog/2023-01-31-incremental-entity-provider.md b/microsite/blog/2023-01-31-incremental-entity-provider.md index 64ac69c7a0..ff5f346ccd 100644 --- a/microsite/blog/2023-01-31-incremental-entity-provider.md +++ b/microsite/blog/2023-01-31-incremental-entity-provider.md @@ -8,7 +8,7 @@ authorURL: https://frontside.com/ At the heart of [Backstage](https://backstage.io/) is the [Backstage Software Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview), which is a data store that allows an organization to centralize and visualize its many software services and components. Backstage inspects and transforms an organization's disparate software services and parts into a centralized data store. -![catalog pipeline](./assets/2023-01-31/catalog-pipeline.png) +![catalog pipeline](assets/2023-01-31/catalog-pipeline.png) A common use case is for an organization to want to surface ownership and metadata about repositories. Backstage provides a mechanism for discovering and transforming repository information into a standard data structure and persisting it into the Backstage [Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview). This process is known as ingestion, where all data is transformed into a standard Backstage data structure known as an entity. Entities in the Catalog’s data store are accessible to the Backstage App via the REST API. @@ -28,9 +28,9 @@ A large organization typically deals with massive datasets. Until recently, inge This is a problem that [DevEx team at HP](http://hp.com) faced when building their software catalog with Backstage. [Damon Kaswell](https://github.com/dekoding), Senior Application Developer on the DevEx team at HP, shared their experience at [BackstageCon 2022](https://www.youtube.com/watch?v=5qHyZntKXRU&list=PLj6h78yzYM2OKySsTuiip3BqmdYZQRnSf&index=13), detailing the problem and the solution that [Frontside](https://frontside.com/) created in collaboration with developers on HP’s DevEx team. -![Damon Kaswell](./assets/2023-01-31/damon.jpg) +![Damon Kaswell](assets/2023-01-31/damon.jpg) -The solution HP and [Frontside](https://frontside.com/) arrived at was to implement an incremental entity provider. An incremental entity provider effectively performs a full mutation using a series of delta mutations combined with a mark and sweep mechanism. It paginates through the dataset, tracking entities retrieved from each page and the cursor of the next page, pausing ingestion every few minutes to give the processing loop time to process existing entities. Once it reaches the end of the dataset, it determines which entities were not ingested during this ingestion cycle and emits a delta mutation to delete unmarked entities. +The solution HP and [Frontside](https://frontside.com/) arrived at was to implement an incremental entity provider. An incremental entity provider effectively performs a full mutation using a series of delta mutations combined with a mark and sweep mechanism. It paginates through the dataset, tracking entities retrieved from each page and the cursor of the next page, pausing ingestion every few seconds to give the processing loop time to process existing entities. Once it reaches the end of the dataset, it determines which entities were not ingested during this ingestion cycle and emits a delta mutation to delete unmarked entities. Simply by adding a few new tables to the database schema, the incremental ingestion entity provider converts any existing entity provider into an incremental entity provider. These tables allow the incremental entity provider to be long-lived and keep track of its current location in the dataset by persisting a cursor that it uses to page through any large dataset. The larger the dataset, the more pages of data or bursts of work the incremental entity provider will ingest—but there will be no out-of-memory errors, effectively removing scalability problems. From 26fb21aa8befd417e2b12b1e37380faa7a37bfff Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Wed, 1 Feb 2023 13:05:01 -0500 Subject: [PATCH 052/423] feat(SearchType.Accordion): implement displaying result counts Signed-off-by: Phil Kuang --- .changeset/three-geckos-press.md | 5 ++ .../app/src/components/search/SearchPage.tsx | 1 + plugins/search/api-report.md | 1 + .../SearchType/SearchType.Accordion.test.tsx | 36 ++++++++++++++- .../SearchType/SearchType.Accordion.tsx | 46 +++++++++++++++++-- 5 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 .changeset/three-geckos-press.md diff --git a/.changeset/three-geckos-press.md b/.changeset/three-geckos-press.md new file mode 100644 index 0000000000..fc1af4fdc0 --- /dev/null +++ b/.changeset/three-geckos-press.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Implement a `showCounts` option to display result counts per type in `SearchType.Accordion` diff --git a/packages/app/src/components/search/SearchPage.tsx b/packages/app/src/components/search/SearchPage.tsx index 8167889b02..6c4f06aed9 100644 --- a/packages/app/src/components/search/SearchPage.tsx +++ b/packages/app/src/components/search/SearchPage.tsx @@ -79,6 +79,7 @@ const SearchPage = () => { ; defaultValue?: string; + showCounts?: boolean; }; // @public diff --git a/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx b/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx index da1cae46b9..e0acee025a 100644 --- a/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { TestApiProvider } from '@backstage/test-utils'; -import { act, render } from '@testing-library/react'; +import { act, render, waitFor } from '@testing-library/react'; import user from '@testing-library/user-event'; import { searchApiRef, @@ -34,6 +34,8 @@ jest.mock('@backstage/plugin-search-react', () => ({ setTypes: (types: any) => setTypesMock(types), pageCursor: '', setPageCursor: (pageCursor: any) => setPageCursorMock(pageCursor), + term: 'abc', + filters: { foo: 'bar' }, }), })); @@ -48,7 +50,7 @@ describe('SearchType.Accordion', () => { }; beforeEach(() => { - query.mockResolvedValue({ results: [] }); + query.mockResolvedValue({ results: [], numberOfResults: 1234 }); }); const Wrapper = ({ children }: { children: React.ReactNode }) => { @@ -132,4 +134,34 @@ describe('SearchType.Accordion', () => { expect(queryByText('Collapse')).not.toBeInTheDocument(); }); + + it('should show result counts if enabled', async () => { + const { getAllByText } = render( + + + , + ); + + expect(query).toHaveBeenCalledWith({ + term: 'abc', + types: [], + filters: { foo: 'bar' }, + pageLimit: 0, + }); + expect(query).toHaveBeenCalledWith({ + term: 'abc', + types: [expectedType.value], + filters: {}, + pageLimit: 0, + }); + await waitFor(() => { + const countLabels = getAllByText('1234 results'); + expect(countLabels.length).toEqual(2); + expect(countLabels[0]).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/search/src/components/SearchType/SearchType.Accordion.tsx b/plugins/search/src/components/SearchType/SearchType.Accordion.tsx index 49f5cf74ca..67785b89cb 100644 --- a/plugins/search/src/components/SearchType/SearchType.Accordion.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Accordion.tsx @@ -15,7 +15,8 @@ */ import React, { cloneElement, Fragment, useEffect, useState } from 'react'; -import { useSearch } from '@backstage/plugin-search-react'; +import { useApi } from '@backstage/core-plugin-api'; +import { searchApiRef, useSearch } from '@backstage/plugin-search-react'; import { Accordion, AccordionSummary, @@ -32,6 +33,7 @@ import { } from '@material-ui/core'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import AllIcon from '@material-ui/icons/FontDownload'; +import useAsync from 'react-use/lib/useAsync'; const useStyles = makeStyles(theme => ({ card: { @@ -81,13 +83,15 @@ export type SearchTypeAccordionProps = { icon: JSX.Element; }>; defaultValue?: string; + showCounts?: boolean; }; export const SearchTypeAccordion = (props: SearchTypeAccordionProps) => { const classes = useStyles(); - const { setPageCursor, setTypes, types } = useSearch(); + const { filters, setPageCursor, setTypes, term, types } = useSearch(); + const searchApi = useApi(searchApiRef); const [expanded, setExpanded] = useState(true); - const { defaultValue, name, types: givenTypes } = props; + const { defaultValue, name, showCounts, types: givenTypes } = props; const toggleExpanded = () => setExpanded(prevState => !prevState); const handleClick = (type: string) => { @@ -116,6 +120,37 @@ export const SearchTypeAccordion = (props: SearchTypeAccordionProps) => { ]; const selected = types[0] || ''; + const { value: resultCounts } = useAsync(async () => { + if (!showCounts) { + return {}; + } + + const counts = await Promise.all( + definedTypes + .map(t => t.value) + .map(async type => { + const { numberOfResults } = await searchApi.query({ + term, + types: type ? [type] : [], + filters: + types.includes(type) || (!types.length && !type) ? filters : {}, + pageLimit: 0, + }); + + return [ + type, + numberOfResults !== undefined + ? `${ + numberOfResults >= 10000 ? `>10000` : numberOfResults + } results` + : ' -- ', + ]; + }), + ); + + return Object.fromEntries(counts); + }, [filters, showCounts, term, types]); + return ( @@ -161,7 +196,10 @@ export const SearchTypeAccordion = (props: SearchTypeAccordionProps) => { className: classes.listItemIcon, })} - + ))} From d2e1364c981dd94d9aaceee3af36d82aab12e5f2 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Wed, 1 Feb 2023 14:09:07 -0500 Subject: [PATCH 053/423] add target to fix all prettier issues Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- package.json | 1 + packages/catalog-model/examples/apis/hello-world-trpc-api.yaml | 2 +- plugins/api-docs/dev/trpc-example-api.yaml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 912dd53b8a..e08ca3adfd 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "create-plugin": "echo \"use 'yarn new' instead\"", "release": "node scripts/prepare-release.js && changeset version && yarn prettier --write '{packages,plugins}/*/{package.json,CHANGELOG.md}' '.changeset/*.json' && yarn install --no-immutable", "prettier:check": "prettier --check .", + "prettier:fix": "prettier --write .", "storybook": "yarn ./storybook run start", "snyk:test": "npx snyk test --yarn-workspaces --strict-out-of-sync=false", "snyk:test:package": "yarn snyk:test --include", diff --git a/packages/catalog-model/examples/apis/hello-world-trpc-api.yaml b/packages/catalog-model/examples/apis/hello-world-trpc-api.yaml index eff7efa8f1..f5807537b3 100644 --- a/packages/catalog-model/examples/apis/hello-world-trpc-api.yaml +++ b/packages/catalog-model/examples/apis/hello-world-trpc-api.yaml @@ -10,7 +10,7 @@ spec: definition: | import { z } from 'zod'; import { publicProcedure, router } from '../trpc'; - + export const apiRouter = router({ version: publicProcedure.query(() => { return { version: '0.42.0' }; diff --git a/plugins/api-docs/dev/trpc-example-api.yaml b/plugins/api-docs/dev/trpc-example-api.yaml index eff7efa8f1..f5807537b3 100644 --- a/plugins/api-docs/dev/trpc-example-api.yaml +++ b/plugins/api-docs/dev/trpc-example-api.yaml @@ -10,7 +10,7 @@ spec: definition: | import { z } from 'zod'; import { publicProcedure, router } from '../trpc'; - + export const apiRouter = router({ version: publicProcedure.query(() => { return { version: '0.42.0' }; From 60a466094c1478f797ab569479a1897c89d98581 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Wed, 1 Feb 2023 14:39:43 -0500 Subject: [PATCH 054/423] update api-report.md Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- plugins/api-docs/api-report.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/api-docs/api-report.md b/plugins/api-docs/api-report.md index 0872d97355..070e950202 100644 --- a/plugins/api-docs/api-report.md +++ b/plugins/api-docs/api-report.md @@ -173,4 +173,12 @@ export const ProvidedApisCard: (props: { export const ProvidingComponentsCard: (props: { variant?: InfoCardVariants; }) => JSX.Element; + +// @public (undocumented) +export const TrpcApiDefinitionWidget: React_2.FC; + +// @public (undocumented) +export type TrpcApiDefinitionWidgetProps = { + definition: string; +}; ``` From ec34b535c044ce97f60ce422ecfcd315a43be3d9 Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Wed, 1 Feb 2023 14:23:32 -0500 Subject: [PATCH 055/423] feat(AdrSearchResultListItem): support displaying icon & hook up extensions Signed-off-by: Phil Kuang --- .changeset/nine-ravens-kiss.md | 5 +++ .changeset/proud-glasses-live.md | 5 +++ plugins/adr/api-report.md | 13 +++++-- plugins/adr/package.json | 1 + plugins/adr/src/index.ts | 4 +-- plugins/adr/src/plugin.ts | 20 +++++++++++ .../src/search/AdrSearchResultListItem.tsx | 35 ++++++++++--------- plugins/adr/src/search/index.ts | 2 +- yarn.lock | 1 + 9 files changed, 63 insertions(+), 23 deletions(-) create mode 100644 .changeset/nine-ravens-kiss.md create mode 100644 .changeset/proud-glasses-live.md diff --git a/.changeset/nine-ravens-kiss.md b/.changeset/nine-ravens-kiss.md new file mode 100644 index 0000000000..a507db6b03 --- /dev/null +++ b/.changeset/nine-ravens-kiss.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-adr': minor +--- + +The `AdrSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. diff --git a/.changeset/proud-glasses-live.md b/.changeset/proud-glasses-live.md new file mode 100644 index 0000000000..ded7a53ce7 --- /dev/null +++ b/.changeset/proud-glasses-live.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-adr': patch +--- + +Support displaying an icon on `AdrSearchResultListItem` diff --git a/plugins/adr/api-report.md b/plugins/adr/api-report.md index d6480cd090..4ced4e9416 100644 --- a/plugins/adr/api-report.md +++ b/plugins/adr/api-report.md @@ -11,6 +11,7 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { isAdrAvailable } from '@backstage/plugin-adr-common'; +import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; @@ -82,12 +83,18 @@ export type AdrReadResult = { }; // @public -export function AdrSearchResultListItem(props: { +export const AdrSearchResultListItem: ( + props: AdrSearchResultListItemProps, +) => JSX.Element | null; + +// @public (undocumented) +export type AdrSearchResultListItemProps = { lineClamp?: number; highlight?: ResultHighlight; + icon?: ReactNode; rank?: number; - result: AdrDocument; -}): JSX.Element; + result?: AdrDocument; +}; // @public export const EntityAdrContent: (props: { diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 9d915b7af7..5f3d3ba12a 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -39,6 +39,7 @@ "remark-gfm": "^3.0.1" }, "peerDependencies": { + "@types/react": "^16.13.1 || ^17.0.0", "react": "^16.13.1 || ^17.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, diff --git a/plugins/adr/src/index.ts b/plugins/adr/src/index.ts index 2ec76b0fd6..f24b3ac531 100644 --- a/plugins/adr/src/index.ts +++ b/plugins/adr/src/index.ts @@ -30,5 +30,5 @@ export type { } from './api'; export { isAdrAvailable } from '@backstage/plugin-adr-common'; export * from './components/AdrReader'; -export { adrPlugin, EntityAdrContent } from './plugin'; -export * from './search'; +export { adrPlugin, AdrSearchResultListItem, EntityAdrContent } from './plugin'; +export type { AdrSearchResultListItemProps } from './search'; diff --git a/plugins/adr/src/plugin.ts b/plugins/adr/src/plugin.ts index f23df826cd..05e4adec4a 100644 --- a/plugins/adr/src/plugin.ts +++ b/plugins/adr/src/plugin.ts @@ -21,7 +21,9 @@ import { createRoutableExtension, discoveryApiRef, } from '@backstage/core-plugin-api'; +import { createSearchResultListItemExtension } from '@backstage/plugin-search-react'; import { rootRouteRef } from './routes'; +import { AdrSearchResultListItemProps } from './search'; /** * The Backstage plugin that holds ADR specific components @@ -57,3 +59,21 @@ export const EntityAdrContent = adrPlugin.provide( mountPoint: rootRouteRef, }), ); + +/** + * React extension used to render results on Search page or modal + * + * @public + */ +export const AdrSearchResultListItem: ( + props: AdrSearchResultListItemProps, +) => JSX.Element | null = adrPlugin.provide( + createSearchResultListItemExtension({ + name: 'AdrSearchResultListItem', + component: () => + import('./search/AdrSearchResultListItem').then( + m => m.AdrSearchResultListItem, + ), + predicate: result => result.type === 'adr', + }), +); diff --git a/plugins/adr/src/search/AdrSearchResultListItem.tsx b/plugins/adr/src/search/AdrSearchResultListItem.tsx index 3a11b5cf9a..118333a439 100644 --- a/plugins/adr/src/search/AdrSearchResultListItem.tsx +++ b/plugins/adr/src/search/AdrSearchResultListItem.tsx @@ -14,19 +14,19 @@ * limitations under the License. */ -import React from 'react'; +import React, { ReactNode } from 'react'; import { Box, Chip, Divider, ListItem, + ListItemIcon, ListItemText, makeStyles, } from '@material-ui/core'; import Typography from '@material-ui/core/Typography'; import { parseEntityRef } from '@backstage/catalog-model'; import { Link } from '@backstage/core-components'; -import { useAnalytics } from '@backstage/core-plugin-api'; import { AdrDocument } from '@backstage/plugin-adr-common'; import { humanizeEntityRef } from '@backstage/plugin-catalog-react'; import { ResultHighlight } from '@backstage/plugin-search-common'; @@ -43,35 +43,36 @@ const useStyles = makeStyles({ }, }); +/** + * @public + */ +export type AdrSearchResultListItemProps = { + lineClamp?: number; + highlight?: ResultHighlight; + icon?: ReactNode; + rank?: number; + result?: AdrDocument; +}; + /** * A component to display an ADR search result. * @public */ -export function AdrSearchResultListItem(props: { - lineClamp?: number; - highlight?: ResultHighlight; - rank?: number; - result: AdrDocument; -}) { - const { lineClamp = 5, highlight, rank, result } = props; +export function AdrSearchResultListItem(props: AdrSearchResultListItemProps) { + const { lineClamp = 5, highlight, icon, result } = props; const classes = useStyles(); - const analytics = useAnalytics(); - const handleClick = () => { - analytics.captureEvent('discover', result.title, { - attributes: { to: result.location }, - value: rank, - }); - }; + if (!result) return null; return ( <> + {icon && {icon}} + {highlight?.fields.title ? ( Date: Tue, 31 Jan 2023 17:27:15 -0500 Subject: [PATCH 056/423] Add unit tests for post /proxy endpoint Signed-off-by: Ruben Vallejo --- .../src/service/KubernetesBuilder.test.ts | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts index 2766f9abfc..5e0caaf6a5 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts @@ -31,6 +31,10 @@ import { import { KubernetesBuilder } from './KubernetesBuilder'; import { KubernetesFanOutHandler } from './KubernetesFanOutHandler'; import { CatalogApi } from '@backstage/catalog-client'; +import { HEADER_KUBERNETES_CLUSTER } from './KubernetesProxy'; +import { setupServer } from 'msw/node'; +import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import { rest } from 'msw'; describe('KubernetesBuilder', () => { let app: express.Express; @@ -267,4 +271,78 @@ describe('KubernetesBuilder', () => { expect(response.status).toEqual(200); }); }); + + describe('post /proxy', () => { + const worker = setupServer(); + setupRequestMockHandlers(worker); + + it('returns the given request body', async () => { + const requestBody = { + kind: 'Namespace', + apiVersion: 'v1', + metadata: { + name: 'new-ns', + }, + }; + + const proxyEndpointRequest = request(app) + .post('/proxy/api/v1/namespaces') + .set(HEADER_KUBERNETES_CLUSTER, 'some-cluster') + .send(requestBody); + + worker.use( + rest.post('https://localhost:1234/api/v1/namespaces', (req, res, ctx) => + req + .arrayBuffer() + .then(body => + res( + ctx.set('content-type', `${req.headers.get('content-type')}`), + ctx.body(body), + ), + ), + ), + rest.all(proxyEndpointRequest.url, (req, _res, _ctx) => + req.passthrough(), + ), + ); + + const response = await proxyEndpointRequest; + + expect(response.body).toStrictEqual(requestBody); + }); + + it('supports yaml content type', async () => { + const requestBody = `--- +kind: Namespace +apiVersion: v1 +metadata: + name: new-ns +`; + + const proxyEndpointRequest = request(app) + .post('/proxy/api/v1/namespaces') + .set(HEADER_KUBERNETES_CLUSTER, 'some-cluster') + .set('content-type', 'application/yaml') + .send(requestBody); + + worker.use( + rest.post('https://localhost:1234/api/v1/namespaces', (req, res, ctx) => + req + .arrayBuffer() + .then(body => + res( + ctx.set('content-type', `${req.headers.get('content-type')}`), + ctx.body(body), + ), + ), + ), + rest.all(proxyEndpointRequest.url, (req, _res, _ctx) => + req.passthrough(), + ), + ); + + const response = await proxyEndpointRequest; + expect(response.text).toEqual(requestBody); + }); + }); }); From 81c5dca2ff5e3dac321f04995d1c402c2dded00a Mon Sep 17 00:00:00 2001 From: Ruben Vallejo Date: Tue, 31 Jan 2023 17:29:32 -0500 Subject: [PATCH 057/423] Passing post proxy unit tests, proxy now supports write operations Signed-off-by: Ruben Vallejo --- .../src/service/KubernetesBuilder.test.ts | 47 +++++++------------ .../src/service/KubernetesBuilder.ts | 3 +- 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts index 5e0caaf6a5..cc2dea26c0 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts @@ -276,6 +276,21 @@ describe('KubernetesBuilder', () => { const worker = setupServer(); setupRequestMockHandlers(worker); + beforeEach(() => { + worker.use( + rest.post('https://localhost:1234/api/v1/namespaces', (req, res, ctx) => + req + .arrayBuffer() + .then(body => + res( + ctx.set('content-type', `${req.headers.get('content-type')}`), + ctx.body(body), + ), + ), + ), + ); + }); + it('returns the given request body', async () => { const requestBody = { kind: 'Namespace', @@ -290,21 +305,7 @@ describe('KubernetesBuilder', () => { .set(HEADER_KUBERNETES_CLUSTER, 'some-cluster') .send(requestBody); - worker.use( - rest.post('https://localhost:1234/api/v1/namespaces', (req, res, ctx) => - req - .arrayBuffer() - .then(body => - res( - ctx.set('content-type', `${req.headers.get('content-type')}`), - ctx.body(body), - ), - ), - ), - rest.all(proxyEndpointRequest.url, (req, _res, _ctx) => - req.passthrough(), - ), - ); + worker.use(rest.all(proxyEndpointRequest.url, req => req.passthrough())); const response = await proxyEndpointRequest; @@ -325,21 +326,7 @@ metadata: .set('content-type', 'application/yaml') .send(requestBody); - worker.use( - rest.post('https://localhost:1234/api/v1/namespaces', (req, res, ctx) => - req - .arrayBuffer() - .then(body => - res( - ctx.set('content-type', `${req.headers.get('content-type')}`), - ctx.body(body), - ), - ), - ), - rest.all(proxyEndpointRequest.url, (req, _res, _ctx) => - req.passthrough(), - ), - ); + worker.use(rest.all(proxyEndpointRequest.url, req => req.passthrough())); const response = await proxyEndpointRequest; expect(response.text).toEqual(requestBody); diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts index 1e7b704ec5..92773ece6d 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts @@ -265,6 +265,7 @@ export class KubernetesBuilder { ): express.Router { const logger = this.env.logger; const router = Router(); + router.use('/proxy', proxy.createRequestHandler()); router.use(express.json()); // @deprecated @@ -297,8 +298,6 @@ export class KubernetesBuilder { }); }); - router.use('/proxy', proxy.createRequestHandler()); - addResourceRoutesToRouter(router, catalogApi, objectsProvider); return router; From 7ff81f76926b89522109094a6063d1fd480a076d Mon Sep 17 00:00:00 2001 From: Ruben Vallejo Date: Wed, 1 Feb 2023 10:31:26 -0500 Subject: [PATCH 058/423] generate changeset Signed-off-by: Ruben Vallejo --- .changeset/neat-schools-raise.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/neat-schools-raise.md diff --git a/.changeset/neat-schools-raise.md b/.changeset/neat-schools-raise.md new file mode 100644 index 0000000000..b778ba8795 --- /dev/null +++ b/.changeset/neat-schools-raise.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +--- + +Kubernetes proxy endpoint now accepts content types that are not json From e4a78a13dac6dd32d27b9857c780fe524e03b795 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Wed, 1 Feb 2023 15:54:12 -0500 Subject: [PATCH 059/423] add trpc example to development build, ensure syntax highlighting works Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- packages/catalog-model/examples/all-apis.yaml | 1 + .../components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/catalog-model/examples/all-apis.yaml b/packages/catalog-model/examples/all-apis.yaml index e23f1b3656..472897bfac 100644 --- a/packages/catalog-model/examples/all-apis.yaml +++ b/packages/catalog-model/examples/all-apis.yaml @@ -6,6 +6,7 @@ metadata: spec: targets: - ./apis/hello-world-api.yaml + - ./apis/hello-world-trpc-api.yaml - ./apis/petstore-api.yaml - ./apis/spotify-api.yaml - ./apis/streetlights-api.yaml diff --git a/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx b/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx index c4cf56bedb..81bec09769 100644 --- a/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx @@ -33,7 +33,7 @@ export const TrpcApiDefinitionWidget: React.FC = ( ); From 4a123fe82a823c33d81c426a59c2e073ceec309d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 2 Feb 2023 11:06:06 +1100 Subject: [PATCH 060/423] Prefer the github login annotation over the name field when applying location annotations Signed-off-by: Jack Grigg --- .../src/lib/annotation.ts | 23 +++++++++++++++++++ .../src/lib/defaultTransformers.ts | 3 ++- .../src/providers/GithubOrgEntityProvider.ts | 8 +++++-- 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 plugins/catalog-backend-module-github/src/lib/annotation.ts diff --git a/plugins/catalog-backend-module-github/src/lib/annotation.ts b/plugins/catalog-backend-module-github/src/lib/annotation.ts new file mode 100644 index 0000000000..b80e10c8b5 --- /dev/null +++ b/plugins/catalog-backend-module-github/src/lib/annotation.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +/** + * The value of this annotation is the so-called login that identifies a user on +[GitHub](https://github.com) + * + * @public + */ +export const ANNOTATION_GITHUB_USER_LOGIN = 'github.com/user-login'; diff --git a/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts b/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts index efd3eedd5d..cf6edde1dc 100644 --- a/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts +++ b/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts @@ -16,6 +16,7 @@ import { GroupEntity, UserEntity } from '@backstage/catalog-model'; import { graphql } from '@octokit/graphql'; +import { ANNOTATION_GITHUB_USER_LOGIN } from './annotation'; import { GithubTeam, GithubUser } from './github'; /** @@ -63,7 +64,7 @@ export const defaultUserTransformer: UserTransformer = async ( metadata: { name: item.login, annotations: { - 'github.com/user-login': item.login, + [ANNOTATION_GITHUB_USER_LOGIN]: item.login, }, }, spec: { diff --git a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts index 3093c2a897..95e3780f76 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts @@ -65,6 +65,7 @@ import { getOrganizationTeam, getOrganizationTeamsFromUsers, } from '../lib/github'; +import { ANNOTATION_GITHUB_USER_LOGIN } from '../lib/annotation'; /** * Options for {@link GithubOrgEntityProvider}. @@ -602,10 +603,13 @@ export function withLocations( org: string, entity: Entity, ): Entity { + const login = + entity.metadata.annotations[ANNOTATION_GITHUB_USER_LOGIN] || + entity.metadata.name; const location = entity.kind === 'Group' - ? `url:${baseUrl}/orgs/${org}/teams/${entity.metadata.name}` - : `url:${baseUrl}/${entity.metadata.name}`; + ? `url:${baseUrl}/orgs/${org}/teams/${login}` + : `url:${baseUrl}/${login}`; return merge( { metadata: { From 057f05c1eb1aa58b2bbaee98542705a9c69413b6 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 2 Feb 2023 14:53:40 +1100 Subject: [PATCH 061/423] add support for groups via team slug splitting and some tests Signed-off-by: Jack Grigg --- .../src/lib/annotation.ts | 11 +++++++++++ .../src/lib/defaultTransformers.ts | 7 +++++-- .../src/lib/util.ts | 11 +++++++++++ .../providers/GithubOrgEntityProvider.test.ts | 16 ++++++++++++---- .../src/providers/GithubOrgEntityProvider.ts | 18 +++++++++++++++--- 5 files changed, 54 insertions(+), 9 deletions(-) diff --git a/plugins/catalog-backend-module-github/src/lib/annotation.ts b/plugins/catalog-backend-module-github/src/lib/annotation.ts index b80e10c8b5..bfb31e1b47 100644 --- a/plugins/catalog-backend-module-github/src/lib/annotation.ts +++ b/plugins/catalog-backend-module-github/src/lib/annotation.ts @@ -21,3 +21,14 @@ * @public */ export const ANNOTATION_GITHUB_USER_LOGIN = 'github.com/user-login'; + +/** + * The value of this annotation is the so-called slug that identifies a team on +[GitHub](https://github.com) (either the public one, or a private GitHub +Enterprise installation) that is related to this entity. It is on the format +`/`, and is the same as can be seen in the URL location bar +of the browser when viewing that team. + * + * @public + */ +export const ANNOTATION_GITHUB_TEAM_SLUG = 'github.com/team-slug'; diff --git a/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts b/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts index cf6edde1dc..7669fd5b47 100644 --- a/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts +++ b/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts @@ -16,7 +16,10 @@ import { GroupEntity, UserEntity } from '@backstage/catalog-model'; import { graphql } from '@octokit/graphql'; -import { ANNOTATION_GITHUB_USER_LOGIN } from './annotation'; +import { + ANNOTATION_GITHUB_TEAM_SLUG, + ANNOTATION_GITHUB_USER_LOGIN, +} from './annotation'; import { GithubTeam, GithubUser } from './github'; /** @@ -88,7 +91,7 @@ export const defaultUserTransformer: UserTransformer = async ( export const defaultOrganizationTeamTransformer: TeamTransformer = async team => { const annotations: { [annotationName: string]: string } = { - 'github.com/team-slug': team.combinedSlug, + [ANNOTATION_GITHUB_TEAM_SLUG]: team.combinedSlug, }; if (team.editTeamUrl) { diff --git a/plugins/catalog-backend-module-github/src/lib/util.ts b/plugins/catalog-backend-module-github/src/lib/util.ts index d284fdabde..54ee575a6c 100644 --- a/plugins/catalog-backend-module-github/src/lib/util.ts +++ b/plugins/catalog-backend-module-github/src/lib/util.ts @@ -88,3 +88,14 @@ export function satisfiesForkFilter( // if forks are allowed, allow all repos through return true; } + +// Given the github organisation team slug, returns a tuple containing [organisation, team] +export function splitTeamSlug(slug: string): [string, string] { + const parts = slug.split('/'); + if (parts.length !== 2) { + throw new Error( + `Github team slug '${slug}' was not in the expected format /`, + ); + } + return [parts[0], parts[1]]; +} diff --git a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts index c24cd573e0..2711425998 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts @@ -181,7 +181,10 @@ describe('GithubOrgEntityProvider', () => { apiVersion: 'backstage.io/v1alpha1', kind: 'User', metadata: { - name: 'githubuser', + name: 'user-name', + annotations: { + 'github.com/user-login': 'githubuser', + }, }, spec: { memberOf: [], @@ -192,12 +195,13 @@ describe('GithubOrgEntityProvider', () => { apiVersion: 'backstage.io/v1alpha1', kind: 'User', metadata: { - name: 'githubuser', + name: 'user-name', annotations: { 'backstage.io/managed-by-location': 'url:https://github.com/githubuser', 'backstage.io/managed-by-origin-location': 'url:https://github.com/githubuser', + 'github.com/user-login': 'githubuser', }, }, spec: { @@ -211,7 +215,10 @@ describe('GithubOrgEntityProvider', () => { apiVersion: 'backstage.io/v1alpha1', kind: 'Group', metadata: { - name: 'mygroup', + name: 'group-name', + annotations: { + 'github.com/team-slug': 'backstage/mygroup', + }, }, spec: { type: 'team', @@ -223,12 +230,13 @@ describe('GithubOrgEntityProvider', () => { apiVersion: 'backstage.io/v1alpha1', kind: 'Group', metadata: { - name: 'mygroup', + name: 'group-name', annotations: { 'backstage.io/managed-by-location': 'url:https://github.com/orgs/backstage/teams/mygroup', 'backstage.io/managed-by-origin-location': 'url:https://github.com/orgs/backstage/teams/mygroup', + 'github.com/team-slug': 'backstage/mygroup', }, }, spec: { diff --git a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts index 95e3780f76..2a888e6f91 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts @@ -65,7 +65,11 @@ import { getOrganizationTeam, getOrganizationTeamsFromUsers, } from '../lib/github'; -import { ANNOTATION_GITHUB_USER_LOGIN } from '../lib/annotation'; +import { + ANNOTATION_GITHUB_TEAM_SLUG, + ANNOTATION_GITHUB_USER_LOGIN, +} from '../lib/annotation'; +import { splitTeamSlug } from '../lib/util'; /** * Options for {@link GithubOrgEntityProvider}. @@ -604,11 +608,19 @@ export function withLocations( entity: Entity, ): Entity { const login = - entity.metadata.annotations[ANNOTATION_GITHUB_USER_LOGIN] || + entity.metadata.annotations?.[ANNOTATION_GITHUB_USER_LOGIN] || entity.metadata.name; + + let team = entity.metadata.name; + const slug = entity.metadata.annotations?.[ANNOTATION_GITHUB_TEAM_SLUG]; + if (slug) { + const [_, slugTeam] = splitTeamSlug(slug); + team = slugTeam; + } + const location = entity.kind === 'Group' - ? `url:${baseUrl}/orgs/${org}/teams/${login}` + ? `url:${baseUrl}/orgs/${org}/teams/${team}` : `url:${baseUrl}/${login}`; return merge( { From 80afd5ff8b1723af8ba943bab375abb0d4cb3c09 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 2 Feb 2023 15:01:48 +1100 Subject: [PATCH 062/423] changeset Signed-off-by: Jack Grigg --- .changeset/serious-grapes-brush.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/serious-grapes-brush.md diff --git a/.changeset/serious-grapes-brush.md b/.changeset/serious-grapes-brush.md new file mode 100644 index 0000000000..94eead7282 --- /dev/null +++ b/.changeset/serious-grapes-brush.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-github': patch +--- + +Use github team slug and login annotations rather than entity name to infer location annotations From 20573bfe6a39c19ebdf4e9bd01e7c88eefa2295a Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 2 Feb 2023 15:52:59 +1100 Subject: [PATCH 063/423] Fix comment Signed-off-by: Jack Grigg --- plugins/catalog-backend-module-github/src/lib/annotation.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-backend-module-github/src/lib/annotation.ts b/plugins/catalog-backend-module-github/src/lib/annotation.ts index bfb31e1b47..3b2f7b87a8 100644 --- a/plugins/catalog-backend-module-github/src/lib/annotation.ts +++ b/plugins/catalog-backend-module-github/src/lib/annotation.ts @@ -16,7 +16,10 @@ /** * The value of this annotation is the so-called login that identifies a user on -[GitHub](https://github.com) +[GitHub](https://github.com) (either the public one, or a private GitHub +Enterprise installation) that is related to this entity. It is on the format +``, and is the same as can be seen in the URL location bar of the +browser when viewing that user. * * @public */ From ce1220a4b8c9e7138c00ae3a18acae9898d8d7fb Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Wed, 1 Feb 2023 14:56:07 +0100 Subject: [PATCH 064/423] support custom list item props on search extensions Co-authored-by: Camila Belo Signed-off-by: Emma Indal --- docs/features/search/how-to-guides.md | 14 +++++++++ plugins/catalog/api-report.md | 3 +- plugins/catalog/src/plugin.ts | 7 +++-- plugins/explore/api-report.md | 3 +- plugins/explore/src/plugin.ts | 7 +++-- plugins/search-react/api-report.md | 11 +++++++ plugins/search-react/src/extensions.tsx | 39 +++++++++++++++---------- plugins/techdocs/api-report.md | 3 +- plugins/techdocs/src/plugin.ts | 7 +++-- 9 files changed, 70 insertions(+), 24 deletions(-) diff --git a/docs/features/search/how-to-guides.md b/docs/features/search/how-to-guides.md index 6f113630f6..b464168724 100644 --- a/docs/features/search/how-to-guides.md +++ b/docs/features/search/how-to-guides.md @@ -235,6 +235,20 @@ export const YourSearchResultListItemExtension = plugin.provide( ); ``` +If your list item accept props, you can extend the `SearchResultListItemExtensionProps` with your component specific props: + +```tsx +export const YourSearchResultListItemExtension: ( + props: SearchResultListItemExtensionProps, +) => JSX.Element | null = plugin.provide( + createSearchResultListItemExtension({ + name: 'YourSearchResultListItem', + component: () => + import('./components').then(m => m.YourSearchResultListItem), + }), +); +``` + Additionally, you can define a predicate function that receives a result and returns whether your extension should be used to render it or not: ```tsx diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index 901120bd22..6d746f6a7c 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -19,6 +19,7 @@ import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; +import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; import { StarredEntitiesApi } from '@backstage/plugin-catalog-react'; import { StorageApi } from '@backstage/core-plugin-api'; import { StyleRules } from '@material-ui/core/styles/withStyles'; @@ -108,7 +109,7 @@ export const catalogPlugin: BackstagePlugin< // @public (undocumented) export const CatalogSearchResultListItem: ( - props: CatalogSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null; // @public diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index 12c22eb537..ea6ddcaff2 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -31,7 +31,10 @@ import { fetchApiRef, storageApiRef, } from '@backstage/core-plugin-api'; -import { createSearchResultListItemExtension } from '@backstage/plugin-search-react'; +import { + createSearchResultListItemExtension, + SearchResultListItemExtensionProps, +} from '@backstage/plugin-search-react'; import { DefaultStarredEntitiesApi } from './apis'; import { AboutCardProps } from './components/AboutCard'; import { DefaultCatalogPageProps } from './components/CatalogPage'; @@ -254,7 +257,7 @@ export const RelatedEntitiesCard: ( /** @public */ export const CatalogSearchResultListItem: ( - props: CatalogSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null = catalogPlugin.provide( createSearchResultListItemExtension({ name: 'CatalogSearchResultListItem', diff --git a/plugins/explore/api-report.md b/plugins/explore/api-report.md index e7adde4b77..da960ae951 100644 --- a/plugins/explore/api-report.md +++ b/plugins/explore/api-report.md @@ -19,6 +19,7 @@ import { IndexableDocument } from '@backstage/plugin-search-common'; import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; +import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; import { TabProps } from '@material-ui/core'; // @public @deprecated (undocumented) @@ -126,7 +127,7 @@ export const ToolExplorerContent: (props: { // @public (undocumented) export const ToolSearchResultListItem: ( - props: ToolSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null; // @public diff --git a/plugins/explore/src/plugin.ts b/plugins/explore/src/plugin.ts index 5a4bec53c5..84e7657355 100644 --- a/plugins/explore/src/plugin.ts +++ b/plugins/explore/src/plugin.ts @@ -22,7 +22,10 @@ import { discoveryApiRef, fetchApiRef, } from '@backstage/core-plugin-api'; -import { createSearchResultListItemExtension } from '@backstage/plugin-search-react'; +import { + createSearchResultListItemExtension, + SearchResultListItemExtensionProps, +} from '@backstage/plugin-search-react'; import { ExploreClient, exploreApiRef } from './api'; import { ToolSearchResultListItemProps } from './components/ToolSearchResultListItem'; // import { exampleTools } from './util/examples'; @@ -70,7 +73,7 @@ export const explorePlugin = createPlugin({ /** @public */ export const ToolSearchResultListItem: ( - props: ToolSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null = explorePlugin.provide( createSearchResultListItemExtension({ name: 'ToolSearchResultListItem', diff --git a/plugins/search-react/api-report.md b/plugins/search-react/api-report.md index 0d6598feca..375af20d5c 100644 --- a/plugins/search-react/api-report.md +++ b/plugins/search-react/api-report.md @@ -14,6 +14,7 @@ import { InputBaseProps } from '@material-ui/core'; import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; import { LinkProps } from '@backstage/core-components'; +import { ListItemProps } from '@material-ui/core'; import { ListItemTextProps } from '@material-ui/core'; import { ListProps } from '@material-ui/core'; import { PropsWithChildren } from 'react'; @@ -392,6 +393,16 @@ export type SearchResultListItemExtensionOptions< predicate?: (result: SearchResult_2) => boolean; }; +// @public +export type SearchResultListItemExtensionProps = Props & + PropsWithChildren< + { + rank?: number; + result?: SearchDocument; + noTrack?: boolean; + } & Omit + >; + // @public export const SearchResultListItemExtensions: ( props: SearchResultListItemExtensionsProps, diff --git a/plugins/search-react/src/extensions.tsx b/plugins/search-react/src/extensions.tsx index 30611b0879..6c854e24e0 100644 --- a/plugins/search-react/src/extensions.tsx +++ b/plugins/search-react/src/extensions.tsx @@ -33,7 +33,7 @@ import { } from '@backstage/core-plugin-api'; import { SearchDocument, SearchResult } from '@backstage/plugin-search-common'; -import { ListItem, List, ListProps } from '@material-ui/core'; +import { ListItem, List, ListProps, ListItemProps } from '@material-ui/core'; import { DefaultResultListItem } from './components'; @@ -73,26 +73,34 @@ const findSearchResultListItemExtensionElement = ( }; /** - * @internal - * Props for {@link SearchResultListItemExtension}. + * @public + * Extends props for any search result list item extension */ -type SearchResultListItemExtensionProps = PropsWithChildren<{ - rank?: number; - result?: SearchDocument; - noTrack?: boolean; -}>; +export type SearchResultListItemExtensionProps = Props & + PropsWithChildren< + { + rank?: number; + result?: SearchDocument; + noTrack?: boolean; + } & Omit + >; /** * @internal * Extends children with extension capabilities. * @param props - see {@link SearchResultListItemExtensionProps}. */ -const SearchResultListItemExtension = ({ - rank, - result, - noTrack, - children, -}: SearchResultListItemExtensionProps) => { +const SearchResultListItemExtension = ( + props: SearchResultListItemExtensionProps, +) => { + const { + rank, + result, + noTrack, + children, + alignItems = 'flex-start', + ...rest + } = props; const analytics = useAnalytics(); const handleClickCapture = useCallback(() => { @@ -107,8 +115,9 @@ const SearchResultListItemExtension = ({ return ( {children} diff --git a/plugins/techdocs/api-report.md b/plugins/techdocs/api-report.md index ddc90d07bb..9452b38feb 100644 --- a/plugins/techdocs/api-report.md +++ b/plugins/techdocs/api-report.md @@ -19,6 +19,7 @@ import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; +import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; import { TableColumn } from '@backstage/core-components'; import { TableOptions } from '@backstage/core-components'; import { TableProps } from '@backstage/core-components'; @@ -400,7 +401,7 @@ export type TechDocsSearchProps = { // @public export const TechDocsSearchResultListItem: ( - props: TechDocsSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null; // @public diff --git a/plugins/techdocs/src/plugin.ts b/plugins/techdocs/src/plugin.ts index 331eefe121..bdd4814898 100644 --- a/plugins/techdocs/src/plugin.ts +++ b/plugins/techdocs/src/plugin.ts @@ -33,7 +33,10 @@ import { fetchApiRef, identityApiRef, } from '@backstage/core-plugin-api'; -import { createSearchResultListItemExtension } from '@backstage/plugin-search-react'; +import { + createSearchResultListItemExtension, + SearchResultListItemExtensionProps, +} from '@backstage/plugin-search-react'; import { TechDocsSearchResultListItemProps } from './search/components/TechDocsSearchResultListItem'; /** @@ -162,7 +165,7 @@ export const TechDocsReaderPage = techdocsPlugin.provide( * @public */ export const TechDocsSearchResultListItem: ( - props: TechDocsSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null = techdocsPlugin.provide( createSearchResultListItemExtension({ name: 'TechDocsSearchResultListItem', From ecf174b7b59f4aa7c68ba7fab7356b75277744ed Mon Sep 17 00:00:00 2001 From: MitchWijt Date: Thu, 2 Feb 2023 09:45:21 +0100 Subject: [PATCH 065/423] chore: improve description Signed-off-by: MitchWijt --- microsite/data/plugins/graphql-voyager.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/data/plugins/graphql-voyager.yaml b/microsite/data/plugins/graphql-voyager.yaml index 0bb56fb469..c6ebf5e412 100644 --- a/microsite/data/plugins/graphql-voyager.yaml +++ b/microsite/data/plugins/graphql-voyager.yaml @@ -3,7 +3,7 @@ title: GraphQL Voyager author: PostNL authorUrl: https://github.com/postnl category: Debugging -description: Integrates the GraphQL Voyager tool inside Backstage. +description: Integrates the GraphQL Voyager tool inside Backstage as a plugin. documentation: https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager iconUrl: https://res.cloudinary.com/apideck/image/upload/v1612724234/icons/graphql-voyager.png npmPackageName: '@backstage/plugin-graphql-voyager' From 0d036dfc30801aa700215fcc148a118da1533db2 Mon Sep 17 00:00:00 2001 From: MitchWijt Date: Thu, 2 Feb 2023 10:04:10 +0100 Subject: [PATCH 066/423] chore: yarn.lock collisions Signed-off-by: MitchWijt --- yarn.lock | 151 +++++++++++++++++++++++------------------------------- 1 file changed, 63 insertions(+), 88 deletions(-) diff --git a/yarn.lock b/yarn.lock index d0f4833c0c..cabba4a417 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17055,7 +17055,7 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.4, array-includes@npm:^3.1.5, array-includes@npm:^3.1.6": +"array-includes@npm:^3.1.5, array-includes@npm:^3.1.6": version: 3.1.6 resolution: "array-includes@npm:3.1.6" dependencies: @@ -17091,15 +17091,15 @@ __metadata: languageName: node linkType: hard -"array.prototype.flat@npm:^1.2.3, array.prototype.flat@npm:^1.2.5": - version: 1.3.0 - resolution: "array.prototype.flat@npm:1.3.0" +"array.prototype.flat@npm:^1.2.3, array.prototype.flat@npm:^1.3.1": + version: 1.3.1 + resolution: "array.prototype.flat@npm:1.3.1" dependencies: call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 es-shim-unscopables: ^1.0.0 - checksum: 2a652b3e8dc0bebb6117e42a5ab5738af0203a14c27341d7bb2431467bdb4b348e2c5dc555dfcda8af0a5e4075c400b85311ded73861c87290a71a17c3e0a257 + checksum: 5a8415949df79bf6e01afd7e8839bbde5a3581300e8ad5d8449dea52639e9e59b26a467665622783697917b43bf39940a6e621877c7dd9b3d1c1f97484b9b88b languageName: node linkType: hard @@ -20593,7 +20593,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:2.6.9, debug@npm:^2.6.0, debug@npm:^2.6.9": +"debug@npm:2.6.9, debug@npm:^2.6.0": version: 2.6.9 resolution: "debug@npm:2.6.9" dependencies: @@ -21668,7 +21668,7 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.19.0, es-abstract@npm:^1.19.2, es-abstract@npm:^1.19.5, es-abstract@npm:^1.20.4": +"es-abstract@npm:^1.19.0, es-abstract@npm:^1.19.5, es-abstract@npm:^1.20.4": version: 1.20.4 resolution: "es-abstract@npm:1.20.4" dependencies: @@ -22164,23 +22164,26 @@ __metadata: languageName: node linkType: hard -"eslint-import-resolver-node@npm:^0.3.6": - version: 0.3.6 - resolution: "eslint-import-resolver-node@npm:0.3.6" +"eslint-import-resolver-node@npm:^0.3.7": + version: 0.3.7 + resolution: "eslint-import-resolver-node@npm:0.3.7" dependencies: debug: ^3.2.7 - resolve: ^1.20.0 - checksum: 6266733af1e112970e855a5bcc2d2058fb5ae16ad2a6d400705a86b29552b36131ffc5581b744c23d550de844206fb55e9193691619ee4dbf225c4bde526b1c8 + is-core-module: ^2.11.0 + resolve: ^1.22.1 + checksum: 3379aacf1d2c6952c1b9666c6fa5982c3023df695430b0d391c0029f6403a7775414873d90f397e98ba6245372b6c8960e16e74d9e4a3b0c0a4582f3bdbe3d6e languageName: node linkType: hard -"eslint-module-utils@npm:^2.1.1, eslint-module-utils@npm:^2.7.3": - version: 2.7.3 - resolution: "eslint-module-utils@npm:2.7.3" +"eslint-module-utils@npm:^2.1.1, eslint-module-utils@npm:^2.7.4": + version: 2.7.4 + resolution: "eslint-module-utils@npm:2.7.4" dependencies: debug: ^3.2.7 - find-up: ^2.1.0 - checksum: 77048263f309167a1e6a1e1b896bfb5ddd1d3859b2e2abbd9c32c432aee13d610d46e6820b1ca81b37fba437cf423a404bc6649be64ace9148a3062d1886a678 + peerDependenciesMeta: + eslint: + optional: true + checksum: 5da13645daff145a5c922896b258f8bba560722c3767254e458d894ff5fbb505d6dfd945bffa932a5b0ae06714da2379bd41011c4c20d2d59cc83e23895360f7 languageName: node linkType: hard @@ -22210,25 +22213,27 @@ __metadata: linkType: hard "eslint-plugin-import@npm:^2.25.4": - version: 2.26.0 - resolution: "eslint-plugin-import@npm:2.26.0" + version: 2.27.5 + resolution: "eslint-plugin-import@npm:2.27.5" dependencies: - array-includes: ^3.1.4 - array.prototype.flat: ^1.2.5 - debug: ^2.6.9 + array-includes: ^3.1.6 + array.prototype.flat: ^1.3.1 + array.prototype.flatmap: ^1.3.1 + debug: ^3.2.7 doctrine: ^2.1.0 - eslint-import-resolver-node: ^0.3.6 - eslint-module-utils: ^2.7.3 + eslint-import-resolver-node: ^0.3.7 + eslint-module-utils: ^2.7.4 has: ^1.0.3 - is-core-module: ^2.8.1 + is-core-module: ^2.11.0 is-glob: ^4.0.3 minimatch: ^3.1.2 - object.values: ^1.1.5 - resolve: ^1.22.0 + object.values: ^1.1.6 + resolve: ^1.22.1 + semver: ^6.3.0 tsconfig-paths: ^3.14.1 peerDependencies: eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 0bf77ad80339554481eafa2b1967449e1f816b94c7a6f9614ce33fb4083c4e6c050f10d241dd50b4975d47922880a34de1e42ea9d8e6fd663ebb768baa67e655 + checksum: f500571a380167e25d72a4d925ef9a7aae8899eada57653e5f3051ec3d3c16d08271fcefe41a30a9a2f4fefc232f066253673ee4ea77b30dba65ae173dade85d languageName: node linkType: hard @@ -22410,8 +22415,8 @@ __metadata: linkType: hard "eslint@npm:^8.6.0": - version: 8.31.0 - resolution: "eslint@npm:8.31.0" + version: 8.33.0 + resolution: "eslint@npm:8.33.0" dependencies: "@eslint/eslintrc": ^1.4.1 "@humanwhocodes/config-array": ^0.11.8 @@ -22454,7 +22459,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 5e5688bb864edc6b12d165849994812eefa67fb3fc44bb26f53659b63edcd8bcc68389d27cc6cc9e5b79ee22f24b6f311fa3ed047bddcafdec7d84c1b5561e4f + checksum: 727e63ab8b7acf281442323c5971f6afdd5b656fbcebc4476cf54e35af51b2f180617433fc5e1952f0449ca3f43a905527f9407ea4b8a7ea7562fc9c3f278d4c languageName: node linkType: hard @@ -23441,15 +23446,6 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^2.1.0": - version: 2.1.0 - resolution: "find-up@npm:2.1.0" - dependencies: - locate-path: ^2.0.0 - checksum: 43284fe4da09f89011f08e3c32cd38401e786b19226ea440b75386c1b12a4cb738c94969808d53a84f564ede22f732c8409e3cfc3f7fb5b5c32378ad0bbf28bd - languageName: node - linkType: hard - "find-up@npm:^3.0.0": version: 3.0.0 resolution: "find-up@npm:3.0.0" @@ -24186,15 +24182,15 @@ __metadata: linkType: hard "glob@npm:^8.0.0, glob@npm:^8.0.1, glob@npm:^8.0.3": - version: 8.0.3 - resolution: "glob@npm:8.0.3" + version: 8.1.0 + resolution: "glob@npm:8.1.0" dependencies: fs.realpath: ^1.0.0 inflight: ^1.0.4 inherits: 2 minimatch: ^5.0.1 once: ^1.3.0 - checksum: 50bcdea19d8e79d8de5f460b1939ffc2b3299eac28deb502093fdca22a78efebc03e66bf54f0abc3d3d07d8134d19a32850288b7440d77e072aa55f9d33b18c5 + checksum: 92fbea3221a7d12075f26f0227abac435de868dd0736a17170663783296d0dd8d3d532a5672b4488a439bf5d7fb85cdd07c11185d6cd39184f0385cbdfb86a47 languageName: node linkType: hard @@ -25840,12 +25836,12 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.1.0, is-core-module@npm:^2.8.1, is-core-module@npm:^2.9.0": - version: 2.10.0 - resolution: "is-core-module@npm:2.10.0" +"is-core-module@npm:^2.1.0, is-core-module@npm:^2.11.0, is-core-module@npm:^2.9.0": + version: 2.11.0 + resolution: "is-core-module@npm:2.11.0" dependencies: has: ^1.0.3 - checksum: 0f3f77811f430af3256fa7bbc806f9639534b140f8ee69476f632c3e1eb4e28a38be0b9d1b8ecf596179c841b53576129279df95e7051d694dac4ceb6f967593 + checksum: f96fd490c6b48eb4f6d10ba815c6ef13f410b0ba6f7eb8577af51697de523e5f2cd9de1c441b51d27251bf0e4aebc936545e33a5d26d5d51f28d25698d4a8bab languageName: node linkType: hard @@ -28470,16 +28466,6 @@ __metadata: languageName: node linkType: hard -"locate-path@npm:^2.0.0": - version: 2.0.0 - resolution: "locate-path@npm:2.0.0" - dependencies: - p-locate: ^2.0.0 - path-exists: ^3.0.0 - checksum: 02d581edbbbb0fa292e28d96b7de36b5b62c2fa8b5a7e82638ebb33afa74284acf022d3b1e9ae10e3ffb7658fbc49163fcd5e76e7d1baaa7801c3e05a81da755 - languageName: node - linkType: hard - "locate-path@npm:^3.0.0": version: 3.0.0 resolution: "locate-path@npm:3.0.0" @@ -30459,7 +30445,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:2.6.7, node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.5, node-fetch@npm:^2.6.7": +"node-fetch@npm:2.6.7": version: 2.6.7 resolution: "node-fetch@npm:2.6.7" dependencies: @@ -30483,6 +30469,20 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.5, node-fetch@npm:^2.6.7": + version: 2.6.9 + resolution: "node-fetch@npm:2.6.9" + dependencies: + whatwg-url: ^5.0.0 + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: acb04f9ce7224965b2b59e71b33c639794d8991efd73855b0b250921382b38331ffc9d61bce502571f6cc6e11a8905ca9b1b6d4aeb586ab093e2756a1fd190d0 + languageName: node + linkType: hard + "node-forge@npm:^1, node-forge@npm:^1.3.1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -31001,7 +31001,7 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.5, object.values@npm:^1.1.6": +"object.values@npm:^1.1.6": version: 1.1.6 resolution: "object.values@npm:1.1.6" dependencies: @@ -31297,15 +31297,6 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^1.1.0": - version: 1.3.0 - resolution: "p-limit@npm:1.3.0" - dependencies: - p-try: ^1.0.0 - checksum: 281c1c0b8c82e1ac9f81acd72a2e35d402bf572e09721ce5520164e9de07d8274451378a3470707179ad13240535558f4b277f02405ad752e08c7d5b0d54fbfd - languageName: node - linkType: hard - "p-limit@npm:^2.0.0, p-limit@npm:^2.2.0": version: 2.3.0 resolution: "p-limit@npm:2.3.0" @@ -31324,15 +31315,6 @@ __metadata: languageName: node linkType: hard -"p-locate@npm:^2.0.0": - version: 2.0.0 - resolution: "p-locate@npm:2.0.0" - dependencies: - p-limit: ^1.1.0 - checksum: e2dceb9b49b96d5513d90f715780f6f4972f46987dc32a0e18bc6c3fc74a1a5d73ec5f81b1398af5e58b99ea1ad03fd41e9181c01fa81b4af2833958696e3081 - languageName: node - linkType: hard - "p-locate@npm:^3.0.0": version: 3.0.0 resolution: "p-locate@npm:3.0.0" @@ -31415,13 +31397,6 @@ __metadata: languageName: node linkType: hard -"p-try@npm:^1.0.0": - version: 1.0.0 - resolution: "p-try@npm:1.0.0" - checksum: 3b5303f77eb7722144154288bfd96f799f8ff3e2b2b39330efe38db5dd359e4fb27012464cd85cb0a76e9b7edd1b443568cb3192c22e7cffc34989df0bafd605 - languageName: node - linkType: hard - "p-try@npm:^2.0.0": version: 2.2.0 resolution: "p-try@npm:2.2.0" @@ -34719,7 +34694,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.0, resolve@npm:~1.22.1": +"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:~1.22.1": version: 1.22.1 resolution: "resolve@npm:1.22.1" dependencies: @@ -34764,7 +34739,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.0#~builtin, resolve@patch:resolve@~1.22.1#~builtin": +"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin, resolve@patch:resolve@~1.22.1#~builtin": version: 1.22.1 resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin::version=1.22.1&hash=07638b" dependencies: From 3b5990bca19163c1bd781e312ff1359b9f6ee7bc Mon Sep 17 00:00:00 2001 From: MitchWijt Date: Fri, 27 Jan 2023 16:25:35 +0100 Subject: [PATCH 067/423] feat(plugin): Add graphql-voyager as new backstage plugin Signed-off-by: MitchWijt --- microsite/data/plugins/graphql-voyager.yaml | 13 ++ plugins/graphql-voyager/.eslintrc.js | 1 + plugins/graphql-voyager/README.md | 75 ++++++++++ plugins/graphql-voyager/api-report.md | 64 ++++++++ plugins/graphql-voyager/package.json | 53 +++++++ .../GraphQLVoyagerBrowser.test.tsx | 94 ++++++++++++ .../GraphQLVoyagerBrowser.tsx | 131 ++++++++++++++++ .../components/GraphQLVoyagerBrowser/index.ts | 16 ++ .../GraphQLVoyagerPage.test.tsx | 64 ++++++++ .../GraphQLVoyagerPage/GraphQLVoyagerPage.tsx | 62 ++++++++ .../components/GraphQLVoyagerPage/index.ts | 16 ++ .../graphql-voyager/src/components/index.ts | 17 +++ plugins/graphql-voyager/src/index.ts | 18 +++ .../src/lib/api/GraphQLVoyagerEndpoints.ts | 29 ++++ plugins/graphql-voyager/src/lib/api/index.ts | 17 +++ plugins/graphql-voyager/src/lib/api/types.ts | 141 ++++++++++++++++++ plugins/graphql-voyager/src/plugin.test.ts | 22 +++ plugins/graphql-voyager/src/plugin.ts | 38 +++++ plugins/graphql-voyager/src/routes.ts | 20 +++ plugins/graphql-voyager/src/setupTests.ts | 17 +++ 20 files changed, 908 insertions(+) create mode 100644 microsite/data/plugins/graphql-voyager.yaml create mode 100644 plugins/graphql-voyager/.eslintrc.js create mode 100644 plugins/graphql-voyager/README.md create mode 100644 plugins/graphql-voyager/api-report.md create mode 100644 plugins/graphql-voyager/package.json create mode 100644 plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.test.tsx create mode 100644 plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx create mode 100644 plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/index.ts create mode 100644 plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx create mode 100644 plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx create mode 100644 plugins/graphql-voyager/src/components/GraphQLVoyagerPage/index.ts create mode 100644 plugins/graphql-voyager/src/components/index.ts create mode 100644 plugins/graphql-voyager/src/index.ts create mode 100644 plugins/graphql-voyager/src/lib/api/GraphQLVoyagerEndpoints.ts create mode 100644 plugins/graphql-voyager/src/lib/api/index.ts create mode 100644 plugins/graphql-voyager/src/lib/api/types.ts create mode 100644 plugins/graphql-voyager/src/plugin.test.ts create mode 100644 plugins/graphql-voyager/src/plugin.ts create mode 100644 plugins/graphql-voyager/src/routes.ts create mode 100644 plugins/graphql-voyager/src/setupTests.ts diff --git a/microsite/data/plugins/graphql-voyager.yaml b/microsite/data/plugins/graphql-voyager.yaml new file mode 100644 index 0000000000..0bb56fb469 --- /dev/null +++ b/microsite/data/plugins/graphql-voyager.yaml @@ -0,0 +1,13 @@ +--- +title: GraphQL Voyager +author: PostNL +authorUrl: https://github.com/postnl +category: Debugging +description: Integrates the GraphQL Voyager tool inside Backstage. +documentation: https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager +iconUrl: https://res.cloudinary.com/apideck/image/upload/v1612724234/icons/graphql-voyager.png +npmPackageName: '@backstage/plugin-graphql-voyager' +tags: + - graphql + - graphql-voyager +addedDate: '2023-01-27' diff --git a/plugins/graphql-voyager/.eslintrc.js b/plugins/graphql-voyager/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/graphql-voyager/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/graphql-voyager/README.md b/plugins/graphql-voyager/README.md new file mode 100644 index 0000000000..f2f5265e2f --- /dev/null +++ b/plugins/graphql-voyager/README.md @@ -0,0 +1,75 @@ +# graphql-voyager + +Welcome to the graphql-voyager plugin! + +_This plugin was created through the Backstage CLI_ + +## Getting started + +### Installing + +To get started, first install the plugin with the following command: + +```bash +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-graphql-voyager +``` + +### Adding the page + +In order to be able to navigate to the graphQL voyager page, a new route needs to be added to the app. This can be done in the following way: + +```tsx +// packages/app/App.tsx + + import { GraphQLVoyagerPage } from "@backstage/plugin-graphql-voyager"; + + const routes = ( + + }/> +``` + +### Configuration + +In order for the plugin to function correctly. GraphQL endpoints need to be added / configured through the GraphQLVoyager API. This can be done by implementing the `graphQlVoyagerApiRef` exported by this plugin. + +Add your own configuration to the `packages/app/src/apis.ts` file the following way: + +```ts +import { identityApiRef } from './IdentityApi'; +import { GraphQLVoyagerEndpoints } from './GraphQLVoyagerEndpoints'; + +export const apis: AnyApiFactory[] = [ + createApiFactory({ + api: graphQlVoyagerApiRef, + deps: { identityApi: identityApiRef }, + factory: ({ identityApiRef }) => { + GraphQLVoyagerEndpoints.from([ + { + id: `graphql-voyager-endpoint-id`, + title: 'endpoint-title', + introspectionErrorMessage: + 'Unable to perform introspection, make sure you are on the correct environment.', + introspection: async (query: any) => { + const token = 'someSecretJWTComingFromIdentityApiRef'; + + const res = await fetch('graphQLEndpoint', { + method: 'POST', + body: JSON.stringify({ query }), + headers: { + 'Content-Type': 'application/json', + Authorization: token, + }, + }); + + return res.json(); + }, + voyagerProps: { + hideDocs: true, + }, + }, + ]); + }, + }), +]; +``` diff --git a/plugins/graphql-voyager/api-report.md b/plugins/graphql-voyager/api-report.md new file mode 100644 index 0000000000..21423a8c30 --- /dev/null +++ b/plugins/graphql-voyager/api-report.md @@ -0,0 +1,64 @@ +## API Report File for "@backstage/plugin-graphql-voyager" + +> 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 { RouteRef } from '@backstage/core-plugin-api'; +import { VoyagerDisplayOptions } from 'graphql-voyager/typings/components/Voyager'; +import { WorkerCallback } from 'graphql-voyager/typings/utils/types'; + +// @public (undocumented) +export type GraphQLVoyagerApi = { + getEndpoints(): Promise; +}; + +// @public (undocumented) +export const graphQlVoyagerApiRef: ApiRef; + +// @public (undocumented) +export type GraphQLVoyagerEndpoint = { + id: string; + title: string; + introspection: (body: any) => Promise; + introspectionErrorMessage: string; + voyagerProps?: { + displayOptions?: VoyagerDisplayOptions; + hideDocs?: boolean; + hideSettings?: boolean; + workerURI?: string; + loadWorker?: WorkerCallback; + }; +}; + +// @public (undocumented) +export class GraphQLVoyagerEndpoints implements GraphQLVoyagerApi { + // (undocumented) + static from(endpoints: GraphQLVoyagerEndpoint[]): GraphQLVoyagerEndpoints; + // (undocumented) + getEndpoints(): Promise; +} + +// @public (undocumented) +export const GraphqlVoyagerPage: () => JSX.Element; + +// @public (undocumented) +export const graphqlVoyagerPlugin: BackstagePlugin< + { + root: RouteRef; + }, + {}, + {} +>; + +// @public (undocumented) +export const introspectionQuery: string; + +// @public (undocumented) +export const Router: () => JSX.Element; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json new file mode 100644 index 0000000000..1cc7bb19e6 --- /dev/null +++ b/plugins/graphql-voyager/package.json @@ -0,0 +1,53 @@ +{ + "name": "@backstage/plugin-graphql-voyager", + "description": "Backstage plugin for GraphQL Voyager", + "version": "0.1.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/core-components": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/theme": "workspace:^", + "@material-ui/core": "^4.9.13", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "4.0.0-alpha.57", + "graphql-voyager": "^1.0.0-rc.31", + "react-use": "^17.2.4" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/dev-utils": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^14.0.0", + "@types/node": "*", + "cross-fetch": "^3.1.5", + "msw": "^0.47.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.test.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.test.tsx new file mode 100644 index 0000000000..76ccbd9965 --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.test.tsx @@ -0,0 +1,94 @@ +/* + * Copyright 2023 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 { renderInTestApp } from '@backstage/test-utils'; +import { GraphQLVoyagerBrowser } from './GraphQLVoyagerBrowser'; + +jest.mock('graphql-voyager', () => ({ Voyager: () => '' })); + +describe('GraphQLVoyagerBrowser', () => { + it('should render error text if there are no endpoints', async () => { + const rendered = await renderInTestApp( + , + ); + + expect(rendered.getByText('No endpoints available')).toBeInTheDocument(); + }); + + it('should render endpoint tabs', async () => { + const rendered = await renderInTestApp( + , + ); + + expect(rendered.getByText('Endpoint A')).toBeInTheDocument(); + expect(rendered.getByText('Endpoint B')).toBeInTheDocument(); + }); + + it('Should render the introspection error message when introspection fails', async () => { + const rendered = await renderInTestApp( + , + ); + + expect(rendered.getByText('Failed to introspect A')).toBeInTheDocument(); + }); +}); diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx new file mode 100644 index 0000000000..a4a5533642 --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx @@ -0,0 +1,131 @@ +/* + * Copyright 2023 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 { + GraphQLVoyagerEndpoint, + introspectionQuery, +} from '../../lib/api/types'; +import { Dispatch, SetStateAction, useEffect, useState } from 'react'; +import { Divider, makeStyles, Tab, Tabs, Typography } from '@material-ui/core'; +import React, { Suspense } from 'react'; +import { BackstageTheme } from '@backstage/theme'; +import { Content, Progress } from '@backstage/core-components'; +import { Voyager } from 'graphql-voyager'; + +const useStyles = makeStyles(theme => ({ + root: { + height: '100%', + display: 'flex', + flexFlow: 'column nowrap', + }, + tabs: { + background: theme.palette.background.paper, + }, +})); + +type GraphQLVoyagerBrowserProps = { + endpoints: GraphQLVoyagerEndpoint[]; +}; + +type IntrospectionResult = { + data?: Object; +}; + +const NoEndpoints = () => { + return No endpoints available; +}; + +const VoyagerBrowser = (props: GraphQLVoyagerBrowserProps) => { + const { endpoints } = props; + const [tabIndex, setTabIndex] = useState(0); + const [isLoading, setIsLoading] = useState(true); + const [introspectionResult, setIntrospectionResult]: [ + IntrospectionResult, + Dispatch>, + ] = useState({}); + const classes = useStyles(); + + const { + voyagerProps = {}, + introspectionErrorMessage, + introspection, + } = endpoints[tabIndex]; + + useEffect(() => { + const fetchIntrospection = async () => { + setIsLoading(true); + + const data = await introspection(introspectionQuery); + setIntrospectionResult(data); + + setIsLoading(false); + }; + + fetchIntrospection(); + }, [tabIndex, introspection]); + + let voyagerContent: JSX.Element; + + if (isLoading) { + voyagerContent = Loading...; + } else if (!introspectionResult.data) { + voyagerContent = ( + + {introspectionErrorMessage} + + ); + } else { + voyagerContent = ( + + ); + } + + return ( +
    + }> + setTabIndex(value)} + indicatorColor="primary" + > + {endpoints.map(({ title }, index) => ( + + ))} + + + {voyagerContent} + +
    + ); +}; + +/** @public */ +export const GraphQLVoyagerBrowser = (props: GraphQLVoyagerBrowserProps) => { + const hasEndpoints = checkEndpoints(props); + + if (!hasEndpoints) { + return ; + } + return ; +}; + +function checkEndpoints(props: GraphQLVoyagerBrowserProps) { + return props.endpoints.length; +} diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/index.ts b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/index.ts new file mode 100644 index 0000000000..3beb0ccd95 --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './GraphQLVoyagerBrowser'; diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx new file mode 100644 index 0000000000..e40e81d7a6 --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx @@ -0,0 +1,64 @@ +/* + * Copyright 2023 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 { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; + +import { GraphQLVoyagerPage } from './GraphQLVoyagerPage'; +import { GraphQLVoyagerApi, graphQlVoyagerApiRef } from '../../lib/api'; + +jest.mock('../GraphQLVoyagerBrowser', () => ({ + GraphQLVoyagerBrowser: () => '', +})); + +describe('GraphQLVoyagerPage', () => { + it('should show error when no endpoints are loaded', async () => { + const loadingApi: GraphQLVoyagerApi = { + async getEndpoints() { + throw new Error('No endpoints'); + }, + }; + + const rendered = await renderInTestApp( + + + , + ); + + expect(rendered.getByText('Welcome to Voyager!')).toBeInTheDocument(); + expect( + rendered.getByText( + 'Failed to load GraphQL endpoints, Error: No endpoints', + ), + ).toBeInTheDocument(); + }); + + it('should show GraphQLVoyagerBrowser', async () => { + const loadingApi: GraphQLVoyagerApi = { + async getEndpoints() { + return []; + }, + }; + + const rendered = await renderInTestApp( + + + , + ); + + expect(rendered.getByText('Welcome to Voyager!')).toBeInTheDocument(); + expect(rendered.getByText('')).toBeInTheDocument(); + }); +}); diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx new file mode 100644 index 0000000000..fa15eae86f --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx @@ -0,0 +1,62 @@ +/* + * Copyright 2023 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 { Header, Page, Content, Progress } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; +import 'graphql-voyager/dist/voyager.css'; +import { graphQlVoyagerApiRef } from '../../lib/api'; +import useAsync from 'react-use/lib/useAsync'; +import { Typography } from '@material-ui/core'; +import { GraphQLVoyagerBrowser } from '../GraphQLVoyagerBrowser'; + +/** @public */ +export const GraphQLVoyagerPage = () => { + const graphQLVoyagerApi = useApi(graphQlVoyagerApiRef); + const { value, loading, error } = useAsync(() => + graphQLVoyagerApi.getEndpoints(), + ); + + let content: JSX.Element; + + if (loading) { + content = ( + + + + ); + } else if (error) { + content = ( + + + Failed to load GraphQL endpoints, {String(error)} + + + ); + } else { + content = ( + + + + ); + } + + return ( + +
    + {content} + + ); +}; diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/index.ts b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/index.ts new file mode 100644 index 0000000000..5ee042fd5f --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './GraphQLVoyagerPage'; diff --git a/plugins/graphql-voyager/src/components/index.ts b/plugins/graphql-voyager/src/components/index.ts new file mode 100644 index 0000000000..76c4229839 --- /dev/null +++ b/plugins/graphql-voyager/src/components/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './GraphQLVoyagerPage'; +export * from './GraphQLVoyagerBrowser'; diff --git a/plugins/graphql-voyager/src/index.ts b/plugins/graphql-voyager/src/index.ts new file mode 100644 index 0000000000..2e7852bc51 --- /dev/null +++ b/plugins/graphql-voyager/src/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 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 { graphqlVoyagerPlugin, GraphqlVoyagerPage } from './plugin'; +export { GraphQLVoyagerPage as Router } from './components'; +export * from './lib/api'; diff --git a/plugins/graphql-voyager/src/lib/api/GraphQLVoyagerEndpoints.ts b/plugins/graphql-voyager/src/lib/api/GraphQLVoyagerEndpoints.ts new file mode 100644 index 0000000000..4d08ffbce3 --- /dev/null +++ b/plugins/graphql-voyager/src/lib/api/GraphQLVoyagerEndpoints.ts @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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 { GraphQLVoyagerApi, GraphQLVoyagerEndpoint } from './types'; + +/** @public */ +export class GraphQLVoyagerEndpoints implements GraphQLVoyagerApi { + private constructor(private readonly endpoints: GraphQLVoyagerEndpoint[]) {} + + static from(endpoints: GraphQLVoyagerEndpoint[]) { + return new GraphQLVoyagerEndpoints(endpoints); + } + + async getEndpoints() { + return this.endpoints; + } +} diff --git a/plugins/graphql-voyager/src/lib/api/index.ts b/plugins/graphql-voyager/src/lib/api/index.ts new file mode 100644 index 0000000000..c52eedafb7 --- /dev/null +++ b/plugins/graphql-voyager/src/lib/api/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './GraphQLVoyagerEndpoints'; +export * from './types'; diff --git a/plugins/graphql-voyager/src/lib/api/types.ts b/plugins/graphql-voyager/src/lib/api/types.ts new file mode 100644 index 0000000000..08e6f13923 --- /dev/null +++ b/plugins/graphql-voyager/src/lib/api/types.ts @@ -0,0 +1,141 @@ +/* + * Copyright 2023 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 { VoyagerDisplayOptions } from 'graphql-voyager/typings/components/Voyager'; +import { WorkerCallback } from 'graphql-voyager/typings/utils/types'; + +/** @public */ +export type GraphQLVoyagerEndpoint = { + id: string; + title: string; + introspection: (body: any) => Promise; + introspectionErrorMessage: string; + voyagerProps?: { + displayOptions?: VoyagerDisplayOptions; + hideDocs?: boolean; + hideSettings?: boolean; + workerURI?: string; + loadWorker?: WorkerCallback; + }; +}; + +/** @public */ +export type GraphQLVoyagerApi = { + getEndpoints(): Promise; +}; + +/** @public */ +export const graphQlVoyagerApiRef = createApiRef({ + id: 'plugin.graphqlvoyager.api', +}); + +/** @public */ +export const introspectionQuery: string = `query IntrospectionQuery { + __schema { + + queryType { name } + mutationType { name } + subscriptionType { name } + types { + ...FullType + } + directives { + name + description + + locations + args { + ...InputValue + } + } + } + } + + fragment FullType on __Type { + kind + name + description + + fields(includeDeprecated: true) { + name + description + args { + ...InputValue + } + type { + ...TypeRef + } + isDeprecated + deprecationReason + } + inputFields { + ...InputValue + } + interfaces { + ...TypeRef + } + enumValues(includeDeprecated: true) { + name + description + isDeprecated + deprecationReason + } + possibleTypes { + ...TypeRef + } + } + + fragment InputValue on __InputValue { + name + description + type { ...TypeRef } + defaultValue + + + } + + fragment TypeRef on __Type { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + } + } + } + } + } + } + } + }`; diff --git a/plugins/graphql-voyager/src/plugin.test.ts b/plugins/graphql-voyager/src/plugin.test.ts new file mode 100644 index 0000000000..df7acc7143 --- /dev/null +++ b/plugins/graphql-voyager/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2023 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 { graphqlVoyagerPlugin } from './plugin'; + +describe('graphql-voyager', () => { + it('should export plugin', () => { + expect(graphqlVoyagerPlugin).toBeDefined(); + }); +}); diff --git a/plugins/graphql-voyager/src/plugin.ts b/plugins/graphql-voyager/src/plugin.ts new file mode 100644 index 0000000000..bd33209a1d --- /dev/null +++ b/plugins/graphql-voyager/src/plugin.ts @@ -0,0 +1,38 @@ +/* + * Copyright 2023 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 { + createPlugin, + createRoutableExtension, +} from '@backstage/core-plugin-api'; + +import { rootRouteRef } from './routes'; + +/** @public */ +export const graphqlVoyagerPlugin = createPlugin({ + id: 'graphql-voyager', + routes: { + root: rootRouteRef, + }, +}); + +/** @public */ +export const GraphqlVoyagerPage = graphqlVoyagerPlugin.provide( + createRoutableExtension({ + name: 'GraphqlVoyagerPage', + component: () => import('./components').then(m => m.GraphQLVoyagerPage), + mountPoint: rootRouteRef, + }), +); diff --git a/plugins/graphql-voyager/src/routes.ts b/plugins/graphql-voyager/src/routes.ts new file mode 100644 index 0000000000..12f06c1cb5 --- /dev/null +++ b/plugins/graphql-voyager/src/routes.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2023 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 } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + id: 'graphql-voyager', +}); diff --git a/plugins/graphql-voyager/src/setupTests.ts b/plugins/graphql-voyager/src/setupTests.ts new file mode 100644 index 0000000000..73dd8dce47 --- /dev/null +++ b/plugins/graphql-voyager/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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'; From d1fb4b7bf1d547a31f722b94cb4062e9b23d1bbd Mon Sep 17 00:00:00 2001 From: MitchWijt Date: Tue, 31 Jan 2023 16:15:44 +0100 Subject: [PATCH 068/423] feat(plugin): resolve remarks of review Signed-off-by: MitchWijt --- .changeset/tasty-jobs-help.md | 5 + plugins/graphql-voyager/README.md | 10 +- plugins/graphql-voyager/package.json | 6 +- .../GraphQLVoyagerBrowser.tsx | 96 +++++++------------ .../GraphQLVoyagerPage.test.tsx | 6 +- .../GraphQLVoyagerPage/GraphQLVoyagerPage.tsx | 51 +++++----- 6 files changed, 75 insertions(+), 99 deletions(-) create mode 100644 .changeset/tasty-jobs-help.md diff --git a/.changeset/tasty-jobs-help.md b/.changeset/tasty-jobs-help.md new file mode 100644 index 0000000000..02afa71656 --- /dev/null +++ b/.changeset/tasty-jobs-help.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-graphql-voyager': minor +--- + +Add the new GraphQL Voyager tool as a plugin for backstage, expose necessary API and components needed for it. diff --git a/plugins/graphql-voyager/README.md b/plugins/graphql-voyager/README.md index f2f5265e2f..fe87e1d843 100644 --- a/plugins/graphql-voyager/README.md +++ b/plugins/graphql-voyager/README.md @@ -22,11 +22,11 @@ In order to be able to navigate to the graphQL voyager page, a new route needs t ```tsx // packages/app/App.tsx - import { GraphQLVoyagerPage } from "@backstage/plugin-graphql-voyager"; + import { GraphQLVoyagerPage } from '@backstage/plugin-graphql-voyager'; const routes = ( - }/> + }/> ``` ### Configuration @@ -36,15 +36,15 @@ In order for the plugin to function correctly. GraphQL endpoints need to be adde Add your own configuration to the `packages/app/src/apis.ts` file the following way: ```ts -import { identityApiRef } from './IdentityApi'; -import { GraphQLVoyagerEndpoints } from './GraphQLVoyagerEndpoints'; +import { identityApiRef } from '@backstage/core-plugin-api'; +import { GraphQLVoyagerEndpoints } from '@backstage/plugin-graphql-voyager'; export const apis: AnyApiFactory[] = [ createApiFactory({ api: graphQlVoyagerApiRef, deps: { identityApi: identityApiRef }, factory: ({ identityApiRef }) => { - GraphQLVoyagerEndpoints.from([ + return GraphQLVoyagerEndpoints.from([ { id: `graphql-voyager-endpoint-id`, title: 'endpoint-title', diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index 1cc7bb19e6..02e8ec95ca 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-voyager", "description": "Backstage plugin for GraphQL Voyager", - "version": "0.1.0", + "version": "0.0.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -26,7 +26,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/theme": "workspace:^", - "@material-ui/core": "^4.9.13", + "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "graphql-voyager": "^1.0.0-rc.31", @@ -45,7 +45,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.47.0" + "msw": "^0.49.0" }, "files": [ "dist" diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx index a4a5533642..d2f9262983 100644 --- a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx @@ -17,100 +17,76 @@ import { GraphQLVoyagerEndpoint, introspectionQuery, } from '../../lib/api/types'; -import { Dispatch, SetStateAction, useEffect, useState } from 'react'; -import { Divider, makeStyles, Tab, Tabs, Typography } from '@material-ui/core'; +import { useState } from 'react'; +import { makeStyles, Tab, Tabs, Typography } from '@material-ui/core'; import React, { Suspense } from 'react'; import { BackstageTheme } from '@backstage/theme'; -import { Content, Progress } from '@backstage/core-components'; +import { Content, ErrorPanel, Progress } from '@backstage/core-components'; import { Voyager } from 'graphql-voyager'; +import useAsync from 'react-use/lib/useAsync'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(() => ({ root: { height: '100%', display: 'flex', flexFlow: 'column nowrap', }, - tabs: { - background: theme.palette.background.paper, - }, })); type GraphQLVoyagerBrowserProps = { endpoints: GraphQLVoyagerEndpoint[]; }; -type IntrospectionResult = { - data?: Object; -}; - const NoEndpoints = () => { return No endpoints available; }; +const VoyagerBrowserContent = ({ + endpoint, +}: { + endpoint: GraphQLVoyagerEndpoint; +}) => { + const { id, introspection, introspectionErrorMessage, voyagerProps } = + endpoint; + const { value, loading, error } = useAsync( + () => introspection(introspectionQuery), + [endpoint], + ); + + if (loading) { + return ; + } else if (error) { + return ; + } + return value.data ? ( + + ) : ( + + {introspectionErrorMessage} + + ); +}; + const VoyagerBrowser = (props: GraphQLVoyagerBrowserProps) => { const { endpoints } = props; const [tabIndex, setTabIndex] = useState(0); - const [isLoading, setIsLoading] = useState(true); - const [introspectionResult, setIntrospectionResult]: [ - IntrospectionResult, - Dispatch>, - ] = useState({}); const classes = useStyles(); - const { - voyagerProps = {}, - introspectionErrorMessage, - introspection, - } = endpoints[tabIndex]; - - useEffect(() => { - const fetchIntrospection = async () => { - setIsLoading(true); - - const data = await introspection(introspectionQuery); - setIntrospectionResult(data); - - setIsLoading(false); - }; - - fetchIntrospection(); - }, [tabIndex, introspection]); - - let voyagerContent: JSX.Element; - - if (isLoading) { - voyagerContent = Loading...; - } else if (!introspectionResult.data) { - voyagerContent = ( - - {introspectionErrorMessage} - - ); - } else { - voyagerContent = ( - - ); - } - return (
    }> setTabIndex(value)} indicatorColor="primary" > - {endpoints.map(({ title }, index) => ( - + {endpoints.map(({ title, id }, index) => ( + ))} - - {voyagerContent} + + +
    ); diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx index e40e81d7a6..67c257be2b 100644 --- a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx @@ -38,11 +38,7 @@ describe('GraphQLVoyagerPage', () => { ); expect(rendered.getByText('Welcome to Voyager!')).toBeInTheDocument(); - expect( - rendered.getByText( - 'Failed to load GraphQL endpoints, Error: No endpoints', - ), - ).toBeInTheDocument(); + expect(rendered.getByText('Error: No endpoints')).toBeInTheDocument(); }); it('should show GraphQLVoyagerBrowser', async () => { diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx index fa15eae86f..8b32a25f87 100644 --- a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx @@ -14,49 +14,48 @@ * limitations under the License. */ import React from 'react'; -import { Header, Page, Content, Progress } from '@backstage/core-components'; +import { + Header, + Page, + Content, + Progress, + ErrorPanel, +} from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; import 'graphql-voyager/dist/voyager.css'; import { graphQlVoyagerApiRef } from '../../lib/api'; import useAsync from 'react-use/lib/useAsync'; -import { Typography } from '@material-ui/core'; import { GraphQLVoyagerBrowser } from '../GraphQLVoyagerBrowser'; -/** @public */ -export const GraphQLVoyagerPage = () => { +type GraphQLVoyagerPageProps = { + title?: string; +}; + +const VoyagerContent = () => { const graphQLVoyagerApi = useApi(graphQlVoyagerApiRef); + const { value, loading, error } = useAsync(() => graphQLVoyagerApi.getEndpoints(), ); - let content: JSX.Element; - if (loading) { - content = ( - - - - ); + return ; } else if (error) { - content = ( - - - Failed to load GraphQL endpoints, {String(error)} - - - ); - } else { - content = ( - - - - ); + return ; } + return ; +}; + +/** @public */ +export const GraphQLVoyagerPage = (props: GraphQLVoyagerPageProps) => { + const { title = 'Welcome to Voyager!' } = props; return ( -
    - {content} +
    + + + ); }; From ab1c6c633866790db213d32180b51bdffe9cf4b1 Mon Sep 17 00:00:00 2001 From: MitchWijt Date: Wed, 1 Feb 2023 08:06:49 +0100 Subject: [PATCH 069/423] chore: export added page props Signed-off-by: MitchWijt --- plugins/graphql-voyager/api-report.md | 11 +++++++++-- .../GraphQLVoyagerPage/GraphQLVoyagerPage.tsx | 3 ++- plugins/graphql-voyager/src/index.ts | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/plugins/graphql-voyager/api-report.md b/plugins/graphql-voyager/api-report.md index 21423a8c30..9b488f9356 100644 --- a/plugins/graphql-voyager/api-report.md +++ b/plugins/graphql-voyager/api-report.md @@ -43,7 +43,14 @@ export class GraphQLVoyagerEndpoints implements GraphQLVoyagerApi { } // @public (undocumented) -export const GraphqlVoyagerPage: () => JSX.Element; +export const GraphqlVoyagerPage: ( + props: GraphQLVoyagerPageProps, +) => JSX.Element; + +// @public (undocumented) +export type GraphQLVoyagerPageProps = { + title?: string; +}; // @public (undocumented) export const graphqlVoyagerPlugin: BackstagePlugin< @@ -58,7 +65,7 @@ export const graphqlVoyagerPlugin: BackstagePlugin< export const introspectionQuery: string; // @public (undocumented) -export const Router: () => JSX.Element; +export const Router: (props: GraphQLVoyagerPageProps) => JSX.Element; // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx index 8b32a25f87..f3c4f70b4f 100644 --- a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx @@ -27,7 +27,8 @@ import { graphQlVoyagerApiRef } from '../../lib/api'; import useAsync from 'react-use/lib/useAsync'; import { GraphQLVoyagerBrowser } from '../GraphQLVoyagerBrowser'; -type GraphQLVoyagerPageProps = { +/** @public */ +export type GraphQLVoyagerPageProps = { title?: string; }; diff --git a/plugins/graphql-voyager/src/index.ts b/plugins/graphql-voyager/src/index.ts index 2e7852bc51..9e314c2eef 100644 --- a/plugins/graphql-voyager/src/index.ts +++ b/plugins/graphql-voyager/src/index.ts @@ -15,4 +15,5 @@ */ export { graphqlVoyagerPlugin, GraphqlVoyagerPage } from './plugin'; export { GraphQLVoyagerPage as Router } from './components'; +export type { GraphQLVoyagerPageProps } from './components'; export * from './lib/api'; From ddb465f65e5600a892f53977a55152dcda3c9454 Mon Sep 17 00:00:00 2001 From: MitchWijt Date: Thu, 2 Feb 2023 09:45:21 +0100 Subject: [PATCH 070/423] chore: improve description Signed-off-by: MitchWijt --- microsite/data/plugins/graphql-voyager.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/data/plugins/graphql-voyager.yaml b/microsite/data/plugins/graphql-voyager.yaml index 0bb56fb469..c6ebf5e412 100644 --- a/microsite/data/plugins/graphql-voyager.yaml +++ b/microsite/data/plugins/graphql-voyager.yaml @@ -3,7 +3,7 @@ title: GraphQL Voyager author: PostNL authorUrl: https://github.com/postnl category: Debugging -description: Integrates the GraphQL Voyager tool inside Backstage. +description: Integrates the GraphQL Voyager tool inside Backstage as a plugin. documentation: https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager iconUrl: https://res.cloudinary.com/apideck/image/upload/v1612724234/icons/graphql-voyager.png npmPackageName: '@backstage/plugin-graphql-voyager' From ebaf9381bf231bcf82f6957b1dfc11ff282fd9e9 Mon Sep 17 00:00:00 2001 From: MitchWijt Date: Thu, 2 Feb 2023 10:04:10 +0100 Subject: [PATCH 071/423] chore: yarn.lock collisions Signed-off-by: MitchWijt --- yarn.lock | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/yarn.lock b/yarn.lock index 4e56cb9839..274355903b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30118,6 +30118,20 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.5, node-fetch@npm:^2.6.7": + version: 2.6.9 + resolution: "node-fetch@npm:2.6.9" + dependencies: + whatwg-url: ^5.0.0 + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: acb04f9ce7224965b2b59e71b33c639794d8991efd73855b0b250921382b38331ffc9d61bce502571f6cc6e11a8905ca9b1b6d4aeb586ab093e2756a1fd190d0 + languageName: node + linkType: hard + "node-forge@npm:^1, node-forge@npm:^1.3.1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" From 060713cab7b1a750ad92f3ccffe305c49b9cbd67 Mon Sep 17 00:00:00 2001 From: Callum Linington Date: Thu, 2 Feb 2023 10:39:59 +0000 Subject: [PATCH 072/423] docs(azure): add note around token usage Signed-off-by: Callum Linington --- docs/integrations/azure/locations.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/integrations/azure/locations.md b/docs/integrations/azure/locations.md index 3b3e3dd5ed..93a7264af9 100644 --- a/docs/integrations/azure/locations.md +++ b/docs/integrations/azure/locations.md @@ -28,3 +28,5 @@ The configuration is a structure with two elements: - `host`: The DevOps host; only `dev.azure.com` is supported. - `token` (optional): A personal access token as expected by Azure DevOps. + +> Note: The token should just be provided as the raw token generated by Azure DevOps using the format `:{raw_token}` \ No newline at end of file From 19d4abf72c9e35b5c7ffde16fd94cb026312afad Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Thu, 2 Feb 2023 11:45:01 +0000 Subject: [PATCH 073/423] make `EventParams` typed for tidier event handling Signed-off-by: Brian Fletcher --- .changeset/thick-tables-travel.md | 5 +++++ plugins/events-node/src/api/EventParams.ts | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/thick-tables-travel.md diff --git a/.changeset/thick-tables-travel.md b/.changeset/thick-tables-travel.md new file mode 100644 index 0000000000..d74ed18b8a --- /dev/null +++ b/.changeset/thick-tables-travel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-events-node': patch +--- + +Make `EventParams` typed for implementing tidier event handling. diff --git a/plugins/events-node/src/api/EventParams.ts b/plugins/events-node/src/api/EventParams.ts index 6912827281..80a81fc495 100644 --- a/plugins/events-node/src/api/EventParams.ts +++ b/plugins/events-node/src/api/EventParams.ts @@ -17,7 +17,7 @@ /** * @public */ -export interface EventParams { +export interface EventParams { /** * Topic for which this event should be published. */ @@ -25,7 +25,7 @@ export interface EventParams { /** * Event payload. */ - eventPayload: unknown; + eventPayload: PayloadType; /** * Metadata (e.g., HTTP headers and similar for events received from external). */ From 0d2336696d6beefb5cff7de2b7d352863bb60b33 Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Thu, 2 Feb 2023 12:14:37 +0000 Subject: [PATCH 074/423] api-report Signed-off-by: Brian Fletcher --- plugins/events-node/api-report.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/events-node/api-report.md b/plugins/events-node/api-report.md index 51136fd301..21d2926570 100644 --- a/plugins/events-node/api-report.md +++ b/plugins/events-node/api-report.md @@ -14,8 +14,8 @@ export interface EventBroker { } // @public (undocumented) -export interface EventParams { - eventPayload: unknown; +export interface EventParams { + eventPayload: PayloadType; metadata?: Record; topic: string; } From 6856ab98f4e2d3ecbbd317a0dba8867addef583f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Feb 2023 12:15:00 +0000 Subject: [PATCH 075/423] Update dependency @asyncapi/react-component to v1.0.0-next.47 Signed-off-by: Renovate Bot --- .changeset/renovate-53e8b07.md | 5 +++ plugins/api-docs/package.json | 2 +- yarn.lock | 67 +++++++++++++++++----------------- 3 files changed, 40 insertions(+), 34 deletions(-) create mode 100644 .changeset/renovate-53e8b07.md diff --git a/.changeset/renovate-53e8b07.md b/.changeset/renovate-53e8b07.md new file mode 100644 index 0000000000..cb19d8fe8b --- /dev/null +++ b/.changeset/renovate-53e8b07.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Updated dependency `@asyncapi/react-component` to `1.0.0-next.47`. diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index e6dd3d6e1f..a23a123dc3 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -32,7 +32,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@asyncapi/react-component": "1.0.0-next.44", + "@asyncapi/react-component": "1.0.0-next.47", "@backstage/catalog-model": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", diff --git a/yarn.lock b/yarn.lock index 4e56cb9839..b04785483a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -217,14 +217,16 @@ __metadata: languageName: node linkType: hard -"@asyncapi/avro-schema-parser@npm:^0.3.0": - version: 0.3.0 - resolution: "@asyncapi/avro-schema-parser@npm:0.3.0" - checksum: 3086bc16a634600fe4d7c83f52f9558684c0d79193958fcb9275cacfb550700eaa718aa9ed1d3c89d1d77253f67e0f33ea91e137ef08aa722d67ded9373bf142 +"@asyncapi/avro-schema-parser@npm:^1.1.0": + version: 1.1.0 + resolution: "@asyncapi/avro-schema-parser@npm:1.1.0" + dependencies: + avsc: ^5.7.3 + checksum: 31bb6285a49f255e809088164ac4638103b2ec3e761c9c85be116af8abd9fe429626ba79ba6b3899d3823a77216741d9d793841e600145f2956328f3ce45a0e0 languageName: node linkType: hard -"@asyncapi/openapi-schema-parser@npm:^2.0.0": +"@asyncapi/openapi-schema-parser@npm:^2.0.1": version: 2.0.1 resolution: "@asyncapi/openapi-schema-parser@npm:2.0.1" dependencies: @@ -233,12 +235,12 @@ __metadata: languageName: node linkType: hard -"@asyncapi/parser@npm:^1.17.0": - version: 1.17.0 - resolution: "@asyncapi/parser@npm:1.17.0" +"@asyncapi/parser@npm:^1.18.0": + version: 1.18.0 + resolution: "@asyncapi/parser@npm:1.18.0" dependencies: "@apidevtools/json-schema-ref-parser": ^9.0.6 - "@asyncapi/specs": ^3.2.0 + "@asyncapi/specs": ^4.1.0 "@fmvilas/pseudo-yaml-ast": ^0.3.1 ajv: ^6.10.1 js-yaml: ^3.13.1 @@ -246,34 +248,35 @@ __metadata: lodash.clonedeep: ^4.5.0 node-fetch: ^2.6.0 tiny-merge-patch: ^0.1.2 - checksum: 6ac0bd3c9c90abf331cfdfb054dab047cf0324ee803633c2abc6dad96b12c64d033e4fb94907906adfb521ba16e9b23083b2a6acc7719ccd22154a7867046a95 + checksum: 7e08cae52990ce97299170faf99aaf27a8e2e02e6b03df28518d256f5687f394c26fd0a4aba235514ed4e3c2fd081a79321a489c20987ed22122afdb0b9ea0dd languageName: node linkType: hard -"@asyncapi/react-component@npm:1.0.0-next.44": - version: 1.0.0-next.44 - resolution: "@asyncapi/react-component@npm:1.0.0-next.44" +"@asyncapi/react-component@npm:1.0.0-next.47": + version: 1.0.0-next.47 + resolution: "@asyncapi/react-component@npm:1.0.0-next.47" dependencies: - "@asyncapi/avro-schema-parser": ^0.3.0 - "@asyncapi/openapi-schema-parser": ^2.0.0 - "@asyncapi/parser": ^1.17.0 + "@asyncapi/avro-schema-parser": ^1.1.0 + "@asyncapi/openapi-schema-parser": ^2.0.1 + "@asyncapi/parser": ^1.18.0 highlight.js: ^10.7.2 isomorphic-dompurify: ^0.13.0 marked: ^4.0.14 openapi-sampler: ^1.2.1 - react-icons: ^4.4.0 use-resize-observer: ^8.0.0 peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: 1d96db3bc6a4655884969a7639467836376c028df1a00f8930adf4e1b6ecb43e6a2d61df5c68e63d6c105d319fecb3f2ac0e4146274a81a874fbde17f4dbac1c + checksum: 837b6378f1188945a0e92d93efe71691a8dad120fad5624b58b325ec86c51435b874464ec0c47308ffacda9ee4d77ad8217881584bd74081f6db2211f09cc60c languageName: node linkType: hard -"@asyncapi/specs@npm:^3.2.0": - version: 3.2.0 - resolution: "@asyncapi/specs@npm:3.2.0" - checksum: 09971262aefc8844ab3e7c0c3652711862ac562dd5d614f23b496185690430a81df8e50eddba657f4141e0fd9548ef622fe6c20f4e3dec8054be23f774798335 +"@asyncapi/specs@npm:^4.1.0": + version: 4.1.0 + resolution: "@asyncapi/specs@npm:4.1.0" + dependencies: + "@types/json-schema": ^7.0.11 + checksum: 6e95f3c1ef7267480cdfc69f5a015f63b9101874289e31843a629346a3ea07490e3043b296a089bf3458e877c664d83d4b4738dcb53d37d7e13b75c7bc08c879 languageName: node linkType: hard @@ -4401,7 +4404,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-api-docs@workspace:plugins/api-docs" dependencies: - "@asyncapi/react-component": 1.0.0-next.44 + "@asyncapi/react-component": 1.0.0-next.47 "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/core-app-api": "workspace:^" @@ -14751,7 +14754,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.7, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.11, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.7, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": version: 7.0.11 resolution: "@types/json-schema@npm:7.0.11" checksum: 527bddfe62db9012fccd7627794bd4c71beb77601861055d87e3ee464f2217c85fca7a4b56ae677478367bbd248dbde13553312b7d4dbc702a2f2bbf60c4018d @@ -17172,6 +17175,13 @@ __metadata: languageName: node linkType: hard +"avsc@npm:^5.7.3": + version: 5.7.7 + resolution: "avsc@npm:5.7.7" + checksum: e3361aa88a61397b3345876263f79c8c8bfe013d849142202758205459a37e24cdbf02edc49ae019d6e82d93bbc7bc73e9e7fefca049aae91626bae28de4d1a9 + languageName: node + linkType: hard + "aws-lambda@npm:^1.0.7": version: 1.0.7 resolution: "aws-lambda@npm:1.0.7" @@ -33270,15 +33280,6 @@ __metadata: languageName: node linkType: hard -"react-icons@npm:^4.4.0": - version: 4.4.0 - resolution: "react-icons@npm:4.4.0" - peerDependencies: - react: "*" - checksum: dd93a1dcc8ac8a3cf46a2b33e80b586fa967331fa5fcb90d061abf276155a8363a331643e203d67cb9bab4261d00a757da854bcce1fce2c6e4258bf3e33f711b - languageName: node - linkType: hard - "react-immutable-proptypes@npm:2.2.0": version: 2.2.0 resolution: "react-immutable-proptypes@npm:2.2.0" From 02ac6ed2dbd4fd07e3e558a13b81729dd2ad62db Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Thu, 2 Feb 2023 13:20:27 +0000 Subject: [PATCH 076/423] rename type to TPayload Signed-off-by: Brian Fletcher --- plugins/events-node/api-report.md | 4 ++-- plugins/events-node/src/api/EventParams.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/events-node/api-report.md b/plugins/events-node/api-report.md index 21d2926570..8428003b85 100644 --- a/plugins/events-node/api-report.md +++ b/plugins/events-node/api-report.md @@ -14,8 +14,8 @@ export interface EventBroker { } // @public (undocumented) -export interface EventParams { - eventPayload: PayloadType; +export interface EventParams { + eventPayload: TPayload; metadata?: Record; topic: string; } diff --git a/plugins/events-node/src/api/EventParams.ts b/plugins/events-node/src/api/EventParams.ts index 80a81fc495..19a562aee0 100644 --- a/plugins/events-node/src/api/EventParams.ts +++ b/plugins/events-node/src/api/EventParams.ts @@ -17,7 +17,7 @@ /** * @public */ -export interface EventParams { +export interface EventParams { /** * Topic for which this event should be published. */ @@ -25,7 +25,7 @@ export interface EventParams { /** * Event payload. */ - eventPayload: PayloadType; + eventPayload: TPayload; /** * Metadata (e.g., HTTP headers and similar for events received from external). */ From 192f68d53c79a357197eabbc80e07e32d01ef749 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Thu, 2 Feb 2023 09:16:57 -0500 Subject: [PATCH 077/423] add trpc to api catalog Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- .../catalog-model/src/schema/kinds/API.v1alpha1.schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-model/src/schema/kinds/API.v1alpha1.schema.json b/packages/catalog-model/src/schema/kinds/API.v1alpha1.schema.json index fae1225764..3d5af710e0 100644 --- a/packages/catalog-model/src/schema/kinds/API.v1alpha1.schema.json +++ b/packages/catalog-model/src/schema/kinds/API.v1alpha1.schema.json @@ -46,7 +46,7 @@ "type": { "type": "string", "description": "The type of the API definition.", - "examples": ["openapi", "asyncapi", "graphql", "grpc"], + "examples": ["openapi", "asyncapi", "graphql", "grpc", "trpc"], "minLength": 1 }, "lifecycle": { From c79913beec85259172b777956536492a79a01057 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Thu, 2 Feb 2023 09:21:28 -0500 Subject: [PATCH 078/423] enable 'readOnly' configuration for PagerDutyCard This exposes a `readOnly` configuration option for the `PagerDutyCard` to address issue #16147. Signed-off-by: Mike Ball --- plugins/pagerduty/README.md | 20 +++++++++++++++- .../components/PagerDutyCard/index.test.tsx | 23 +++++++++++++++++++ .../src/components/PagerDutyCard/index.tsx | 14 +++++++++-- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/plugins/pagerduty/README.md b/plugins/pagerduty/README.md index 7b3124ab0f..98f769e9f3 100644 --- a/plugins/pagerduty/README.md +++ b/plugins/pagerduty/README.md @@ -6,7 +6,7 @@ # How it Works - The Backstage PagerDuty plugin allows PagerDuty information about a Backstage entity to be displayed within Backstage. This includes active incidents, recent change events, as well as the current on-call responders' names, email addresses, and links to their profiles in PagerDuty. -- Incidents can be manually triggered via the plugin with a user-provided description, which will in turn notify the current on-call responders. +- Incidents can be manually triggered via the plugin with a user-provided description, which will in turn notify the current on-call responders (Alternatively, the plugin can be configured with an optional `readOnly` property to suppress the ability to trigger incidents from the plugin). - _Note: This feature is only available when providing the `pagerduty.com/integration-key` annotation_ - Change events will be displayed in a separate tab. If the change event payload has additional links the first link only will be rendered. @@ -145,6 +145,24 @@ pagerduty: eventsBaseUrl: 'https://events.pagerduty.com/v2' ``` +To suppress the rendering of the actionable incident-creation button, the `PagerDutyCard` can also be instantiated in `readOnly` mode: + +```ts + +``` + +**WARNING**: In current implementation, the PagerDuty plugin requires the `/pagerduty` proxy endpoint be exposed by the Backstage backend as an unprotected endpoint, in effect enabling PagerDuty API access using the configured `PAGERDUTY_TOKEN` for any user or process with access to the `/pagerduty` Backstage backend endpoint. If you regard this as problematic, consider using the plugin in `readOnly` mode (``) using the following proxy configuration: + +```yaml +proxy: + '/pagerduty': + target: https://api.pagerduty.com + headers: + Authorization: Token token=${PAGERDUTY_TOKEN} + # prohibit the `/pagerduty` proxy endpoint from servicing non-GET requests + allowedMethods: ['GET'] +``` + # How to Uninstall 1. Remove any configuration added in Backstage yaml files, such as the proxy configuration in `app-config.yaml` and the integration key in an entity's annotations. diff --git a/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx b/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx index 85202a9cfc..34c8914fde 100644 --- a/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx +++ b/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx @@ -356,4 +356,27 @@ describe('PageDutyCard', () => { expect(getByText('Empty escalation policy')).toBeInTheDocument(); }); }); + + describe('when entity has all annotations but the plugin has been configured to be "read only"', () => { + it('queries by integration key but does not render the "Create Incident" button', async () => { + mockPagerDutyApi.getServiceByEntity = jest + .fn() + .mockImplementationOnce(async () => ({ service })); + + const { getByText, queryByTestId } = render( + wrapInTestApp( + + + + + , + ), + ); + await waitFor(() => !queryByTestId('progress')); + expect(getByText('Service Directory')).toBeInTheDocument(); + expect(getByText('Nice! No incidents found!')).toBeInTheDocument(); + expect(getByText('Empty escalation policy')).toBeInTheDocument(); + expect(() => getByText('Create Incident')).toThrow(); + }); + }); }); diff --git a/plugins/pagerduty/src/components/PagerDutyCard/index.tsx b/plugins/pagerduty/src/components/PagerDutyCard/index.tsx index 15967fae01..fd23166d88 100644 --- a/plugins/pagerduty/src/components/PagerDutyCard/index.tsx +++ b/plugins/pagerduty/src/components/PagerDutyCard/index.tsx @@ -54,7 +54,13 @@ export const isPluginApplicableToEntity = (entity: Entity) => ); /** @public */ -export const PagerDutyCard = () => { +export type PagerDutyCardProps = { + readOnly?: boolean; +}; + +/** @public */ +export const PagerDutyCard = (props: PagerDutyCardProps) => { + const { readOnly } = props; const { entity } = useEntity(); const pagerDutyEntity = getPagerDutyEntity(entity); const api = useApi(pagerDutyApiRef); @@ -156,7 +162,11 @@ export const PagerDutyCard = () => { title="PagerDuty" subheader={ } /> From 804746dd58e7b7b0f1a0ee98068658f460d6f0db Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Thu, 2 Feb 2023 09:27:34 -0500 Subject: [PATCH 079/423] add changeset noting PagerDutyCard `readOnly` prop Signed-off-by: Mike Ball --- .changeset/rich-bags-sleep.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/rich-bags-sleep.md diff --git a/.changeset/rich-bags-sleep.md b/.changeset/rich-bags-sleep.md new file mode 100644 index 0000000000..68a7716ca1 --- /dev/null +++ b/.changeset/rich-bags-sleep.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-pagerduty': patch +--- + +The PagerDutyCard now supports an optional `readOnly` property (``) for the suppressing the rendering of the "Create Incident" button from the Backstage UI. From 90bcf686a637ae275935ee636e49c2d51bc90dc5 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 2 Feb 2023 16:13:06 +0100 Subject: [PATCH 080/423] chore: use the maintainers group Signed-off-by: blam --- .github/CODEOWNERS | 150 ++++++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 82d868a408..7545302d93 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,78 +4,78 @@ # The last matching pattern takes precedence. # https://help.github.com/articles/about-codeowners/ -* @backstage/reviewers -yarn.lock @backstage/reviewers @backstage-service -*/yarn.lock @backstage/reviewers @backstage-service -/.changeset/cost-insights-* @backstage/reviewers @backstage/silver-lining -/.changeset @backstage/reviewers @backstage/techdocs-core -/cypress/src/integration/plugins/techdocs.spec.ts @backstage/reviewers @backstage/techdocs-core -/docs/assets/search @backstage/reviewers @backstage/techdocs-core -/docs/features/search @backstage/reviewers @backstage/techdocs-core -/docs/features/techdocs @backstage/reviewers @backstage/techdocs-core -/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 -/plugins/azure-devops @backstage/reviewers @marleypowell @awanlin -/plugins/azure-devops-backend @backstage/reviewers @marleypowell @awanlin -/plugins/azure-devops-common @backstage/reviewers @marleypowell @awanlin -/plugins/bitbucket-cloud-common @backstage/reviewers @pjungermann -/plugins/bitrise @backstage/reviewers @backstage/sda-se-reviewers -/plugins/catalog @backstage/reviewers @backstage/catalog-core -/plugins/catalog-* @backstage/reviewers @backstage/catalog-core -/plugins/catalog-backend-module-aws @backstage/reviewers @backstage/catalog-core @pjungermann -/plugins/catalog-backend-module-bitbucket-cloud @backstage/reviewers @backstage/catalog-core @pjungermann -/plugins/catalog-backend-module-msgraph @backstage/reviewers @backstage/catalog-core @pjungermann -/plugins/catalog-graph @backstage/reviewers @backstage/catalog-core @backstage/sda-se-reviewers -/plugins/circleci @backstage/reviewers @adamdmharvey -/plugins/cloudbuild @backstage/reviewers @trivago/ebarrios -/plugins/code-coverage @backstage/reviewers @alde @nissayeva -/plugins/code-coverage-backend @backstage/reviewers @alde @nissayeva -/plugins/cost-insights @backstage/reviewers @backstage/silver-lining -/plugins/cost-insights-* @backstage/reviewers @backstage/silver-lining -/plugins/events-backend @backstage/reviewers @pjungermann -/plugins/events-backend-module-aws-sqs @backstage/reviewers @pjungermann -/plugins/events-backend-module-azure @backstage/reviewers @pjungermann -/plugins/events-backend-module-bitbucket-cloud @backstage/reviewers @pjungermann -/plugins/events-backend-module-gerrit @backstage/reviewers @pjungermann -/plugins/events-backend-module-github @backstage/reviewers @pjungermann -/plugins/events-backend-module-gitlab @backstage/reviewers @pjungermann -/plugins/events-backend-test-utils @backstage/reviewers @pjungermann -/plugins/events-node @backstage/reviewers @pjungermann -/plugins/explore @backstage/reviewers @backstage/sda-se-reviewers -/plugins/explore-react @backstage/reviewers @backstage/sda-se-reviewers -/plugins/fossa @backstage/reviewers @backstage/sda-se-reviewers -/plugins/gcalendar @backstage/reviewers @szubster @ptychu @kielosz @alexrybch -/plugins/git-release-manager @backstage/reviewers @erikengervall -/plugins/home @backstage/reviewers @backstage/techdocs-core -/plugins/ilert @backstage/reviewers @yacut -/plugins/jenkins @backstage/reviewers @timja -/plugins/jenkins-backend @backstage/reviewers @timja -/plugins/kafka @backstage/reviewers @nirga @andrewthauer -/plugins/kafka-backend @backstage/reviewers @nirga @andrewthauer -/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/rollbar @backstage/reviewers @andrewthauer -/plugins/rollbar-backend @backstage/reviewers @andrewthauer -/plugins/scaffolder-backend-module-rails @backstage/reviewers @angeliski -/plugins/scaffolder-backend-module-yeoman @backstage/reviewers @pawelmitka -/plugins/search @backstage/reviewers @backstage/techdocs-core -/plugins/search-* @backstage/reviewers @backstage/techdocs-core -/plugins/sonarqube @backstage/reviewers @backstage/sda-se-reviewers -/plugins/stack-overflow @backstage/reviewers @backstage/techdocs-core -/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 -/tech-insights-tech-insights-node @backstage/reviewers @xantier @iain-b +* @backstage/maintainers +yarn.lock @backstage/maintainers @backstage-service +*/yarn.lock @backstage/maintainers @backstage-service +/.changeset/cost-insights-* @backstage/maintainers @backstage/silver-lining +/.changeset @backstage/maintainers @backstage/techdocs-core +/cypress/src/integration/plugins/techdocs.spec.ts @backstage/maintainers @backstage/techdocs-core +/docs/assets/search @backstage/maintainers @backstage/techdocs-core +/docs/features/search @backstage/maintainers @backstage/techdocs-core +/docs/features/techdocs @backstage/maintainers @backstage/techdocs-core +/docs/plugins/integrating-search-into-plugins.md @backstage/maintainers @backstage/techdocs-core +/packages/techdocs-cli @backstage/maintainers @backstage/techdocs-core +/packages/techdocs-cli-embedded-app @backstage/maintainers @backstage/techdocs-core +/plugins/adr @backstage/maintainers @kuangp +/plugins/adr-* @backstage/maintainers @kuangp +/plugins/allure @backstage/maintainers @deepak-bhardwaj-ps +/plugins/apache-airflow @backstage/maintainers @cmpadden +/plugins/api-docs @backstage/maintainers @backstage/sda-se-reviewers +/plugins/azure-devops @backstage/maintainers @marleypowell @awanlin +/plugins/azure-devops-backend @backstage/maintainers @marleypowell @awanlin +/plugins/azure-devops-common @backstage/maintainers @marleypowell @awanlin +/plugins/bitbucket-cloud-common @backstage/maintainers @pjungermann +/plugins/bitrise @backstage/maintainers @backstage/sda-se-reviewers +/plugins/catalog @backstage/maintainers @backstage/catalog-core +/plugins/catalog-* @backstage/maintainers @backstage/catalog-core +/plugins/catalog-backend-module-aws @backstage/maintainers @backstage/catalog-core @pjungermann +/plugins/catalog-backend-module-bitbucket-cloud @backstage/maintainers @backstage/catalog-core @pjungermann +/plugins/catalog-backend-module-msgraph @backstage/maintainers @backstage/catalog-core @pjungermann +/plugins/catalog-graph @backstage/maintainers @backstage/catalog-core @backstage/sda-se-reviewers +/plugins/circleci @backstage/maintainers @adamdmharvey +/plugins/cloudbuild @backstage/maintainers @trivago/ebarrios +/plugins/code-coverage @backstage/maintainers @alde @nissayeva +/plugins/code-coverage-backend @backstage/maintainers @alde @nissayeva +/plugins/cost-insights @backstage/maintainers @backstage/silver-lining +/plugins/cost-insights-* @backstage/maintainers @backstage/silver-lining +/plugins/events-backend @backstage/maintainers @pjungermann +/plugins/events-backend-module-aws-sqs @backstage/maintainers @pjungermann +/plugins/events-backend-module-azure @backstage/maintainers @pjungermann +/plugins/events-backend-module-bitbucket-cloud @backstage/maintainers @pjungermann +/plugins/events-backend-module-gerrit @backstage/maintainers @pjungermann +/plugins/events-backend-module-github @backstage/maintainers @pjungermann +/plugins/events-backend-module-gitlab @backstage/maintainers @pjungermann +/plugins/events-backend-test-utils @backstage/maintainers @pjungermann +/plugins/events-node @backstage/maintainers @pjungermann +/plugins/explore @backstage/maintainers @backstage/sda-se-reviewers +/plugins/explore-react @backstage/maintainers @backstage/sda-se-reviewers +/plugins/fossa @backstage/maintainers @backstage/sda-se-reviewers +/plugins/gcalendar @backstage/maintainers @szubster @ptychu @kielosz @alexrybch +/plugins/git-release-manager @backstage/maintainers @erikengervall +/plugins/home @backstage/maintainers @backstage/techdocs-core +/plugins/ilert @backstage/maintainers @yacut +/plugins/jenkins @backstage/maintainers @timja +/plugins/jenkins-backend @backstage/maintainers @timja +/plugins/kafka @backstage/maintainers @nirga @andrewthauer +/plugins/kafka-backend @backstage/maintainers @nirga @andrewthauer +/plugins/kubernetes @backstage/maintainers @backstage/warpspeed +/plugins/kubernetes-* @backstage/maintainers @backstage/warpspeed +/plugins/newrelic-dashboard @backstage/maintainers @mufaddal7 +/plugins/playlist @backstage/maintainers @kuangp +/plugins/playlist-* @backstage/maintainers @kuangp +/plugins/rollbar @backstage/maintainers @andrewthauer +/plugins/rollbar-backend @backstage/maintainers @andrewthauer +/plugins/scaffolder-backend-module-rails @backstage/maintainers @angeliski +/plugins/scaffolder-backend-module-yeoman @backstage/maintainers @pawelmitka +/plugins/search @backstage/maintainers @backstage/techdocs-core +/plugins/search-* @backstage/maintainers @backstage/techdocs-core +/plugins/sonarqube @backstage/maintainers @backstage/sda-se-reviewers +/plugins/stack-overflow @backstage/maintainers @backstage/techdocs-core +/plugins/stack-overflow-backend @backstage/maintainers @backstage/techdocs-core +/plugins/techdocs @backstage/maintainers @backstage/techdocs-core +/plugins/techdocs-* @backstage/maintainers @backstage/techdocs-core +/plugins/user-settings-backend @backstage/maintainers @backstage/sda-se-reviewers +/tech-insights-backend @backstage/maintainers @xantier @iain-b +/tech-insights-backend-module-jsonfc @backstage/maintainers @xantier @iain-b +/tech-insights-tech-insights-common @backstage/maintainers @xantier @iain-b +/tech-insights-tech-insights-node @backstage/maintainers @xantier @iain-b From bb74ee421a629248995b1a78692ed8fb3d6b8a8f Mon Sep 17 00:00:00 2001 From: Callum Linington Date: Thu, 2 Feb 2023 15:19:13 +0000 Subject: [PATCH 081/423] docs(azure): update token usage to align to implementation Signed-off-by: Callum Linington --- docs/integrations/azure/locations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/azure/locations.md b/docs/integrations/azure/locations.md index 93a7264af9..a0d933d824 100644 --- a/docs/integrations/azure/locations.md +++ b/docs/integrations/azure/locations.md @@ -29,4 +29,4 @@ The configuration is a structure with two elements: - `host`: The DevOps host; only `dev.azure.com` is supported. - `token` (optional): A personal access token as expected by Azure DevOps. -> Note: The token should just be provided as the raw token generated by Azure DevOps using the format `:{raw_token}` \ No newline at end of file +> Note: The token should just be provided as the raw token generated by Azure DevOps using the format `raw_token` with no base64 encoding. Formatting and base64'ing is handled by dependent libraries handling the Azure DevOps API \ No newline at end of file From f92679c3c0eb85ae878ce5638c70dc40519a5a55 Mon Sep 17 00:00:00 2001 From: ivgo Date: Thu, 2 Feb 2023 14:08:50 +0100 Subject: [PATCH 082/423] Add screenshot to README.md & missing repository information in package.json Signed-off-by: ivgo --- plugins/entity-validation/README.md | 2 ++ .../docs/entity-validation.png | Bin 0 -> 93063 bytes plugins/entity-validation/package.json | 5 +++++ 3 files changed, 7 insertions(+) create mode 100644 plugins/entity-validation/docs/entity-validation.png diff --git a/plugins/entity-validation/README.md b/plugins/entity-validation/README.md index 0e80ebd29b..1f864d0857 100644 --- a/plugins/entity-validation/README.md +++ b/plugins/entity-validation/README.md @@ -2,6 +2,8 @@ This plugin creates a new page in Backstage where the user can validate the entities. +![Entity Validation](./docs/entity-validation.png) + ## Getting started First of all, install the package in the `app` package by running the following command: diff --git a/plugins/entity-validation/docs/entity-validation.png b/plugins/entity-validation/docs/entity-validation.png new file mode 100644 index 0000000000000000000000000000000000000000..00cb5fafe06667d93ce2e7f1f60165eb76815926 GIT binary patch literal 93063 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

    _*Tp2!C!Fp2u6iZ!o6_lV}-5G1HrNHpz4?HEh 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 Date: Thu, 2 Feb 2023 16:40:10 +0100 Subject: [PATCH 083/423] chore: add screenshot to readme and alter changeset Signed-off-by: MitchWijt --- .changeset/tasty-jobs-help.md | 2 ++ plugins/graphql-voyager/README.md | 3 ++- plugins/graphql-voyager/src/assets/plugin.png | Bin 0 -> 338238 bytes 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 plugins/graphql-voyager/src/assets/plugin.png diff --git a/.changeset/tasty-jobs-help.md b/.changeset/tasty-jobs-help.md index 02afa71656..ad1df8fb8c 100644 --- a/.changeset/tasty-jobs-help.md +++ b/.changeset/tasty-jobs-help.md @@ -3,3 +3,5 @@ --- Add the new GraphQL Voyager tool as a plugin for backstage, expose necessary API and components needed for it. + +For more information on how to use this plugin and configure it, please navigate to the [README](https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager/README.md) of the plugin. diff --git a/plugins/graphql-voyager/README.md b/plugins/graphql-voyager/README.md index fe87e1d843..2c903cd9e5 100644 --- a/plugins/graphql-voyager/README.md +++ b/plugins/graphql-voyager/README.md @@ -2,7 +2,8 @@ Welcome to the graphql-voyager plugin! -_This plugin was created through the Backstage CLI_ +Presents a graph structure of your entire GraphQL API, with tabs for multiple API urls: +![](./src/assets/plugin.png) ## Getting started diff --git a/plugins/graphql-voyager/src/assets/plugin.png b/plugins/graphql-voyager/src/assets/plugin.png new file mode 100644 index 0000000000000000000000000000000000000000..602c7abde3cc6f58dbe580ca819e02becf338e70 GIT binary patch literal 338238 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

    BOe&laIKG6HJi{J`PDP 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%0DfO^-iV=ApiagD(I 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 literal 0 HcmV?d00001 From df8782378d9a00887713cee932f9f71d50c87c84 Mon Sep 17 00:00:00 2001 From: Callum Linington Date: Thu, 2 Feb 2023 15:44:32 +0000 Subject: [PATCH 084/423] chore: prettier Signed-off-by: Callum Linington --- docs/integrations/azure/locations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/azure/locations.md b/docs/integrations/azure/locations.md index a0d933d824..1fc476f418 100644 --- a/docs/integrations/azure/locations.md +++ b/docs/integrations/azure/locations.md @@ -29,4 +29,4 @@ The configuration is a structure with two elements: - `host`: The DevOps host; only `dev.azure.com` is supported. - `token` (optional): A personal access token as expected by Azure DevOps. -> Note: The token should just be provided as the raw token generated by Azure DevOps using the format `raw_token` with no base64 encoding. Formatting and base64'ing is handled by dependent libraries handling the Azure DevOps API \ No newline at end of file +> Note: The token should just be provided as the raw token generated by Azure DevOps using the format `raw_token` with no base64 encoding. Formatting and base64'ing is handled by dependent libraries handling the Azure DevOps API From 654228f15a7e0f0e9fbb34788363812b5d87461a Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 2 Feb 2023 17:07:23 +0100 Subject: [PATCH 085/423] chore: updating codeowners Signed-off-by: blam --- .github/CODEOWNERS | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 7545302d93..ba00be1242 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -8,14 +8,14 @@ yarn.lock @backstage/maintainers @backstage-service */yarn.lock @backstage/maintainers @backstage-service /.changeset/cost-insights-* @backstage/maintainers @backstage/silver-lining -/.changeset @backstage/maintainers @backstage/techdocs-core -/cypress/src/integration/plugins/techdocs.spec.ts @backstage/maintainers @backstage/techdocs-core -/docs/assets/search @backstage/maintainers @backstage/techdocs-core -/docs/features/search @backstage/maintainers @backstage/techdocs-core -/docs/features/techdocs @backstage/maintainers @backstage/techdocs-core -/docs/plugins/integrating-search-into-plugins.md @backstage/maintainers @backstage/techdocs-core -/packages/techdocs-cli @backstage/maintainers @backstage/techdocs-core -/packages/techdocs-cli-embedded-app @backstage/maintainers @backstage/techdocs-core +/.changeset @backstage/owners +/cypress/src/integration/plugins/techdocs.spec.ts @backstage/techdocs-core +/docs/assets/search @backstage/techdocs-core +/docs/features/search @backstage/techdocs-core +/docs/features/techdocs @backstage/techdocs-core +/docs/plugins/integrating-search-into-plugins.md @backstage/techdocs-core +/packages/techdocs-cli @backstage/techdocs-core +/packages/techdocs-cli-embedded-app @backstage/techdocs-core /plugins/adr @backstage/maintainers @kuangp /plugins/adr-* @backstage/maintainers @kuangp /plugins/allure @backstage/maintainers @deepak-bhardwaj-ps @@ -52,7 +52,7 @@ yarn.lock @backstage/maintainers @back /plugins/fossa @backstage/maintainers @backstage/sda-se-reviewers /plugins/gcalendar @backstage/maintainers @szubster @ptychu @kielosz @alexrybch /plugins/git-release-manager @backstage/maintainers @erikengervall -/plugins/home @backstage/maintainers @backstage/techdocs-core +/plugins/home @backstage/techdocs-core /plugins/ilert @backstage/maintainers @yacut /plugins/jenkins @backstage/maintainers @timja /plugins/jenkins-backend @backstage/maintainers @timja @@ -67,13 +67,13 @@ yarn.lock @backstage/maintainers @back /plugins/rollbar-backend @backstage/maintainers @andrewthauer /plugins/scaffolder-backend-module-rails @backstage/maintainers @angeliski /plugins/scaffolder-backend-module-yeoman @backstage/maintainers @pawelmitka -/plugins/search @backstage/maintainers @backstage/techdocs-core -/plugins/search-* @backstage/maintainers @backstage/techdocs-core +/plugins/search @backstage/techdocs-core +/plugins/search-* @backstage/techdocs-core /plugins/sonarqube @backstage/maintainers @backstage/sda-se-reviewers -/plugins/stack-overflow @backstage/maintainers @backstage/techdocs-core -/plugins/stack-overflow-backend @backstage/maintainers @backstage/techdocs-core -/plugins/techdocs @backstage/maintainers @backstage/techdocs-core -/plugins/techdocs-* @backstage/maintainers @backstage/techdocs-core +/plugins/stack-overflow @backstage/techdocs-core +/plugins/stack-overflow-backend @backstage/techdocs-core +/plugins/techdocs @backstage/techdocs-core +/plugins/techdocs-* @backstage/techdocs-core /plugins/user-settings-backend @backstage/maintainers @backstage/sda-se-reviewers /tech-insights-backend @backstage/maintainers @xantier @iain-b /tech-insights-backend-module-jsonfc @backstage/maintainers @xantier @iain-b From 802513dd9ffa339ff3b679e2177a3ca6f9642f31 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 2 Feb 2023 17:32:06 +0100 Subject: [PATCH 086/423] chore: remove extra codeowners Signed-off-by: blam --- .github/CODEOWNERS | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ba00be1242..a89028a324 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,7 +7,6 @@ * @backstage/maintainers yarn.lock @backstage/maintainers @backstage-service */yarn.lock @backstage/maintainers @backstage-service -/.changeset/cost-insights-* @backstage/maintainers @backstage/silver-lining /.changeset @backstage/owners /cypress/src/integration/plugins/techdocs.spec.ts @backstage/techdocs-core /docs/assets/search @backstage/techdocs-core From ac57d09f8fbcefa27c8caa409e1339eacfab5c34 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 2 Feb 2023 17:32:53 +0100 Subject: [PATCH 087/423] fix cost-insights too Signed-off-by: blam --- .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a89028a324..5a51bd8b95 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -35,8 +35,8 @@ yarn.lock @backstage/maintainers @back /plugins/cloudbuild @backstage/maintainers @trivago/ebarrios /plugins/code-coverage @backstage/maintainers @alde @nissayeva /plugins/code-coverage-backend @backstage/maintainers @alde @nissayeva -/plugins/cost-insights @backstage/maintainers @backstage/silver-lining -/plugins/cost-insights-* @backstage/maintainers @backstage/silver-lining +/plugins/cost-insights @backstage/silver-lining +/plugins/cost-insights-* @backstage/silver-lining /plugins/events-backend @backstage/maintainers @pjungermann /plugins/events-backend-module-aws-sqs @backstage/maintainers @pjungermann /plugins/events-backend-module-azure @backstage/maintainers @pjungermann From e32d73b26a04e0b3243787c7eeed87c720aa9b7d Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 2 Feb 2023 17:36:05 +0100 Subject: [PATCH 088/423] chore: fix Signed-off-by: blam --- .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5a51bd8b95..a89028a324 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -35,8 +35,8 @@ yarn.lock @backstage/maintainers @back /plugins/cloudbuild @backstage/maintainers @trivago/ebarrios /plugins/code-coverage @backstage/maintainers @alde @nissayeva /plugins/code-coverage-backend @backstage/maintainers @alde @nissayeva -/plugins/cost-insights @backstage/silver-lining -/plugins/cost-insights-* @backstage/silver-lining +/plugins/cost-insights @backstage/maintainers @backstage/silver-lining +/plugins/cost-insights-* @backstage/maintainers @backstage/silver-lining /plugins/events-backend @backstage/maintainers @pjungermann /plugins/events-backend-module-aws-sqs @backstage/maintainers @pjungermann /plugins/events-backend-module-azure @backstage/maintainers @pjungermann From 3201f1de3943d11c21a9ed7b8634c299764ac794 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 2 Feb 2023 17:41:33 +0100 Subject: [PATCH 089/423] chore: make changesets unowned Signed-off-by: blam --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a89028a324..3f9e390a85 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,7 +7,7 @@ * @backstage/maintainers yarn.lock @backstage/maintainers @backstage-service */yarn.lock @backstage/maintainers @backstage-service -/.changeset @backstage/owners +/.changeset /cypress/src/integration/plugins/techdocs.spec.ts @backstage/techdocs-core /docs/assets/search @backstage/techdocs-core /docs/features/search @backstage/techdocs-core From 6760ed19766d1240d9f7b4d76750a0e91d8c6314 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 2 Feb 2023 17:43:43 +0100 Subject: [PATCH 090/423] chore: only the .mds Signed-off-by: blam --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3f9e390a85..bb6f8da19b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,7 +7,7 @@ * @backstage/maintainers yarn.lock @backstage/maintainers @backstage-service */yarn.lock @backstage/maintainers @backstage-service -/.changeset +/.changeset/*.md /cypress/src/integration/plugins/techdocs.spec.ts @backstage/techdocs-core /docs/assets/search @backstage/techdocs-core /docs/features/search @backstage/techdocs-core From 3a0cf26a4a12af7e511c24e7d0886487303c8274 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Thu, 2 Feb 2023 12:31:14 -0500 Subject: [PATCH 091/423] add generated PagerDuty API report Signed-off-by: Mike Ball --- plugins/pagerduty/api-report.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/pagerduty/api-report.md b/plugins/pagerduty/api-report.md index 5bfe84e63f..2c8f9dea49 100644 --- a/plugins/pagerduty/api-report.md +++ b/plugins/pagerduty/api-report.md @@ -13,8 +13,10 @@ import { Entity } from '@backstage/catalog-model'; import { FetchApi } from '@backstage/core-plugin-api'; import { ReactNode } from 'react'; +// Warning: (ae-forgotten-export) The symbol "PagerDutyCardProps" needs to be exported by the entry point index.d.ts +// // @public (undocumented) -export const EntityPagerDutyCard: () => JSX.Element; +export const EntityPagerDutyCard: (props: PagerDutyCardProps) => JSX.Element; // @public (undocumented) const isPluginApplicableToEntity: (entity: Entity) => boolean; @@ -45,7 +47,7 @@ export type PagerDutyAssignee = { }; // @public (undocumented) -export const PagerDutyCard: () => JSX.Element; +export const PagerDutyCard: (props: PagerDutyCardProps) => JSX.Element; // @public (undocumented) export type PagerDutyChangeEvent = { From 335ce2a7a6fd86dcc04a51f00589f7e99b370854 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Feb 2023 18:33:10 +0000 Subject: [PATCH 092/423] chore(deps): bump http-cache-semantics in /microsite-next Bumps [http-cache-semantics](https://github.com/kornelski/http-cache-semantics) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/kornelski/http-cache-semantics/releases) - [Commits](https://github.com/kornelski/http-cache-semantics/compare/v4.1.0...v4.1.1) --- updated-dependencies: - dependency-name: http-cache-semantics dependency-type: indirect ... Signed-off-by: dependabot[bot] --- microsite-next/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index 5f27b0f062..54797053cb 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -6051,9 +6051,9 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0": - version: 4.1.0 - resolution: "http-cache-semantics@npm:4.1.0" - checksum: 974de94a81c5474be07f269f9fd8383e92ebb5a448208223bfb39e172a9dbc26feff250192ecc23b9593b3f92098e010406b0f24bd4d588d631f80214648ed42 + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 languageName: node linkType: hard From 9265d3fd7da3cfb66120e91043c39e364e860d76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Feb 2023 18:33:25 +0000 Subject: [PATCH 093/423] chore(deps): bump http-cache-semantics from 4.1.0 to 4.1.1 in /storybook Bumps [http-cache-semantics](https://github.com/kornelski/http-cache-semantics) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/kornelski/http-cache-semantics/releases) - [Commits](https://github.com/kornelski/http-cache-semantics/compare/v4.1.0...v4.1.1) --- updated-dependencies: - dependency-name: http-cache-semantics dependency-type: indirect ... Signed-off-by: dependabot[bot] --- storybook/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 7c73f5d0cc..8e5b2b8c56 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -6783,9 +6783,9 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.1.0": - version: 4.1.0 - resolution: "http-cache-semantics@npm:4.1.0" - checksum: 974de94a81c5474be07f269f9fd8383e92ebb5a448208223bfb39e172a9dbc26feff250192ecc23b9593b3f92098e010406b0f24bd4d588d631f80214648ed42 + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 languageName: node linkType: hard From e446c345bab799356466f7e3695f5a8094a7c9ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Feb 2023 18:41:13 +0000 Subject: [PATCH 094/423] chore(deps): bump http-cache-semantics from 4.1.0 to 4.1.1 Bumps [http-cache-semantics](https://github.com/kornelski/http-cache-semantics) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/kornelski/http-cache-semantics/releases) - [Commits](https://github.com/kornelski/http-cache-semantics/compare/v4.1.0...v4.1.1) --- updated-dependencies: - dependency-name: http-cache-semantics dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index cdf50e0c78..752aaf629f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25063,9 +25063,9 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0": - version: 4.1.0 - resolution: "http-cache-semantics@npm:4.1.0" - checksum: 974de94a81c5474be07f269f9fd8383e92ebb5a448208223bfb39e172a9dbc26feff250192ecc23b9593b3f92098e010406b0f24bd4d588d631f80214648ed42 + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 languageName: node linkType: hard From 960cbbc5d040c5bf2562de2f7325b49e1a09d748 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Thu, 2 Feb 2023 13:55:13 -0500 Subject: [PATCH 095/423] correct generated PagerDuty API report Signed-off-by: Mike Ball --- plugins/pagerduty/api-report.md | 7 +++++-- plugins/pagerduty/src/components/index.ts | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/pagerduty/api-report.md b/plugins/pagerduty/api-report.md index 2c8f9dea49..b460086976 100644 --- a/plugins/pagerduty/api-report.md +++ b/plugins/pagerduty/api-report.md @@ -13,8 +13,6 @@ import { Entity } from '@backstage/catalog-model'; import { FetchApi } from '@backstage/core-plugin-api'; import { ReactNode } from 'react'; -// Warning: (ae-forgotten-export) The symbol "PagerDutyCardProps" needs to be exported by the entry point index.d.ts -// // @public (undocumented) export const EntityPagerDutyCard: (props: PagerDutyCardProps) => JSX.Element; @@ -49,6 +47,11 @@ export type PagerDutyAssignee = { // @public (undocumented) export const PagerDutyCard: (props: PagerDutyCardProps) => JSX.Element; +// @public (undocumented) +export type PagerDutyCardProps = { + readOnly?: boolean; +}; + // @public (undocumented) export type PagerDutyChangeEvent = { id: string; diff --git a/plugins/pagerduty/src/components/index.ts b/plugins/pagerduty/src/components/index.ts index 17bb2c03dc..e7c1ff4e72 100644 --- a/plugins/pagerduty/src/components/index.ts +++ b/plugins/pagerduty/src/components/index.ts @@ -23,6 +23,8 @@ export type { PagerDutyUser, } from './types'; +export type { PagerDutyCardProps } from './PagerDutyCard'; + export { isPluginApplicableToEntity, isPluginApplicableToEntity as isPagerDutyAvailable, From 5ecab049d4e8d39c95425cbef90bd2d48651f234 Mon Sep 17 00:00:00 2001 From: Mark Shields <4237425+beejiujitsu@users.noreply.github.com> Date: Thu, 2 Feb 2023 11:03:50 -0500 Subject: [PATCH 096/423] feat(docs): IAP, where to find audience value Signed-off-by: Mark Shields <4237425+beejiujitsu@users.noreply.github.com> --- docs/auth/google/gcp-iap-auth.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/auth/google/gcp-iap-auth.md b/docs/auth/google/gcp-iap-auth.md index f9a78bbc71..ce08f87865 100644 --- a/docs/auth/google/gcp-iap-auth.md +++ b/docs/auth/google/gcp-iap-auth.md @@ -29,7 +29,10 @@ auth: jwtHeader: x-custom-header # Optional: Only if you are using a custom header for the IAP JWT ``` -You can find the project number and service ID in the Google Cloud Console. +The full `audience` value can be obtained by visiting your [Identity-Aware Proxy Google Cloud console](https://console.cloud.google.com/security/iap), selecting your project, finding your Backend Service to proxy, clicking the 3 vertical dots then "Get JWT Audience Code", and copying from the resulting popup, which will look similar to the following: + +Screenshot 2023-02-02 at 10 58 10 AM + This config section must be in place for the provider to load at all. Now let's add the provider itself. From 39e2fac63f10ea5101171aa1ff64d36717b27623 Mon Sep 17 00:00:00 2001 From: Mark Shields <4237425+beejiujitsu@users.noreply.github.com> Date: Thu, 2 Feb 2023 14:34:33 -0500 Subject: [PATCH 097/423] upload screeenshot as asset Signed-off-by: Mark Shields <4237425+beejiujitsu@users.noreply.github.com> --- .../auth/gcp-iap-jwt-audience-code-popup.png | Bin 0 -> 38032 bytes docs/auth/google/gcp-iap-auth.md | 3 +-- 2 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 docs/assets/auth/gcp-iap-jwt-audience-code-popup.png diff --git a/docs/assets/auth/gcp-iap-jwt-audience-code-popup.png b/docs/assets/auth/gcp-iap-jwt-audience-code-popup.png new file mode 100644 index 0000000000000000000000000000000000000000..72b69b3b01f6f0230c14f12eda50fed00f2d6213 GIT binary patch literal 38032 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

    7*awPeQ`v}f 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 literal 0 HcmV?d00001 diff --git a/docs/auth/google/gcp-iap-auth.md b/docs/auth/google/gcp-iap-auth.md index ce08f87865..36eece85c5 100644 --- a/docs/auth/google/gcp-iap-auth.md +++ b/docs/auth/google/gcp-iap-auth.md @@ -31,8 +31,7 @@ auth: The full `audience` value can be obtained by visiting your [Identity-Aware Proxy Google Cloud console](https://console.cloud.google.com/security/iap), selecting your project, finding your Backend Service to proxy, clicking the 3 vertical dots then "Get JWT Audience Code", and copying from the resulting popup, which will look similar to the following: -Screenshot 2023-02-02 at 10 58 10 AM - +![Identity-Aware Proxy JWT Audience Code popup](../../assets/auth/gcp-iap-jwt-audience-code-popup.png) This config section must be in place for the provider to load at all. Now let's add the provider itself. From 6c70919f1ad6412d1d7f8bba5e20a184428c965c Mon Sep 17 00:00:00 2001 From: Christopher Kruse Date: Mon, 30 Jan 2023 10:58:49 -0800 Subject: [PATCH 098/423] fix: better error around github teams not found Adds a literate error around the `createGithubRepoWithCollaboratorsAndTopics` function in order to provide that error in the scaffolder logs. Prior to this, the only thing returned was "Not Found," which didn't provide much information for someone trying to determine what failed in the background. Fixes #10160 Signed-off-by: Christopher Kruse --- .changeset/olive-ads-peel.md | 5 ++++ .../actions/builtin/github/helpers.ts | 23 +++++++++++------ .../actions/builtin/publish/github.test.ts | 25 +++++++++++++++++++ 3 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 .changeset/olive-ads-peel.md diff --git a/.changeset/olive-ads-peel.md b/.changeset/olive-ads-peel.md new file mode 100644 index 0000000000..7a7c73ddb7 --- /dev/null +++ b/.changeset/olive-ads-peel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Provide better error messaging when GitHub fails due to missing team definitions diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts index dae5e16374..25f343da9e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts @@ -190,13 +190,22 @@ export async function createGithubRepoWithCollaboratorsAndTopics( if (access?.startsWith(`${owner}/`)) { const [, team] = access.split('/'); - await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ - org: owner, - team_slug: team, - owner, - repo, - permission: 'admin', - }); + try { + await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ + org: owner, + team_slug: team, + owner, + repo, + permission: 'admin', + }); + } catch (e) { + if (e.data.message === 'Not Found') { + const message = `Received 'Not Found' from the API; one of org: + ${owner}, team: ${team} or repo: ${repo} was not found within GitHub.`; + logger.warn(message); + throw new Error(message, { cause: e }); + } + } // No need to add access if it's the person who owns the personal account } else if (access && access !== owner) { await client.rest.repos.addCollaborator({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts index 8ead489ea4..0edeafecfd 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts @@ -518,6 +518,31 @@ describe('publish:github', () => { }); }); + it('should provide an adequate failure message when adding access', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + mockOctokit.rest.teams.addOrUpdateRepoPermissionsInOrg.mockRejectedValue({ + status: 404, + data: { + message: 'Not Found', + documentation_url: + 'https://docs.github.com/en/rest/teams/teams#add-or-update-team-repository-permissions', + }, + }); + await expect(action.handler(mockContext)).rejects.toThrow( + "Received 'Not Found' from the API;", + ); + }); + it('should add outside collaborators when provided', async () => { mockOctokit.rest.users.getByUsername.mockResolvedValue({ data: { type: 'User' }, From 8cd21b9b596f78758c46a249fd8fde979390c4d2 Mon Sep 17 00:00:00 2001 From: Christopher Kruse Date: Thu, 2 Feb 2023 11:40:44 -0800 Subject: [PATCH 099/423] fix: check for teams before creating repository Shifts the team check for the 'access' parameter to happen prior to the repo creation, so that repositories are not created and have no permissions set on them due to missing teams. Signed-off-by: Christopher Kruse --- .../builtin/github/githubRepoCreate.test.ts | 8 +++ .../actions/builtin/github/helpers.ts | 46 +++++++++------ .../actions/builtin/publish/github.test.ts | 56 ++++++++++++++----- 3 files changed, 81 insertions(+), 29 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts index f15747fd6b..a9ef8c3daa 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts @@ -42,6 +42,7 @@ const mockOctokit = { }, teams: { addOrUpdateRepoPermissionsInOrg: jest.fn(), + getByName: jest.fn(), }, }, }; @@ -96,6 +97,13 @@ describe('github:repo:create', () => { data: { type: 'Organization' }, }); + mockOctokit.rest.teams.getByName.mockResolvedValue({ + data: { + name: 'blam', + id: 42, + }, + }); + mockOctokit.rest.repos.createInOrg.mockResolvedValue({ data: {} }); await action.handler(mockContext); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts index 25f343da9e..dc8c4cd856 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts @@ -135,6 +135,10 @@ export async function createGithubRepoWithCollaboratorsAndTopics( username: owner, }); + if (access?.startsWith(`${owner}/`)) { + await validateAccessTeam(client, access); + } + const repoCreationPromise = user.data.type === 'Organization' ? client.rest.repos.createInOrg({ @@ -190,22 +194,13 @@ export async function createGithubRepoWithCollaboratorsAndTopics( if (access?.startsWith(`${owner}/`)) { const [, team] = access.split('/'); - try { - await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ - org: owner, - team_slug: team, - owner, - repo, - permission: 'admin', - }); - } catch (e) { - if (e.data.message === 'Not Found') { - const message = `Received 'Not Found' from the API; one of org: - ${owner}, team: ${team} or repo: ${repo} was not found within GitHub.`; - logger.warn(message); - throw new Error(message, { cause: e }); - } - } + await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ + org: owner, + team_slug: team, + owner, + repo, + permission: 'admin', + }); // No need to add access if it's the person who owns the personal account } else if (access && access !== owner) { await client.rest.repos.addCollaborator({ @@ -360,3 +355,22 @@ function extractCollaboratorName( if ('user' in collaborator) return collaborator.user; return collaborator.team; } + +async function validateAccessTeam(client: Octokit, access: string) { + const [org, team_slug] = access.split('/'); + try { + // Below rule disabled because of a 'getByName' check for a different library + // incorrectly triggers here. + // eslint-disable-next-line testing-library/no-await-sync-query + await client.rest.teams.getByName({ + org, + team_slug, + }); + } catch (e) { + if (e.response.data.message === 'Not Found') { + const message = `Received 'Not Found' from the API; one of org: + ${org} or team: ${team_slug} was not found within GitHub.`; + throw new Error(message, { cause: e }); + } + } +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts index 0edeafecfd..94b51f3e94 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts @@ -45,6 +45,7 @@ const mockOctokit = { replaceAllTopics: jest.fn(), }, teams: { + getByName: jest.fn(), addOrUpdateRepoPermissionsInOrg: jest.fn(), }, }, @@ -96,11 +97,41 @@ describe('publish:github', () => { }); }); + it('should fail to create if the team is not found in the org', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'Organization' }, + }); + + mockOctokit.rest.teams.getByName.mockRejectedValue({ + response: { + status: 404, + data: { + message: 'Not Found', + documentation_url: + 'https://docs.github.com/en/rest/teams/teams#add-or-update-team-repository-permissions', + }, + }, + }); + + await expect(action.handler(mockContext)).rejects.toThrow( + "Received 'Not Found' from the API;", + ); + + expect(mockOctokit.rest.repos.createInOrg).not.toHaveBeenCalled(); + }); + it('should call the githubApis with the correct values for createInOrg', async () => { mockOctokit.rest.users.getByUsername.mockResolvedValue({ data: { type: 'Organization' }, }); + mockOctokit.rest.teams.getByName.mockResolvedValue({ + data: { + name: 'blam', + id: 42, + }, + }); + mockOctokit.rest.repos.createInOrg.mockResolvedValue({ data: {} }); await action.handler(mockContext); @@ -523,24 +554,23 @@ describe('publish:github', () => { data: { type: 'User' }, }); - mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ - data: { - clone_url: 'https://github.com/clone/url.git', - html_url: 'https://github.com/html/url', - }, - }); - - mockOctokit.rest.teams.addOrUpdateRepoPermissionsInOrg.mockRejectedValue({ - status: 404, - data: { - message: 'Not Found', - documentation_url: - 'https://docs.github.com/en/rest/teams/teams#add-or-update-team-repository-permissions', + mockOctokit.rest.teams.getByName.mockRejectedValue({ + response: { + status: 404, + data: { + message: 'Not Found', + documentation_url: + 'https://docs.github.com/en/rest/teams/teams#add-or-update-team-repository-permissions', + }, }, }); await expect(action.handler(mockContext)).rejects.toThrow( "Received 'Not Found' from the API;", ); + + expect( + mockOctokit.rest.repos.createForAuthenticatedUser, + ).not.toHaveBeenCalled(); }); it('should add outside collaborators when provided', async () => { From d51668882d678bbaf971ea3d4f9e73c020e3491d Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Thu, 2 Feb 2023 16:48:00 -0500 Subject: [PATCH 100/423] updates catalog-model changeset to include the tRPC API type Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- .changeset/many-pans-unite.md | 5 +++++ .../components/GraphQlDefinitionWidget/GraphQlDefinition.tsx | 2 +- .../TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/many-pans-unite.md diff --git a/.changeset/many-pans-unite.md b/.changeset/many-pans-unite.md new file mode 100644 index 0000000000..59c068cec1 --- /dev/null +++ b/.changeset/many-pans-unite.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-model': minor +--- + +Adds the tRPC API type to the catalog. diff --git a/plugins/api-docs/src/components/GraphQlDefinitionWidget/GraphQlDefinition.tsx b/plugins/api-docs/src/components/GraphQlDefinitionWidget/GraphQlDefinition.tsx index 3dbe941be3..d3fddf70cf 100644 --- a/plugins/api-docs/src/components/GraphQlDefinitionWidget/GraphQlDefinition.tsx +++ b/plugins/api-docs/src/components/GraphQlDefinitionWidget/GraphQlDefinition.tsx @@ -44,7 +44,7 @@ type Props = { definition: string; }; -export const GraphQlDefinition: React.FC = ({ definition }: Props) => { +export const GraphQlDefinition = ({ definition }: Props) => { const classes = useStyles(); const schema = buildSchema(definition); diff --git a/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx b/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx index 81bec09769..af73335dbd 100644 --- a/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx @@ -24,7 +24,7 @@ export type TrpcApiDefinitionWidgetProps = { }; /** @public */ -export const TrpcApiDefinitionWidget: React.FC = ( +export const TrpcApiDefinitionWidget = ( props: TrpcApiDefinitionWidgetProps, ) => { const { definition } = props; From 799fe4a97886684018bb34478072dd331fd3f9b5 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Thu, 2 Feb 2023 16:58:26 -0500 Subject: [PATCH 101/423] correct grammar typo in changeset Signed-off-by: Mike Ball --- .changeset/rich-bags-sleep.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/rich-bags-sleep.md b/.changeset/rich-bags-sleep.md index 68a7716ca1..14312ac7f4 100644 --- a/.changeset/rich-bags-sleep.md +++ b/.changeset/rich-bags-sleep.md @@ -2,4 +2,4 @@ '@backstage/plugin-pagerduty': patch --- -The PagerDutyCard now supports an optional `readOnly` property (``) for the suppressing the rendering of the "Create Incident" button from the Backstage UI. +The PagerDutyCard now supports an optional `readOnly` property (``) for suppressing the rendering of the "Create Incident" button from the Backstage UI. From 560fd3e6ae27d0aaecf44a0fe48a796301d8de7c Mon Sep 17 00:00:00 2001 From: Waldir Montoya Date: Thu, 2 Feb 2023 21:19:02 -0500 Subject: [PATCH 102/423] Update the ecosystem model section of the docs Signed-off-by: Waldir Montoya --- .../permission-framework-overview.drawio.svg | 2 +- .../software-model-entities.drawio.svg | 2 +- .../features/software-catalog/system-model.md | 23 +++++++++++++++++++ docs/permissions/overview.md | 2 ++ 4 files changed, 27 insertions(+), 2 deletions(-) mode change 100755 => 100644 docs/assets/software-catalog/software-model-entities.drawio.svg diff --git a/docs/assets/permissions/permission-framework-overview.drawio.svg b/docs/assets/permissions/permission-framework-overview.drawio.svg index c7e628f8a6..3740384748 100644 --- a/docs/assets/permissions/permission-framework-overview.drawio.svg +++ b/docs/assets/permissions/permission-framework-overview.drawio.svg @@ -1,4 +1,4 @@ -
    User
    User
    Plugin
    Plugin
    Permission Response
    Permission Response
    Permission Framework
    Permission Framework
    Action
    (Read request)
    Action...
    Resources
    Resources
    Resource read permission
    Resource read...
    Permission Policy
    Permission Policy
    Permission Request
    Permission Request
    Provided by Backstage
    Provided by Backstage
    Configured by integrators
    Configured by integrators
    Configured by plugin authors
    Configured by plugin authors
    Permission Backend
    Permission hooks
    Integration helpers
    ...
    Permission Backend...
    1
    1
    2
    2
    3
    3
    4
    4
    Text is not SVG - cannot display
    \ No newline at end of file +
    User
    User
    Plugin
    Plugin
    Permission Response
    Permission Response
    Permission Framework
    Permission Framework
    Action
    (Read request)
    Action...
    Resources
    Resources
    Resource read permission
    Resource read...
    Permission Policy
    Permission Policy
    Permission Request
    Permission Request
    Provided by Backstage
    Provided by Backstage
    Configured by integrators
    Configured by integrators
    Configured by plugin authors
    Configured by plugin authors
    Permission Backend
    Permission hooks
    Integration helpers
    ...
    Permission Backend...
    1
    1
    2
    2
    3
    3
    4
    4
    5
    5
    User gets a response
    User gets a response
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/docs/assets/software-catalog/software-model-entities.drawio.svg b/docs/assets/software-catalog/software-model-entities.drawio.svg old mode 100755 new mode 100644 index e14cc93e62..d087583245 --- a/docs/assets/software-catalog/software-model-entities.drawio.svg +++ b/docs/assets/software-catalog/software-model-entities.drawio.svg @@ -1,4 +1,4 @@ -
    Domain
    Domain
    partOf
    partOf
    System
    System
    dependsOn
    dependsOn
    partOf
    partOf
    Resource
    (e.g. SQL Database, S3 bucket, ...)
    Resource...
    consumesAPI
    consumesAPI
    API
    (e.g. OpenAPI, gRPC API, Avro, Dataset, ...)
    API...
    providesAPI
    providesAPI
    partOf
    partOf
    Component
    (e.g. backend service, data pipeline ...)
    Component...
    partOf
    partOf
    dependsOn
    dependsOn
    Text is not SVG - cannot display
    \ No newline at end of file +
    Domain
    (e.g.  domain
    models, metrics, KPIs, business purpose)
    Domain...
    partOf
    partOf
    System
    Collection of entities that cooperate to perform some function
    System...
    dependsOn
    dependsOn
    partOf
    partOf
    Resource
    (e.g. SQL Database, S3 bucket, ...)
    Resource...
    consumesAPI
    consumesAPI
    API
    (e.g. OpenAPI, gRPC API, Avro, Dataset, ...)
    API...
    providesAPI
    providesAPI
    partOf
    partOf
    Component
    (e.g. backend service, data pipeline ...)
    Component...
    partOf
    partOf
    dependsOn
    dependsOn
    Kind: Group
    Kind: Group
    Kind: User
    Kind: User
    OwnerOf
    OwnerOf
    OwnedBy
    OwnedBy
    Service
    Service
    website
    website
    website
    website
    Types
    Types
    service
    service
    website
    website
    library
    library
    asyncapi
    asyncapi
    graphql
    graphql
    grpc
    grpc
    Types
    Types
    openapi
    openapi
    business-unit
    business-unit
    product-area
    product-area
    root
    root
    Types
    Types
    team
    team
    s3-bucket
    s3-bucket
    cluster
    cluster
    Types
    Types
    database
    database
    Kind: Template
    Parameters rendered in the
    frontend and the steps executed in  the scaffolding process
    Kind: Template...
    Kind: Location
    a marker that references other places to look for catalog data
    Kind: Location...
    memberOf
    memberOf
    hasMember
    hasMember
    parentOf
    parentOf
    childOf
    childOf
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/docs/features/software-catalog/system-model.md b/docs/features/software-catalog/system-model.md index 409f3e8450..a71bfefc39 100644 --- a/docs/features/software-catalog/system-model.md +++ b/docs/features/software-catalog/system-model.md @@ -108,3 +108,26 @@ domain would come with some documentation on how to accept payments for a new product or use-case, share the same entity types in their APIs, and integrate well with each other. Other domains could be “Content Ingestion”, “Ads” or “Search”. + +### User + +A user describes a person, such as an employee, a contractor, or similar. + +### Group + +A group describes an organizational entity, such as for example a team, a +business unit, or a loose collection of people in an interest group. + +### Location + +A location is a marker that references other places to look for catalog data. + +### Type + +The type field in the system has no set meaning. It is up to the user to assign their own types and use them as desired, such as for link validation or creating custom UI components. Some common pre-defined types are depicted in the ecosystem modeling diagram. + +### Template + +A template definition describes both the parameters that are rendered in the +frontend part of the scaffolding wizard, and the steps that are executed when +scaffolding that component. diff --git a/docs/permissions/overview.md b/docs/permissions/overview.md index b972814aeb..693f848c82 100644 --- a/docs/permissions/overview.md +++ b/docs/permissions/overview.md @@ -34,6 +34,8 @@ The permission framework was designed with a few key properties in mind: 4. An authorization decision is sent to the plugin from the permission backend. +5. The user is either granted access or an error is shown. The plugin is responsible for implementing a response to the user. + ## How do I get started? See the "[getting started](./getting-started.md)" permission documentation for Backstage integrators. From f9ae9c3aa5dd746a313d1ab354ca7cec36e86d1e Mon Sep 17 00:00:00 2001 From: Amritpal Nagra Date: Thu, 2 Feb 2023 23:15:13 +0530 Subject: [PATCH 103/423] change hyper link text to be descriptive, rather than as text Signed-off-by: Amritpal Nagra --- docs/features/software-templates/writing-templates.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 71aa0ab758..6cab3947b1 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -112,11 +112,11 @@ steps which would be rendered as different steps in the scaffolder plugin frontend. Each `Step` is `JSONSchema` with some extra goodies for styling what it might -look like in the frontend. For these steps we rely very heavily on this library: -https://github.com/rjsf-team/react-jsonschema-form. They have some great docs -too here: https://react-jsonschema-form.readthedocs.io/ and a playground where -you can play around with some examples here -https://rjsf-team.github.io/react-jsonschema-form. +look like in the frontend. For these steps we rely very heavily on this +[library](https://github.com/rjsf-team/react-jsonschema-form). They have some +[great docs](https://react-jsonschema-form.readthedocs.io/) and a +[playground](https://rjsf-team.github.io/react-jsonschema-form) where you can +play around with some examples. There's another option for that library called `uiSchema` which we've taken advantage of, and we've merged it with the existing `JSONSchema` that you From 855be5bf86b52ff4f7e35be12bf0d90a5e681053 Mon Sep 17 00:00:00 2001 From: Amritpal Nagra Date: Fri, 3 Feb 2023 14:34:58 +0530 Subject: [PATCH 104/423] update url to point to new docs Signed-off-by: Amritpal Nagra --- docs/features/software-templates/writing-templates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 6cab3947b1..a272f05f3f 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -114,7 +114,7 @@ frontend. Each `Step` is `JSONSchema` with some extra goodies for styling what it might look like in the frontend. For these steps we rely very heavily on this [library](https://github.com/rjsf-team/react-jsonschema-form). They have some -[great docs](https://react-jsonschema-form.readthedocs.io/) and a +[great docs](https://rjsf-team.github.io/react-jsonschema-form/docs/) and a [playground](https://rjsf-team.github.io/react-jsonschema-form) where you can play around with some examples. From 4b8b2faf8623757963e3f55ba17cdf293b3c90ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Fri, 3 Feb 2023 10:11:21 +0100 Subject: [PATCH 105/423] fix api reports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- plugins/api-docs/api-report.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/api-docs/api-report.md b/plugins/api-docs/api-report.md index 070e950202..a4f61872f2 100644 --- a/plugins/api-docs/api-report.md +++ b/plugins/api-docs/api-report.md @@ -175,7 +175,9 @@ export const ProvidingComponentsCard: (props: { }) => JSX.Element; // @public (undocumented) -export const TrpcApiDefinitionWidget: React_2.FC; +export const TrpcApiDefinitionWidget: ( + props: TrpcApiDefinitionWidgetProps, +) => JSX.Element; // @public (undocumented) export type TrpcApiDefinitionWidgetProps = { From 9cfcdb99586e15ab6b630f118675c8c1ddbb6bc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MALIN=20WID=C3=88N?= Date: Wed, 21 Dec 2022 14:43:54 +0100 Subject: [PATCH 106/423] create a new branch with every thing from PR #14868 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MALIN WIDÈN --- cypress/support/commands.ts | 52 + cypress/support/e2e.ts | 35 + packages/techdocs-cli/cypress.config.js | 30 + packages/techdocs-cli/cypress.json | 17 - ...eSnapshot - Backstage TechDocs Page #0.png | Bin ... toMatchImageSnapshot - MkDocs Page #0.png | Bin .../backstage_serve.cy.js} | 4 +- .../mkdocs_serve.cy.js} | 4 +- .../techdocs-cli/cypress/plugins/index.js | 41 - .../cypress/support/{index.js => e2e.js} | 2 +- packages/techdocs-cli/package.json | 2 +- yarn.lock | 1221 ++--------------- 12 files changed, 260 insertions(+), 1148 deletions(-) create mode 100644 cypress/support/commands.ts create mode 100644 cypress/support/e2e.ts create mode 100644 packages/techdocs-cli/cypress.config.js delete mode 100644 packages/techdocs-cli/cypress.json rename packages/techdocs-cli/cypress/{integration => e2e}/__image_snapshots__/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png (100%) rename packages/techdocs-cli/cypress/{integration => e2e}/__image_snapshots__/TechDocs Live Preview - MkDocs Serve toMatchImageSnapshot - MkDocs Page #0.png (100%) rename packages/techdocs-cli/cypress/{integration/backstage_serve.js => e2e/backstage_serve.cy.js} (94%) rename packages/techdocs-cli/cypress/{integration/mkdocs_serve.js => e2e/mkdocs_serve.cy.js} (94%) delete mode 100644 packages/techdocs-cli/cypress/plugins/index.js rename packages/techdocs-cli/cypress/support/{index.js => e2e.js} (94%) diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts new file mode 100644 index 0000000000..fd4db77d61 --- /dev/null +++ b/cypress/support/commands.ts @@ -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. + */ + +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts new file mode 100644 index 0000000000..c71790471e --- /dev/null +++ b/cypress/support/e2e.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. + */ + +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands'; + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/packages/techdocs-cli/cypress.config.js b/packages/techdocs-cli/cypress.config.js new file mode 100644 index 0000000000..c4b007634a --- /dev/null +++ b/packages/techdocs-cli/cypress.config.js @@ -0,0 +1,30 @@ +/* + * 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 { defineConfig } from 'cypress'; +import { initPlugin } from '@frsource/cypress-plugin-visual-regression-diff/plugins'; + +module.exports = defineConfig({ + e2e: { + setupNodeEvents(on, config) { + initPlugin(on, config); + }, + excludeSpecPattern: ['**/__snapshots__/*', '**/__image_snapshots__/*'], + }, + + viewportWidth: 1920, + viewportHeight: 1080, + includeShadowDom: true, +}); diff --git a/packages/techdocs-cli/cypress.json b/packages/techdocs-cli/cypress.json deleted file mode 100644 index b6f3b96019..0000000000 --- a/packages/techdocs-cli/cypress.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "env": { - "mkDocsBaseUrl": "http://localhost:8000", - "backstageBaseUrl": "http://localhost:3000", - "cypress-plugin-snapshots": { - "autoCleanUp": false, - "imageConfig": { - "resizeDevicePixelRatio": true, - "threshold": 0.01 - } - } - }, - "viewportWidth": 1920, - "viewportHeight": 1080, - "includeShadowDom": true, - "ignoreTestFiles": ["**/__snapshots__/*", "**/__image_snapshots__/*"] -} diff --git a/packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png b/packages/techdocs-cli/cypress/e2e/__image_snapshots__/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png similarity index 100% rename from packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png rename to packages/techdocs-cli/cypress/e2e/__image_snapshots__/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png diff --git a/packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - MkDocs Serve toMatchImageSnapshot - MkDocs Page #0.png b/packages/techdocs-cli/cypress/e2e/__image_snapshots__/TechDocs Live Preview - MkDocs Serve toMatchImageSnapshot - MkDocs Page #0.png similarity index 100% rename from packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - MkDocs Serve toMatchImageSnapshot - MkDocs Page #0.png rename to packages/techdocs-cli/cypress/e2e/__image_snapshots__/TechDocs Live Preview - MkDocs Serve toMatchImageSnapshot - MkDocs Page #0.png diff --git a/packages/techdocs-cli/cypress/integration/backstage_serve.js b/packages/techdocs-cli/cypress/e2e/backstage_serve.cy.js similarity index 94% rename from packages/techdocs-cli/cypress/integration/backstage_serve.js rename to packages/techdocs-cli/cypress/e2e/backstage_serve.cy.js index 15fc03f8f4..0267c8bfe6 100644 --- a/packages/techdocs-cli/cypress/integration/backstage_serve.js +++ b/packages/techdocs-cli/cypress/e2e/backstage_serve.cy.js @@ -48,11 +48,11 @@ describe('TechDocs Live Preview - Backstage Serve', () => { cy.get('.md-footer').should('have.length', 1); }); - it('toMatchImageSnapshot - Backstage TechDocs Page', () => { + it('matchImage - Backstage TechDocs Page', () => { cy.visit( `${Cypress.env('backstageBaseUrl')}/docs/default/component/local`, ).then(() => { - cy.document().toMatchImageSnapshot(); + cy.document().matchImage(); }); }); }); diff --git a/packages/techdocs-cli/cypress/integration/mkdocs_serve.js b/packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js similarity index 94% rename from packages/techdocs-cli/cypress/integration/mkdocs_serve.js rename to packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js index 1ace7298ce..d9da6caeca 100644 --- a/packages/techdocs-cli/cypress/integration/mkdocs_serve.js +++ b/packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js @@ -40,9 +40,9 @@ describe('TechDocs Live Preview - MkDocs Serve', () => { cy.get('.md-footer').should('have.length', 1); }); - it('toMatchImageSnapshot - MkDocs Page', () => { + it('matchImage - MkDocs Page', () => { cy.visit(Cypress.env('mkDocsBaseUrl')).then(() => { - cy.document().toMatchImageSnapshot(); + cy.document().matchImage(); }); }); }); diff --git a/packages/techdocs-cli/cypress/plugins/index.js b/packages/techdocs-cli/cypress/plugins/index.js deleted file mode 100644 index 92faabb6ad..0000000000 --- a/packages/techdocs-cli/cypress/plugins/index.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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. - */ - -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -const { initPlugin } = require('cypress-plugin-snapshots/plugin'); - -/** - * @type {Cypress.PluginConfig} - */ -// eslint-disable-next-line no-unused-vars -module.exports = (on, config) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config - initPlugin(on, config); - return config; -}; diff --git a/packages/techdocs-cli/cypress/support/index.js b/packages/techdocs-cli/cypress/support/e2e.js similarity index 94% rename from packages/techdocs-cli/cypress/support/index.js rename to packages/techdocs-cli/cypress/support/e2e.js index a1a5b10ea4..f06a08e9a5 100644 --- a/packages/techdocs-cli/cypress/support/index.js +++ b/packages/techdocs-cli/cypress/support/e2e.js @@ -30,7 +30,7 @@ // Import commands.js using ES2015 syntax: import './commands'; -import 'cypress-plugin-snapshots/commands'; +import '@frsource/cypress-plugin-visual-regression-diff/commands'; // Alternatively you can use CommonJS syntax: // require('./commands') diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 4e6bde27c2..5f2e7db65d 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -37,6 +37,7 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", + "@frsource/cypress-plugin-visual-regression-diff": "^3.2.8", "@types/commander": "^2.12.2", "@types/fs-extra": "^9.0.6", "@types/http-proxy": "^1.17.4", @@ -44,7 +45,6 @@ "@types/serve-handler": "^6.1.0", "@types/webpack-env": "^1.15.3", "cypress": "^10.0.0", - "cypress-plugin-snapshots": "^1.4.4", "find-process": "^1.4.5", "nodemon": "^2.0.2", "techdocs-cli-embedded-app": "link:../techdocs-cli-embedded-app", diff --git a/yarn.lock b/yarn.lock index 752aaf629f..7844d0fadb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3295,7 +3295,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": version: 7.20.13 resolution: "@babel/runtime@npm:7.20.13" dependencies: @@ -9428,6 +9428,30 @@ __metadata: languageName: node linkType: hard +"@frsource/base64@npm:1.0.5": + version: 1.0.5 + resolution: "@frsource/base64@npm:1.0.5" + checksum: ba526dd81df4e91b0abbcc34fc6818c8ff132e5230c23a4448a365ba934f782a86abb2a8566050f9450905851e467a7160f01f3d321fbb0fa3c8c516c5a82b9b + languageName: node + linkType: hard + +"@frsource/cypress-plugin-visual-regression-diff@npm:^3.2.8": + version: 3.2.8 + resolution: "@frsource/cypress-plugin-visual-regression-diff@npm:3.2.8" + dependencies: + "@frsource/base64": 1.0.5 + glob: 8.0.3 + meta-png: 1.0.5 + move-file: 2.1.0 + pixelmatch: 5.3.0 + pngjs: 6.0.0 + sharp: 0.31.2 + peerDependencies: + cypress: ">=4.5.0" + checksum: 7e5a1daf3a36ec7f62ea643da8eff73aadb595e4fb8b400abec37e38a356a200de1ce47ff2e14666e71556300e4d044d5fa5ad21bdd2d214b93402addb1a490e + languageName: node + linkType: hard + "@gar/promisify@npm:^1.0.1, @gar/promisify@npm:^1.1.3": version: 1.1.3 resolution: "@gar/promisify@npm:1.1.3" @@ -10794,460 +10818,6 @@ __metadata: languageName: node linkType: hard -"@jimp/bmp@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/bmp@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - bmp-js: ^0.1.0 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 3a5a7600add0edf68a0d8f8397dd0ca37fa20d93b4d9ea8321875acd92e4a632a31ac1af0fc2129cff76cdc77aa77b359327613f822c0bc48781f007459e44f8 - languageName: node - linkType: hard - -"@jimp/core@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/core@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - any-base: ^1.1.0 - buffer: ^5.2.0 - core-js: ^3.4.1 - exif-parser: ^0.1.12 - file-type: ^9.0.0 - load-bmfont: ^1.3.1 - mkdirp: ^0.5.1 - phin: ^2.9.1 - pixelmatch: ^4.0.2 - tinycolor2: ^1.4.1 - checksum: f67db147a114b7a220621b80f9c65cf0d1434f4bd7ab8203b44246b79093f9ec46170a6205755eae7fe53c14d2935d8565f5a2185ccd4495ae1cd6f13bcf4852 - languageName: node - linkType: hard - -"@jimp/custom@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/custom@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/core": ^0.10.3 - core-js: ^3.4.1 - checksum: 8a282c9387cb975a533d140a8e0c9f7c23b12b6e6a92e9a1e979b7cc7d89e623189c47b0d0119aa7e497149f0d9a85e4ec14a605921527340c307b7750ba519a - languageName: node - linkType: hard - -"@jimp/gif@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/gif@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - omggif: ^1.0.9 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: a23253e6762e6f19b0fa6deaa9db3bca25b313eb5ea506dd3d844407598d86cf4188cc92c091019a4257450821ffe24f0475cc2e4a1ef24998d95d176078cf2f - languageName: node - linkType: hard - -"@jimp/jpeg@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/jpeg@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - jpeg-js: ^0.3.4 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: cb830ddf3fddbc4f833086ffbf8f21e0c73863522cce86d6f6c82d4f0183d0619ee280736c5ed07563bfcf9f884fd96bdb845a95c5a8a6e11f961f4e95cb4b24 - languageName: node - linkType: hard - -"@jimp/plugin-blit@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-blit@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 5858557359eb0405c29741c8ffe98b4bb26b42564c178402e21b74733c02e04233d2a1af095cff4cd2864ab43d79e01033559f250b3eb879600138007a7d7453 - languageName: node - linkType: hard - -"@jimp/plugin-blur@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-blur@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: d3a2e14d4dc5f3b5ad010888e70193cc8f7327aeda67989eba3f49de2e5324fa6adf89e3a7f1597343f59688ce6e299ad5818aa6c670ed8596ddfba0ca281db3 - languageName: node - linkType: hard - -"@jimp/plugin-circle@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-circle@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: d351c85f4a9aeb404302a03f5d99e6486b95f271f2c628758c8e3d1574bc268278ffc34d9d00d3221d6079431b06a5e6a5a3922863994000b5eb3c81f8c27d35 - languageName: node - linkType: hard - -"@jimp/plugin-color@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-color@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - tinycolor2: ^1.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 2014802f3b0465abbd7682336836183293a26315acbb84826f5207a374f807c574e120790738dcf51aba2cb7e9a481003289ef8bf429facb9fe36a19ce5b6924 - languageName: node - linkType: hard - -"@jimp/plugin-contain@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-contain@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-blit": ">=0.3.5" - "@jimp/plugin-resize": ">=0.3.5" - "@jimp/plugin-scale": ">=0.3.5" - checksum: 91d77621a350a733839fa8bc15880bc74ac666682a651e676797207dc4f55cba465f3695f6280f3d05122d67067a0a94f3905f323410d880484dd769055c9b49 - languageName: node - linkType: hard - -"@jimp/plugin-cover@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-cover@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-crop": ">=0.3.5" - "@jimp/plugin-resize": ">=0.3.5" - "@jimp/plugin-scale": ">=0.3.5" - checksum: ca664509c2d42e987a56e80fa848ec3e5590a1f919c0a607d7a03b8192571456c0287a2f768785bf816ecfe7889a7a786490a408866acc94ce5306b39ca82f6b - languageName: node - linkType: hard - -"@jimp/plugin-crop@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-crop@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 54e79b6fa831f813f28dac53187dfa1684d00ece8a98433c30c1e61333ba2b5373758889d202418a55c99dffe235daf153454f35691324b42dd9a103a65d3bd2 - languageName: node - linkType: hard - -"@jimp/plugin-displace@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-displace@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 17b5792ce07ac3b7b5aa8c457626fb46ded0a8f05027c4580fac1b22428e7c2c0ff04e0ad4f7249c179322afa7921e57afc88ace03e2d08b67e864c24ef5c060 - languageName: node - linkType: hard - -"@jimp/plugin-dither@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-dither@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 77caaceebccceb73e32616fd79517d9640d217403577715e08146bf2a67599822070be8a51783ad76402e0303f6bc9afcebf75f75cc73ae44c684e3c1e1248ea - languageName: node - linkType: hard - -"@jimp/plugin-fisheye@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-fisheye@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: f60d9c6c40d6fa1b85658ffa23568f95aeab1635165f2b74266b128be0f9b4bf963cfa755e5a43b7f18421340a4bb7b628ab75821b34b602924154b55c0f39ce - languageName: node - linkType: hard - -"@jimp/plugin-flip@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-flip@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-rotate": ">=0.3.5" - checksum: 6542b9e595e3b95cf8ac741226e9089ab1edd3fa19bc4ac159afd5bc3801a55f6ee93ade029626dbde7977eb1fbca51c71d9c6546b5285754eb29b54a7f5f5ff - languageName: node - linkType: hard - -"@jimp/plugin-gaussian@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-gaussian@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 465ca178b9a9062eb6db4a57fe3b47236270bad9600cfb4aae162aad43f20e5cf90c19bf77bd08867f25abd0679c6018412e0ad8cb3777640dad5c3f51e64dd9 - languageName: node - linkType: hard - -"@jimp/plugin-invert@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-invert@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 917419301a961541466e04c7fc974fc95f35e3f95f75e6bfef141270f06b68bcdf61321cad2d545cd8115a6e3a99992345f964bdb94cbdb48aaf42885b8fcae7 - languageName: node - linkType: hard - -"@jimp/plugin-mask@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-mask@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 7870fe46d9fcec6145476bcceed23568012e87953772e7ea2b82c8ed48375ee525db6b977816574b47e08c595bd6123c8d9cd24a95e649677d0ec1fada4e6831 - languageName: node - linkType: hard - -"@jimp/plugin-normalize@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-normalize@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: f34ebf3ef03d83b2cb9a8779d39a3e10707aeae4dfe67e1bb30202589e72d09c0e9a61b429de4e4886728f0faabbb83a6ff081f2e9bf79b517e2ea387c53a9a4 - languageName: node - linkType: hard - -"@jimp/plugin-print@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-print@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - load-bmfont: ^1.4.0 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-blit": ">=0.3.5" - checksum: 772a7d82741af583293006f699bbbaf116c264327412ea6ed0f3b7fb14d0dcbef51278e6fce3e966ad23e655114bfe949106d551d06459819b26e461638e8a5e - languageName: node - linkType: hard - -"@jimp/plugin-resize@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-resize@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: aff691d2936bd88d59a68b36a6f06b306d0f7c654baec7b43371e6b250397b3a19d0b98a620ad26738ed51357f5899a8002761d8f6f0ae6074e6c63905895a5d - languageName: node - linkType: hard - -"@jimp/plugin-rotate@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-rotate@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-blit": ">=0.3.5" - "@jimp/plugin-crop": ">=0.3.5" - "@jimp/plugin-resize": ">=0.3.5" - checksum: f1771365753a64387e455006467dd41e09c1e329180e57df77ef78f72dfac7d889e5d03adae1038f4c6ac081a9d5113c59541983fdda6bf08da9af852650c468 - languageName: node - linkType: hard - -"@jimp/plugin-scale@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-scale@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-resize": ">=0.3.5" - checksum: 356e8ab040bf842845a29cc0a6d7170fd15c1a9e9407028b88771bff01ecb6870c8f26d15b59b432914c430e611f36f54f932aaa7a68dcc9e32efae2f6dd1946 - languageName: node - linkType: hard - -"@jimp/plugin-shadow@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-shadow@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-blur": ">=0.3.5" - "@jimp/plugin-resize": ">=0.3.5" - checksum: 7f07387160b31732b3d43a2c4d44f8716be7a08b2f0fcfd58d18ca76ed62d825629c6273434bd23d02ade6a18bc8d7c7020eb9ab0ccc95acd85e718b5ab2c7a0 - languageName: node - linkType: hard - -"@jimp/plugin-threshold@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-threshold@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-color": ">=0.8.0" - "@jimp/plugin-resize": ">=0.8.0" - checksum: 550de37f82ccfaacb954b0e183a7bfa77f80f33ec9f5b08756ce778675284e486a2b5860c69c6d15a38d1d7030f1896e1ac79e8675603ead9e36c075f3cf636e - languageName: node - linkType: hard - -"@jimp/plugins@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugins@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/plugin-blit": ^0.10.3 - "@jimp/plugin-blur": ^0.10.3 - "@jimp/plugin-circle": ^0.10.3 - "@jimp/plugin-color": ^0.10.3 - "@jimp/plugin-contain": ^0.10.3 - "@jimp/plugin-cover": ^0.10.3 - "@jimp/plugin-crop": ^0.10.3 - "@jimp/plugin-displace": ^0.10.3 - "@jimp/plugin-dither": ^0.10.3 - "@jimp/plugin-fisheye": ^0.10.3 - "@jimp/plugin-flip": ^0.10.3 - "@jimp/plugin-gaussian": ^0.10.3 - "@jimp/plugin-invert": ^0.10.3 - "@jimp/plugin-mask": ^0.10.3 - "@jimp/plugin-normalize": ^0.10.3 - "@jimp/plugin-print": ^0.10.3 - "@jimp/plugin-resize": ^0.10.3 - "@jimp/plugin-rotate": ^0.10.3 - "@jimp/plugin-scale": ^0.10.3 - "@jimp/plugin-shadow": ^0.10.3 - "@jimp/plugin-threshold": ^0.10.3 - core-js: ^3.4.1 - timm: ^1.6.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 28833f4ce43f911c41b5c251759f5e38406ba99249a7c00d11a81e4ce58027eb993ca0c220601c3702832c2855dbb0554762bf724107bb4fdd0a2c1cf8753895 - languageName: node - linkType: hard - -"@jimp/png@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/png@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - pngjs: ^3.3.3 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 1520b669d0dc6a0b47d7357c5e75a080e3a56db0459fad5c56e299b03c4a7bf560540480b08fa2e1eaf283ba153efb26a3e90d90fe373069c6c6184f7ea3e163 - languageName: node - linkType: hard - -"@jimp/tiff@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/tiff@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - core-js: ^3.4.1 - utif: ^2.0.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 6ff41bc962afdbcd223b331beed232b5aecf2b0ba06cccddaef5b5d4b925fa51d6a26d226080baabd25d7dceb0b9b0e5c69b60c44494822cb69988c3221c6514 - languageName: node - linkType: hard - -"@jimp/types@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/types@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/bmp": ^0.10.3 - "@jimp/gif": ^0.10.3 - "@jimp/jpeg": ^0.10.3 - "@jimp/png": ^0.10.3 - "@jimp/tiff": ^0.10.3 - core-js: ^3.4.1 - timm: ^1.6.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 68ea0f1a1f3116ba779c898c9fb38fb7b822addaa14ac153aea4cdc9e274efc34a46a6ad4c8a9978fb88b4ab5a826190e28b89b431dce735ee760997f2d66678 - languageName: node - linkType: hard - -"@jimp/utils@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/utils@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - core-js: ^3.4.1 - regenerator-runtime: ^0.13.3 - checksum: bd36b8bbaaf878190afe357f1bcebed9215dae503f06603039e6a106045588003b845150cb5a5ba6dd4d973e7e7b95779158ae921011fb6bd79083c8cb177804 - languageName: node - linkType: hard - "@josephg/resolvable@npm:^1.0.0": version: 1.0.1 resolution: "@josephg/resolvable@npm:1.0.1" @@ -13831,6 +13401,7 @@ __metadata: "@backstage/cli-common": "workspace:^" "@backstage/config": "workspace:^" "@backstage/plugin-techdocs-node": "workspace:^" + "@frsource/cypress-plugin-visual-regression-diff": ^3.2.8 "@types/commander": ^2.12.2 "@types/dockerode": ^3.3.0 "@types/fs-extra": ^9.0.6 @@ -13840,7 +13411,6 @@ __metadata: "@types/webpack-env": ^1.15.3 commander: ^9.1.0 cypress: ^10.0.0 - cypress-plugin-snapshots: ^1.4.4 dockerode: ^3.3.1 find-process: ^1.4.5 fs-extra: ^10.0.1 @@ -16573,13 +16143,6 @@ __metadata: languageName: node linkType: hard -"after@npm:0.8.2": - version: 0.8.2 - resolution: "after@npm:0.8.2" - checksum: 52ea9be2e97d764de256dfb3843d68cb180d2d464748010ea0d8079ee28190190080a53e4005a62adbf4337c2d613906db82f08c0091cccb8e817625ccf94c52 - languageName: node - linkType: hard - "agent-base@npm:6, agent-base@npm:^6.0.2": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -16776,13 +16339,6 @@ __metadata: languageName: node linkType: hard -"any-base@npm:^1.1.0": - version: 1.1.0 - resolution: "any-base@npm:1.1.0" - checksum: c1fd040de52e710e2de7d9ae4df52bac589f35622adb24686c98ce21c7b824859a8db9614bc119ed8614f42fd08918b2612e6a6c385480462b3100a1af59289d - languageName: node - linkType: hard - "any-promise@npm:^1.0.0": version: 1.3.0 resolution: "any-promise@npm:1.3.0" @@ -17160,13 +16716,6 @@ __metadata: languageName: node linkType: hard -"arraybuffer.slice@npm:~0.0.7": - version: 0.0.7 - resolution: "arraybuffer.slice@npm:0.0.7" - checksum: c6bacada71e8fe3e63c5f5ac5f23810e617faa1bcf33be21db43f40819edc7e186172d4a6fb8f1b9baea26689fc8da6ddeb78cefa2cc9723156c0247c3587118 - languageName: node - linkType: hard - "arrify@npm:^1.0.1": version: 1.0.1 resolution: "arrify@npm:1.0.1" @@ -17712,7 +17261,7 @@ __metadata: languageName: node linkType: hard -"backo2@npm:1.0.2, backo2@npm:^1.0.2": +"backo2@npm:^1.0.2": version: 1.0.2 resolution: "backo2@npm:1.0.2" checksum: fda8d0a0f4810068d23715f2f45153146d6ee8f62dd827ce1e0b6cc3c8328e84ad61e11399a83931705cef702fe7cbb457856bf99b9bd10c4ed57b0786252385 @@ -17754,13 +17303,6 @@ __metadata: languageName: node linkType: hard -"base64-arraybuffer@npm:0.1.4": - version: 0.1.4 - resolution: "base64-arraybuffer@npm:0.1.4" - checksum: d249a929e27b2430d7ba1527e91a36e14da37ae2f80e350c4d696a038257718f8da07577e820e7262f86a0ecd573c283db10c46502080f53ae11bfdd99b6a029 - languageName: node - linkType: hard - "base64-js@npm:^1.0.2, base64-js@npm:^1.3.0, base64-js@npm:^1.3.1, base64-js@npm:^1.5.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" @@ -17775,13 +17317,6 @@ __metadata: languageName: node linkType: hard -"base64id@npm:2.0.0": - version: 2.0.0 - resolution: "base64id@npm:2.0.0" - checksum: 581b1d37e6cf3738b7ccdd4d14fe2bfc5c238e696e2720ee6c44c183b838655842e22034e53ffd783f872a539915c51b0d4728a49c7cc678ac5a758e00d62168 - languageName: node - linkType: hard - "base64url@npm:3.x.x": version: 3.0.1 resolution: "base64url@npm:3.0.1" @@ -17943,13 +17478,6 @@ __metadata: languageName: node linkType: hard -"blob@npm:0.0.5": - version: 0.0.5 - resolution: "blob@npm:0.0.5" - checksum: ca6a025f1108b7fd317fba0a0d64424f5cf47be6f4653ec8ba44777804a4e5c86c8d7a7e41f75fe52fd77c5bfc3479f68e017abe649a241c15c3fc07bfc59e7b - languageName: node - linkType: hard - "bluebird@npm:3.7.2, bluebird@npm:^3.3.5, bluebird@npm:^3.5.5, bluebird@npm:^3.7.2": version: 3.7.2 resolution: "bluebird@npm:3.7.2" @@ -17957,13 +17485,6 @@ __metadata: languageName: node linkType: hard -"bmp-js@npm:^0.1.0": - version: 0.1.0 - resolution: "bmp-js@npm:0.1.0" - checksum: 2f6cf7eeabae2aa50eb768122f59e9752caa97248028cb8b5cf0d9db7cf8fb3a60262aeb2c6889dd21357ab061b2fb318f21f20d2b24963ba36ead8e264c6654 - languageName: node - linkType: hard - "bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.1.1, bn.js@npm:^4.11.9": version: 4.12.0 resolution: "bn.js@npm:4.12.0" @@ -18211,13 +17732,6 @@ __metadata: languageName: node linkType: hard -"buffer-equal@npm:0.0.1": - version: 0.0.1 - resolution: "buffer-equal@npm:0.0.1" - checksum: ca4b52e6c01143529d957a78cb9a93e4257f172bbab30d9eb87c20ae085ed23c5e07f236ac051202dacbf3d17aba42e1455f84cba21ea79b67d57f2b05e9a613 - languageName: node - linkType: hard - "buffer-from@npm:^1.0.0": version: 1.1.2 resolution: "buffer-from@npm:1.1.2" @@ -18260,7 +17774,7 @@ __metadata: languageName: node linkType: hard -"buffer@npm:^5.2.0, buffer@npm:^5.2.1, buffer@npm:^5.5.0, buffer@npm:^5.6.0": +"buffer@npm:^5.2.1, buffer@npm:^5.5.0, buffer@npm:^5.6.0": version: 5.7.1 resolution: "buffer@npm:5.7.1" dependencies: @@ -19187,7 +18701,7 @@ __metadata: languageName: node linkType: hard -"color@npm:^4.0.1": +"color@npm:^4.0.1, color@npm:^4.2.3": version: 4.2.3 resolution: "color@npm:4.2.3" dependencies: @@ -19377,34 +18891,13 @@ __metadata: languageName: node linkType: hard -"component-bind@npm:1.0.0": - version: 1.0.0 - resolution: "component-bind@npm:1.0.0" - checksum: 746c5810b9f8735643840ad04072e1ab817444d44dc1aadc813f1f1a17c47c27616584caa0db93db7e687bfe73b65073d8246c785bcdac80f8f3627d3bb26883 - languageName: node - linkType: hard - -"component-emitter@npm:1.2.1": - version: 1.2.1 - resolution: "component-emitter@npm:1.2.1" - checksum: 00599b827635cab65bb20e5e3e2db4cea120b76b6626ce3ac6c85d7f5f39bbadd9fec530da444380035dd1c8ff08f9badca54d40b68feaf74bc64f75d537ef61 - languageName: node - linkType: hard - -"component-emitter@npm:^1.3.0, component-emitter@npm:~1.3.0": +"component-emitter@npm:^1.3.0": version: 1.3.0 resolution: "component-emitter@npm:1.3.0" checksum: b3c46de38ffd35c57d1c02488355be9f218e582aec72d72d1b8bbec95a3ac1b38c96cd6e03ff015577e68f550fbb361a3bfdbd9bb248be9390b7b3745691be6b languageName: node linkType: hard -"component-inherit@npm:0.0.3": - version: 0.0.3 - resolution: "component-inherit@npm:0.0.3" - checksum: 9f5b872a6b3a396cf827d471d07db5626d7918202ab6c1d59f2b849bab18ce4fe61d9b2b7b6ae5cd547b81f27a3de5ae678f438bfe4fadce8f26a1526ba86a74 - languageName: node - linkType: hard - "compress-commons@npm:^4.1.0": version: 4.1.0 resolution: "compress-commons@npm:4.1.0" @@ -19648,7 +19141,7 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.4.2, cookie@npm:^0.4.2, cookie@npm:~0.4.1": +"cookie@npm:0.4.2, cookie@npm:^0.4.2": version: 0.4.2 resolution: "cookie@npm:0.4.2" checksum: a00833c998bedf8e787b4c342defe5fa419abd96b32f4464f718b91022586b8f1bafbddd499288e75c037642493c83083da426c6a9080d309e3bd90fd11baa9b @@ -19709,7 +19202,7 @@ __metadata: languageName: node linkType: hard -"core-js@npm:^3.4.1, core-js@npm:^3.6.5": +"core-js@npm:^3.6.5": version: 3.27.2 resolution: "core-js@npm:3.27.2" checksum: 718debd426f55a6b97cf9b757c936be258afd6d4f7052f89d0f96c982d7013e9000b0b006df42831a0cf32adad298e34d6a19052dce9ae1c7ab87162c0c665e0 @@ -20263,31 +19756,6 @@ __metadata: languageName: node linkType: hard -"cypress-plugin-snapshots@npm:^1.4.4": - version: 1.4.4 - resolution: "cypress-plugin-snapshots@npm:1.4.4" - dependencies: - diff2html: ^2.7.0 - fs-extra: ^7.0.1 - image-size: ^0.7.2 - jimp: ^0.10.3 - js-base64: ^2.5.1 - lodash: ^4.17.13 - pixelmatch: ^4.0.2 - pngjs: ^3.3.3 - prettier: ^1.16.4 - rimraf: ^2.6.3 - sanitize-filename: ^1.6.1 - socket.io: ^2.2.0 - socket.io-client: ^2.2.0 - source-map-support: ^0.5.10 - unidiff: 1.0.2 - peerDependencies: - cypress: ^4.5.0 - checksum: 75b8d6b6e0353f7d2ac617c503f33c84c7c5f4e650dbaf59a76558e971bcc82532d2ac37b9eeccb7382354a13fe5d0068c8e97a9f7f6f1af6135cf5286c285f9 - languageName: node - linkType: hard - "cypress@npm:^10.0.0": version: 10.11.0 resolution: "cypress@npm:10.11.0" @@ -20655,24 +20123,6 @@ __metadata: languageName: node linkType: hard -"debug@npm:~3.1.0": - version: 3.1.0 - resolution: "debug@npm:3.1.0" - dependencies: - ms: 2.0.0 - checksum: 0b52718ab957254a5b3ca07fc34543bc778f358620c206a08452251eb7fc193c3ea3505072acbf4350219c14e2d71ceb7bdaa0d3370aa630b50da790458d08b3 - languageName: node - linkType: hard - -"debug@npm:~4.1.0": - version: 4.1.1 - resolution: "debug@npm:4.1.1" - dependencies: - ms: ^2.1.1 - checksum: 1e681f5cce94ba10f8dde74b20b42e4d8cf0d2a6700f4c165bb3bb6885565ef5ca5885bf07e704974a835f2415ff095a63164f539988a1f07e8a69fe8b1d65ad - languageName: node - linkType: hard - "debuglog@npm:^1.0.1": version: 1.0.1 resolution: "debuglog@npm:1.0.1" @@ -20966,7 +20416,7 @@ __metadata: languageName: node linkType: hard -"detect-libc@npm:^2.0.0": +"detect-libc@npm:^2.0.0, detect-libc@npm:^2.0.1": version: 2.0.1 resolution: "detect-libc@npm:2.0.1" checksum: ccb05fcabbb555beb544d48080179c18523a343face9ee4e1a86605a8715b4169f94d663c21a03c310ac824592f2ba9a5270218819bb411ad7be578a527593d7 @@ -21031,18 +20481,6 @@ __metadata: languageName: node linkType: hard -"diff2html@npm:^2.7.0": - version: 2.12.2 - resolution: "diff2html@npm:2.12.2" - dependencies: - diff: ^4.0.1 - hogan.js: ^3.0.2 - merge: ^1.2.1 - whatwg-fetch: ^3.0.0 - checksum: 4d659fb558575406881bc9e6b892a236d038bca1335cbdde65ebfde462cf1cff7a7ab4a2e82d9874205e658dd2caa31699ba24ea4efb714d7c7277ddb96c7768 - languageName: node - linkType: hard - "diff3@npm:0.0.3": version: 0.0.3 resolution: "diff3@npm:0.0.3" @@ -21050,13 +20488,6 @@ __metadata: languageName: node linkType: hard -"diff@npm:^2.2.2": - version: 2.2.3 - resolution: "diff@npm:2.2.3" - checksum: b5b6fbe1848c621ef6f6c154e689842f7bb992b4c0ae257b70f5577b0906812537bf2eccda14d0215f90579567c8880eb44f1cf3851bd615583214a4f4d61ce3 - languageName: node - linkType: hard - "diff@npm:^4.0.1": version: 4.0.2 resolution: "diff@npm:4.0.2" @@ -21223,13 +20654,6 @@ __metadata: languageName: node linkType: hard -"dom-walk@npm:^0.1.0": - version: 0.1.1 - resolution: "dom-walk@npm:0.1.1" - checksum: f55db10d0344b87cca1046a2356915a8e9ddee90fc97d3ebb26c4021e593cce47d24cbef18aac721421787c6a60fa14dd079a0b81f8610c9aeeec52177fd2acf - languageName: node - linkType: hard - "domain-browser@npm:^1.1.1": version: 1.2.0 resolution: "domain-browser@npm:1.2.0" @@ -21554,52 +20978,6 @@ __metadata: languageName: node linkType: hard -"engine.io-client@npm:~3.5.0": - version: 3.5.2 - resolution: "engine.io-client@npm:3.5.2" - dependencies: - component-emitter: ~1.3.0 - component-inherit: 0.0.3 - debug: ~3.1.0 - engine.io-parser: ~2.2.0 - has-cors: 1.1.0 - indexof: 0.0.1 - parseqs: 0.0.6 - parseuri: 0.0.6 - ws: ~7.4.2 - xmlhttprequest-ssl: ~1.6.2 - yeast: 0.1.2 - checksum: 2a4a8407ea939c45826d3483e39fe017e66d488dfd101282a79644f75196f7b84cac9d6f981e3ace1ab231e2469c18b25d79b114f20ab58d0eaa393bf66f213e - languageName: node - linkType: hard - -"engine.io-parser@npm:~2.2.0": - version: 2.2.1 - resolution: "engine.io-parser@npm:2.2.1" - dependencies: - after: 0.8.2 - arraybuffer.slice: ~0.0.7 - base64-arraybuffer: 0.1.4 - blob: 0.0.5 - has-binary2: ~1.0.2 - checksum: c7291955c1af4b6c384c2642c2d10a4df0ca7b6acc5cb178dd4933bcb1522eccc3d89ffae6e6080ce760451378fce49db47af3fb9999cae08de310e75f3c29d6 - languageName: node - linkType: hard - -"engine.io@npm:~3.6.0": - version: 3.6.1 - resolution: "engine.io@npm:3.6.1" - dependencies: - accepts: ~1.3.4 - base64id: 2.0.0 - cookie: ~0.4.1 - debug: ~4.1.0 - engine.io-parser: ~2.2.0 - ws: ~7.4.2 - checksum: 7dd9eddc79aedf61a63141e6208ee89936c659445378f965bff6d5eb3e9cb4815aff735f2b1886487e2be51116a343e89d972ae5790bf2ac9fdcb2572baf8935 - languageName: node - linkType: hard - "enhanced-resolve@npm:^5.10.0": version: 5.10.0 resolution: "enhanced-resolve@npm:5.10.0" @@ -22913,13 +22291,6 @@ __metadata: languageName: node linkType: hard -"exif-parser@npm:^0.1.12": - version: 0.1.12 - resolution: "exif-parser@npm:0.1.12" - checksum: 6ba50cb9e0b45a6efa37e966a9582ecd171b5c5b3ef0c47542f2b862c521f70d2f656dde85b4d2a5dd8e1163486b09049f4c412e9c6176bfbda1654a5b2f021c - languageName: node - linkType: hard - "exit-on-epipe@npm:~1.0.1": version: 1.0.1 resolution: "exit-on-epipe@npm:1.0.1" @@ -23365,13 +22736,6 @@ __metadata: languageName: node linkType: hard -"file-type@npm:^9.0.0": - version: 9.0.0 - resolution: "file-type@npm:9.0.0" - checksum: 9ea78b29c3762d967eb1e3e4f45e401388b6d252b12c217f78f5ea97556ff7e35e4c7255cab68810ac414d51b776bd4e83504c86f132c262a454251561189efa - languageName: node - linkType: hard - "file-uri-to-path@npm:1.0.0": version: 1.0.0 resolution: "file-uri-to-path@npm:1.0.0" @@ -24200,6 +23564,19 @@ __metadata: languageName: node linkType: hard +"glob@npm:8.0.3": + version: 8.0.3 + resolution: "glob@npm:8.0.3" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^5.0.1 + once: ^1.3.0 + checksum: 50bcdea19d8e79d8de5f460b1939ffc2b3299eac28deb502093fdca22a78efebc03e66bf54f0abc3d3d07d8134d19a32850288b7440d77e072aa55f9d33b18c5 + languageName: node + linkType: hard + "glob@npm:^7.0.0, glob@npm:^7.1.1, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.1.7, glob@npm:^7.2.0": version: 7.2.3 resolution: "glob@npm:7.2.3" @@ -24270,16 +23647,6 @@ __metadata: languageName: node linkType: hard -"global@npm:~4.4.0": - version: 4.4.0 - resolution: "global@npm:4.4.0" - dependencies: - min-document: ^2.19.0 - process: ^0.11.10 - checksum: 9c057557c8f5a5bcfbeb9378ba4fe2255d04679452be504608dd5f13b54edf79f7be1db1031ea06a4ec6edd3b9f5f17d2d172fb47e6c69dae57fd84b7e72b77f - languageName: node - linkType: hard - "globals@npm:^11.1.0, globals@npm:^11.12.0": version: 11.12.0 resolution: "globals@npm:11.12.0" @@ -24705,22 +24072,6 @@ __metadata: languageName: node linkType: hard -"has-binary2@npm:~1.0.2": - version: 1.0.3 - resolution: "has-binary2@npm:1.0.3" - dependencies: - isarray: 2.0.1 - checksum: 9183a617830b1f50b35961fbe39278cc43089cdac7c47a7f16aafb9d8190553fa360e5da34a479d6c988db40ea10aa02bca5abcb2451b5fc3924ae2f013ffdab - languageName: node - linkType: hard - -"has-cors@npm:1.1.0": - version: 1.1.0 - resolution: "has-cors@npm:1.1.0" - checksum: 549ce94113fd23895b22d71ade9809918577b8558cd4d701fe79045d8b1d58d87eba870260b28f6a3229be933a691c55653afd496d0fc52e98fd2ff577f01197 - languageName: node - linkType: hard - "has-flag@npm:^3.0.0": version: 3.0.0 resolution: "has-flag@npm:3.0.0" @@ -24897,18 +24248,6 @@ __metadata: languageName: node linkType: hard -"hogan.js@npm:^3.0.2": - version: 3.0.2 - resolution: "hogan.js@npm:3.0.2" - dependencies: - mkdirp: 0.3.0 - nopt: 1.0.10 - bin: - hulk: ./bin/hulk - checksum: c7bbff84faa9ca265c39f4a2100546ba0388fcc9c5bac8526f488592ce3fcaa042eba6ac25db277f4478ec3855b9bc28ce59acffbf6e8a28d45a17df7590c6aa - languageName: node - linkType: hard - "hoist-non-react-statics@npm:^2.3.1": version: 2.5.5 resolution: "hoist-non-react-statics@npm:2.5.5" @@ -25364,15 +24703,6 @@ __metadata: languageName: node linkType: hard -"image-size@npm:^0.7.2": - version: 0.7.5 - resolution: "image-size@npm:0.7.5" - bin: - image-size: bin/image-size.js - checksum: f88860c9d9b5c8ad00d3de9d6f5ba105bda5a5024bfb6b90559a075a4b838ed4f5d3cba14edf0f18fe5d75df596a172b52feca43848e11c34f31f4df2c88a011 - languageName: node - linkType: hard - "immer@npm:9.0.7": version: 9.0.7 resolution: "immer@npm:9.0.7" @@ -25487,13 +24817,6 @@ __metadata: languageName: node linkType: hard -"indexof@npm:0.0.1": - version: 0.0.1 - resolution: "indexof@npm:0.0.1" - checksum: 0fb04e8b147b8585d981a6df1564f25bb3678d6fa74e33e5cecc1464b10f78e15e8ef6bb688f135fe5c2844a128fac8a7831cbe5adc81fdcf12681b093dfcc25 - languageName: node - linkType: hard - "infer-owner@npm:^1.0.4": version: 1.0.4 resolution: "infer-owner@npm:1.0.4" @@ -25940,13 +25263,6 @@ __metadata: languageName: node linkType: hard -"is-function@npm:^1.0.1": - version: 1.0.2 - resolution: "is-function@npm:1.0.2" - checksum: 7d564562e07b4b51359547d3ccc10fb93bb392fd1b8177ae2601ee4982a0ece86d952323fc172a9000743a3971f09689495ab78a1d49a9b14fc97a7e28521dc0 - languageName: node - linkType: hard - "is-generator-fn@npm:^2.0.0": version: 2.1.0 resolution: "is-generator-fn@npm:2.1.0" @@ -26386,13 +25702,6 @@ __metadata: languageName: node linkType: hard -"isarray@npm:2.0.1": - version: 2.0.1 - resolution: "isarray@npm:2.0.1" - checksum: a0521973213019b82889f028a41528ce7a3f103a710357b6875066202ee5a1fa9ae4135f915f3be9160b8c7a3ae4b39b073b804da3b58fa6b72f8b4b1e3dfef5 - languageName: node - linkType: hard - "isarray@npm:^1.0.0, isarray@npm:~1.0.0": version: 1.0.0 resolution: "isarray@npm:1.0.0" @@ -27166,20 +26475,6 @@ __metadata: languageName: node linkType: hard -"jimp@npm:^0.10.3": - version: 0.10.3 - resolution: "jimp@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/custom": ^0.10.3 - "@jimp/plugins": ^0.10.3 - "@jimp/types": ^0.10.3 - core-js: ^3.4.1 - regenerator-runtime: ^0.13.3 - checksum: ace7d9d76c2802e26392603c1fdfc988e7c468941ac127405f6752db9b5c89e1e27f202f96b764eede001ac245be0b46f52bb87eb91a42374027050568a7e816 - languageName: node - linkType: hard - "jju@npm:~1.4.0": version: 1.4.0 resolution: "jju@npm:1.4.0" @@ -27228,20 +26523,6 @@ __metadata: languageName: node linkType: hard -"jpeg-js@npm:^0.3.4": - version: 0.3.7 - resolution: "jpeg-js@npm:0.3.7" - checksum: 85a1ab09fe696fdd7b94ee077f1b8d1de307ffd7a83c0c45cc5cc56b0d7b47e561b92f6f090165648387875d674ba3076e3fedf395d5be4ef46760b6ebc804fe - languageName: node - linkType: hard - -"js-base64@npm:^2.5.1": - version: 2.6.4 - resolution: "js-base64@npm:2.6.4" - checksum: 5f4084078d6c46f8529741d110df84b14fac3276b903760c21fa8cc8521370d607325dfe1c1a9fbbeaae1ff8e602665aaeef1362427d8fef704f9e3659472ce8 - languageName: node - linkType: hard - "js-base64@npm:^3.6.0": version: 3.7.4 resolution: "js-base64@npm:3.7.4" @@ -28410,22 +27691,6 @@ __metadata: languageName: node linkType: hard -"load-bmfont@npm:^1.3.1, load-bmfont@npm:^1.4.0": - version: 1.4.1 - resolution: "load-bmfont@npm:1.4.1" - dependencies: - buffer-equal: 0.0.1 - mime: ^1.3.4 - parse-bmfont-ascii: ^1.0.3 - parse-bmfont-binary: ^1.0.5 - parse-bmfont-xml: ^1.1.4 - phin: ^2.9.1 - xhr: ^2.0.1 - xtend: ^4.0.0 - checksum: 688d932fb0dc4c9333747736ccd926261f0b91734b7bdb6ff24f8659ef068a0f0b2278084b208851afac0beec79af7bd6664fe2ed5b6c5e1db88755fc25f785e - languageName: node - linkType: hard - "load-json-file@npm:^1.0.0": version: 1.1.0 resolution: "load-json-file@npm:1.1.0" @@ -28730,7 +27995,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:4.17.21, lodash@npm:^4.17.10, lodash@npm:^4.17.11, lodash@npm:^4.17.13, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.7.0, lodash@npm:~4.17.0, lodash@npm:~4.17.15": +"lodash@npm:4.17.21, lodash@npm:^4.17.10, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.7.0, lodash@npm:~4.17.0, lodash@npm:~4.17.15": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -29399,13 +28664,6 @@ __metadata: languageName: node linkType: hard -"merge@npm:^1.2.1": - version: 1.2.1 - resolution: "merge@npm:1.2.1" - checksum: 2298c4fdcf64561f320b92338681f7ffcafafb579a6e294066ae3e7bd10ae25df363903d2f028072733b9f79a1f75d2b999aef98ad5d73de13641da39cda0913 - languageName: node - linkType: hard - "meros@npm:1.2.1, meros@npm:^1.1.4": version: 1.2.1 resolution: "meros@npm:1.2.1" @@ -29418,6 +28676,13 @@ __metadata: languageName: node linkType: hard +"meta-png@npm:1.0.5": + version: 1.0.5 + resolution: "meta-png@npm:1.0.5" + checksum: b8c92a696d5e78ef7f0ab53eb9039f108ee0c55cdac9d70e92e5fe2187b090176c0489426d58e594c7d1096481dac37913dd1265f28dfa39926db4d702a5e21d + languageName: node + linkType: hard + "methods@npm:^1.0.0, methods@npm:^1.1.2, methods@npm:~1.1.2": version: 1.1.2 resolution: "methods@npm:1.1.2" @@ -29807,7 +29072,7 @@ __metadata: languageName: node linkType: hard -"mime@npm:1.6.0, mime@npm:^1.3.4": +"mime@npm:1.6.0": version: 1.6.0 resolution: "mime@npm:1.6.0" bin: @@ -29869,15 +29134,6 @@ __metadata: languageName: node linkType: hard -"min-document@npm:^2.19.0": - version: 2.19.0 - resolution: "min-document@npm:2.19.0" - dependencies: - dom-walk: ^0.1.0 - checksum: da6437562ea2228041542a2384528e74e22d1daa1a4ec439c165abf0b9d8a63e17e3b8a6dc6e0c731845e85301198730426932a0e813d23f932ca668340c9623 - languageName: node - linkType: hard - "min-indent@npm:^1.0.0": version: 1.0.1 resolution: "min-indent@npm:1.0.1" @@ -30093,24 +29349,6 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:0.3.0": - version: 0.3.0 - resolution: "mkdirp@npm:0.3.0" - checksum: 3ec9cda8bd89b64892728e5092bc79e88382e444d4bbde040c2fb8d7034dc70682cfdd729e93241fd5243d2397324c420ef68c717d806db51bf96c0fc80f4b1d - languageName: node - linkType: hard - -"mkdirp@npm:^0.5.1": - version: 0.5.5 - resolution: "mkdirp@npm:0.5.5" - dependencies: - minimist: ^1.2.5 - bin: - mkdirp: bin/cmd.js - checksum: 3bce20ea525f9477befe458ab85284b0b66c8dc3812f94155af07c827175948cdd8114852ac6c6d82009b13c1048c37f6d98743eb019651ee25c39acc8aabe7d - languageName: node - linkType: hard - "mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" @@ -30147,6 +29385,15 @@ __metadata: languageName: node linkType: hard +"move-file@npm:2.1.0": + version: 2.1.0 + resolution: "move-file@npm:2.1.0" + dependencies: + path-exists: ^4.0.0 + checksum: 2b92bbe047a302b593fcb2c0bf1131bb090ec80b3264569fc80d782c8ff829eecc13573943fa4d804c9747dec612ef2d1e84a5cfcf29cbc64a69ffcbb7ea09b3 + languageName: node + linkType: hard + "mri@npm:1.1.4": version: 1.1.4 resolution: "mri@npm:1.1.4" @@ -30453,6 +29700,15 @@ __metadata: languageName: node linkType: hard +"node-addon-api@npm:^5.0.0": + version: 5.1.0 + resolution: "node-addon-api@npm:5.1.0" + dependencies: + node-gyp: latest + checksum: 2508bd2d2981945406243a7bd31362fc7af8b70b8b4d65f869c61731800058fb818cc2fd36c8eac714ddd0e568cc85becf5e165cebbdf7b5024d5151bbc75ea1 + languageName: node + linkType: hard + "node-cache@npm:^5.1.2": version: 5.1.2 resolution: "node-cache@npm:5.1.2" @@ -30648,17 +29904,6 @@ __metadata: languageName: node linkType: hard -"nopt@npm:1.0.10, nopt@npm:~1.0.10": - version: 1.0.10 - resolution: "nopt@npm:1.0.10" - dependencies: - abbrev: 1 - bin: - nopt: ./bin/nopt.js - checksum: f62575aceaa3be43f365bf37a596b89bbac2e796b001b6d2e2a85c2140a4e378ff919e2753ccba959c4fd344776fc88c29b393bc167fa939fb1513f126f4cd45 - languageName: node - linkType: hard - "nopt@npm:^5.0.0": version: 5.0.0 resolution: "nopt@npm:5.0.0" @@ -30681,6 +29926,17 @@ __metadata: languageName: node linkType: hard +"nopt@npm:~1.0.10": + version: 1.0.10 + resolution: "nopt@npm:1.0.10" + dependencies: + abbrev: 1 + bin: + nopt: ./bin/nopt.js + checksum: f62575aceaa3be43f365bf37a596b89bbac2e796b001b6d2e2a85c2140a4e378ff919e2753ccba959c4fd344776fc88c29b393bc167fa939fb1513f126f4cd45 + languageName: node + linkType: hard + "normalize-package-data@npm:^2.3.2, normalize-package-data@npm:^2.5.0": version: 2.5.0 resolution: "normalize-package-data@npm:2.5.0" @@ -31084,13 +30340,6 @@ __metadata: languageName: node linkType: hard -"omggif@npm:^1.0.9": - version: 1.0.10 - resolution: "omggif@npm:1.0.10" - checksum: 15102e46b6fa0fba32d7e948f702623cdc3cdcdfd64b2d33c6e29a61f366ffd0f250da55d66f5217dce5b93ba9c67763fa998652791a5c7f2201a3bde2c4db45 - languageName: node - linkType: hard - "on-finished@npm:2.4.1, on-finished@npm:^2.3.0": version: 2.4.1 resolution: "on-finished@npm:2.4.1" @@ -31473,7 +30722,7 @@ __metadata: languageName: node linkType: hard -"pako@npm:^1.0.10, pako@npm:^1.0.5, pako@npm:~1.0.5": +"pako@npm:^1.0.10, pako@npm:~1.0.5": version: 1.0.11 resolution: "pako@npm:1.0.11" checksum: 1be2bfa1f807608c7538afa15d6f25baa523c30ec870a3228a89579e474a4d992f4293859524e46d5d87fd30fa17c5edf34dbef0671251d9749820b488660b16 @@ -31520,30 +30769,6 @@ __metadata: languageName: node linkType: hard -"parse-bmfont-ascii@npm:^1.0.3": - version: 1.0.6 - resolution: "parse-bmfont-ascii@npm:1.0.6" - checksum: de3f6671f183c3e9d64bb4812b0407693b5fd0d24e9d16b2e106bb9eef809d64a6cc061f39ca29bb10c5c2e47e241e91b7aeefa587391fff7ccb27ab9db5012e - languageName: node - linkType: hard - -"parse-bmfont-binary@npm:^1.0.5": - version: 1.0.6 - resolution: "parse-bmfont-binary@npm:1.0.6" - checksum: ca37fb1e92f5941fddc5342b45857fafd27f00d2bd5fa44dd504bec6faeab97536c95ad45260c2dd5fc4c63de71e525663d3cdac09d038cbca803d97c669add5 - languageName: node - linkType: hard - -"parse-bmfont-xml@npm:^1.1.4": - version: 1.1.4 - resolution: "parse-bmfont-xml@npm:1.1.4" - dependencies: - xml-parse-from-string: ^1.0.0 - xml2js: ^0.4.5 - checksum: 879e5435be44f22b8c4934e2e1d2754a6d90a9ddb16309360daff965e1428d877b673f3d1fafaab4fef437c912a0db9f85545e0dd375ec62df7d4d328450d257 - languageName: node - linkType: hard - "parse-conflict-json@npm:^2.0.1": version: 2.0.1 resolution: "parse-conflict-json@npm:2.0.1" @@ -31594,13 +30819,6 @@ __metadata: languageName: node linkType: hard -"parse-headers@npm:^2.0.0": - version: 2.0.4 - resolution: "parse-headers@npm:2.0.4" - checksum: 29519ac013e100c11a67d0fc64eb33ae86523abf547f71dba36d484dcd16a2835dd11f31303f4ded27c40133dca5a5fe4d15b77f49091e470a6f74a023c59c4a - languageName: node - linkType: hard - "parse-json@npm:^2.2.0": version: 2.2.0 resolution: "parse-json@npm:2.2.0" @@ -31673,20 +30891,6 @@ __metadata: languageName: node linkType: hard -"parseqs@npm:0.0.6": - version: 0.0.6 - resolution: "parseqs@npm:0.0.6" - checksum: 7fc4ff4ba59764060bb8529875f6d4313056ea6939ff579b22dd7bd6f6033035e1fd2d6a559ab48ef0a7fa29a9d7731c982bfd1594e9115141fe1c328485ce9e - languageName: node - linkType: hard - -"parseuri@npm:0.0.6": - version: 0.0.6 - resolution: "parseuri@npm:0.0.6" - checksum: fa430e40f0c75293a28e5f1023da5f51a5038d5e34c48c517b0d5187143f6bcc67d3091a062b68765db4a22757e488c7d15854f9d1921f2c2b9afa5ca0629a84 - languageName: node - linkType: hard - "parseurl@npm:^1.3.3, parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" @@ -32177,13 +31381,6 @@ __metadata: languageName: node linkType: hard -"phin@npm:^2.9.1": - version: 2.9.3 - resolution: "phin@npm:2.9.3" - checksum: 7e2abd7be74a54eb7be92dccb1d7a019725c8adaa79ac22a38f25220f9a859393e654ea753a559d326aed7bbc966fadac88270cc8c39d78896f7784219560c47 - languageName: node - linkType: hard - "picocolors@npm:^1.0.0": version: 1.0.0 resolution: "picocolors@npm:1.0.0" @@ -32300,14 +31497,14 @@ __metadata: languageName: node linkType: hard -"pixelmatch@npm:^4.0.2": - version: 4.0.2 - resolution: "pixelmatch@npm:4.0.2" +"pixelmatch@npm:5.3.0": + version: 5.3.0 + resolution: "pixelmatch@npm:5.3.0" dependencies: - pngjs: ^3.0.0 + pngjs: ^6.0.0 bin: pixelmatch: bin/pixelmatch - checksum: 9c5c1329001938cae6d01e2bb84a909ba767f8256bcafc075422cea2a4dbaa8bebd44fceaa4b4ce7cdc36d11f20d4f1ba0cf669851d5649b32d8d1d27e4f5a36 + checksum: f542713d89536551181ad9ddb666a1792ba00a8632d831093232a075cb3ccac05856e7a453ed7d0a41aaef64dcb5962e8ae5cbe646dd2761790d8ee51b0a0743 languageName: node linkType: hard @@ -32359,10 +31556,10 @@ __metadata: languageName: node linkType: hard -"pngjs@npm:^3.0.0, pngjs@npm:^3.3.3": - version: 3.4.0 - resolution: "pngjs@npm:3.4.0" - checksum: 8bd40bd698abd16b72c97b85cb858c80894fbedc76277ce72a784aa441e14795d45d9856e97333ca469b34b67528860ffc8a7317ca6beea349b645366df00bcd +"pngjs@npm:6.0.0, pngjs@npm:^6.0.0": + version: 6.0.0 + resolution: "pngjs@npm:6.0.0" + checksum: ab6c285086060087097eab9fe6b5a528a24f9e79c03dea2b4fd6264ed4fdb5beff4a3257eeeaf2a9dc18249b539609c2a4e4013c567164a1f6b5ba2c974d5ecb languageName: node linkType: hard @@ -32852,6 +32049,28 @@ __metadata: languageName: node linkType: hard +"prebuild-install@npm:^7.1.1": + version: 7.1.1 + resolution: "prebuild-install@npm:7.1.1" + dependencies: + detect-libc: ^2.0.0 + expand-template: ^2.0.3 + github-from-package: 0.0.0 + minimist: ^1.2.3 + mkdirp-classic: ^0.5.3 + napi-build-utils: ^1.0.1 + node-abi: ^3.3.0 + pump: ^3.0.0 + rc: ^1.2.7 + simple-get: ^4.0.0 + tar-fs: ^2.0.0 + tunnel-agent: ^0.6.0 + bin: + prebuild-install: bin.js + checksum: dbf96d0146b6b5827fc8f67f72074d2e19c69628b9a7a0a17d0fad1bf37e9f06922896972e074197fc00a52eae912993e6ef5a0d471652f561df5cb516f3f467 + languageName: node + linkType: hard + "precond@npm:0.2": version: 0.2.3 resolution: "precond@npm:0.2.3" @@ -32885,15 +32104,6 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^1.16.4": - version: 1.19.1 - resolution: "prettier@npm:1.19.1" - bin: - prettier: ./bin-prettier.js - checksum: bc78219e0f8173a808f4c6c8e0a137dd8ebd4fbe013e63fe1a37a82b48612f17b8ae8e18a992adf802ee2cf7428f14f084e7c2846ca5759cf4013c6e54810e1f - languageName: node - linkType: hard - "prettier@npm:^2.2.1, prettier@npm:^2.7.1": version: 2.8.1 resolution: "prettier@npm:2.8.1" @@ -34396,7 +33606,7 @@ __metadata: languageName: node linkType: hard -"regenerator-runtime@npm:^0.13.11, regenerator-runtime@npm:^0.13.3, regenerator-runtime@npm:^0.13.4": +"regenerator-runtime@npm:^0.13.11, regenerator-runtime@npm:^0.13.4": version: 0.13.11 resolution: "regenerator-runtime@npm:0.13.11" checksum: 27481628d22a1c4e3ff551096a683b424242a216fee44685467307f14d58020af1e19660bf2e26064de946bad7eff28950eae9f8209d55723e2d9351e632bbb4 @@ -35234,15 +34444,6 @@ __metadata: languageName: node linkType: hard -"sanitize-filename@npm:^1.6.1": - version: 1.6.3 - resolution: "sanitize-filename@npm:1.6.3" - dependencies: - truncate-utf8-bytes: ^1.0.0 - checksum: aa733c012b7823cf65730603cf3b503c641cee6b239771d3164ca482f22d81a50e434a713938d994071db18e4202625669cc56bccc9d13d818b4c983b5f47fde - languageName: node - linkType: hard - "sax@npm:1.2.1": version: 1.2.1 resolution: "sax@npm:1.2.1" @@ -35621,6 +34822,23 @@ __metadata: languageName: node linkType: hard +"sharp@npm:0.31.2": + version: 0.31.2 + resolution: "sharp@npm:0.31.2" + dependencies: + color: ^4.2.3 + detect-libc: ^2.0.1 + node-addon-api: ^5.0.0 + node-gyp: latest + prebuild-install: ^7.1.1 + semver: ^7.3.8 + simple-get: ^4.0.1 + tar-fs: ^2.1.1 + tunnel-agent: ^0.6.0 + checksum: 076717b7a073ea47bb522ff2931b74b6608daeb6f7ae334e4848d47fdf4d23bcb18cd49044fd5fb27ef27a1a4aa87d141894d67d1c4bb15a6e2e63cf4dbe329e + languageName: node + linkType: hard + "shebang-command@npm:^1.2.0": version: 1.2.0 resolution: "shebang-command@npm:1.2.0" @@ -35864,68 +35082,6 @@ __metadata: languageName: node linkType: hard -"socket.io-adapter@npm:~1.1.0": - version: 1.1.2 - resolution: "socket.io-adapter@npm:1.1.2" - checksum: 8e18df7f8c471001b65e43542c5c743b63f041781bca097b4a407dd199dd757c14c0d470992f84923f48e75729a2ac0ae634fec820f20881cadae8a495bf68e9 - languageName: node - linkType: hard - -"socket.io-client@npm:2.5.0, socket.io-client@npm:^2.2.0": - version: 2.5.0 - resolution: "socket.io-client@npm:2.5.0" - dependencies: - backo2: 1.0.2 - component-bind: 1.0.0 - component-emitter: ~1.3.0 - debug: ~3.1.0 - engine.io-client: ~3.5.0 - has-binary2: ~1.0.2 - indexof: 0.0.1 - parseqs: 0.0.6 - parseuri: 0.0.6 - socket.io-parser: ~3.3.0 - to-array: 0.1.4 - checksum: a33accaf02c4a4c47ac9b09018fa4b9fa67a648a0cc92602e520ec884520050796786eb0df78fc1a9bf51e7b3d7b50ba4ffd3bda6e44df2c253a77100124669c - languageName: node - linkType: hard - -"socket.io-parser@npm:~3.3.0": - version: 3.3.3 - resolution: "socket.io-parser@npm:3.3.3" - dependencies: - component-emitter: ~1.3.0 - debug: ~3.1.0 - isarray: 2.0.1 - checksum: 6cf464e324e4207811dbf994822c0aa18ba01d615fbed8e3f069927e0e402fdc9b3ac3d2657f18d481fb8c584b1fd40152ced15b3686982a51ec843c6a76dbc2 - languageName: node - linkType: hard - -"socket.io-parser@npm:~3.4.0": - version: 3.4.1 - resolution: "socket.io-parser@npm:3.4.1" - dependencies: - component-emitter: 1.2.1 - debug: ~4.1.0 - isarray: 2.0.1 - checksum: f8bac61298375680aceb6c72ffbb47a2d950daa05e01a3b67d9330945073ae01e35aa131dcddd7e0b354ca302c51742bebaae57a50c188d4c1fe8af9461aa38d - languageName: node - linkType: hard - -"socket.io@npm:^2.2.0": - version: 2.5.0 - resolution: "socket.io@npm:2.5.0" - dependencies: - debug: ~4.1.0 - engine.io: ~3.6.0 - has-binary2: ~1.0.2 - socket.io-adapter: ~1.1.0 - socket.io-client: 2.5.0 - socket.io-parser: ~3.4.0 - checksum: 6f20a413352cb0a8bb13063249fe425c81fb54beca1bdd71221262305cf21232e6a37fdd4a232b5695dbd4d3204281a9313829c9c373c5ba01c5bd7218edd094 - languageName: node - linkType: hard - "sockjs@npm:^0.3.24": version: 0.3.24 resolution: "sockjs@npm:0.3.24" @@ -36003,7 +35159,7 @@ __metadata: languageName: node linkType: hard -"source-map-support@npm:^0.5.10, source-map-support@npm:^0.5.16, source-map-support@npm:~0.5.20": +"source-map-support@npm:^0.5.16, source-map-support@npm:~0.5.20": version: 0.5.21 resolution: "source-map-support@npm:0.5.21" dependencies: @@ -37382,13 +36538,6 @@ __metadata: languageName: node linkType: hard -"timm@npm:^1.6.1": - version: 1.7.1 - resolution: "timm@npm:1.7.1" - checksum: c80df538ec7fae50a0e3183931b20fbe97f6f2c06907d9675eb7b9d90b3f788af7742285c730192db3b066c4ab22ebae75f8d21970c5b03f38d928d5bb2a0339 - languageName: node - linkType: hard - "timsort@npm:^0.3.0": version: 0.3.0 resolution: "timsort@npm:0.3.0" @@ -37424,13 +36573,6 @@ __metadata: languageName: node linkType: hard -"tinycolor2@npm:^1.4.1": - version: 1.4.2 - resolution: "tinycolor2@npm:1.4.2" - checksum: 57ed262e08815a4ab0ed933edafdbc6555a17081781766149813b44a080ecbe58b3ee281e81c0e75b42e4d41679f138cfa98eabf043f829e0683c04adb12c031 - languageName: node - linkType: hard - "title-case@npm:^3.0.3": version: 3.0.3 resolution: "title-case@npm:3.0.3" @@ -37474,13 +36616,6 @@ __metadata: languageName: node linkType: hard -"to-array@npm:0.1.4": - version: 0.1.4 - resolution: "to-array@npm:0.1.4" - checksum: 396a04df5a5e74df5c8891ebb819d575d626e2929312fec3d649b4d38203bbf7185c270cb31fcad903564743895e935f2e965770bd1c6eb137dde48c4d60788d - languageName: node - linkType: hard - "to-arraybuffer@npm:^1.0.0": version: 1.0.1 resolution: "to-arraybuffer@npm:1.0.1" @@ -37654,15 +36789,6 @@ __metadata: languageName: node linkType: hard -"truncate-utf8-bytes@npm:^1.0.0": - version: 1.0.2 - resolution: "truncate-utf8-bytes@npm:1.0.2" - dependencies: - utf8-byte-length: ^1.0.1 - checksum: ad097314709ea98444ad9c80c03aac8da805b894f37ceb5685c49ad297483afe3a5ec9572ebcaff699dda72b6cd447a2ba2a3fd10e96c2628cd16d94abeb328a - languageName: node - linkType: hard - "tryer@npm:^1.0.1": version: 1.0.1 resolution: "tryer@npm:1.0.1" @@ -38126,15 +37252,6 @@ __metadata: languageName: node linkType: hard -"unidiff@npm:1.0.2": - version: 1.0.2 - resolution: "unidiff@npm:1.0.2" - dependencies: - diff: ^2.2.2 - checksum: 442d699d44a07f7511e2ec5b6433fb562d6ddce9eb91c6c28ff23bdda60595d9d7e8c6341937f18996ca03c198d93cc9b8fb448dde211ddeeb45bb45bff8ca1e - languageName: node - linkType: hard - "unified@npm:^10.0.0": version: 10.1.0 resolution: "unified@npm:10.1.0" @@ -38442,22 +37559,6 @@ __metadata: languageName: node linkType: hard -"utf8-byte-length@npm:^1.0.1": - version: 1.0.4 - resolution: "utf8-byte-length@npm:1.0.4" - checksum: f188ca076ec094d58e7009fcc32623c5830c7f0f3e15802bfa4fdd1e759454a481fc4ac05e0fa83b7736e77af628a9ee0e57dcc89683d688fde3811473e42143 - languageName: node - linkType: hard - -"utif@npm:^2.0.1": - version: 2.0.1 - resolution: "utif@npm:2.0.1" - dependencies: - pako: ^1.0.5 - checksum: 66b0bffc18f08834a34c44846f189b2223418e8bddfff3882e07fccea54436737f7334e27c86cbff46e247487dc92377b7a17428a7aafc5d5c733d61bed39038 - languageName: node - linkType: hard - "util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -39116,7 +38217,7 @@ __metadata: languageName: node linkType: hard -"whatwg-fetch@npm:>=0.10.0, whatwg-fetch@npm:^3.0.0, whatwg-fetch@npm:^3.4.1": +"whatwg-fetch@npm:>=0.10.0, whatwg-fetch@npm:^3.4.1": version: 3.6.2 resolution: "whatwg-fetch@npm:3.6.2" checksum: ee976b7249e7791edb0d0a62cd806b29006ad7ec3a3d89145921ad8c00a3a67e4be8f3fb3ec6bc7b58498724fd568d11aeeeea1f7827e7e1e5eae6c8a275afed @@ -39435,21 +38536,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:~7.4.2": - version: 7.4.6 - resolution: "ws@npm:7.4.6" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 3a990b32ed08c72070d5e8913e14dfcd831919205be52a3ff0b4cdd998c8d554f167c9df3841605cde8b11d607768cacab3e823c58c96a5c08c987e093eb767a - languageName: node - linkType: hard - "xcase@npm:^2.0.1": version: 2.0.1 resolution: "xcase@npm:2.0.1" @@ -39457,18 +38543,6 @@ __metadata: languageName: node linkType: hard -"xhr@npm:^2.0.1": - version: 2.6.0 - resolution: "xhr@npm:2.6.0" - dependencies: - global: ~4.4.0 - is-function: ^1.0.1 - parse-headers: ^2.0.0 - xtend: ^4.0.0 - checksum: a1db277e37737caf3ed363d2a33ce4b4ea5b5fc190b663a6f70bc252799185b840ccaa166eaeeea4841c9c60b87741f0a24e29cbcf6708dd425986d4df186d2f - languageName: node - linkType: hard - "xml-but-prettier@npm:^1.0.1": version: 1.0.1 resolution: "xml-but-prettier@npm:1.0.1" @@ -39513,13 +38587,6 @@ __metadata: languageName: node linkType: hard -"xml-parse-from-string@npm:^1.0.0": - version: 1.0.1 - resolution: "xml-parse-from-string@npm:1.0.1" - checksum: 5155cb98e428409829f4060ce542c55438b2f7646d11fd306d850eaf12d35c06ffd9e86d76aa5230121a533b958fd1a319d6f90a5c113391853d0ff01f4da7bb - languageName: node - linkType: hard - "xml2js@npm:0.4.19": version: 0.4.19 resolution: "xml2js@npm:0.4.19" @@ -39530,7 +38597,7 @@ __metadata: languageName: node linkType: hard -"xml2js@npm:^0.4.11, xml2js@npm:^0.4.19, xml2js@npm:^0.4.23, xml2js@npm:^0.4.5": +"xml2js@npm:^0.4.11, xml2js@npm:^0.4.19, xml2js@npm:^0.4.23": version: 0.4.23 resolution: "xml2js@npm:0.4.23" dependencies: @@ -39582,13 +38649,6 @@ __metadata: languageName: node linkType: hard -"xmlhttprequest-ssl@npm:~1.6.2": - version: 1.6.3 - resolution: "xmlhttprequest-ssl@npm:1.6.3" - checksum: ac8e5de1cdd170bddb928de75393e8977e7eb80c0d8c24fe4be07f6aa1d5c8e2e42296d29abca6591ec2046cc708c220791ecfa56db43c958b8e4de8e7d39984 - languageName: node - linkType: hard - "xpath@npm:0.0.32": version: 0.0.32 resolution: "xpath@npm:0.0.32" @@ -39793,13 +38853,6 @@ __metadata: languageName: node linkType: hard -"yeast@npm:0.1.2": - version: 0.1.2 - resolution: "yeast@npm:0.1.2" - checksum: 81a250b69f601fed541e9518eb2972e75631dd81231689503d7f288612d4eec793b29c208d6807fd6bfc4c2a43614d0c6db233739a4ae6223e244aaed6a885c0 - languageName: node - linkType: hard - "yeoman-environment@npm:^3.9.1": version: 3.13.0 resolution: "yeoman-environment@npm:3.13.0" From 7e9536ada8ea3c288ce8633bd5637f16ca5f30b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MALIN=20WID=C3=88N?= Date: Wed, 7 Dec 2022 14:13:19 +0100 Subject: [PATCH 107/423] add the new package @frsource/cypress-plugin-visual-regression-diff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MALIN WIDÈN --- yarn.lock | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7844d0fadb..5b268ef6fd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,6 +1,3 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - __metadata: version: 6 cacheKey: 8 @@ -13401,7 +13398,7 @@ __metadata: "@backstage/cli-common": "workspace:^" "@backstage/config": "workspace:^" "@backstage/plugin-techdocs-node": "workspace:^" - "@frsource/cypress-plugin-visual-regression-diff": ^3.2.8 + "@frsource/cypress-plugin-visual-regression-diff": ^3.2.4 "@types/commander": ^2.12.2 "@types/dockerode": ^3.3.0 "@types/fs-extra": ^9.0.6 From f08ee791f39bdd7d03b0bb4634da6183e3c4593c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MALIN=20WID=C3=88N?= Date: Wed, 7 Dec 2022 14:18:41 +0100 Subject: [PATCH 108/423] update to cypress 10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MALIN WIDÈN --- packages/techdocs-cli/cypress.config.js | 16 ++++++++++ .../techdocs-cli/cypress/plugins/index.js | 30 +++++++++++++++++++ yarn.lock | 5 +++- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 packages/techdocs-cli/cypress/plugins/index.js diff --git a/packages/techdocs-cli/cypress.config.js b/packages/techdocs-cli/cypress.config.js index c4b007634a..b33ab2eace 100644 --- a/packages/techdocs-cli/cypress.config.js +++ b/packages/techdocs-cli/cypress.config.js @@ -21,9 +21,25 @@ module.exports = defineConfig({ setupNodeEvents(on, config) { initPlugin(on, config); }, +<<<<<<< HEAD excludeSpecPattern: ['**/__snapshots__/*', '**/__image_snapshots__/*'], }, +======= + }, + excludeSpecPattern: ['**/__snapshots__/*', '**/__image_snapshots__/*'], + env: { + mkDocsBaseUrl: 'http://localhost:8000', + backstageBaseUrl: 'http://localhost:3000', + 'cypress-plugin-snapshots': { + autoCleanUp: false, + imageConfig: { + resizeDevicePixelRatio: true, + threshold: 0.01, + }, + }, + }, +>>>>>>> 533a1a2db2 (update to cypress 10) viewportWidth: 1920, viewportHeight: 1080, includeShadowDom: true, diff --git a/packages/techdocs-cli/cypress/plugins/index.js b/packages/techdocs-cli/cypress/plugins/index.js new file mode 100644 index 0000000000..61af7e7f9b --- /dev/null +++ b/packages/techdocs-cli/cypress/plugins/index.js @@ -0,0 +1,30 @@ +/* + * 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. + */ + +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +require('@frsource/cypress-plugin-visual-regression-diff/plugin'); diff --git a/yarn.lock b/yarn.lock index 5b268ef6fd..7844d0fadb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,3 +1,6 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + __metadata: version: 6 cacheKey: 8 @@ -13398,7 +13401,7 @@ __metadata: "@backstage/cli-common": "workspace:^" "@backstage/config": "workspace:^" "@backstage/plugin-techdocs-node": "workspace:^" - "@frsource/cypress-plugin-visual-regression-diff": ^3.2.4 + "@frsource/cypress-plugin-visual-regression-diff": ^3.2.8 "@types/commander": ^2.12.2 "@types/dockerode": ^3.3.0 "@types/fs-extra": ^9.0.6 From f188cc4108defacbfc0ac061de0470ca8b84df16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MALIN=20WID=C3=88N?= Date: Wed, 7 Dec 2022 14:45:10 +0100 Subject: [PATCH 109/423] add changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MALIN WIDÈN --- .changeset/cool-ladybugs-argue.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/cool-ladybugs-argue.md diff --git a/.changeset/cool-ladybugs-argue.md b/.changeset/cool-ladybugs-argue.md new file mode 100644 index 0000000000..fe948a8c74 --- /dev/null +++ b/.changeset/cool-ladybugs-argue.md @@ -0,0 +1,8 @@ +--- +'@backstage/core-components': minor +'@backstage/create-app': minor +'@techdocs/cli': minor +'@backstage/plugin-dynatrace': minor +--- + +Change from cypress-plugin-snapshots to cypress-plugin-visual-regression-diff and update to cypress 10 From fbfda48dffe1eb1cd51e378dc7adee0a59c851a7 Mon Sep 17 00:00:00 2001 From: malin-mallan <78034678+malin-mallan@users.noreply.github.com> Date: Tue, 20 Dec 2022 16:00:42 +0100 Subject: [PATCH 110/423] Delete cool-ladybugs-argue.md Signed-off-by: malin-mallan <78034678+malin-mallan@users.noreply.github.com> --- .changeset/cool-ladybugs-argue.md | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 .changeset/cool-ladybugs-argue.md diff --git a/.changeset/cool-ladybugs-argue.md b/.changeset/cool-ladybugs-argue.md deleted file mode 100644 index fe948a8c74..0000000000 --- a/.changeset/cool-ladybugs-argue.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/core-components': minor -'@backstage/create-app': minor -'@techdocs/cli': minor -'@backstage/plugin-dynatrace': minor ---- - -Change from cypress-plugin-snapshots to cypress-plugin-visual-regression-diff and update to cypress 10 From ea7caa40b9ac3592c7a93279b2b336d0c7a81bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MALIN=20WID=C3=88N?= Date: Wed, 21 Dec 2022 15:02:05 +0100 Subject: [PATCH 111/423] solve merge conflict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MALIN WIDÈN --- packages/techdocs-cli/cypress.config.js | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/packages/techdocs-cli/cypress.config.js b/packages/techdocs-cli/cypress.config.js index b33ab2eace..abaa324d76 100644 --- a/packages/techdocs-cli/cypress.config.js +++ b/packages/techdocs-cli/cypress.config.js @@ -21,25 +21,9 @@ module.exports = defineConfig({ setupNodeEvents(on, config) { initPlugin(on, config); }, -<<<<<<< HEAD + excludeSpecPattern: ['**/__snapshots__/*', '**/__image_snapshots__/*'], }, - -======= - }, - excludeSpecPattern: ['**/__snapshots__/*', '**/__image_snapshots__/*'], - env: { - mkDocsBaseUrl: 'http://localhost:8000', - backstageBaseUrl: 'http://localhost:3000', - 'cypress-plugin-snapshots': { - autoCleanUp: false, - imageConfig: { - resizeDevicePixelRatio: true, - threshold: 0.01, - }, - }, - }, ->>>>>>> 533a1a2db2 (update to cypress 10) viewportWidth: 1920, viewportHeight: 1080, includeShadowDom: true, From 266e5eb9e31094109aed21bc2104bbc12828e158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MALIN=20WID=C3=88N?= Date: Tue, 20 Dec 2022 16:58:54 +0100 Subject: [PATCH 112/423] change folder structure in techdocs-cli/cypress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MALIN WIDÈN --- .../techdocs-cli/cypress/plugins/index.js | 30 ------------------- 1 file changed, 30 deletions(-) delete mode 100644 packages/techdocs-cli/cypress/plugins/index.js diff --git a/packages/techdocs-cli/cypress/plugins/index.js b/packages/techdocs-cli/cypress/plugins/index.js deleted file mode 100644 index 61af7e7f9b..0000000000 --- a/packages/techdocs-cli/cypress/plugins/index.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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. - */ - -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -require('@frsource/cypress-plugin-visual-regression-diff/plugin'); From 9060ad0ab9b249d2dae59a71cf87795d003ef72e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 31 Jan 2023 10:30:37 +0100 Subject: [PATCH 113/423] dedupe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- yarn.lock | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7844d0fadb..e5d7307f12 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30103,7 +30103,7 @@ __metadata: languageName: node linkType: hard -"npmlog@npm:^4.0.1, npmlog@npm:^4.1.2": +"npmlog@npm:^4.1.2": version: 4.1.2 resolution: "npmlog@npm:4.1.2" dependencies: @@ -32026,30 +32026,7 @@ __metadata: languageName: node linkType: hard -"prebuild-install@npm:^7.1.0": - version: 7.1.0 - resolution: "prebuild-install@npm:7.1.0" - dependencies: - detect-libc: ^2.0.0 - expand-template: ^2.0.3 - github-from-package: 0.0.0 - minimist: ^1.2.3 - mkdirp-classic: ^0.5.3 - napi-build-utils: ^1.0.1 - node-abi: ^3.3.0 - npmlog: ^4.0.1 - pump: ^3.0.0 - rc: ^1.2.7 - simple-get: ^4.0.0 - tar-fs: ^2.0.0 - tunnel-agent: ^0.6.0 - bin: - prebuild-install: bin.js - checksum: 204f2d89c6d6179fa1039036514aa72f7d0b537e421ef72c40840286e318f41489f00f22c6acc725cce6e10d43825b69dcabeaadfc917db781c58cd56fc25f90 - languageName: node - linkType: hard - -"prebuild-install@npm:^7.1.1": +"prebuild-install@npm:^7.1.0, prebuild-install@npm:^7.1.1": version: 7.1.1 resolution: "prebuild-install@npm:7.1.1" dependencies: From c578ab658393caf2c0f9bdaf686efd036925b9b1 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Fri, 3 Feb 2023 10:34:35 +0000 Subject: [PATCH 114/423] docs: adjust code block type in permission tutorial step 1 Signed-off-by: MT Lewis --- docs/permissions/plugin-authors/01-setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/permissions/plugin-authors/01-setup.md b/docs/permissions/plugin-authors/01-setup.md index 04e31b859e..a38b81e679 100644 --- a/docs/permissions/plugin-authors/01-setup.md +++ b/docs/permissions/plugin-authors/01-setup.md @@ -48,7 +48,7 @@ The source code is available here: Create a new `packages/backend/src/plugins/todolist.ts` with the following content: - ```javascript + ```typescript import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; import { createRouter } from '@internal/plugin-todo-list-backend'; import { Router } from 'express'; From 8d6d1fb789ba3a6a8982df2083c017dd6583a8ec Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Fri, 3 Feb 2023 10:34:53 +0000 Subject: [PATCH 115/423] docs: miscellaneous permission tutorial step 2 fixes Signed-off-by: MT Lewis --- .../02-adding-a-basic-permission-check.md | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md b/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md index 241b175987..551e48f91a 100644 --- a/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md +++ b/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md @@ -146,7 +146,7 @@ In order to test the logic above, the integrators of your backstage instance nee - async handle(): Promise { + async handle( + request: PolicyQuery, -+ user?: BackstageIdentityResponse, ++ _user?: BackstageIdentityResponse, + ): Promise { + if (isPermission(request.permission, todoListCreatePermission)) { + return { @@ -204,7 +204,7 @@ First we'll clean up the `plugins/todo-list-backend/src/service/router.test.ts`: const router = await createRouter({ logger: getVoidLogger(), identity: {} as DefaultIdentityClient, -+ permissions: toPermissionEvaluator, ++ permissions: permissionEvaluator, }); app = express().use(router); }); @@ -235,7 +235,7 @@ Then we want to update the `plugins/todo-list-backend/src/service/standaloneServ + ServerTokenManager, } from '@backstage/backend-common'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; - import { ServerPermissionClient } from '@backstage/plugin-permission-node'; ++ import { ServerPermissionClient } from '@backstage/plugin-permission-node'; import { Server } from 'http'; import { Logger } from 'winston'; import { createRouter } from './router'; @@ -285,4 +285,44 @@ Then we want to update the `plugins/todo-list-backend/src/service/standaloneServ module.hot?.accept(); ``` +Finally, we need to update `plugins/todo-list-backend/src/plugin.ts`: + +```diff + import { loggerToWinstonLogger } from '@backstage/backend-common'; + import { + coreServices, + createBackendPlugin, + } from '@backstage/backend-plugin-api'; + import { createRouter } from './service/router'; + + /** + * The example TODO list backend plugin. + * + * @alpha + */ + export const exampleTodoListPlugin = createBackendPlugin({ + id: 'exampleTodoList', + register(env) { + env.registerInit({ + deps: { + identity: coreServices.identity, + logger: coreServices.logger, + httpRouter: coreServices.httpRouter, ++ permissions: coreServices.permissions, + }, +- async init({ identity, logger, httpRouter }) { ++ async init({ identity, logger, httpRouter, permissions }) { + httpRouter.use( + await createRouter({ + identity, + logger: loggerToWinstonLogger(logger), + permissions, + }), + ); + }, + }); + }, + }); +``` + Now when you run `yarn tsc` you should have no more errors. From ce2c9ac363abbfcfcbb74eb8436b27c402e49766 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Fri, 3 Feb 2023 10:45:31 +0000 Subject: [PATCH 116/423] docs: miscellaneous permission tutorial step 3 fixes Signed-off-by: MT Lewis --- .../03-adding-a-resource-permission-check.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md index 8913b6d438..b063727c71 100644 --- a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md +++ b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md @@ -76,7 +76,7 @@ This enables decisions based on characteristics of the resource, but it's import Install the missing module: ``` -$ yarn workspace @internal/plugin-todo-list-backend add @backstage/plugin-permission-node +$ yarn workspace @internal/plugin-todo-list-backend add @backstage/plugin-permission-node zod ``` Create a new `plugins/todo-list-backend/src/service/rules.ts` file and append the following code: @@ -89,7 +89,8 @@ import { Todo, TodoFilter } from './todos'; export const createTodoListPermissionRule = makeCreatePermissionRule< Todo, - TodoFilter + TodoFilter, + typeof TODO_LIST_RESOURCE_TYPE >(); export const isOwner = createTodoListPermissionRule({ @@ -97,8 +98,8 @@ export const isOwner = createTodoListPermissionRule({ description: 'Should allow only if the todo belongs to the user', resourceType: TODO_LIST_RESOURCE_TYPE, paramsSchema: z.object({ - userId: z.string().describe('User ID to match on the resource') - }) + userId: z.string().describe('User ID to match on the resource'), + }), apply: (resource: Todo, { userId }) => { return resource.author === userId; }, @@ -187,6 +188,7 @@ Make sure `todoListConditions` and `createTodoListConditionalDecision` are expor ```diff export * from './service/router'; + export * from './conditionExports'; + export { exampleTodoListPlugin } from './plugin'; ``` ## Test the authorized update endpoint @@ -209,7 +211,6 @@ Let's go back to the permission policy's handle function and try to authorize ou + import { + todoListCreatePermission, + todoListUpdatePermission, -+ TODO_LIST_RESOURCE_TYPE, + } from '@internal/plugin-todo-list-common'; + import { + todoListConditions, @@ -217,7 +218,11 @@ Let's go back to the permission policy's handle function and try to authorize ou + } from '@internal/plugin-todo-list-backend'; ... - + async handle( + request: PolicyQuery, +- _user?: BackstageIdentityResponse, ++ user?: BackstageIdentityResponse, + ): Promise { if (isPermission(request.permission, todoListCreatePermission)) { return { result: AuthorizeResult.ALLOW, @@ -236,6 +241,7 @@ Let's go back to the permission policy's handle function and try to authorize ou return { result: AuthorizeResult.ALLOW, }; + } ``` For any incoming update requests, we now return a _Conditional Decision_. We are saying: From f3bf8fea2439e714734b186c6eeb3db7157f11af Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Fri, 3 Feb 2023 11:00:56 +0000 Subject: [PATCH 117/423] docs: miscellaneous permission tutorial step 4 fixes Signed-off-by: MT Lewis --- .../04-authorizing-access-to-paginated-data.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md b/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md index 8ddcffdcd9..e84f53f176 100644 --- a/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md +++ b/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md @@ -15,7 +15,7 @@ One possible solution may leverage the batching functionality to authorize all o - res.json(getAll()) + const items = getAll(); + const decisions = await permissions.authorize( -+ items.map(({ id }) => ({ permission: todosListRead, resourceRef: id })), ++ items.map(({ id }) => ({ permission: todoListReadPermission, resourceRef: id })), + ); + const filteredItems = decisions.filter( @@ -53,7 +53,7 @@ Let's add another permission to the plugin. resourceType: TODO_LIST_RESOURCE_TYPE, }); + -+ export const todosListRead = createPermission({ ++ export const todoListReadPermission = createPermission({ + name: 'todos.list.read', + attributes: { action: 'read' }, + resourceType: TODO_LIST_RESOURCE_TYPE, @@ -81,10 +81,9 @@ So far we've only used the `PermissionEvaluator.authorize` method, which will ev import { todosListCreate, todosListUpdate, -+ todosListRead, ++ todoListReadPermission, TODO_LIST_RESOURCE_TYPE, } from './permissions'; -+ import { rules } from './rules'; + const transformConditions: ConditionTransformer = createConditionTransformer(Object.values(rules)); @@ -95,7 +94,7 @@ So far we've only used the `PermissionEvaluator.authorize` method, which will ev + ); + + const decision = ( -+ await permissions.authorizeConditional([{ permission: todosListRead }], { ++ await permissions.authorizeConditional([{ permission: todoListReadPermission }], { + token, + }) + )[0]; @@ -110,7 +109,6 @@ So far we've only used the `PermissionEvaluator.authorize` method, which will ev + } else { + res.json(getAll()); + } -+ } - res.json(getAll()); }); ``` @@ -121,7 +119,7 @@ Since `TodoFilter` used in our plugin matches the structure of the conditions ob ## Test the authorized read endpoint -Let's update our permission policy to return a conditional result whenever a `todosListRead` permission is received. In this case, we can reuse the decision returned for the `todosListCreate` permission. +Let's update our permission policy to return a conditional result whenever a `todoListReadPermission` permission is received. In this case, we can reuse the decision returned for the `todosListCreate` permission. ```diff // packages/backend/src/plugins/permission.ts @@ -132,7 +130,6 @@ import { todoListCreatePermission, todoListUpdatePermission, + todoListReadPermission, - TODO_LIST_RESOURCE_TYPE, } from '@internal/plugin-todo-list-common'; ... From 812ffcc292798cf5202e7f2d6afbcb5586528682 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Fri, 3 Feb 2023 12:55:50 +0000 Subject: [PATCH 118/423] docs: miscellaneous permission tutorial step 5 fixes Signed-off-by: MT Lewis --- .../05-frontend-authorization.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/permissions/plugin-authors/05-frontend-authorization.md b/docs/permissions/plugin-authors/05-frontend-authorization.md index d494ea60ba..753ce56461 100644 --- a/docs/permissions/plugin-authors/05-frontend-authorization.md +++ b/docs/permissions/plugin-authors/05-frontend-authorization.md @@ -56,7 +56,11 @@ Let's make the following changes in `plugins/todo-list/src/components/TodoListPa - Add - + {!loadingPermission && ( -+ + )} @@ -118,7 +122,10 @@ Providing a disabled state can be a helpful signal to users, but there may be ca - - - -+ }> ++ } ++ > + + + @@ -149,11 +156,15 @@ Providing a disabled state can be a helpful signal to users, but there may be ca onChange={e => (title.current = e.target.value)} /> - {!loadingPermission && ( -- - )} -+ From 27226d88a992b0c88dc7fe1767f931d03178f738 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 3 Feb 2023 14:21:57 +0100 Subject: [PATCH 119/423] chore: fixing api-reports Signed-off-by: blam --- plugins/badges-backend/api-report.md | 2 +- plugins/bitbucket-cloud-common/api-report.md | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/badges-backend/api-report.md b/plugins/badges-backend/api-report.md index 0ecf41ee85..8ca4b561a2 100644 --- a/plugins/badges-backend/api-report.md +++ b/plugins/badges-backend/api-report.md @@ -79,7 +79,7 @@ export type BadgeSpec = { }; // @public (undocumented) -export type BadgeStyle = typeof BADGE_STYLES[number]; +export type BadgeStyle = (typeof BADGE_STYLES)[number]; // @public (undocumented) export const createDefaultBadgeFactories: () => BadgeFactories; diff --git a/plugins/bitbucket-cloud-common/api-report.md b/plugins/bitbucket-cloud-common/api-report.md index 5182579a4b..95e6f36836 100644 --- a/plugins/bitbucket-cloud-common/api-report.md +++ b/plugins/bitbucket-cloud-common/api-report.md @@ -132,7 +132,7 @@ export namespace Models { readonly Plaintext: 'plaintext'; }; export type BaseCommitSummaryMarkupEnum = - typeof BaseCommitSummaryMarkupEnum[keyof typeof BaseCommitSummaryMarkupEnum]; + (typeof BaseCommitSummaryMarkupEnum)[keyof typeof BaseCommitSummaryMarkupEnum]; export interface Branch { default_merge_strategy?: string; // (undocumented) @@ -150,7 +150,7 @@ export namespace Models { readonly FastForward: 'fast_forward'; }; export type BranchMergeStrategiesEnum = - typeof BranchMergeStrategiesEnum[keyof typeof BranchMergeStrategiesEnum]; + (typeof BranchMergeStrategiesEnum)[keyof typeof BranchMergeStrategiesEnum]; export interface Commit extends BaseCommit { // (undocumented) participants?: Array; @@ -179,7 +179,7 @@ export namespace Models { }; // (undocumented) export type CommitFileAttributesEnum = - typeof CommitFileAttributesEnum[keyof typeof CommitFileAttributesEnum]; + (typeof CommitFileAttributesEnum)[keyof typeof CommitFileAttributesEnum]; export interface Link { // (undocumented) href?: string; @@ -221,7 +221,7 @@ export namespace Models { }; // (undocumented) export type ParticipantRoleEnum = - typeof ParticipantRoleEnum[keyof typeof ParticipantRoleEnum]; + (typeof ParticipantRoleEnum)[keyof typeof ParticipantRoleEnum]; const // (undocumented) ParticipantStateEnum: { readonly Approved: 'approved'; @@ -230,7 +230,7 @@ export namespace Models { }; // (undocumented) export type ParticipantStateEnum = - typeof ParticipantStateEnum[keyof typeof ParticipantStateEnum]; + (typeof ParticipantStateEnum)[keyof typeof ParticipantStateEnum]; export interface Project extends ModelObject { // (undocumented) created_on?: string; @@ -306,7 +306,7 @@ export namespace Models { readonly NoForks: 'no_forks'; }; export type RepositoryForkPolicyEnum = - typeof RepositoryForkPolicyEnum[keyof typeof RepositoryForkPolicyEnum]; + (typeof RepositoryForkPolicyEnum)[keyof typeof RepositoryForkPolicyEnum]; const // (undocumented) RepositoryScmEnum: { readonly Git: 'git'; @@ -336,7 +336,7 @@ export namespace Models { } // (undocumented) export type RepositoryScmEnum = - typeof RepositoryScmEnum[keyof typeof RepositoryScmEnum]; + (typeof RepositoryScmEnum)[keyof typeof RepositoryScmEnum]; // (undocumented) export interface SearchCodeSearchResult { // (undocumented) From 8f6b71ae39ac5d1ade7a4abe90a4737105f105e2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 3 Feb 2023 13:27:32 +0000 Subject: [PATCH 120/423] Update dependency @graphql-tools/schema to v9.0.15 Signed-off-by: Renovate Bot --- yarn.lock | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3d809a40c8..f042b70bf5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10070,7 +10070,7 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/merge@npm:8.3.16, @graphql-tools/merge@npm:^8.2.6": +"@graphql-tools/merge@npm:8.3.16": version: 8.3.16 resolution: "@graphql-tools/merge@npm:8.3.16" dependencies: @@ -10082,6 +10082,18 @@ __metadata: languageName: node linkType: hard +"@graphql-tools/merge@npm:8.3.17, @graphql-tools/merge@npm:^8.2.6": + version: 8.3.17 + resolution: "@graphql-tools/merge@npm:8.3.17" + dependencies: + "@graphql-tools/utils": 9.2.0 + tslib: ^2.4.0 + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 943e1ad64575ab9ae6726d434cf7b08e80099442f9d25c1ac9f11fdac7bd0e8e73109f0e2469b47650ad0a0731ac850ede844b5ff8a7eab352027a42c1e78c79 + languageName: node + linkType: hard + "@graphql-tools/mock@npm:^8.1.2": version: 8.6.8 resolution: "@graphql-tools/mock@npm:8.6.8" @@ -10191,7 +10203,7 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/schema@npm:9.0.14, @graphql-tools/schema@npm:^9.0.0": +"@graphql-tools/schema@npm:9.0.14": version: 9.0.14 resolution: "@graphql-tools/schema@npm:9.0.14" dependencies: @@ -10205,6 +10217,20 @@ __metadata: languageName: node linkType: hard +"@graphql-tools/schema@npm:^9.0.0": + version: 9.0.15 + resolution: "@graphql-tools/schema@npm:9.0.15" + dependencies: + "@graphql-tools/merge": 8.3.17 + "@graphql-tools/utils": 9.2.0 + tslib: ^2.4.0 + value-or-promise: 1.0.12 + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 4361cb1a355e8811fd9b762bd137a2f8fd287b05f03cb574bc3d5e6855aeceef462e72bacfa89dd9028138e9fe3cafc4d69c95d7f9a9b6ab7f037ca3e36f52a9 + languageName: node + linkType: hard + "@graphql-tools/url-loader@npm:7.16.28, @graphql-tools/url-loader@npm:^7.13.2, @graphql-tools/url-loader@npm:^7.9.7": version: 7.16.28 resolution: "@graphql-tools/url-loader@npm:7.16.28" @@ -10283,7 +10309,7 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/utils@npm:9.1.4, @graphql-tools/utils@npm:^9.0.0, @graphql-tools/utils@npm:^9.1.1": +"@graphql-tools/utils@npm:9.1.4": version: 9.1.4 resolution: "@graphql-tools/utils@npm:9.1.4" dependencies: @@ -10294,6 +10320,18 @@ __metadata: languageName: node linkType: hard +"@graphql-tools/utils@npm:9.2.0, @graphql-tools/utils@npm:^9.0.0, @graphql-tools/utils@npm:^9.1.1": + version: 9.2.0 + resolution: "@graphql-tools/utils@npm:9.2.0" + dependencies: + "@graphql-typed-document-node/core": ^3.1.1 + tslib: ^2.4.0 + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 9754f8c6d52490df395626cef224542f37ca040ced6688c8ad80b1e0498006186529a50ac21979465123debba093db33dbfe8f1f7a9101f969dec0f31dc9a45b + languageName: node + linkType: hard + "@graphql-tools/wrap@npm:9.2.23": version: 9.2.23 resolution: "@graphql-tools/wrap@npm:9.2.23" From 179d3015184ce0b0a2d9b9b1abc7a4f422256943 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Jan 2023 22:55:41 +0100 Subject: [PATCH 121/423] added eslint-plugin Signed-off-by: Patrik Oldsberg --- .changeset/tough-jeans-camp.md | 5 + .github/vale/Vocab/Backstage/accept.txt | 3 +- packages/eslint-plugin/README.md | 40 ++++++ packages/eslint-plugin/index.js | 29 ++++ packages/eslint-plugin/package.json | 16 +++ .../rules/no-forbidden-package-imports.js | 124 ++++++++++++++++++ yarn.lock | 6 + 7 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 .changeset/tough-jeans-camp.md create mode 100644 packages/eslint-plugin/README.md create mode 100644 packages/eslint-plugin/index.js create mode 100644 packages/eslint-plugin/package.json create mode 100644 packages/eslint-plugin/rules/no-forbidden-package-imports.js diff --git a/.changeset/tough-jeans-camp.md b/.changeset/tough-jeans-camp.md new file mode 100644 index 0000000000..b7c08593e1 --- /dev/null +++ b/.changeset/tough-jeans-camp.md @@ -0,0 +1,5 @@ +--- +'@backstage/eslint-plugin': minor +--- + +Added a new ESLint plugin with common rules for Backstage projects. diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index f24b701d36..9e7cf7aa98 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -336,6 +336,7 @@ subfolders subheader subheaders subkey +subpath subroutes subtree superfences @@ -418,4 +419,4 @@ Dominik Henneke Kuang Frontside -Kaswell \ No newline at end of file +Kaswell diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md new file mode 100644 index 0000000000..a063d801d3 --- /dev/null +++ b/packages/eslint-plugin/README.md @@ -0,0 +1,40 @@ +# @backstage/eslint-plugin + +A collection of ESLint rules useful to Backstage projects. + +## Usage + +This ESLint plugin is part of the default lint configuration provided by the [Backstage CLI](https://www.npmjs.com/package/@backstage/cli), so you generally do not need to install it manually. + +If you do wish to install this plugin manually, start by adding it as a development dependency to your project: + +```sh +yarn add --dev @backstage/eslint-plugin +``` + +Then add it to your ESLint configuration: + +```js +extends: [ + 'plugin:@backstage/recommended', +], +``` + +Alternatively, if you want to install in individual rules manually: + +```js +plugins: [ + '@backstage', +], +rules: { + '@backstage/no-forbidden-package-imports': 'error', +} +``` + +## Rules + +The following rules are provided by this plugin: + +| Rule | Description | +| ----------------------------------------- | ------------------------------------------------------------------------------- | +| `@backstage/no-forbidden-package-imports` | Disallow internal monorepo imports from package subpaths that are not exported. | diff --git a/packages/eslint-plugin/index.js b/packages/eslint-plugin/index.js new file mode 100644 index 0000000000..11d17b2b8f --- /dev/null +++ b/packages/eslint-plugin/index.js @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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. + */ + +module.exports = { + configs: { + recommended: { + plugins: ['@backstage'], + rules: { + '@backstage/no-forbidden-package-imports': 'error', + }, + }, + }, + rules: { + 'no-forbidden-package-imports': require('./rules/no-forbidden-package-imports'), + }, +}; diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json new file mode 100644 index 0000000000..9724cec32b --- /dev/null +++ b/packages/eslint-plugin/package.json @@ -0,0 +1,16 @@ +{ + "name": "@backstage/eslint-plugin", + "description": "Backstage ESLint plugin", + "version": "0.0.0", + "publishConfig": { + "access": "public" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/eslint-plugin" + }, + "license": "Apache-2.0", + "main": "./index.js" +} diff --git a/packages/eslint-plugin/rules/no-forbidden-package-imports.js b/packages/eslint-plugin/rules/no-forbidden-package-imports.js new file mode 100644 index 0000000000..d5cce80368 --- /dev/null +++ b/packages/eslint-plugin/rules/no-forbidden-package-imports.js @@ -0,0 +1,124 @@ +'use strict'; +/* + * Copyright 2023 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. + */ + +// @ts-check + +// Note: this file is ES5, because we want to avoid having to transpile it for local development + +var fs = require('fs'); +var path = require('path'); +/** @type {import('@manypkg/get-packages')} */ +var manypkg = require('@manypkg/get-packages'); + +// Loads all packages in the monorepo once, and caches the result +var getPackageMap = (function () { + var map = undefined; + var lastLoadAt = undefined; + + /** @returns {Record} */ + return function (/** @type {string} */ dir) { + if (map) { + // Only cache for 5 seconds, to avoid the need to reload ESLint servers + if (Date.now() - lastLoadAt > 5000) { + map = undefined; + } else { + return map; + } + } + var packages = manypkg.getPackagesSync(dir).packages; + if (!packages) { + return undefined; + } + map = {}; + lastLoadAt = Date.now(); + packages.forEach(function (pkg) { + map[pkg.packageJson.name] = pkg; + }); + return map; + }; +})(); + +module.exports = { + meta: { + type: 'problem', + messages: { + forbidden: '{{packageName}} does not export {{subPath}}', + }, + }, + create: function (/** @type import('eslint').Rule.RuleContext */ context) { + var packageMap = getPackageMap(context.getCwd()); + if (!packageMap) { + return; + } + + function checkImport(node) { + if (!node.source) { + return; + } + var importPath = node.source.value; + if (importPath[0] === '.') { + return; + } + + var pathParts = importPath.split('/'); + + // Check for match with plain name, then namespaced name + var name = pathParts.shift(); + if (!packageMap[name]) { + name += '/' + pathParts.shift(); + } + if (!packageMap[name]) { + return; + } + + // Empty subpaths are always allowed + var subPath = pathParts.join('/'); + if (!subPath) { + return; + } + + var pkg = packageMap[name]; + + // If the import is listed in the package.json exports field, we allow it + var exp = pkg.packageJson.exports; + if (exp && (exp[subPath] || exp['./' + subPath])) { + return; + } + + // If there's a package.json in the target directory, we allow the import + if (fs.existsSync(path.resolve(pkg.dir, subPath, 'package.json'))) { + return; + } + + context.report({ + node: node, + messageId: 'forbidden', + data: { + packageName: pkg.packageJson.name || '', + subPath: subPath, + }, + }); + } + + return { + ImportDeclaration: checkImport, + ExportAllDeclaration: checkImport, + ExportNamedDeclaration: checkImport, + ImportExpression: checkImport, + }; + }, +}; diff --git a/yarn.lock b/yarn.lock index 3d809a40c8..ac5c6d0541 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4095,6 +4095,12 @@ __metadata: languageName: unknown linkType: soft +"@backstage/eslint-plugin@workspace:packages/eslint-plugin": + version: 0.0.0-use.local + resolution: "@backstage/eslint-plugin@workspace:packages/eslint-plugin" + languageName: unknown + linkType: soft + "@backstage/integration-aws-node@workspace:^, @backstage/integration-aws-node@workspace:packages/integration-aws-node": version: 0.0.0-use.local resolution: "@backstage/integration-aws-node@workspace:packages/integration-aws-node" From 98b2bd1b51688ae5947a755dc13e023a6fa5e739 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Jan 2023 21:53:55 +0100 Subject: [PATCH 122/423] eslint-plugin: added missing deps + lint config Signed-off-by: Patrik Oldsberg --- packages/eslint-plugin/.eslintrc.js | 35 +++++++++++++++++++++++++++++ packages/eslint-plugin/package.json | 11 ++++++++- yarn.lock | 3 +++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 packages/eslint-plugin/.eslintrc.js diff --git a/packages/eslint-plugin/.eslintrc.js b/packages/eslint-plugin/.eslintrc.js new file mode 100644 index 0000000000..aaf907cfbc --- /dev/null +++ b/packages/eslint-plugin/.eslintrc.js @@ -0,0 +1,35 @@ +/* + * Copyright 2023 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. + */ + +// Custom lint config here since source is ES5 +module.exports = { + plugins: ['import'], + parserOptions: { + ecmaVersion: 5, + }, + rules: { + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: false, + optionalDependencies: true, + peerDependencies: true, + bundledDependencies: true, + }, + ], + 'no-unused-expressions': 'off', + }, +}; diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 9724cec32b..ee5e62c41e 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -12,5 +12,14 @@ "directory": "packages/eslint-plugin" }, "license": "Apache-2.0", - "main": "./index.js" + "main": "./index.js", + "scripts": { + "lint": "backstage-cli package lint" + }, + "dependencies": { + "@manypkg/get-packages": "^1.1.3" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + } } diff --git a/yarn.lock b/yarn.lock index ac5c6d0541..06cd22d84a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4098,6 +4098,9 @@ __metadata: "@backstage/eslint-plugin@workspace:packages/eslint-plugin": version: 0.0.0-use.local resolution: "@backstage/eslint-plugin@workspace:packages/eslint-plugin" + dependencies: + "@backstage/cli": "workspace:^" + "@manypkg/get-packages": ^1.1.3 languageName: unknown linkType: soft From 4d05d5bf8362ac5e86c6e75918aa7cdbb14a3a79 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 11:10:38 +0100 Subject: [PATCH 123/423] eslint-plugin: refactor to ES2021 and add no-undeclared-imports rule Signed-off-by: Patrik Oldsberg --- packages/eslint-plugin/.eslintrc.js | 7 +- packages/eslint-plugin/index.js | 2 + packages/eslint-plugin/lib/getPackages.js | 63 +++++++ packages/eslint-plugin/lib/visitImports.js | 100 +++++++++++ packages/eslint-plugin/package.json | 3 +- .../rules/no-forbidden-package-imports.js | 91 ++-------- .../rules/no-undeclared-imports.js | 156 ++++++++++++++++++ yarn.lock | 1 + 8 files changed, 339 insertions(+), 84 deletions(-) create mode 100644 packages/eslint-plugin/lib/getPackages.js create mode 100644 packages/eslint-plugin/lib/visitImports.js create mode 100644 packages/eslint-plugin/rules/no-undeclared-imports.js diff --git a/packages/eslint-plugin/.eslintrc.js b/packages/eslint-plugin/.eslintrc.js index aaf907cfbc..74f93a6475 100644 --- a/packages/eslint-plugin/.eslintrc.js +++ b/packages/eslint-plugin/.eslintrc.js @@ -17,8 +17,9 @@ // Custom lint config here since source is ES5 module.exports = { plugins: ['import'], - parserOptions: { - ecmaVersion: 5, + env: { + node: true, + es2021: true, }, rules: { 'import/no-extraneous-dependencies': [ @@ -30,6 +31,6 @@ module.exports = { bundledDependencies: true, }, ], - 'no-unused-expressions': 'off', + // 'no-unused-expressions': 'off', }, }; diff --git a/packages/eslint-plugin/index.js b/packages/eslint-plugin/index.js index 11d17b2b8f..cf1dd20ab7 100644 --- a/packages/eslint-plugin/index.js +++ b/packages/eslint-plugin/index.js @@ -20,10 +20,12 @@ module.exports = { plugins: ['@backstage'], rules: { '@backstage/no-forbidden-package-imports': 'error', + '@backstage/no-undeclared-imports': 'error', }, }, }, rules: { 'no-forbidden-package-imports': require('./rules/no-forbidden-package-imports'), + 'no-undeclared-imports': require('./rules/no-undeclared-imports'), }, }; diff --git a/packages/eslint-plugin/lib/getPackages.js b/packages/eslint-plugin/lib/getPackages.js new file mode 100644 index 0000000000..91043fe0d5 --- /dev/null +++ b/packages/eslint-plugin/lib/getPackages.js @@ -0,0 +1,63 @@ +/* + * Copyright 2023 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. + */ + +// @ts-check + +/** @type {import('@manypkg/get-packages')} */ +const manypkg = require('@manypkg/get-packages'); + +/** + * @typedef ExtendedPackage + * @type {import('@manypkg/get-packages').Package & { packageJson: { exports?: Record }}} packageJson + */ + +/** + * @typedef PackageMap + * @type object + * + * @property {ExtendedPackage} root + * @property {ExtendedPackage[]} list + * @property {Map} map + */ + +// Loads all packages in the monorepo once, and caches the result +module.exports = (function () { + let result = undefined; + let lastLoadAt = undefined; + + /** @returns {PackageMap | undefined} */ + return function getPackages(/** @type {string} */ dir) { + if (result) { + // Only cache for 5 seconds, to avoid the need to reload ESLint servers + if (Date.now() - lastLoadAt > 5000) { + result = undefined; + } else { + return result; + } + } + const packages = manypkg.getPackagesSync(dir); + if (!packages) { + return undefined; + } + result = { + map: new Map(packages.packages.map(pkg => [pkg.packageJson.name, pkg])), + list: packages.packages, + root: packages.root, + }; + lastLoadAt = Date.now(); + return result; + }; +})(); diff --git a/packages/eslint-plugin/lib/visitImports.js b/packages/eslint-plugin/lib/visitImports.js new file mode 100644 index 0000000000..d73c3203a8 --- /dev/null +++ b/packages/eslint-plugin/lib/visitImports.js @@ -0,0 +1,100 @@ +/* + * Copyright 2023 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. + */ + +// @ts-check + +const getPackages = require('./getPackages'); + +/** + * @typedef LocalImport + * @type {object} + * @property {'local'} type + * @property {string} path + */ + +/** + * @typedef InternalImport + * @type {object} + * @property {'internal'} type + * @property {string} path + * @property {import('./getPackages').ExtendedPackage} package + */ + +/** + * @typedef ExternalImport + * @type {object} + * @property {'external'} type + * @property {string} path + * @property {string} packageName + */ + +/** + * @callback ImportVisitor + * @param {import('eslint').Rule.Node} node + * @param {LocalImport | InternalImport | ExternalImport} import + */ + +/** + * @param visitor - Visitor callback + * @param {import('eslint').Rule.RuleContext} context + * @param {ImportVisitor} visitor + */ +module.exports = function visitImports(context, visitor) { + const packages = getPackages(context.getCwd()); + if (!packages) { + return; + } + + function visit(node) { + if (!node.source) { + return; + } + const importPath = node.source.value; + if (importPath[0] === '.') { + return visitor(node, { type: 'local', path: importPath }); + } + + const pathParts = importPath.split('/'); + + // Check for match with plain name, then namespaced name + let packageName; + let subPath; + if (importPath[0] === '@') { + packageName = pathParts.slice(0, 2).join('/'); + subPath = pathParts.slice(2).join('/'); + } else { + packageName = pathParts[0]; + subPath = pathParts.slice(1).join('/'); + } + const pkg = packages?.map.get(packageName); + if (!pkg) { + return visitor(node, { + type: 'external', + path: subPath, + packageName: packageName, + }); + } + + return visitor(node, { type: 'internal', path: subPath, package: pkg }); + } + + return { + ImportDeclaration: visit, + ExportAllDeclaration: visit, + ExportNamedDeclaration: visit, + ImportExpression: visit, + }; +}; diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index ee5e62c41e..73862d2295 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -17,7 +17,8 @@ "lint": "backstage-cli package lint" }, "dependencies": { - "@manypkg/get-packages": "^1.1.3" + "@manypkg/get-packages": "^1.1.3", + "minimatch": "^5.1.2" }, "devDependencies": { "@backstage/cli": "workspace:^" diff --git a/packages/eslint-plugin/rules/no-forbidden-package-imports.js b/packages/eslint-plugin/rules/no-forbidden-package-imports.js index d5cce80368..bbf342dba0 100644 --- a/packages/eslint-plugin/rules/no-forbidden-package-imports.js +++ b/packages/eslint-plugin/rules/no-forbidden-package-imports.js @@ -1,4 +1,3 @@ -'use strict'; /* * Copyright 2023 The Backstage Authors * @@ -17,41 +16,9 @@ // @ts-check -// Note: this file is ES5, because we want to avoid having to transpile it for local development - -var fs = require('fs'); -var path = require('path'); -/** @type {import('@manypkg/get-packages')} */ -var manypkg = require('@manypkg/get-packages'); - -// Loads all packages in the monorepo once, and caches the result -var getPackageMap = (function () { - var map = undefined; - var lastLoadAt = undefined; - - /** @returns {Record} */ - return function (/** @type {string} */ dir) { - if (map) { - // Only cache for 5 seconds, to avoid the need to reload ESLint servers - if (Date.now() - lastLoadAt > 5000) { - map = undefined; - } else { - return map; - } - } - var packages = manypkg.getPackagesSync(dir).packages; - if (!packages) { - return undefined; - } - map = {}; - lastLoadAt = Date.now(); - packages.forEach(function (pkg) { - map[pkg.packageJson.name] = pkg; - }); - return map; - }; -})(); +const visitImports = require('../lib/visitImports'); +/** @type {import('eslint').Rule.RuleModule} */ module.exports = { meta: { type: 'problem', @@ -59,48 +26,19 @@ module.exports = { forbidden: '{{packageName}} does not export {{subPath}}', }, }, - create: function (/** @type import('eslint').Rule.RuleContext */ context) { - var packageMap = getPackageMap(context.getCwd()); - if (!packageMap) { - return; - } - - function checkImport(node) { - if (!node.source) { + create(context) { + return visitImports(context, (node, imp) => { + if (imp.type !== 'internal') { return; } - var importPath = node.source.value; - if (importPath[0] === '.') { - return; - } - - var pathParts = importPath.split('/'); - - // Check for match with plain name, then namespaced name - var name = pathParts.shift(); - if (!packageMap[name]) { - name += '/' + pathParts.shift(); - } - if (!packageMap[name]) { - return; - } - // Empty subpaths are always allowed - var subPath = pathParts.join('/'); - if (!subPath) { + if (!imp.path) { return; } - var pkg = packageMap[name]; - // If the import is listed in the package.json exports field, we allow it - var exp = pkg.packageJson.exports; - if (exp && (exp[subPath] || exp['./' + subPath])) { - return; - } - - // If there's a package.json in the target directory, we allow the import - if (fs.existsSync(path.resolve(pkg.dir, subPath, 'package.json'))) { + const exp = imp.package.packageJson.exports; + if (exp && (exp[imp.path] || exp['./' + imp.path])) { return; } @@ -108,17 +46,10 @@ module.exports = { node: node, messageId: 'forbidden', data: { - packageName: pkg.packageJson.name || '', - subPath: subPath, + packageName: imp.package.packageJson.name || imp.package.dir, + subPath: imp.path, }, }); - } - - return { - ImportDeclaration: checkImport, - ExportAllDeclaration: checkImport, - ExportNamedDeclaration: checkImport, - ImportExpression: checkImport, - }; + }); }, }; diff --git a/packages/eslint-plugin/rules/no-undeclared-imports.js b/packages/eslint-plugin/rules/no-undeclared-imports.js new file mode 100644 index 0000000000..462b4b2e31 --- /dev/null +++ b/packages/eslint-plugin/rules/no-undeclared-imports.js @@ -0,0 +1,156 @@ +/* + * Copyright 2023 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. + */ + +// @ts-check + +const path = require('path'); +const getPackageMap = require('../lib/getPackages'); +const visitImports = require('../lib/visitImports'); +const minimatch = require('minimatch'); + +const depFields = { + dep: 'dependencies', + dev: 'devDependencies', + peer: 'peerDependencies', +}; + +const peerDeps = ['react', 'react-dom', 'react-router', 'react-router-dom']; +const devModulePatterns = [ + new minimatch.Minimatch('!src/**'), + new minimatch.Minimatch('src/**/*.test.*'), + new minimatch.Minimatch('src/**/*.stories.*'), + new minimatch.Minimatch('src/**/__testUtils__/**'), + new minimatch.Minimatch('src/**/__mocks__/**'), + new minimatch.Minimatch('src/setupTests.*'), +]; + +function getExpectedDepType( + /** @type {string} */ impPath, + /** @type {string} */ modulePath, +) { + if (peerDeps.includes(impPath)) { + return 'peer'; + } + for (const pattern of devModulePatterns) { + if (pattern.match(modulePath)) { + return 'dev'; + } + } + return 'dep'; +} + +/** + * + * @param {import('@manypkg/get-packages').Package['packageJson']} pkg + * @param {string} name + * @param {ReturnType} expectedType + * @returns {{oldDepsField?: string, depsField: string} | undefined} + */ +function findConflict(pkg, name, expectedType) { + const isDep = pkg.dependencies?.[name]; + const isDevDep = pkg.devDependencies?.[name]; + const isPeerDep = pkg.peerDependencies?.[name]; + const depsField = depFields[expectedType]; + + if (expectedType === 'dep' && !isDep) { + const oldDepsField = isDevDep ? depFields.dev : undefined; + return { oldDepsField, depsField }; + } else if (expectedType === 'dev' && !isDevDep && !isDep && !isPeerDep) { + return { oldDepsField: undefined, depsField }; + } else if (expectedType === 'peer' && !isPeerDep) { + const oldDepsField = isDep + ? depFields.dep + : isDevDep + ? depFields.dev + : undefined; + + return { oldDepsField, depsField }; + } +} + +function getAddFlagForConflict(conflict) { + switch (conflict?.depsField) { + case depFields.dep: + return ''; + case depFields.dev: + return ' --dev'; + case depFields.peer: + return ' --peer'; + default: + return ''; + } +} + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + meta: { + type: 'problem', + messages: { + undeclared: + "{{ packageName }} must be declared in {{ depsField }} of {{ packageJsonPath }}, run 'yarn --cwd {{ packagePath }} add{{ addFlag }} {{ packageName }}' from the project root.", + switch: + '{{ packageName }} is declared in {{ oldDepsField }}, but should be moved to {{ depsField }} in {{ packageJsonPath }}.', + }, + }, + create(context) { + const packages = getPackageMap(context.getCwd()); + if (!packages) { + return {}; + } + const filePath = context.getPhysicalFilename + ? context.getPhysicalFilename() + : context.getFilename(); + + const localPkg = packages.list.find(p => + filePath.startsWith(p.dir + path.sep), + ); + if (!localPkg) { + return {}; + } + + return visitImports(context, (node, imp) => { + if (imp.type !== 'external') { + return; + } + + const modulePath = path.relative(localPkg.dir, filePath); + const expectedType = getExpectedDepType(imp.packageName, modulePath); + + const conflict = findConflict( + localPkg.packageJson, + imp.packageName, + expectedType, + ); + + if (conflict) { + const packagePath = path.relative(packages.root.dir, localPkg.dir); + const packageJsonPath = path.join(packagePath, 'package.json'); + + context.report({ + node, + messageId: conflict.oldDepsField ? 'switch' : 'undeclared', + data: { + ...conflict, + packagePath, + addFlag: getAddFlagForConflict(conflict), + packageName: imp.packageName, + packageJsonPath: packageJsonPath, + }, + }); + } + }); + }, +}; diff --git a/yarn.lock b/yarn.lock index 06cd22d84a..e0e1da349c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4101,6 +4101,7 @@ __metadata: dependencies: "@backstage/cli": "workspace:^" "@manypkg/get-packages": ^1.1.3 + minimatch: ^5.1.2 languageName: unknown linkType: soft From f459b168f03033ca6c4025ce16941d7bc0480835 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 14:19:19 +0100 Subject: [PATCH 124/423] eslint-plugin: add support for detecting Node.js builtins Signed-off-by: Patrik Oldsberg --- packages/eslint-plugin/lib/visitImports.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/lib/visitImports.js b/packages/eslint-plugin/lib/visitImports.js index d73c3203a8..c89d65fb49 100644 --- a/packages/eslint-plugin/lib/visitImports.js +++ b/packages/eslint-plugin/lib/visitImports.js @@ -16,6 +16,7 @@ // @ts-check +const { builtinModules } = require('module'); const getPackages = require('./getPackages'); /** @@ -41,10 +42,18 @@ const getPackages = require('./getPackages'); * @property {string} packageName */ +/** + * @typedef BuiltinImport + * @type {object} + * @property {'builtin'} type + * @property {string} path + * @property {string} packageName + */ + /** * @callback ImportVisitor * @param {import('eslint').Rule.Node} node - * @param {LocalImport | InternalImport | ExternalImport} import + * @param {LocalImport | InternalImport | ExternalImport | BuiltinImport} import */ /** @@ -81,10 +90,17 @@ module.exports = function visitImports(context, visitor) { } const pkg = packages?.map.get(packageName); if (!pkg) { + if ( + packageName.startsWith('node:') || + builtinModules.includes(packageName) + ) { + return visitor(node, { type: 'builtin', path: subPath, packageName }); + } + return visitor(node, { type: 'external', path: subPath, - packageName: packageName, + packageName, }); } From 9e192d7f4a67e5a1c1ad35b2b6c27e2207b6c079 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 14:19:41 +0100 Subject: [PATCH 125/423] eslint-plugin: dogfood lint config Signed-off-by: Patrik Oldsberg --- packages/eslint-plugin/.eslintrc.js | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/eslint-plugin/.eslintrc.js b/packages/eslint-plugin/.eslintrc.js index 74f93a6475..7fc68c3c5d 100644 --- a/packages/eslint-plugin/.eslintrc.js +++ b/packages/eslint-plugin/.eslintrc.js @@ -16,21 +16,13 @@ // Custom lint config here since source is ES5 module.exports = { - plugins: ['import'], + plugins: ['@backstage'], env: { node: true, es2021: true, }, rules: { - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: false, - optionalDependencies: true, - peerDependencies: true, - bundledDependencies: true, - }, - ], - // 'no-unused-expressions': 'off', + '@backstage/no-undeclared-imports': ['error'], + 'no-unused-expressions': 'off', }, }; From 8b4a758ed28e1d1268894f6d71d0847e365e286f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 14:38:40 +0100 Subject: [PATCH 126/423] eslint-plugin: add support for require calls Signed-off-by: Patrik Oldsberg --- packages/eslint-plugin/lib/visitImports.js | 36 ++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/lib/visitImports.js b/packages/eslint-plugin/lib/visitImports.js index c89d65fb49..5184fb8d79 100644 --- a/packages/eslint-plugin/lib/visitImports.js +++ b/packages/eslint-plugin/lib/visitImports.js @@ -56,6 +56,36 @@ const getPackages = require('./getPackages'); * @param {LocalImport | InternalImport | ExternalImport | BuiltinImport} import */ +/** + * @param {import('estree').ImportDeclaration | import('estree').ExportAllDeclaration | import('estree').ExportNamedDeclaration | import('estree').ImportExpression | import('estree').SimpleCallExpression} node + * @returns {string | undefined} + */ +function getImportPath(node) { + /** @type {import('estree').Expression | import('estree').SpreadElement | undefined | null} */ + let pathNode; + + if (node.type === 'CallExpression') { + if ( + node.callee.type === 'Identifier' && + node.callee.name == 'require' && + node.arguments.length === 1 + ) { + pathNode = node.arguments[0]; + } + } else { + pathNode = node.source; + } + + if (pathNode?.type !== 'Literal') { + return undefined; + } + if (typeof pathNode.value !== 'string') { + return undefined; + } + + return pathNode.value; +} + /** * @param visitor - Visitor callback * @param {import('eslint').Rule.RuleContext} context @@ -68,10 +98,11 @@ module.exports = function visitImports(context, visitor) { } function visit(node) { - if (!node.source) { + const importPath = getImportPath(node); + if (!importPath) { return; } - const importPath = node.source.value; + if (importPath[0] === '.') { return visitor(node, { type: 'local', path: importPath }); } @@ -112,5 +143,6 @@ module.exports = function visitImports(context, visitor) { ExportAllDeclaration: visit, ExportNamedDeclaration: visit, ImportExpression: visit, + CallExpression: visit, }; }; From 765b7ee355ddcbb01c57942796a7cc57952c7839 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 16:14:07 +0100 Subject: [PATCH 127/423] eslint-plugin: backwards compatiblity check for packages without exports Signed-off-by: Patrik Oldsberg --- packages/eslint-plugin/lib/getPackages.js | 2 +- .../rules/no-forbidden-package-imports.js | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/lib/getPackages.js b/packages/eslint-plugin/lib/getPackages.js index 91043fe0d5..318d0654c2 100644 --- a/packages/eslint-plugin/lib/getPackages.js +++ b/packages/eslint-plugin/lib/getPackages.js @@ -21,7 +21,7 @@ const manypkg = require('@manypkg/get-packages'); /** * @typedef ExtendedPackage - * @type {import('@manypkg/get-packages').Package & { packageJson: { exports?: Record }}} packageJson + * @type {import('@manypkg/get-packages').Package & { packageJson: { exports?: Record, files?: Array }}} packageJson */ /** diff --git a/packages/eslint-plugin/rules/no-forbidden-package-imports.js b/packages/eslint-plugin/rules/no-forbidden-package-imports.js index bbf342dba0..6c861e17f5 100644 --- a/packages/eslint-plugin/rules/no-forbidden-package-imports.js +++ b/packages/eslint-plugin/rules/no-forbidden-package-imports.js @@ -41,6 +41,20 @@ module.exports = { if (exp && (exp[imp.path] || exp['./' + imp.path])) { return; } + if (!exp) { + // If there's no exports field, we allow anything listed in files, except dist + const files = imp.package.packageJson.files; + if ( + !files || + files.some(f => !f.startsWith('dist') && imp.path.startsWith(f)) + ) { + return; + } + // And also package.json + if (imp.path === 'package.json') { + return; + } + } context.report({ node: node, From d5eee2944cdc4ccb83f643ad22197c8064e28959 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 16:15:17 +0100 Subject: [PATCH 128/423] eslint-plugin: improved peer deps check and consider package role Signed-off-by: Patrik Oldsberg --- .../rules/no-undeclared-imports.js | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/packages/eslint-plugin/rules/no-undeclared-imports.js b/packages/eslint-plugin/rules/no-undeclared-imports.js index 462b4b2e31..cec3503f8f 100644 --- a/packages/eslint-plugin/rules/no-undeclared-imports.js +++ b/packages/eslint-plugin/rules/no-undeclared-imports.js @@ -27,7 +27,6 @@ const depFields = { peer: 'peerDependencies', }; -const peerDeps = ['react', 'react-dom', 'react-router', 'react-router-dom']; const devModulePatterns = [ new minimatch.Minimatch('!src/**'), new minimatch.Minimatch('src/**/*.test.*'), @@ -38,12 +37,34 @@ const devModulePatterns = [ ]; function getExpectedDepType( + localPkg, /** @type {string} */ impPath, /** @type {string} */ modulePath, ) { - if (peerDeps.includes(impPath)) { - return 'peer'; + const role = localPkg?.backstage?.role; + // Some package roles have known dependency types + switch (role) { + case 'common-library': + case 'web-library': + case 'frontend-plugin': + case 'frontend-plugin-module': + case 'node-library': + case 'backend-plugin': + case 'backend-plugin-module': + switch (impPath) { + case 'react': + case 'react-dom': + case 'react-router': + case 'react-router-dom': + return 'peer'; + } + case 'cli': + case 'frontend': + case 'backend': + default: + break; } + for (const pattern of devModulePatterns) { if (pattern.match(modulePath)) { return 'dev'; @@ -65,7 +86,7 @@ function findConflict(pkg, name, expectedType) { const isPeerDep = pkg.peerDependencies?.[name]; const depsField = depFields[expectedType]; - if (expectedType === 'dep' && !isDep) { + if (expectedType === 'dep' && !isDep && !isPeerDep) { const oldDepsField = isDevDep ? depFields.dev : undefined; return { oldDepsField, depsField }; } else if (expectedType === 'dev' && !isDevDep && !isDep && !isPeerDep) { @@ -127,7 +148,11 @@ module.exports = { } const modulePath = path.relative(localPkg.dir, filePath); - const expectedType = getExpectedDepType(imp.packageName, modulePath); + const expectedType = getExpectedDepType( + localPkg, + imp.packageName, + modulePath, + ); const conflict = findConflict( localPkg.packageJson, From 58e481a4f9a4889d11720b18727d96eb2406b749 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 16:15:48 +0100 Subject: [PATCH 129/423] eslint-plugin: ignore type imports when checking deps Signed-off-by: Patrik Oldsberg --- packages/eslint-plugin/lib/visitImports.js | 39 +++++++++++++------ .../rules/no-undeclared-imports.js | 16 ++++++++ 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/packages/eslint-plugin/lib/visitImports.js b/packages/eslint-plugin/lib/visitImports.js index 5184fb8d79..ed16c26c7f 100644 --- a/packages/eslint-plugin/lib/visitImports.js +++ b/packages/eslint-plugin/lib/visitImports.js @@ -23,6 +23,7 @@ const getPackages = require('./getPackages'); * @typedef LocalImport * @type {object} * @property {'local'} type + * @property {'value' | 'type'} kind * @property {string} path */ @@ -30,6 +31,7 @@ const getPackages = require('./getPackages'); * @typedef InternalImport * @type {object} * @property {'internal'} type + * @property {'value' | 'type'} kind * @property {string} path * @property {import('./getPackages').ExtendedPackage} package */ @@ -38,6 +40,7 @@ const getPackages = require('./getPackages'); * @typedef ExternalImport * @type {object} * @property {'external'} type + * @property {'value' | 'type'} kind * @property {string} path * @property {string} packageName */ @@ -46,6 +49,7 @@ const getPackages = require('./getPackages'); * @typedef BuiltinImport * @type {object} * @property {'builtin'} type + * @property {'value' | 'type'} kind * @property {string} path * @property {string} packageName */ @@ -58,9 +62,9 @@ const getPackages = require('./getPackages'); /** * @param {import('estree').ImportDeclaration | import('estree').ExportAllDeclaration | import('estree').ExportNamedDeclaration | import('estree').ImportExpression | import('estree').SimpleCallExpression} node - * @returns {string | undefined} + * @returns {undefined | {path: string, kind: 'type' | 'value'}} */ -function getImportPath(node) { +function getImportInfo(node) { /** @type {import('estree').Expression | import('estree').SpreadElement | undefined | null} */ let pathNode; @@ -83,7 +87,9 @@ function getImportPath(node) { return undefined; } - return pathNode.value; + /** @type {any} */ + const anyNode = node; + return { path: pathNode.value, kind: anyNode.importKind ?? 'value' }; } /** @@ -98,21 +104,21 @@ module.exports = function visitImports(context, visitor) { } function visit(node) { - const importPath = getImportPath(node); - if (!importPath) { + const info = getImportInfo(node); + if (!info) { return; } - if (importPath[0] === '.') { - return visitor(node, { type: 'local', path: importPath }); + if (info.path[0] === '.') { + return visitor(node, { type: 'local', ...info }); } - const pathParts = importPath.split('/'); + const pathParts = info.path.split('/'); // Check for match with plain name, then namespaced name let packageName; let subPath; - if (importPath[0] === '@') { + if (info.path[0] === '@') { packageName = pathParts.slice(0, 2).join('/'); subPath = pathParts.slice(2).join('/'); } else { @@ -125,17 +131,28 @@ module.exports = function visitImports(context, visitor) { packageName.startsWith('node:') || builtinModules.includes(packageName) ) { - return visitor(node, { type: 'builtin', path: subPath, packageName }); + return visitor(node, { + type: 'builtin', + kind: info.kind, + path: subPath, + packageName, + }); } return visitor(node, { type: 'external', + kind: info.kind, path: subPath, packageName, }); } - return visitor(node, { type: 'internal', path: subPath, package: pkg }); + return visitor(node, { + type: 'internal', + kind: info.kind, + path: subPath, + package: pkg, + }); } return { diff --git a/packages/eslint-plugin/rules/no-undeclared-imports.js b/packages/eslint-plugin/rules/no-undeclared-imports.js index cec3503f8f..f7f7b17354 100644 --- a/packages/eslint-plugin/rules/no-undeclared-imports.js +++ b/packages/eslint-plugin/rules/no-undeclared-imports.js @@ -146,6 +146,10 @@ module.exports = { if (imp.type !== 'external') { return; } + // We leave checking of type imports to the repo-tools check + if (imp.kind === 'type') { + return; + } const modulePath = path.relative(localPkg.dir, filePath); const expectedType = getExpectedDepType( @@ -161,6 +165,18 @@ module.exports = { ); if (conflict) { + try { + const fullImport = imp.path + ? `${imp.packageName}/${imp.path}` + : imp.packageName; + require.resolve(fullImport, { + paths: [localPkg.dir], + }); + } catch { + // If the dependency doesn't resolve then it's likely a type import, ignore + return; + } + const packagePath = path.relative(packages.root.dir, localPkg.dir); const packageJsonPath = path.join(packagePath, 'package.json'); From 11df6f42b9c0b8ddb5408b1fb5b5196558f1c413 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 16:16:41 +0100 Subject: [PATCH 130/423] cli: use new eslint plugin + fix issues Signed-off-by: Patrik Oldsberg --- cypress/.eslintrc.js | 9 ------ packages/app/cypress/.eslintrc.json | 9 ------ .../backend-defaults/src/CreateBackend.ts | 2 +- packages/cli/asset-types/asset-types.d.ts | 2 +- packages/cli/config/eslint-factory.js | 31 ++----------------- .../lib/builder/buildTypeDefinitionsWorker.ts | 2 +- packages/cli/src/lib/version.test.ts | 1 - packages/codemods/.eslintrc.js | 15 +-------- packages/codemods/package.json | 2 +- .../LogViewer/RealLogViewer.test.tsx | 2 +- .../LogViewer/useLogViewerSelection.test.tsx | 2 +- packages/create-app/bin/backstage-create-app | 2 +- .../packages/app/cypress/.eslintrc.json | 9 ------ packages/e2e-test/.eslintrc.js | 15 +-------- packages/e2e-test/package.json | 16 +++++----- packages/e2e-test/src/commands/run.ts | 2 +- .../src/commands/type-deps/type-deps.ts | 2 +- .../cypress/.eslintrc.json | 9 ------ packages/techdocs-cli/cypress/.eslintrc.json | 9 ------ .../src/run.ts | 2 +- plugins/code-climate/dev/index.tsx | 2 +- plugins/code-climate/src/setupTests.ts | 2 +- .../example/templates/CostInsightsClient.ts | 2 +- plugins/example-todo-list/.eslintrc.js | 15 +-------- .../scripts/build-nunjucks.js | 2 +- .../src/components/TriggerDialog/testUtils.ts | 2 +- scripts/assemble-manifest.js | 2 +- scripts/check-docs-quality.js | 2 +- scripts/check-if-release.js | 2 +- scripts/create-github-release.js | 2 +- scripts/create-release-tag.js | 2 +- scripts/list-deprecations.js | 2 +- scripts/prepare-release.js | 2 +- scripts/snyk-github-issue-sync.ts | 2 +- scripts/verify-api-reference.js | 2 +- scripts/verify-changesets.js | 2 +- scripts/verify-links.js | 2 +- scripts/verify-lockfile-duplicates.js | 2 +- 38 files changed, 42 insertions(+), 150 deletions(-) diff --git a/cypress/.eslintrc.js b/cypress/.eslintrc.js index a77de4a629..07f264452d 100644 --- a/cypress/.eslintrc.js +++ b/cypress/.eslintrc.js @@ -2,15 +2,6 @@ module.exports = { extends: [require.resolve('@backstage/cli/config/eslint.backend')], rules: { 'no-console': 0, - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: true, - optionalDependencies: false, - peerDependencies: false, - bundledDependencies: false, - }, - ], 'jest/valid-expect': 'off', 'jest/expect-expect': 'off', 'no-restricted-syntax': 'off', diff --git a/packages/app/cypress/.eslintrc.json b/packages/app/cypress/.eslintrc.json index 2b3a458b95..a467608916 100644 --- a/packages/app/cypress/.eslintrc.json +++ b/packages/app/cypress/.eslintrc.json @@ -7,15 +7,6 @@ { "assertFunctionNames": ["expect", "cy.contains"] } - ], - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true, - "optionalDependencies": true, - "peerDependencies": true, - "bundledDependencies": true - } ] } } diff --git a/packages/backend-defaults/src/CreateBackend.ts b/packages/backend-defaults/src/CreateBackend.ts index e6b5a15336..5cbed2c3df 100644 --- a/packages/backend-defaults/src/CreateBackend.ts +++ b/packages/backend-defaults/src/CreateBackend.ts @@ -40,7 +40,7 @@ import { } from '@backstage/backend-plugin-api'; // Internal import of the type to avoid needing to export this. -// eslint-disable-next-line monorepo/no-internal-import +// eslint-disable-next-line @backstage/no-forbidden-package-imports import type { InternalSharedBackendEnvironment } from '@backstage/backend-plugin-api/src/wiring/createSharedEnvironment'; export const defaultServiceFactories = [ diff --git a/packages/cli/asset-types/asset-types.d.ts b/packages/cli/asset-types/asset-types.d.ts index 0bd0922004..9bd158bb8e 100644 --- a/packages/cli/asset-types/asset-types.d.ts +++ b/packages/cli/asset-types/asset-types.d.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ /// /// diff --git a/packages/cli/config/eslint-factory.js b/packages/cli/config/eslint-factory.js index a40aa79fb3..f344af4ab0 100644 --- a/packages/cli/config/eslint-factory.js +++ b/packages/cli/config/eslint-factory.js @@ -60,11 +60,11 @@ function createConfig(dir, extraConfig = {}) { '@spotify/eslint-config-typescript', 'prettier', 'plugin:jest/recommended', - 'plugin:monorepo/recommended', + 'plugin:@backstage/recommended', ...(extraExtends ?? []), ], parser: '@typescript-eslint/parser', - plugins: ['import', ...(plugins ?? [])], + plugins: ['import', 'monorepo', ...(plugins ?? [])], env: { jest: true, ...env, @@ -87,33 +87,8 @@ function createConfig(dir, extraConfig = {}) { '@typescript-eslint/no-shadow': 'error', '@typescript-eslint/no-redeclare': 'error', 'no-undef': 'off', + 'monorepo/no-relative-import': 'error', 'import/newline-after-import': 'error', - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: dir - ? [ - `!${joinPath(dir, 'src/**')}`, - joinPath(dir, 'src/**/*.test.*'), - joinPath(dir, 'src/**/*.stories.*'), - joinPath(dir, 'src/**/__testUtils__/**'), - joinPath(dir, 'src/**/__mocks__/**'), - joinPath(dir, 'src/setupTests.*'), - ] - : [ - // Legacy config for packages that don't provide a dir - '**/*.test.*', - '**/*.stories.*', - '**/__testUtils__/**', - '**/__mocks__/**', - '**/src/setupTests.*', - '**/dev/**', - ], - optionalDependencies: true, - peerDependencies: true, - bundledDependencies: true, - }, - ], 'no-unused-expressions': 'off', '@typescript-eslint/no-unused-expressions': 'error', '@typescript-eslint/consistent-type-assertions': 'error', diff --git a/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts b/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts index 2533131a40..cf37c2a664 100644 --- a/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts +++ b/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts @@ -50,7 +50,7 @@ export async function buildTypeDefinitionsWorker( */ const { PackageJsonLookup, - // eslint-disable-next-line import/no-extraneous-dependencies + // eslint-disable-next-line @backstage/no-undeclared-imports } = require('@rushstack/node-core-library/lib/PackageJsonLookup'); const old = PackageJsonLookup.prototype.tryGetPackageJsonFilePathFor; diff --git a/packages/cli/src/lib/version.test.ts b/packages/cli/src/lib/version.test.ts index fb9bf83e7c..604129679b 100644 --- a/packages/cli/src/lib/version.test.ts +++ b/packages/cli/src/lib/version.test.ts @@ -17,7 +17,6 @@ import mockFs from 'mock-fs'; import { packageVersions, createPackageVersionProvider } from './version'; import { Lockfile } from './versioning'; -// eslint-disable-next-line monorepo/no-internal-import import corePluginApiPkg from '@backstage/core-plugin-api/package.json'; describe('createPackageVersionProvider', () => { diff --git a/packages/codemods/.eslintrc.js b/packages/codemods/.eslintrc.js index f9fb2e27c9..e2a53a6ad2 100644 --- a/packages/codemods/.eslintrc.js +++ b/packages/codemods/.eslintrc.js @@ -1,14 +1 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { - rules: { - 'no-console': 0, - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: true, - optionalDependencies: false, - peerDependencies: false, - bundledDependencies: false, - }, - ], - }, -}); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/codemods/package.json b/packages/codemods/package.json index cbcc0613d4..1ae4d04485 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -35,6 +35,7 @@ "dependencies": { "@backstage/cli-common": "workspace:^", "chalk": "^4.0.0", + "commander": "^9.1.0", "jscodeshift": "^0.14.0", "jscodeshift-add-imports": "^1.0.10" }, @@ -42,7 +43,6 @@ "@backstage/cli": "workspace:^", "@types/jscodeshift": "^0.11.0", "@types/node": "^16.11.26", - "commander": "^9.1.0", "ts-node": "^10.0.0" }, "nodemonConfig": { diff --git a/packages/core-components/src/components/LogViewer/RealLogViewer.test.tsx b/packages/core-components/src/components/LogViewer/RealLogViewer.test.tsx index dd707778e1..e1aac76381 100644 --- a/packages/core-components/src/components/LogViewer/RealLogViewer.test.tsx +++ b/packages/core-components/src/components/LogViewer/RealLogViewer.test.tsx @@ -18,7 +18,7 @@ import React, { ReactNode } from 'react'; import userEvent from '@testing-library/user-event'; import { renderInTestApp } from '@backstage/test-utils'; import { RealLogViewer } from './RealLogViewer'; -// eslint-disable-next-line import/no-extraneous-dependencies +// eslint-disable-next-line @backstage/no-undeclared-imports import copyToClipboard from 'copy-to-clipboard'; // Used by useCopyToClipboard diff --git a/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx b/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx index 7e00d50f33..93a6dfd7e9 100644 --- a/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx +++ b/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx @@ -20,7 +20,7 @@ import { TestApiProvider, MockErrorApi } from '@backstage/test-utils'; import { errorApiRef } from '@backstage/core-plugin-api'; import { AnsiLine } from './AnsiProcessor'; import { useLogViewerSelection } from './useLogViewerSelection'; -// eslint-disable-next-line import/no-extraneous-dependencies +// eslint-disable-next-line @backstage/no-undeclared-imports import copyToClipboard from 'copy-to-clipboard'; // Used by useCopyToClipboard diff --git a/packages/create-app/bin/backstage-create-app b/packages/create-app/bin/backstage-create-app index 60dfd4990a..4639ea96dc 100755 --- a/packages/create-app/bin/backstage-create-app +++ b/packages/create-app/bin/backstage-create-app @@ -25,7 +25,7 @@ if (!isLocal || process.env.BACKSTAGE_E2E_CLI_TEST) { require('..'); } else { // Only used for development, so should be a devDependency - // eslint-disable-next-line import/no-extraneous-dependencies + // eslint-disable-next-line @backstage/no-undeclared-imports require('ts-node').register({ transpileOnly: true, project: path.resolve(__dirname, '../../../tsconfig.json'), diff --git a/packages/create-app/templates/default-app/packages/app/cypress/.eslintrc.json b/packages/create-app/templates/default-app/packages/app/cypress/.eslintrc.json index 2b3a458b95..a467608916 100644 --- a/packages/create-app/templates/default-app/packages/app/cypress/.eslintrc.json +++ b/packages/create-app/templates/default-app/packages/app/cypress/.eslintrc.json @@ -7,15 +7,6 @@ { "assertFunctionNames": ["expect", "cy.contains"] } - ], - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true, - "optionalDependencies": true, - "peerDependencies": true, - "bundledDependencies": true - } ] } } diff --git a/packages/e2e-test/.eslintrc.js b/packages/e2e-test/.eslintrc.js index f9fb2e27c9..e2a53a6ad2 100644 --- a/packages/e2e-test/.eslintrc.js +++ b/packages/e2e-test/.eslintrc.js @@ -1,14 +1 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { - rules: { - 'no-console': 0, - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: true, - optionalDependencies: false, - peerDependencies: false, - bundledDependencies: false, - }, - ], - }, -}); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 374eaa6d18..ee447a1736 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -26,22 +26,24 @@ "clean": "backstage-cli package clean" }, "bin": "bin/e2e-test", - "devDependencies": { - "@backstage/cli": "workspace:^", + "dependencies": { "@backstage/cli-common": "workspace:^", "@backstage/errors": "workspace:^", - "@types/fs-extra": "^9.0.1", - "@types/node": "^16.11.26", - "@types/puppeteer": "^5.4.4", "chalk": "^4.0.0", "commander": "^9.1.0", "cross-fetch": "^3.1.5", "fs-extra": "10.1.0", "handlebars": "^4.7.3", - "nodemon": "^2.0.2", "pgtools": "^0.3.0", "puppeteer": "^17.0.0", - "tree-kill": "^1.2.2", + "tree-kill": "^1.2.2" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@types/fs-extra": "^9.0.1", + "@types/node": "^16.11.26", + "@types/puppeteer": "^5.4.4", + "nodemon": "^2.0.2", "ts-node": "^10.0.0" }, "nodemonConfig": { diff --git a/packages/e2e-test/src/commands/run.ts b/packages/e2e-test/src/commands/run.ts index 3eedb90b21..254198ebb4 100644 --- a/packages/e2e-test/src/commands/run.ts +++ b/packages/e2e-test/src/commands/run.ts @@ -159,7 +159,7 @@ async function buildDistWorkspace(workspaceName: string, rootDir: string) { appendDeps(pkg); } - // eslint-disable-next-line import/no-extraneous-dependencies + // eslint-disable-next-line @backstage/no-forbidden-package-imports appendDeps(require('@backstage/create-app/package.json')); print(`Preparing workspace`); diff --git a/packages/repo-tools/src/commands/type-deps/type-deps.ts b/packages/repo-tools/src/commands/type-deps/type-deps.ts index d4dd28aa14..4f8e5e5529 100644 --- a/packages/repo-tools/src/commands/type-deps/type-deps.ts +++ b/packages/repo-tools/src/commands/type-deps/type-deps.ts @@ -17,7 +17,7 @@ import fs from 'fs'; import { resolve as resolvePath } from 'path'; // Cba polluting root package.json, we'll have this -// eslint-disable-next-line import/no-extraneous-dependencies +// eslint-disable-next-line @backstage/no-undeclared-imports import chalk from 'chalk'; import { getPackages, Package } from '@manypkg/get-packages'; diff --git a/packages/techdocs-cli-embedded-app/cypress/.eslintrc.json b/packages/techdocs-cli-embedded-app/cypress/.eslintrc.json index 2b3a458b95..a467608916 100644 --- a/packages/techdocs-cli-embedded-app/cypress/.eslintrc.json +++ b/packages/techdocs-cli-embedded-app/cypress/.eslintrc.json @@ -7,15 +7,6 @@ { "assertFunctionNames": ["expect", "cy.contains"] } - ], - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true, - "optionalDependencies": true, - "peerDependencies": true, - "bundledDependencies": true - } ] } } diff --git a/packages/techdocs-cli/cypress/.eslintrc.json b/packages/techdocs-cli/cypress/.eslintrc.json index 2481ac5715..06965a82da 100644 --- a/packages/techdocs-cli/cypress/.eslintrc.json +++ b/packages/techdocs-cli/cypress/.eslintrc.json @@ -7,15 +7,6 @@ { "assertFunctionNames": ["expect", "cy.contains", "cy.document"] } - ], - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true, - "optionalDependencies": true, - "peerDependencies": true, - "bundledDependencies": true - } ] } } diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts index 08d95f4417..2a58227862 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -// eslint-disable-next-line import/no-extraneous-dependencies +// eslint-disable-next-line @backstage/no-undeclared-imports import { databaseFactory, discoveryFactory, diff --git a/plugins/code-climate/dev/index.tsx b/plugins/code-climate/dev/index.tsx index d5fc4c28e3..060679337e 100644 --- a/plugins/code-climate/dev/index.tsx +++ b/plugins/code-climate/dev/index.tsx @@ -15,7 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; -// eslint-disable-next-line import/no-extraneous-dependencies +// eslint-disable-next-line @backstage/no-undeclared-imports import { createDevApp, EntityGridItem } from '@backstage/dev-utils'; import { Grid } from '@material-ui/core'; import React from 'react'; diff --git a/plugins/code-climate/src/setupTests.ts b/plugins/code-climate/src/setupTests.ts index 43d9e09713..eb4654b869 100644 --- a/plugins/code-climate/src/setupTests.ts +++ b/plugins/code-climate/src/setupTests.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ import '@testing-library/jest-dom'; import 'cross-fetch/polyfill'; diff --git a/plugins/cost-insights/src/example/templates/CostInsightsClient.ts b/plugins/cost-insights/src/example/templates/CostInsightsClient.ts index 50c3bb1470..046196f26b 100644 --- a/plugins/cost-insights/src/example/templates/CostInsightsClient.ts +++ b/plugins/cost-insights/src/example/templates/CostInsightsClient.ts @@ -22,7 +22,7 @@ // IMPORTANT: Remove the lines below to enable type checking and linting // @ts-nocheck -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ import { CostInsightsApi, diff --git a/plugins/example-todo-list/.eslintrc.js b/plugins/example-todo-list/.eslintrc.js index 8c18e76229..e2a53a6ad2 100644 --- a/plugins/example-todo-list/.eslintrc.js +++ b/plugins/example-todo-list/.eslintrc.js @@ -1,14 +1 @@ -module.exports = { - extends: [require.resolve('@backstage/cli/config/eslint')], - rules: { - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: true, - optionalDependencies: true, - peerDependencies: true, - bundledDependencies: true, - }, - ], - }, -}; +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/scaffolder-backend/scripts/build-nunjucks.js b/plugins/scaffolder-backend/scripts/build-nunjucks.js index 8b98ac4305..8183de77ee 100755 --- a/plugins/scaffolder-backend/scripts/build-nunjucks.js +++ b/plugins/scaffolder-backend/scripts/build-nunjucks.js @@ -16,7 +16,7 @@ */ /* eslint-disable no-restricted-syntax */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ const path = require('path'); diff --git a/plugins/splunk-on-call/src/components/TriggerDialog/testUtils.ts b/plugins/splunk-on-call/src/components/TriggerDialog/testUtils.ts index 764ac94e2c..9beb4e150e 100644 --- a/plugins/splunk-on-call/src/components/TriggerDialog/testUtils.ts +++ b/plugins/splunk-on-call/src/components/TriggerDialog/testUtils.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -// eslint-disable-next-line import/no-extraneous-dependencies +// eslint-disable-next-line @backstage/no-undeclared-imports import { act, fireEvent, diff --git a/scripts/assemble-manifest.js b/scripts/assemble-manifest.js index f68a83447d..f01bc7fd9b 100755 --- a/scripts/assemble-manifest.js +++ b/scripts/assemble-manifest.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ /* * Copyright 2022 The Backstage Authors * diff --git a/scripts/check-docs-quality.js b/scripts/check-docs-quality.js index 10c4b99976..3dcbd6ef81 100755 --- a/scripts/check-docs-quality.js +++ b/scripts/check-docs-quality.js @@ -56,7 +56,7 @@ async function listFiles(dir = '') { // caused by the script. In CI, we want to ensure vale linter is run. async function exitIfMissingVale() { try { - // eslint-disable-next-line import/no-extraneous-dependencies + // eslint-disable-next-line @backstage/no-undeclared-imports await require('command-exists')('vale'); } catch (e) { if (process.env.CI) { diff --git a/scripts/check-if-release.js b/scripts/check-if-release.js index e7dabe14a4..c12b27b0ef 100755 --- a/scripts/check-if-release.js +++ b/scripts/check-if-release.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ /* * Copyright 2020 The Backstage Authors * diff --git a/scripts/create-github-release.js b/scripts/create-github-release.js index 4b3891c5ce..b64d7a9cb5 100755 --- a/scripts/create-github-release.js +++ b/scripts/create-github-release.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ /* * Copyright 2020 The Backstage Authors * diff --git a/scripts/create-release-tag.js b/scripts/create-release-tag.js index 28417024fd..311b46d4e5 100755 --- a/scripts/create-release-tag.js +++ b/scripts/create-release-tag.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ /* * Copyright 2020 The Backstage Authors * diff --git a/scripts/list-deprecations.js b/scripts/list-deprecations.js index 8047158138..22aff96d67 100755 --- a/scripts/list-deprecations.js +++ b/scripts/list-deprecations.js @@ -15,7 +15,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ const _ = require('lodash'); const fs = require('fs-extra'); diff --git a/scripts/prepare-release.js b/scripts/prepare-release.js index 973f4fad58..4019a71cf3 100755 --- a/scripts/prepare-release.js +++ b/scripts/prepare-release.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ /* * Copyright 2022 The Backstage Authors * diff --git a/scripts/snyk-github-issue-sync.ts b/scripts/snyk-github-issue-sync.ts index da64e2ea82..ea7d42a2a4 100755 --- a/scripts/snyk-github-issue-sync.ts +++ b/scripts/snyk-github-issue-sync.ts @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ import { Octokit } from '@octokit/rest'; import minimist from 'minimist'; // Generated by GitHub workflow .github/workflows/snyk-github-issue-creator diff --git a/scripts/verify-api-reference.js b/scripts/verify-api-reference.js index 84a526604d..091e803c33 100755 --- a/scripts/verify-api-reference.js +++ b/scripts/verify-api-reference.js @@ -15,7 +15,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ const { resolve: resolvePath } = require('path'); const { promises: fs } = require('fs'); diff --git a/scripts/verify-changesets.js b/scripts/verify-changesets.js index 9e3064eeac..ae3f07840a 100755 --- a/scripts/verify-changesets.js +++ b/scripts/verify-changesets.js @@ -15,7 +15,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ const { resolve: resolvePath } = require('path'); const fs = require('fs-extra'); diff --git a/scripts/verify-links.js b/scripts/verify-links.js index 05ad387c37..7664cadad5 100755 --- a/scripts/verify-links.js +++ b/scripts/verify-links.js @@ -15,7 +15,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ const { resolve: resolvePath, join: joinPath, dirname } = require('path'); const fs = require('fs').promises; diff --git a/scripts/verify-lockfile-duplicates.js b/scripts/verify-lockfile-duplicates.js index cc22664219..820fba2ea5 100644 --- a/scripts/verify-lockfile-duplicates.js +++ b/scripts/verify-lockfile-duplicates.js @@ -15,7 +15,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ const { execFile: execFileCb } = require('child_process'); const { resolve: resolvePath, dirname: dirnamePath } = require('path'); From 4753d26b949a521c48334882c6bac4eb6cd2a2c3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 16:42:23 +0100 Subject: [PATCH 131/423] eslint-plugin: add no-relative-monorepo-imports rule Signed-off-by: Patrik Oldsberg --- packages/eslint-plugin/index.js | 2 + packages/eslint-plugin/lib/getPackages.js | 10 ++- .../rules/no-relative-monorepo-imports.js | 80 +++++++++++++++++++ .../rules/no-undeclared-imports.js | 4 +- 4 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 packages/eslint-plugin/rules/no-relative-monorepo-imports.js diff --git a/packages/eslint-plugin/index.js b/packages/eslint-plugin/index.js index cf1dd20ab7..20a0ff2d18 100644 --- a/packages/eslint-plugin/index.js +++ b/packages/eslint-plugin/index.js @@ -20,12 +20,14 @@ module.exports = { plugins: ['@backstage'], rules: { '@backstage/no-forbidden-package-imports': 'error', + '@backstage/no-relative-monorepo-imports': 'error', '@backstage/no-undeclared-imports': 'error', }, }, }, rules: { 'no-forbidden-package-imports': require('./rules/no-forbidden-package-imports'), + 'no-relative-monorepo-imports': require('./rules/no-relative-monorepo-imports'), 'no-undeclared-imports': require('./rules/no-undeclared-imports'), }, }; diff --git a/packages/eslint-plugin/lib/getPackages.js b/packages/eslint-plugin/lib/getPackages.js index 318d0654c2..6c8c1a66b2 100644 --- a/packages/eslint-plugin/lib/getPackages.js +++ b/packages/eslint-plugin/lib/getPackages.js @@ -16,7 +16,7 @@ // @ts-check -/** @type {import('@manypkg/get-packages')} */ +const path = require('path'); const manypkg = require('@manypkg/get-packages'); /** @@ -31,6 +31,7 @@ const manypkg = require('@manypkg/get-packages'); * @property {ExtendedPackage} root * @property {ExtendedPackage[]} list * @property {Map} map + * @property {(path: string) => ExtendedPackage | undefined} byPath */ // Loads all packages in the monorepo once, and caches the result @@ -56,6 +57,13 @@ module.exports = (function () { map: new Map(packages.packages.map(pkg => [pkg.packageJson.name, pkg])), list: packages.packages, root: packages.root, + byPath(filePath) { + return packages.packages.find(pkg => { + if (!path.relative(pkg.dir, filePath).startsWith('..')) { + return pkg; + } + }); + }, }; lastLoadAt = Date.now(); return result; diff --git a/packages/eslint-plugin/rules/no-relative-monorepo-imports.js b/packages/eslint-plugin/rules/no-relative-monorepo-imports.js new file mode 100644 index 0000000000..cb18eb506c --- /dev/null +++ b/packages/eslint-plugin/rules/no-relative-monorepo-imports.js @@ -0,0 +1,80 @@ +/* + * Copyright 2023 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. + */ + +// @ts-check + +const path = require('path'); +const visitImports = require('../lib/visitImports'); +const getPackageMap = require('../lib/getPackages'); + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + meta: { + type: 'problem', + messages: { + outside: 'Import of {{path}} is outside of any known monorepo package', + forbidden: + "Relative imports of monorepo packages are forbidden, use '{{newImport}}' instead", + }, + }, + create(context) { + const packages = getPackageMap(context.getCwd()); + if (!packages) { + return {}; + } + const filePath = context.getPhysicalFilename + ? context.getPhysicalFilename() + : context.getFilename(); + + const localPkg = packages.byPath(filePath); + if (!localPkg) { + return {}; + } + + return visitImports(context, (node, imp) => { + if (imp.type !== 'local') { + return; + } + + const target = path.resolve(path.dirname(filePath), imp.path); + if (!path.relative(localPkg.dir, target).startsWith('..')) { + return; + } + + const targetPkg = packages.byPath(target); + if (!targetPkg) { + context.report({ + node: node, + messageId: 'outside', + data: { + path: target, + }, + }); + return; + } + + const targetPath = path.relative(targetPkg.dir, target); + const targetName = targetPkg.packageJson.name ?? ''; + context.report({ + node: node, + messageId: 'forbidden', + data: { + newImport: targetPath ? `${targetName}/${targetPath}` : targetName, + }, + }); + }); + }, +}; diff --git a/packages/eslint-plugin/rules/no-undeclared-imports.js b/packages/eslint-plugin/rules/no-undeclared-imports.js index f7f7b17354..4a8756b71e 100644 --- a/packages/eslint-plugin/rules/no-undeclared-imports.js +++ b/packages/eslint-plugin/rules/no-undeclared-imports.js @@ -135,9 +135,7 @@ module.exports = { ? context.getPhysicalFilename() : context.getFilename(); - const localPkg = packages.list.find(p => - filePath.startsWith(p.dir + path.sep), - ); + const localPkg = packages.byPath(filePath); if (!localPkg) { return {}; } From 906af5db533ee9356b61a7f3844339d3d77cbbb4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 16:48:43 +0100 Subject: [PATCH 132/423] cli: remove unnecessary lint rules and fix issues Signed-off-by: Patrik Oldsberg --- packages/cli/config/eslint-factory.js | 8 +------- packages/cli/package.json | 1 - packages/cli/src/lib/version.ts | 2 +- packages/core-plugin-api/src/app/types.ts | 2 +- packages/create-app/src/index.ts | 1 + packages/create-app/src/lib/versions.ts | 2 +- 6 files changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/cli/config/eslint-factory.js b/packages/cli/config/eslint-factory.js index f344af4ab0..dde853fdff 100644 --- a/packages/cli/config/eslint-factory.js +++ b/packages/cli/config/eslint-factory.js @@ -64,7 +64,7 @@ function createConfig(dir, extraConfig = {}) { ...(extraExtends ?? []), ], parser: '@typescript-eslint/parser', - plugins: ['import', 'monorepo', ...(plugins ?? [])], + plugins: ['import', ...(plugins ?? [])], env: { jest: true, ...env, @@ -87,7 +87,6 @@ function createConfig(dir, extraConfig = {}) { '@typescript-eslint/no-shadow': 'error', '@typescript-eslint/no-redeclare': 'error', 'no-undef': 'off', - 'monorepo/no-relative-import': 'error', 'import/newline-after-import': 'error', 'no-unused-expressions': 'off', '@typescript-eslint/no-unused-expressions': 'error', @@ -110,9 +109,6 @@ function createConfig(dir, extraConfig = {}) { ...(restrictedSrcImports ?? []), ], patterns: [ - // Avoid cross-package imports - '**/../../**/*/src/**', - '**/../../**/*/src', // Prevent imports of stories or tests '*.stories*', '*.test*', @@ -162,8 +158,6 @@ function createConfig(dir, extraConfig = {}) { ...(restrictedImports ?? []), ...(restrictedTestImports ?? []), ], - // Avoid cross-package imports - patterns: ['**/../../**/*/src/**', '**/../../**/*/src'], }, ], }, diff --git a/packages/cli/package.json b/packages/cli/package.json index 909ac8460c..359f16adfa 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -76,7 +76,6 @@ "eslint-plugin-import": "^2.25.4", "eslint-plugin-jest": "^27.0.0", "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-monorepo": "^0.3.2", "eslint-plugin-react": "^7.28.0", "eslint-plugin-react-hooks": "^4.3.0", "eslint-webpack-plugin": "^3.1.1", diff --git a/packages/cli/src/lib/version.ts b/packages/cli/src/lib/version.ts index 5a199236f5..bf89842d5f 100644 --- a/packages/cli/src/lib/version.ts +++ b/packages/cli/src/lib/version.ts @@ -19,7 +19,7 @@ import semver from 'semver'; import { paths } from './paths'; import { Lockfile } from './versioning'; -/* eslint-disable monorepo/no-relative-import */ +/* eslint-disable @backstage/no-relative-monorepo-imports */ /* This is a list of all packages used by the templates. If dependencies are added or removed, diff --git a/packages/core-plugin-api/src/app/types.ts b/packages/core-plugin-api/src/app/types.ts index 2a71eda1f4..f3e0547ca4 100644 --- a/packages/core-plugin-api/src/app/types.ts +++ b/packages/core-plugin-api/src/app/types.ts @@ -17,7 +17,7 @@ // This is a bit of a hack that we use to avoid having to redeclare these types // within this package or have an explicit dependency on core-app-api. // These types end up being inlined and duplicated into this package at build time. -// eslint-disable-next-line no-restricted-imports +// eslint-disable-next-line @backstage/no-relative-monorepo-imports export type { BootErrorPageProps, SignInPageProps, diff --git a/packages/create-app/src/index.ts b/packages/create-app/src/index.ts index 216fab6740..fa235e6175 100644 --- a/packages/create-app/src/index.ts +++ b/packages/create-app/src/index.ts @@ -22,6 +22,7 @@ import { program } from 'commander'; import { exitWithError } from './lib/errors'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports import { version } from '../../../package.json'; import createApp from './createApp'; diff --git a/packages/create-app/src/lib/versions.ts b/packages/create-app/src/lib/versions.ts index b89b1d5463..72f5c2c9d5 100644 --- a/packages/create-app/src/lib/versions.ts +++ b/packages/create-app/src/lib/versions.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/* eslint-disable monorepo/no-relative-import */ +/* eslint-disable @backstage/no-relative-monorepo-imports */ /* This is a list of all packages used by the template. If dependencies are added or removed, From ef73e8626bf906febc682f1f31451a4668e329c3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 17:04:24 +0100 Subject: [PATCH 133/423] eslint-plugin: add docs for no-undeclared-imports Signed-off-by: Patrik Oldsberg --- .../docs/rules/no-undeclared-imports.md | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 packages/eslint-plugin/docs/rules/no-undeclared-imports.md diff --git a/packages/eslint-plugin/docs/rules/no-undeclared-imports.md b/packages/eslint-plugin/docs/rules/no-undeclared-imports.md new file mode 100644 index 0000000000..6102c772e6 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-undeclared-imports.md @@ -0,0 +1,84 @@ +# @backstage/no-undeclared-imports + +Forbid imports of external packages that have not been declared in the appropriate dependencies field in `package.json`. + +## Usage + +Add the rules as follows, it has no options: + +```js +"@backstage/no-undeclared-imports": ["error"] +``` + +The following patterns are considered files used during development, and only need dependencies to be declared in devDependencies: + +```python +!src/** # Any files outside of src are considered dev files +src/**/*.test.* +src/**/*.stories.* +src/**/__testUtils__/** +src/**/__mocks__/** +src/setupTests.* +``` + +## Rule Details + +Given the following `package.json`: + +```json +{ + "name": "@backstage/plugin-foo", + "backstage": { + "role": "frontend-plugin" + }, + "dependencies": { + "react": "^17.0.0" + }, + "devDependencies": { + "@backstage/core-plugin-api": "^1.0.0" + }, + "peerDependencies": { + "@backstage/config": "*" + } +} +``` + +### Fail + +Inside `src/my-plugin.ts`: + +```ts +// Should be declared as a dependency +const _ = require('lodash'); +import _ from 'lodash'; + +// React should be a peer dependency in frontend plugins +import react from 'react'; + +// Should be declared as a dependency, not a dev dependency +import { useApi } from '@backstage/core-plugin-api'; +``` + +Inside `src/my-plugin.test.ts` (a test file): + +```ts +// Should be declared as a dev dependency +const _ = require('lodash'); +import _ from 'lodash'; +``` + +### Pass + +Inside `src/my-plugin.ts`: + +```ts +// Declared in peerDependencies, so it is allowed +import { ConfigReader } from '@backstage/config'; +``` + +Inside `src/my-plugin.test.ts` (a test file): + +```ts +// Declared as a dev dependency inside a test file +import { useApi } from '@backstage/core-plugin-api'; +``` From 5105b9848a6ed57512697f3c80d198dcdabfdbae Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 17:10:51 +0100 Subject: [PATCH 134/423] eslint-plugin: add docs for no-relative-monorepo-imports Signed-off-by: Patrik Oldsberg --- .../rules/no-relative-monorepo-imports.md | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 packages/eslint-plugin/docs/rules/no-relative-monorepo-imports.md diff --git a/packages/eslint-plugin/docs/rules/no-relative-monorepo-imports.md b/packages/eslint-plugin/docs/rules/no-relative-monorepo-imports.md new file mode 100644 index 0000000000..6a41a73fb6 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-relative-monorepo-imports.md @@ -0,0 +1,43 @@ +# @backstage/no-relative-monorepo-imports + +Forbid relative imports that reach outside of the package in a monorepo. + +## Usage + +Add the rules as follows, it has no options: + +```js +"@backstage/no-relative-monorepo-imports": ["error"] +``` + +The following patterns are considered files used during development, and only need dependencies to be declared in devDependencies: + +```python +!src/** # Any files outside of src are considered dev files +src/**/*.test.* +src/**/*.stories.* +src/**/__testUtils__/** +src/**/__mocks__/** +src/setupTests.* +``` + +## Rule Details + +Assuming an import from for example `plugins/bar/src/index.ts`: + +### Fail + +```ts +import { FooCard } from '../../foo'; + +import { FooCard } from '../../foo/src/components/FooCard'; +``` + +### Pass + +```ts +import { FooCard } from '@internal/plugin-foo'; + +// This is allowed by this rule, but not by no-forbidden-package-imports +import { FooCard } from '@internal/plugin-foo/src/components/FooCard'; +``` From 015c0e0f89025c7ad8925a2bf7ad5321efaf4adf Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 17:15:55 +0100 Subject: [PATCH 135/423] eslint-plugin: add docs for no-forbidden-package-imports Signed-off-by: Patrik Oldsberg --- .../rules/no-forbidden-package-imports.md | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 packages/eslint-plugin/docs/rules/no-forbidden-package-imports.md diff --git a/packages/eslint-plugin/docs/rules/no-forbidden-package-imports.md b/packages/eslint-plugin/docs/rules/no-forbidden-package-imports.md new file mode 100644 index 0000000000..7a6ae11c37 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-forbidden-package-imports.md @@ -0,0 +1,52 @@ +# @backstage/no-forbidden-package-imports + +Disallow internal monorepo imports from package subpaths that are not exported. + +## Usage + +Add the rules as follows, it has no options: + +```js +"@backstage/no-forbidden-package-imports": ["error"] +``` + +## Rule Details + +Given the following two target packages: + +```json +{ + "name": "@backstage/plugin-foo", + "files": ["dist", "type-utils"] +} +``` + +```json +{ + "name": "@backstage/plugin-bar", + "exports": { + ".": "./src/index.ts", + "./testUtils": "./src/testUtils/index.ts", + "./package.json": "./package.json" + } +} +``` + +### Fail + +```ts +import { FooCard } from '@backstage/plugin-foo/src/components'; +import { BarCard } from '@backstage/plugin-bar/src/components'; +``` + +### Pass + +```ts +import { FooCard } from '@backstage/plugin-foo'; +import { FooType } from '@backstage/plugin-foo/type-utils'; +import fooPkg from '@backstage/plugin-foo/package.json'; + +import { BarCard } from '@backstage/plugin-bar'; +import { renderBarCardExtension } from '@backstage/plugin-bar/testUtils'; +import barPkg from '@backstage/plugin-bar/package.json'; +``` From 71bf2eb0ed63c7fc3482d3d043e055ac865cb418 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 17:20:24 +0100 Subject: [PATCH 136/423] eslint-plugin: add doc rule links and update README Signed-off-by: Patrik Oldsberg --- packages/eslint-plugin/README.md | 8 +++++--- .../eslint-plugin/rules/no-forbidden-package-imports.js | 5 +++++ .../eslint-plugin/rules/no-relative-monorepo-imports.js | 5 +++++ packages/eslint-plugin/rules/no-undeclared-imports.js | 5 +++++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index a063d801d3..c311670603 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -35,6 +35,8 @@ rules: { The following rules are provided by this plugin: -| Rule | Description | -| ----------------------------------------- | ------------------------------------------------------------------------------- | -| `@backstage/no-forbidden-package-imports` | Disallow internal monorepo imports from package subpaths that are not exported. | +| Rule | Description | +| --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | +| [@backstage/no-forbidden-package-imports](./docs/rules/no-forbidden-package-imports.md) | Disallow internal monorepo imports from package subpaths that are not exported. | +| [@backstage/no-relative-monorepo-imports](./docs/rules/no-relative-monorepo-imports.md) | Forbid relative imports that reach outside of the package in a monorepo. | +| [@backstage/no-undeclared-imports](./docs/rules/no-undeclared-imports.md) | Forbid imports of external packages that have not been declared in the appropriate dependencies field in `package.json`. | diff --git a/packages/eslint-plugin/rules/no-forbidden-package-imports.js b/packages/eslint-plugin/rules/no-forbidden-package-imports.js index 6c861e17f5..e7c1acca27 100644 --- a/packages/eslint-plugin/rules/no-forbidden-package-imports.js +++ b/packages/eslint-plugin/rules/no-forbidden-package-imports.js @@ -25,6 +25,11 @@ module.exports = { messages: { forbidden: '{{packageName}} does not export {{subPath}}', }, + docs: { + description: + 'Disallow internal monorepo imports from package subpaths that are not exported.', + url: 'https://github.com/backstage/backstage/blob/master/packages/eslint-plugin/docs/rules/no-forbidden-package-imports.md', + }, }, create(context) { return visitImports(context, (node, imp) => { diff --git a/packages/eslint-plugin/rules/no-relative-monorepo-imports.js b/packages/eslint-plugin/rules/no-relative-monorepo-imports.js index cb18eb506c..df30d35f67 100644 --- a/packages/eslint-plugin/rules/no-relative-monorepo-imports.js +++ b/packages/eslint-plugin/rules/no-relative-monorepo-imports.js @@ -29,6 +29,11 @@ module.exports = { forbidden: "Relative imports of monorepo packages are forbidden, use '{{newImport}}' instead", }, + docs: { + description: + 'Forbid relative imports that reach outside of the package in a monorepo.', + url: 'https://github.com/backstage/backstage/blob/master/packages/eslint-plugin/docs/rules/no-relative-monorepo-imports.md', + }, }, create(context) { const packages = getPackageMap(context.getCwd()); diff --git a/packages/eslint-plugin/rules/no-undeclared-imports.js b/packages/eslint-plugin/rules/no-undeclared-imports.js index 4a8756b71e..4f60b712d9 100644 --- a/packages/eslint-plugin/rules/no-undeclared-imports.js +++ b/packages/eslint-plugin/rules/no-undeclared-imports.js @@ -125,6 +125,11 @@ module.exports = { switch: '{{ packageName }} is declared in {{ oldDepsField }}, but should be moved to {{ depsField }} in {{ packageJsonPath }}.', }, + docs: { + description: + 'Forbid imports of external packages that have not been declared in the appropriate dependencies field in `package.json`.', + url: 'https://github.com/backstage/backstage/blob/master/packages/eslint-plugin/docs/rules/no-undeclared-imports.md', + }, }, create(context) { const packages = getPackageMap(context.getCwd()); From dd8a9afe668ab0bb69bc2d65130e513ce58e8426 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 17:24:49 +0100 Subject: [PATCH 137/423] added and updated changesets for eslint-plugin addition Signed-off-by: Patrik Oldsberg --- .changeset/few-moons-accept.md | 5 +++++ .changeset/tough-jeans-camp.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/few-moons-accept.md diff --git a/.changeset/few-moons-accept.md b/.changeset/few-moons-accept.md new file mode 100644 index 0000000000..c790e837c8 --- /dev/null +++ b/.changeset/few-moons-accept.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Replaced several monorepo lint rules with new rules from `@backstage/eslint-plugin`. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for a full list of rules. diff --git a/.changeset/tough-jeans-camp.md b/.changeset/tough-jeans-camp.md index b7c08593e1..8c7a53190f 100644 --- a/.changeset/tough-jeans-camp.md +++ b/.changeset/tough-jeans-camp.md @@ -2,4 +2,4 @@ '@backstage/eslint-plugin': minor --- -Added a new ESLint plugin with common rules for Backstage projects. +Added a new ESLint plugin with common rules for Backstage projects. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for more details. From 1b30c9a0f7f77a16e16c238c324b6c6bf4f3b1d4 Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Fri, 3 Feb 2023 19:59:51 +0100 Subject: [PATCH 138/423] feat(search): improve router query errors Signed-off-by: Camila Belo --- .changeset/hip-onions-tan.md | 5 +++++ .../search-backend/src/service/router.test.ts | 17 +++++++++++++++++ plugins/search-backend/src/service/router.ts | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 .changeset/hip-onions-tan.md diff --git a/.changeset/hip-onions-tan.md b/.changeset/hip-onions-tan.md new file mode 100644 index 0000000000..01be0d4867 --- /dev/null +++ b/.changeset/hip-onions-tan.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend': patch +--- + +Change the router's response to include the error message instead of its object type in case it fails during a search query because the messages have more info. diff --git a/plugins/search-backend/src/service/router.test.ts b/plugins/search-backend/src/service/router.test.ts index 1dbd145bce..b4772dd62d 100644 --- a/plugins/search-backend/src/service/router.test.ts +++ b/plugins/search-backend/src/service/router.test.ts @@ -74,6 +74,23 @@ describe('createRouter', () => { }); describe('GET /query', () => { + it('throws meaningful query errors', async () => { + const error = new Error('Query error message'); + mockSearchEngine.query.mockRejectedValueOnce(error); + + const response = await request(app).get('/query'); + + expect(response.status).toEqual(500); + expect(response.body).toMatchObject( + expect.objectContaining({ + error: { + name: 'Error', + message: `There was a problem performing the search query: ${error.message}`, + }, + }), + ); + }); + it('returns empty results array', async () => { const response = await request(app).get('/query'); diff --git a/plugins/search-backend/src/service/router.ts b/plugins/search-backend/src/service/router.ts index b51dcead14..10f47d180f 100644 --- a/plugins/search-backend/src/service/router.ts +++ b/plugins/search-backend/src/service/router.ts @@ -184,7 +184,7 @@ export async function createRouter( } throw new Error( - `There was a problem performing the search query. ${error}`, + `There was a problem performing the search query: ${error.message}`, ); } }, From d5fe9f10934ad24fee2b5db055ee502f0ee349bb Mon Sep 17 00:00:00 2001 From: Mark Anderson-Trocme Date: Fri, 3 Feb 2023 16:09:28 -0500 Subject: [PATCH 139/423] feature: build workflow url Signed-off-by: Mark Anderson-Trocme --- .../src/components/BuildsPage/lib/CITable/CITable.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx b/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx index 8f99f1f69c..6b22d641ee 100644 --- a/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx +++ b/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx @@ -214,7 +214,14 @@ const generatedColumns: TableColumn[] = [ field: 'workflow.name', highlight: true, render: (row: Partial) => ( - {row?.workflow?.name} + + {row?.workflow?.name} + ), }, { From c044a3629b6549981c0b6ae50561cef9bf21ba60 Mon Sep 17 00:00:00 2001 From: Mark Anderson-Trocme Date: Fri, 3 Feb 2023 16:16:47 -0500 Subject: [PATCH 140/423] lint Signed-off-by: Mark Anderson-Trocme --- .../src/components/BuildsPage/lib/CITable/CITable.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx b/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx index 6b22d641ee..22f69ac30f 100644 --- a/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx +++ b/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx @@ -215,10 +215,7 @@ const generatedColumns: TableColumn[] = [ highlight: true, render: (row: Partial) => ( {row?.workflow?.name} From aefe3a562495c2a1e8efbb926958654d85f0e4fb Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 3 Feb 2023 18:06:52 +0100 Subject: [PATCH 141/423] eslint-plugin: added tests for no-relative-monorepo-imports Signed-off-by: Patrik Oldsberg --- packages/eslint-plugin/.eslintrc.js | 3 + packages/eslint-plugin/package.json | 6 +- .../src/__fixtures__/monorepo/package.json | 6 + .../monorepo/packages/bar/package.json | 9 ++ .../monorepo/packages/foo/package.json | 7 + .../src/no-relative-monorepo-imports.test.ts | 68 +++++++++ yarn.lock | 140 +----------------- 7 files changed, 102 insertions(+), 137 deletions(-) create mode 100644 packages/eslint-plugin/src/__fixtures__/monorepo/package.json create mode 100644 packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json create mode 100644 packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json create mode 100644 packages/eslint-plugin/src/no-relative-monorepo-imports.test.ts diff --git a/packages/eslint-plugin/.eslintrc.js b/packages/eslint-plugin/.eslintrc.js index 7fc68c3c5d..01d1b181d7 100644 --- a/packages/eslint-plugin/.eslintrc.js +++ b/packages/eslint-plugin/.eslintrc.js @@ -21,6 +21,9 @@ module.exports = { node: true, es2021: true, }, + parserOptions: { + sourceType: 'module', + }, rules: { '@backstage/no-undeclared-imports': ['error'], 'no-unused-expressions': 'off', diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 73862d2295..84fc16b98f 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -14,13 +14,15 @@ "license": "Apache-2.0", "main": "./index.js", "scripts": { - "lint": "backstage-cli package lint" + "lint": "backstage-cli package lint", + "test": "backstage-cli package test" }, "dependencies": { "@manypkg/get-packages": "^1.1.3", "minimatch": "^5.1.2" }, "devDependencies": { - "@backstage/cli": "workspace:^" + "@backstage/cli": "workspace:^", + "eslint": "^8.33.0" } } diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/package.json new file mode 100644 index 0000000000..c35178c46f --- /dev/null +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/package.json @@ -0,0 +1,6 @@ +{ + "name": "root", + "workspaces": [ + "packages/*" + ] +} diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json new file mode 100644 index 0000000000..8331b20c43 --- /dev/null +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json @@ -0,0 +1,9 @@ +{ + "name": "@internal/bar", + "backstage": { + "role": "frontend-plugin" + }, + "peerDependencies": { + "react": "*" + } +} diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json new file mode 100644 index 0000000000..66341563cd --- /dev/null +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json @@ -0,0 +1,7 @@ +{ + "name": "@internal/foo", + "dependencies": { + "@internal/bar": "1.0.0", + "lodash": "*" + } +} diff --git a/packages/eslint-plugin/src/no-relative-monorepo-imports.test.ts b/packages/eslint-plugin/src/no-relative-monorepo-imports.test.ts new file mode 100644 index 0000000000..6888d258cc --- /dev/null +++ b/packages/eslint-plugin/src/no-relative-monorepo-imports.test.ts @@ -0,0 +1,68 @@ +/* + * Copyright 2023 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 { RuleTester } from 'eslint'; +import path from 'path'; +import rule from '../rules/no-relative-monorepo-imports'; + +const RULE = 'no-relative-monorepo-imports'; +const FIXTURE = path.resolve(__dirname, '__fixtures__/monorepo'); + +const ERR_OUTSIDE = (path: string) => ({ + message: `Import of ${path} is outside of any known monorepo package`, +}); +const ERR_FORBIDDEN = (newImp: string) => ({ + message: `Relative imports of monorepo packages are forbidden, use '${newImp}' instead`, +}); + +process.chdir(FIXTURE); + +const ruleTester = new RuleTester({ + parserOptions: { + sourceType: 'module', + ecmaVersion: 2021, + }, +}); + +ruleTester.run(RULE, rule, { + valid: [ + { + code: `import { version } from '@internal/foo'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + }, + { + code: `import { version } from '@internal/foo/src'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + }, + ], + invalid: [ + { + code: `import { version } from '../../foo'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_FORBIDDEN('@internal/foo')], + }, + { + code: `import { version } from '../../foo/src'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_FORBIDDEN('@internal/foo/src')], + }, + { + code: `import { version } from '../../../package.json'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_OUTSIDE(path.join(FIXTURE, 'package.json'))], + }, + ], +}); diff --git a/yarn.lock b/yarn.lock index e0e1da349c..2d250e9913 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3721,7 +3721,6 @@ __metadata: eslint-plugin-import: ^2.25.4 eslint-plugin-jest: ^27.0.0 eslint-plugin-jsx-a11y: ^6.5.1 - eslint-plugin-monorepo: ^0.3.2 eslint-plugin-react: ^7.28.0 eslint-plugin-react-hooks: ^4.3.0 eslint-webpack-plugin: ^3.1.1 @@ -4101,6 +4100,7 @@ __metadata: dependencies: "@backstage/cli": "workspace:^" "@manypkg/get-packages": ^1.1.3 + eslint: ^8.33.0 minimatch: ^5.1.2 languageName: unknown linkType: soft @@ -16670,15 +16670,6 @@ __metadata: languageName: node linkType: hard -"array-union@npm:^1.0.1": - version: 1.0.2 - resolution: "array-union@npm:1.0.2" - dependencies: - array-uniq: ^1.0.1 - checksum: 82cec6421b6e6766556c484835a6d476a873f1b71cace5ab2b4f1b15b1e3162dc4da0d16f7a2b04d4aec18146c6638fe8f661340b31ba8e469fd811a1b45dc8d - languageName: node - linkType: hard - "array-union@npm:^2.1.0": version: 2.1.0 resolution: "array-union@npm:2.1.0" @@ -16686,13 +16677,6 @@ __metadata: languageName: node linkType: hard -"array-uniq@npm:^1.0.1": - version: 1.0.3 - resolution: "array-uniq@npm:1.0.3" - checksum: 1625f06b093d8bf279b81adfec6e72951c0857d65b5e3f65f053fffe9f9dd61c2fc52cff57e38a4700817e7e3f01a4faa433d505ea9e33cdae4514c334e0bf9e - languageName: node - linkType: hard - "array.prototype.flat@npm:^1.2.3, array.prototype.flat@npm:^1.3.1": version: 1.3.1 resolution: "array.prototype.flat@npm:1.3.1" @@ -20534,15 +20518,6 @@ __metadata: languageName: node linkType: hard -"dir-glob@npm:^2.0.0": - version: 2.2.2 - resolution: "dir-glob@npm:2.2.2" - dependencies: - path-type: ^3.0.0 - checksum: 3aa48714a9f7845ffc30ab03a5c674fe760477cc55e67b0847333371549227d93953e6627ec160f75140c5bea5c5f88d13c01de79bd1997a588efbcf06980842 - languageName: node - linkType: hard - "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -21606,7 +21581,7 @@ __metadata: languageName: node linkType: hard -"eslint-module-utils@npm:^2.1.1, eslint-module-utils@npm:^2.7.4": +"eslint-module-utils@npm:^2.7.4": version: 2.7.4 resolution: "eslint-module-utils@npm:2.7.4" dependencies: @@ -21711,21 +21686,6 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-monorepo@npm:^0.3.2": - version: 0.3.2 - resolution: "eslint-plugin-monorepo@npm:0.3.2" - dependencies: - eslint-module-utils: ^2.1.1 - get-monorepo-packages: ^1.1.0 - globby: ^7.1.1 - load-json-file: ^4.0.0 - minimatch: ^3.0.4 - parse-package-name: ^0.1.0 - path-is-inside: ^1.0.2 - checksum: b6f17efbc9e66aefbf7aacf9aa130bc8e729a6311c412d1b0026ce7d93361c10b0e6e4b10cf434f24ca9a8b2e891bc8e5b82e66dc9ccc5e782f9c18a989eca28 - languageName: node - linkType: hard - "eslint-plugin-notice@npm:^0.9.10": version: 0.9.10 resolution: "eslint-plugin-notice@npm:0.9.10" @@ -21845,7 +21805,7 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.6.0": +"eslint@npm:^8.33.0, eslint@npm:^8.6.0": version: 8.33.0 resolution: "eslint@npm:8.33.0" dependencies: @@ -23438,16 +23398,6 @@ __metadata: languageName: node linkType: hard -"get-monorepo-packages@npm:^1.1.0": - version: 1.2.0 - resolution: "get-monorepo-packages@npm:1.2.0" - dependencies: - globby: ^7.1.1 - load-json-file: ^4.0.0 - checksum: f9321c11b8e11f02138758db6589d8ab8b7e1b05e78cac92493b635faea10aa100c20fe40f2cf110c82ec100c118c6c131dff4c65d32a721c617dc2928f7b277 - languageName: node - linkType: hard - "get-package-type@npm:^0.1.0": version: 0.1.0 resolution: "get-package-type@npm:0.1.0" @@ -23598,7 +23548,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.0.0, glob@npm:^7.1.1, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.1.7, glob@npm:^7.2.0": +"glob@npm:^7.0.0, glob@npm:^7.1.1, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.1.7, glob@npm:^7.2.0": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -23707,20 +23657,6 @@ __metadata: languageName: node linkType: hard -"globby@npm:^7.1.1": - version: 7.1.1 - resolution: "globby@npm:7.1.1" - dependencies: - array-union: ^1.0.1 - dir-glob: ^2.0.0 - glob: ^7.1.2 - ignore: ^3.3.5 - pify: ^3.0.0 - slash: ^1.0.0 - checksum: f0eba08a08ae7c98149a4411661c0bf08c4717d81e6f355cf624fb01880b249737eb8e951bf86124cb3af8ea1c793c0a9d363ed5cdec99bb2c6b68f8a323025f - languageName: node - linkType: hard - "good-listener@npm:^1.2.2": version: 1.2.2 resolution: "good-listener@npm:1.2.2" @@ -24710,13 +24646,6 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^3.3.5": - version: 3.3.10 - resolution: "ignore@npm:3.3.10" - checksum: 23e8cc776e367b56615ab21b78decf973a35dfca5522b39d9b47643d8168473b0d1f18dd1321a1bab466a12ea11a2411903f3b21644f4d5461ee0711ec8678bd - languageName: node - linkType: hard - "ignore@npm:^5.1.4, ignore@npm:^5.2.0": version: 5.2.0 resolution: "ignore@npm:5.2.0" @@ -26828,13 +26757,6 @@ __metadata: languageName: node linkType: hard -"json-parse-better-errors@npm:^1.0.1": - version: 1.0.2 - resolution: "json-parse-better-errors@npm:1.0.2" - checksum: ff2b5ba2a70e88fd97a3cb28c1840144c5ce8fae9cbeeddba15afa333a5c407cf0e42300cd0a2885dbb055227fe68d405070faad941beeffbfde9cf3b2c78c5d - languageName: node - linkType: hard - "json-parse-even-better-errors@npm:^2.3.0, json-parse-even-better-errors@npm:^2.3.1": version: 2.3.1 resolution: "json-parse-even-better-errors@npm:2.3.1" @@ -27725,18 +27647,6 @@ __metadata: languageName: node linkType: hard -"load-json-file@npm:^4.0.0": - version: 4.0.0 - resolution: "load-json-file@npm:4.0.0" - dependencies: - graceful-fs: ^4.1.2 - parse-json: ^4.0.0 - pify: ^3.0.0 - strip-bom: ^3.0.0 - checksum: 8f5d6d93ba64a9620445ee9bde4d98b1eac32cf6c8c2d20d44abfa41a6945e7969456ab5f1ca2fb06ee32e206c9769a20eec7002fe290de462e8c884b6b8b356 - languageName: node - linkType: hard - "load-yaml-file@npm:^0.2.0": version: 0.2.0 resolution: "load-yaml-file@npm:0.2.0" @@ -30849,16 +30759,6 @@ __metadata: languageName: node linkType: hard -"parse-json@npm:^4.0.0": - version: 4.0.0 - resolution: "parse-json@npm:4.0.0" - dependencies: - error-ex: ^1.3.1 - json-parse-better-errors: ^1.0.1 - checksum: 0fe227d410a61090c247e34fa210552b834613c006c2c64d9a05cfe9e89cf8b4246d1246b1a99524b53b313e9ac024438d0680f67e33eaed7e6f38db64cfe7b5 - languageName: node - linkType: hard - "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -30871,13 +30771,6 @@ __metadata: languageName: node linkType: hard -"parse-package-name@npm:^0.1.0": - version: 0.1.0 - resolution: "parse-package-name@npm:0.1.0" - checksum: 7d69b1deeaf82d5a59536c5a8772c8db003b1415dd2465073343dfab5caf90917ecfffdd71d1c004f5cf963c3881ccb8899d0ff820eac705a272e817e246de14 - languageName: node - linkType: hard - "parse-path@npm:^7.0.0": version: 7.0.0 resolution: "parse-path@npm:7.0.0" @@ -31150,7 +31043,7 @@ __metadata: languageName: node linkType: hard -"path-is-inside@npm:1.0.2, path-is-inside@npm:^1.0.2": +"path-is-inside@npm:1.0.2": version: 1.0.2 resolution: "path-is-inside@npm:1.0.2" checksum: 0b5b6c92d3018b82afb1f74fe6de6338c4c654de4a96123cb343f2b747d5606590ac0c890f956ed38220a4ab59baddfd7b713d78a62d240b20b14ab801fa02cb @@ -31249,15 +31142,6 @@ __metadata: languageName: node linkType: hard -"path-type@npm:^3.0.0": - version: 3.0.0 - resolution: "path-type@npm:3.0.0" - dependencies: - pify: ^3.0.0 - checksum: 735b35e256bad181f38fa021033b1c33cfbe62ead42bb2222b56c210e42938eecb272ae1949f3b6db4ac39597a61b44edd8384623ec4d79bfdc9a9c0f12537a6 - languageName: node - linkType: hard - "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -31432,13 +31316,6 @@ __metadata: languageName: node linkType: hard -"pify@npm:^3.0.0": - version: 3.0.0 - resolution: "pify@npm:3.0.0" - checksum: 6cdcbc3567d5c412450c53261a3f10991665d660961e06605decf4544a61a97a54fefe70a68d5c37080ff9d6f4cf51444c90198d1ba9f9309a6c0d6e9f5c4fde - languageName: node - linkType: hard - "pify@npm:^4.0.1": version: 4.0.1 resolution: "pify@npm:4.0.1" @@ -34985,13 +34862,6 @@ __metadata: languageName: node linkType: hard -"slash@npm:^1.0.0": - version: 1.0.0 - resolution: "slash@npm:1.0.0" - checksum: 4b6e21b1fba6184a7e2efb1dd173f692d8a845584c1bbf9dc818ff86f5a52fc91b413008223d17cc684604ee8bb9263a420b1182027ad9762e35388434918860 - languageName: node - linkType: hard - "slash@npm:^2.0.0": version: 2.0.0 resolution: "slash@npm:2.0.0" From 6801eb57805c06c398bd82da72f1429acc634a07 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 4 Feb 2023 10:52:55 +0100 Subject: [PATCH 142/423] eslint-plugin: refactor to fix issues uncovered by more strict parsing Signed-off-by: Patrik Oldsberg --- packages/eslint-plugin/lib/getPackages.js | 12 ++++++------ packages/eslint-plugin/lib/visitImports.js | 12 ++++++++++-- .../eslint-plugin/rules/no-undeclared-imports.js | 13 +++++++++---- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/packages/eslint-plugin/lib/getPackages.js b/packages/eslint-plugin/lib/getPackages.js index 6c8c1a66b2..f5f2c63cc1 100644 --- a/packages/eslint-plugin/lib/getPackages.js +++ b/packages/eslint-plugin/lib/getPackages.js @@ -36,8 +36,10 @@ const manypkg = require('@manypkg/get-packages'); // Loads all packages in the monorepo once, and caches the result module.exports = (function () { + /** @type {PackageMap | undefined} */ let result = undefined; - let lastLoadAt = undefined; + /** @type {number} */ + let lastLoadAt = 0; /** @returns {PackageMap | undefined} */ return function getPackages(/** @type {string} */ dir) { @@ -58,11 +60,9 @@ module.exports = (function () { list: packages.packages, root: packages.root, byPath(filePath) { - return packages.packages.find(pkg => { - if (!path.relative(pkg.dir, filePath).startsWith('..')) { - return pkg; - } - }); + return packages.packages.find( + pkg => !path.relative(pkg.dir, filePath).startsWith('..'), + ); }, }; lastLoadAt = Date.now(); diff --git a/packages/eslint-plugin/lib/visitImports.js b/packages/eslint-plugin/lib/visitImports.js index ed16c26c7f..43401bf5f9 100644 --- a/packages/eslint-plugin/lib/visitImports.js +++ b/packages/eslint-plugin/lib/visitImports.js @@ -56,12 +56,17 @@ const getPackages = require('./getPackages'); /** * @callback ImportVisitor - * @param {import('eslint').Rule.Node} node + * @param {ConsideredNode} node * @param {LocalImport | InternalImport | ExternalImport | BuiltinImport} import */ /** - * @param {import('estree').ImportDeclaration | import('estree').ExportAllDeclaration | import('estree').ExportNamedDeclaration | import('estree').ImportExpression | import('estree').SimpleCallExpression} node + * @typedef ConsideredNode + * @type {import('estree').ImportDeclaration | import('estree').ExportAllDeclaration | import('estree').ExportNamedDeclaration | import('estree').ImportExpression | import('estree').SimpleCallExpression} + */ + +/** + * @param {ConsideredNode} node * @returns {undefined | {path: string, kind: 'type' | 'value'}} */ function getImportInfo(node) { @@ -103,6 +108,9 @@ module.exports = function visitImports(context, visitor) { return; } + /** + * @param {ConsideredNode} node + */ function visit(node) { const info = getImportInfo(node); if (!info) { diff --git a/packages/eslint-plugin/rules/no-undeclared-imports.js b/packages/eslint-plugin/rules/no-undeclared-imports.js index 4f60b712d9..85d7266eb8 100644 --- a/packages/eslint-plugin/rules/no-undeclared-imports.js +++ b/packages/eslint-plugin/rules/no-undeclared-imports.js @@ -37,7 +37,7 @@ const devModulePatterns = [ ]; function getExpectedDepType( - localPkg, + /** @type {any} */ localPkg, /** @type {string} */ impPath, /** @type {string} */ modulePath, ) { @@ -58,6 +58,7 @@ function getExpectedDepType( case 'react-router-dom': return 'peer'; } + break; case 'cli': case 'frontend': case 'backend': @@ -100,10 +101,14 @@ function findConflict(pkg, name, expectedType) { return { oldDepsField, depsField }; } + return undefined; } -function getAddFlagForConflict(conflict) { - switch (conflict?.depsField) { +/** + * @param {string} depsField + */ +function getAddFlagForDepsField(depsField) { + switch (depsField) { case depFields.dep: return ''; case depFields.dev: @@ -189,7 +194,7 @@ module.exports = { data: { ...conflict, packagePath, - addFlag: getAddFlagForConflict(conflict), + addFlag: getAddFlagForDepsField(conflict.depsField), packageName: imp.packageName, packageJsonPath: packageJsonPath, }, From e6d210947ece9b5fcaa90698f2b577936db3445c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 4 Feb 2023 11:15:52 +0100 Subject: [PATCH 143/423] eslint-plugin: add tests for no-undeclared-imports + fixes Signed-off-by: Patrik Oldsberg --- packages/eslint-plugin/.eslintrc.js | 3 + .../rules/no-undeclared-imports.js | 2 +- .../monorepo/packages/bar/package.json | 7 +- .../monorepo/packages/foo/package.json | 7 +- .../src/no-undeclared-imports.test.ts | 194 ++++++++++++++++++ 5 files changed, 209 insertions(+), 4 deletions(-) create mode 100644 packages/eslint-plugin/src/no-undeclared-imports.test.ts diff --git a/packages/eslint-plugin/.eslintrc.js b/packages/eslint-plugin/.eslintrc.js index 01d1b181d7..6b9de4544e 100644 --- a/packages/eslint-plugin/.eslintrc.js +++ b/packages/eslint-plugin/.eslintrc.js @@ -21,8 +21,11 @@ module.exports = { node: true, es2021: true, }, + parser: '@typescript-eslint/parser', parserOptions: { + ecmaVersion: 2018, sourceType: 'module', + lib: require('@backstage/cli/config/tsconfig.json').compilerOptions.lib, }, rules: { '@backstage/no-undeclared-imports': ['error'], diff --git a/packages/eslint-plugin/rules/no-undeclared-imports.js b/packages/eslint-plugin/rules/no-undeclared-imports.js index 85d7266eb8..42624beb5c 100644 --- a/packages/eslint-plugin/rules/no-undeclared-imports.js +++ b/packages/eslint-plugin/rules/no-undeclared-imports.js @@ -161,7 +161,7 @@ module.exports = { const modulePath = path.relative(localPkg.dir, filePath); const expectedType = getExpectedDepType( - localPkg, + localPkg.packageJson, imp.packageName, modulePath, ); diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json index 8331b20c43..c876e00e32 100644 --- a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json @@ -3,7 +3,10 @@ "backstage": { "role": "frontend-plugin" }, - "peerDependencies": { - "react": "*" + "dependencies": { + "react-router": "*" + }, + "devDependencies": { + "react-router-dom": "*" } } diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json index 66341563cd..8a14cad4d3 100644 --- a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json @@ -1,7 +1,12 @@ { "name": "@internal/foo", "dependencies": { - "@internal/bar": "1.0.0", + "@internal/bar": "1.0.0" + }, + "devDependencies": { "lodash": "*" + }, + "peerDependencies": { + "react": "*" } } diff --git a/packages/eslint-plugin/src/no-undeclared-imports.test.ts b/packages/eslint-plugin/src/no-undeclared-imports.test.ts new file mode 100644 index 0000000000..c156558e8d --- /dev/null +++ b/packages/eslint-plugin/src/no-undeclared-imports.test.ts @@ -0,0 +1,194 @@ +/* + * Copyright 2023 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 { RuleTester } from 'eslint'; +import path from 'path'; +import rule from '../rules/no-undeclared-imports'; + +const RULE = 'no-undeclared-imports'; +const FIXTURE = path.resolve(__dirname, '__fixtures__/monorepo'); + +const ERR_UNDECLARED = ( + name: string, + field: string, + path: string, + flag?: string, +) => ({ + message: `${name} must be declared in ${field} of ${path}/package.json, run 'yarn --cwd ${path} add${ + flag ? ` ${flag}` : '' + } ${name}' from the project root.`, +}); +const ERR_SWITCHED = ( + name: string, + old: string, + field: string, + path: string, +) => ({ + message: `${name} is declared in ${old}, but should be moved to ${field} in ${path}/package.json.`, +}); + +process.chdir(FIXTURE); + +const ruleTester = new RuleTester({ + parserOptions: { + sourceType: 'module', + ecmaVersion: 2021, + }, +}); + +ruleTester.run(RULE, rule, { + valid: [ + { + code: `import '@internal/foo'`, + filename: path.join(FIXTURE, 'packages/foo/src/index.ts'), + }, + { + code: `import '@internal/bar'`, + filename: path.join(FIXTURE, 'packages/foo/src/index.ts'), + }, + { + code: `import 'react'`, + filename: path.join(FIXTURE, 'packages/foo/src/index.ts'), + }, + { + code: `import '@internal/foo'`, + filename: path.join(FIXTURE, 'packages/foo/src/index.test.ts'), + }, + { + code: `import '@internal/bar'`, + filename: path.join(FIXTURE, 'packages/foo/src/index.test.ts'), + }, + { + code: `import 'lodash'`, + filename: path.join(FIXTURE, 'packages/foo/src/index.test.ts'), + }, + { + code: `import 'react'`, + filename: path.join(FIXTURE, 'packages/foo/src/index.test.ts'), + }, + { + // We're only able to validate literals + code: `require('lod' + 'ash')`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + }, + ], + invalid: [ + { + code: `import 'lodash'`, + filename: path.join(FIXTURE, 'packages/foo/src/index.ts'), + errors: [ + ERR_SWITCHED( + 'lodash', + 'devDependencies', + 'dependencies', + 'packages/foo', + ), + ], + }, + { + code: `import 'react-router'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_SWITCHED( + 'react-router', + 'dependencies', + 'peerDependencies', + 'packages/bar', + ), + ], + }, + { + code: `import 'react-router-dom'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_SWITCHED( + 'react-router-dom', + 'devDependencies', + 'peerDependencies', + 'packages/bar', + ), + ], + }, + { + code: `import 'lodash'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], + }, + { + code: `import { debounce } from 'lodash'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], + }, + { + code: `import * as _ from 'lodash'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], + }, + { + code: `import _ from 'lodash'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], + }, + { + code: `import('lodash')`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], + }, + { + code: `require('lodash')`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], + }, + { + code: `import 'lodash'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], + }, + { + code: `import 'lodash'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.test.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'devDependencies', 'packages/bar', '--dev'), + ], + }, + { + code: `import 'react'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('react', 'peerDependencies', 'packages/bar', '--peer'), + ], + }, + { + code: `import 'react'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.test.ts'), + errors: [ + ERR_UNDECLARED('react', 'peerDependencies', 'packages/bar', '--peer'), + ], + }, + { + code: `import 'react-dom'`, + filename: path.join(FIXTURE, 'packages/foo/src/index.ts'), + errors: [ERR_UNDECLARED('react-dom', 'dependencies', 'packages/foo')], + }, + { + code: `import 'react-dom'`, + filename: path.join(FIXTURE, 'packages/foo/src/index.test.ts'), + errors: [ + ERR_UNDECLARED('react-dom', 'devDependencies', 'packages/foo', '--dev'), + ], + }, + ], +}); From 2638dd4e7c9aa88ffcf987a33ff86465292094c4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 4 Feb 2023 11:31:00 +0100 Subject: [PATCH 144/423] eslint-plugin: add tests for no-forbidden-package-imports Signed-off-by: Patrik Oldsberg --- .../monorepo/packages/bar/package.json | 5 + .../monorepo/packages/foo/package.json | 6 +- .../src/no-forbidden-package-imports.test.ts | 120 ++++++++++++++++++ 3 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 packages/eslint-plugin/src/no-forbidden-package-imports.test.ts diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json index c876e00e32..efef27047b 100644 --- a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json @@ -1,5 +1,10 @@ { "name": "@internal/bar", + "exports": { + ".": "./src/index.ts", + "./BarPage": "./src/components/Bar.tsx", + "./package.json": "./package.json" + }, "backstage": { "role": "frontend-plugin" }, diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json index 8a14cad4d3..563ec35120 100644 --- a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json @@ -8,5 +8,9 @@ }, "peerDependencies": { "react": "*" - } + }, + "files": [ + "dist", + "type-utils" + ] } diff --git a/packages/eslint-plugin/src/no-forbidden-package-imports.test.ts b/packages/eslint-plugin/src/no-forbidden-package-imports.test.ts new file mode 100644 index 0000000000..349b71319f --- /dev/null +++ b/packages/eslint-plugin/src/no-forbidden-package-imports.test.ts @@ -0,0 +1,120 @@ +/* + * Copyright 2023 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 { RuleTester } from 'eslint'; +import path from 'path'; +import rule from '../rules/no-forbidden-package-imports'; + +const RULE = 'no-forbidden-package-imports'; +const FIXTURE = path.resolve(__dirname, '__fixtures__/monorepo'); + +const ERR = (name: string, path: string) => ({ + message: `${name} does not export ${path}`, +}); + +process.chdir(FIXTURE); + +const ruleTester = new RuleTester({ + parserOptions: { + sourceType: 'module', + ecmaVersion: 2021, + }, +}); + +ruleTester.run(RULE, rule, { + valid: [ + { + code: `import '@internal/foo'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + { + code: `import '@internal/foo/type-utils'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + { + code: `import '@internal/foo/type-utils/anything'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + { + code: `import '@internal/foo/package.json'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + { + code: `import '@internal/bar'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + { + code: `import '@internal/bar/package.json'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + { + code: `import '@internal/bar/BarPage'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + ], + invalid: [ + { + code: `import '@internal/foo/FooPage'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/foo', 'FooPage')], + }, + { + code: `import '@internal/foo/dist'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/foo', 'dist')], + }, + { + code: `import '@internal/foo/dist/FooPage'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/foo', 'dist/FooPage')], + }, + { + code: `import '@internal/foo/src/FooPage'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/foo', 'src/FooPage')], + }, + { + code: `import '@internal/foo/src'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/foo', 'src')], + }, + { + code: `import '@internal/bar/OtherBarPage'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/bar', 'OtherBarPage')], + }, + { + code: `import '@internal/bar/dist'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/bar', 'dist')], + }, + { + code: `import '@internal/bar/dist/BarPage'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/bar', 'dist/BarPage')], + }, + { + code: `import '@internal/bar/src/BarPage'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/bar', 'src/BarPage')], + }, + { + code: `import '@internal/bar/src'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/bar', 'src')], + }, + ], +}); From 02f1316e57d709c7e8e458fa93828ef9ed1e96f2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 4 Feb 2023 13:09:13 +0100 Subject: [PATCH 145/423] changeset: added changesets for eslint plugin fixes that affect the published package Signed-off-by: Patrik Oldsberg --- .changeset/grumpy-fireants-drop.md | 5 +++++ .changeset/wicked-beers-walk.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/grumpy-fireants-drop.md create mode 100644 .changeset/wicked-beers-walk.md diff --git a/.changeset/grumpy-fireants-drop.md b/.changeset/grumpy-fireants-drop.md new file mode 100644 index 0000000000..92b08663f4 --- /dev/null +++ b/.changeset/grumpy-fireants-drop.md @@ -0,0 +1,5 @@ +--- +'@backstage/codemods': patch +--- + +Moved `commander` to being a regular dependency. diff --git a/.changeset/wicked-beers-walk.md b/.changeset/wicked-beers-walk.md new file mode 100644 index 0000000000..160a171eb1 --- /dev/null +++ b/.changeset/wicked-beers-walk.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Updated `packages/app/cypress/.eslintrc.json` to remove the unnecessary `import/no-extraneous-dependencies` rule. From ff63acf30a4bc94377b5c4f220deebe07af4d915 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 4 Feb 2023 13:12:16 +0100 Subject: [PATCH 146/423] repo-tools: make api extraction ignore packages without a role Signed-off-by: Patrik Oldsberg --- .changeset/rare-berries-give.md | 5 +++++ .../repo-tools/src/commands/api-reports/api-extractor.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/rare-berries-give.md diff --git a/.changeset/rare-berries-give.md b/.changeset/rare-berries-give.md new file mode 100644 index 0000000000..39e360bf48 --- /dev/null +++ b/.changeset/rare-berries-give.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': patch +--- + +Packages without a declared `backstage.role` are now ignored. diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index b037f40be6..39df70c21a 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -1107,7 +1107,7 @@ export async function categorizePackageDirs(packageDirs: any[]) { }); const role = pkgJson?.backstage?.role; if (!role) { - throw new Error(`No backstage.role in ${dir}/package.json`); + return; // Ignore packages without roles } if (role === 'cli') { cliPackageDirs.push(dir); From dec4896baa9182120671195fe1fc81008deacbac Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 4 Feb 2023 13:13:11 +0100 Subject: [PATCH 147/423] cli: add missing @backstage/eslint-plugin dependency Signed-off-by: Patrik Oldsberg --- packages/cli/package.json | 1 + yarn.lock | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 359f16adfa..2f5292e3a0 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -34,6 +34,7 @@ "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/eslint-plugin": "workspace:^", "@backstage/release-manifests": "workspace:^", "@backstage/types": "workspace:^", "@manypkg/get-packages": "^1.1.3", diff --git a/yarn.lock b/yarn.lock index 2d250e9913..069b1125a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3660,6 +3660,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/eslint-plugin": "workspace:^" "@backstage/release-manifests": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" @@ -4094,7 +4095,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/eslint-plugin@workspace:packages/eslint-plugin": +"@backstage/eslint-plugin@workspace:^, @backstage/eslint-plugin@workspace:packages/eslint-plugin": version: 0.0.0-use.local resolution: "@backstage/eslint-plugin@workspace:packages/eslint-plugin" dependencies: From baf6e4c96a90b54a52e8acc28e2dcaf706d63bd4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 4 Feb 2023 13:57:18 +0100 Subject: [PATCH 148/423] backend-test-utils: removed unnecessary @backstage/cli dependency Signed-off-by: Patrik Oldsberg --- .changeset/chilled-sheep-collect.md | 5 +++++ packages/backend-test-utils/package.json | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .changeset/chilled-sheep-collect.md diff --git a/.changeset/chilled-sheep-collect.md b/.changeset/chilled-sheep-collect.md new file mode 100644 index 0000000000..b944685e16 --- /dev/null +++ b/.changeset/chilled-sheep-collect.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Removed unnecessary `@backstage/cli` dependency. diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index a01dbaf0fa..d1f0a86d43 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -37,7 +37,6 @@ "@backstage/backend-app-api": "workspace:^", "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", - "@backstage/cli": "workspace:^", "@backstage/config": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/types": "workspace:^", From 489320214f68b13266b5a300e9994d9a39bca57f Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Sat, 4 Feb 2023 08:05:02 -0500 Subject: [PATCH 149/423] improve Vault plugin error messaging This seeks to address issue #16176 by improving the error messaging surfaced to the UI with the Vault plugin encounters non-successful HTTP responses from the Vault API. Signed-off-by: Mike Ball --- plugins/vault/src/api.test.ts | 22 +++++- plugins/vault/src/api.ts | 6 +- .../EntityVaultTable.test.tsx | 69 ++++++++++--------- .../EntityVaultTable/EntityVaultTable.tsx | 7 +- 4 files changed, 64 insertions(+), 40 deletions(-) diff --git a/plugins/vault/src/api.test.ts b/plugins/vault/src/api.test.ts index 4ce6f95c41..471cadc87e 100644 --- a/plugins/vault/src/api.test.ts +++ b/plugins/vault/src/api.test.ts @@ -50,8 +50,10 @@ describe('api', () => { const { path } = req.params; if (path === 'test/success') { return res(ctx.json(mockSecretsResult)); - } else if (path === 'test/error') { + } else if (path === 'test/empty') { return res(ctx.json({ items: [] })); + } else if (path === 'test/not-found') { + return res(ctx.status(404)); } return res(ctx.status(400)); }), @@ -72,7 +74,7 @@ describe('api', () => { it('should return empty secret list', async () => { setupHandlers(); const api = new VaultClient({ discoveryApi }); - expect(await api.listSecrets('test/error')).toEqual([]); + expect(await api.listSecrets('test/empty')).toEqual([]); }); it('should return all the secrets if no path defined', async () => { @@ -80,4 +82,20 @@ describe('api', () => { const api = new VaultClient({ discoveryApi }); expect(await api.listSecrets('')).toEqual(mockSecretsResult.items); }); + + it('should throw an error if the Vault API responds with an HTTP 404', async () => { + setupHandlers(); + const api = new VaultClient({ discoveryApi }); + await expect(api.listSecrets('test/not-found')).rejects.toThrow( + "No secrets found in path 'v1/secrets/test%2Fnot-found'", + ); + }); + + it('should throw an error if the Vault API responds with a non-successful HTTP status code', async () => { + setupHandlers(); + const api = new VaultClient({ discoveryApi }); + await expect(api.listSecrets('test/error')).rejects.toThrow( + 'Request failed with 400 Error', + ); + }); }); diff --git a/plugins/vault/src/api.ts b/plugins/vault/src/api.ts index bdd881e08c..84843c9176 100644 --- a/plugins/vault/src/api.ts +++ b/plugins/vault/src/api.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { DiscoveryApi, createApiRef } from '@backstage/core-plugin-api'; -import { NotFoundError } from '@backstage/errors'; +import { NotFoundError, ResponseError } from '@backstage/errors'; /** * @public @@ -75,9 +75,7 @@ export class VaultClient implements VaultApi { } else if (response.status === 404) { throw new NotFoundError(`No secrets found in path '${path}'`); } - throw new Error( - `Unexpected error while fetching secrets from path '${path}'`, - ); + throw await ResponseError.fromResponse(response); } async listSecrets(secretPath: string): Promise { diff --git a/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.test.tsx b/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.test.tsx index 82a90f23e1..27cc0ed91e 100644 --- a/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.test.tsx +++ b/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.test.tsx @@ -33,40 +33,28 @@ describe('EntityVaultTable', () => { let apis: TestApiRegistry; const mockBaseUrl = 'https://api-vault.com/api/vault'; const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl); - - const entityOk: ComponentEntity = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - metadata: { - name: 'test', - description: 'This is the description', - annotations: { - 'vault.io/secrets-path': 'test/success', + const entity = (secretPath: string) => { + return { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'test', + description: 'This is the description', + annotations: { + 'vault.io/secrets-path': secretPath, + }, }, - }, - spec: { - lifecycle: 'production', - owner: 'owner', - type: 'service', - }, + spec: { + lifecycle: 'production', + owner: 'owner', + type: 'service', + }, + } as ComponentEntity; }; - const entityNotOk: ComponentEntity = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - metadata: { - name: 'test', - description: 'This is the description', - annotations: { - 'vault.io/secrets-path': 'test/error', - }, - }, - spec: { - lifecycle: 'production', - owner: 'owner', - type: 'service', - }, - }; + const entityOk = entity('test/success'); + const entityEmpty = entity('test/empty'); + const entityNotOk = entity('test/error'); const mockSecretsResult: { items: VaultSecret[] } = { items: [ @@ -91,7 +79,7 @@ describe('EntityVaultTable', () => { const { path } = req.params; if (path === 'test/success') { return res(ctx.json(mockSecretsResult)); - } else if (path === 'test/error') { + } else if (path === 'test/empty') { return res(ctx.json([])); } return res(ctx.status(400)); @@ -122,10 +110,25 @@ describe('EntityVaultTable', () => { setupHandlers(); const rendered = await renderInTestApp( - + , ); expect(rendered.getByText(/No secrets found/)).toBeInTheDocument(); }); + + it('should surface an appropriate error when the Vault API responds unsuccessfully', async () => { + setupHandlers(); + const rendered = await renderInTestApp( + + + , + ); + + expect( + rendered.getByText( + /Unexpected error while fetching secrets from path \'test\/error\'\: Request failed with 400 Error/, + ), + ).toBeInTheDocument(); + }); }); diff --git a/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.tsx b/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.tsx index efc345b07f..9191d54b0b 100644 --- a/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.tsx +++ b/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.tsx @@ -81,7 +81,12 @@ export const EntityVaultTable = ({ entity }: { entity: Entity }) => { }); if (error) { - return {error.message}; + return ( + + Unexpected error while fetching secrets from path '{secretPath}':{' '} + {error.message} + + ); } return ( From fd7a77b9c46a7f04f2c9f523a083f297dbac8985 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Sat, 4 Feb 2023 08:08:59 -0500 Subject: [PATCH 150/423] add changeset regarding Vault error improvements Signed-off-by: Mike Ball --- .changeset/mean-squids-kneel.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/mean-squids-kneel.md diff --git a/.changeset/mean-squids-kneel.md b/.changeset/mean-squids-kneel.md new file mode 100644 index 0000000000..41a1bd4086 --- /dev/null +++ b/.changeset/mean-squids-kneel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-vault': patch +--- + +Surface additional context and details to the Backstage UI when the Vault plugin encounters non-successful HTTP responses from the Vault API. From 9ec79c9737a1763c36cab3df3628c77c96f7536a Mon Sep 17 00:00:00 2001 From: albertojuanL Date: Sat, 4 Feb 2023 14:13:24 +0100 Subject: [PATCH 151/423] Use title instead of name when it exists, to sort the list of entities by default Signed-off-by: albertojuanL --- packages/catalog-client/src/CatalogClient.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index af4262b842..a110cfacc7 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -20,6 +20,7 @@ import { parseEntityRef, stringifyEntityRef, stringifyLocationRef, + DEFAULT_NAMESPACE, } from '@backstage/catalog-model'; import { ResponseError } from '@backstage/errors'; import crossFetch from 'cross-fetch'; @@ -176,8 +177,8 @@ export class CatalogClient implements CatalogApi { return 0; } - const aRef = stringifyEntityRef(a); - const bRef = stringifyEntityRef(b); + const aRef = this.stringifySortingEntityRef(a); + const bRef = this.stringifySortingEntityRef(b); if (aRef < bRef) { return -1; } @@ -504,4 +505,14 @@ export class CatalogClient implements CatalogApi { return await response.json(); } + + private stringifySortingEntityRef(ref: Entity): string { + const kind = ref.kind; + const namespace = ref.metadata.namespace ?? DEFAULT_NAMESPACE; + const name = ref.metadata.title || ref.metadata.name; + + return `${kind.toLocaleLowerCase('en-US')}:${namespace.toLocaleLowerCase( + 'en-US', + )}/${name.toLocaleLowerCase('en-US')}`; + } } From d7f55f6bd22633a0718e236ee91c707cc786ec72 Mon Sep 17 00:00:00 2001 From: albertojuanL Date: Sat, 4 Feb 2023 14:19:58 +0100 Subject: [PATCH 152/423] Updated Changeset Signed-off-by: albertojuanL --- .changeset/brown-kings-wait.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/brown-kings-wait.md diff --git a/.changeset/brown-kings-wait.md b/.changeset/brown-kings-wait.md new file mode 100644 index 0000000000..01ff1ae5eb --- /dev/null +++ b/.changeset/brown-kings-wait.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-client': patch +--- + +The list of entities takes into account the title when its different from the name to sort the entities. From a6e109ee761d3a7e30fc795f7222621a8c1ce212 Mon Sep 17 00:00:00 2001 From: albertojuanL Date: Sat, 4 Feb 2023 14:57:50 +0100 Subject: [PATCH 153/423] remove unused import Signed-off-by: albertojuanL --- packages/catalog-client/src/CatalogClient.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index a110cfacc7..1d33b2f55d 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -18,7 +18,6 @@ import { Entity, CompoundEntityRef, parseEntityRef, - stringifyEntityRef, stringifyLocationRef, DEFAULT_NAMESPACE, } from '@backstage/catalog-model'; From f108d111410f45b9e44087fca40e5988346f7631 Mon Sep 17 00:00:00 2001 From: albertojuanL Date: Sat, 4 Feb 2023 16:44:24 +0100 Subject: [PATCH 154/423] Move default sorting logic to the UI Signed-off-by: albertojuanL --- packages/catalog-client/src/CatalogClient.ts | 16 ++------- .../components/CatalogTable/CatalogTable.tsx | 36 ++++++++++++++++++- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 1d33b2f55d..d2d4d64d75 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -19,7 +19,7 @@ import { CompoundEntityRef, parseEntityRef, stringifyLocationRef, - DEFAULT_NAMESPACE, + stringifyEntityRef, } from '@backstage/catalog-model'; import { ResponseError } from '@backstage/errors'; import crossFetch from 'cross-fetch'; @@ -176,8 +176,8 @@ export class CatalogClient implements CatalogApi { return 0; } - const aRef = this.stringifySortingEntityRef(a); - const bRef = this.stringifySortingEntityRef(b); + const aRef = stringifyEntityRef(a); + const bRef = stringifyEntityRef(b); if (aRef < bRef) { return -1; } @@ -504,14 +504,4 @@ export class CatalogClient implements CatalogApi { return await response.json(); } - - private stringifySortingEntityRef(ref: Entity): string { - const kind = ref.kind; - const namespace = ref.metadata.namespace ?? DEFAULT_NAMESPACE; - const name = ref.metadata.title || ref.metadata.name; - - return `${kind.toLocaleLowerCase('en-US')}:${namespace.toLocaleLowerCase( - 'en-US', - )}/${name.toLocaleLowerCase('en-US')}`; - } } diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index 935e002375..e6f9d1458e 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -16,6 +16,8 @@ import { ANNOTATION_EDIT_URL, ANNOTATION_VIEW_URL, + DEFAULT_NAMESPACE, + Entity, RELATION_OWNED_BY, RELATION_PART_OF, } from '@backstage/catalog-model'; @@ -62,6 +64,38 @@ const YellowStar = withStyles({ }, })(Star); +const stringifySortingEntityRef = (ref: Entity): string => { + const kind = ref.kind; + const namespace = ref.metadata.namespace ?? DEFAULT_NAMESPACE; + const name = ref.metadata.title || ref.metadata.name; + + return `${kind.toLocaleLowerCase('en-US')}:${namespace.toLocaleLowerCase( + 'en-US', + )}/${name.toLocaleLowerCase('en-US')}`; +}; + +const refCompare = (a: Entity, b: Entity) => { + // in case field filtering is used, these fields might not be part of the response + if ( + a.metadata?.name === undefined || + a.kind === undefined || + b.metadata?.name === undefined || + b.kind === undefined + ) { + return 0; + } + + const aRef = stringifySortingEntityRef(a); + const bRef = stringifySortingEntityRef(b); + if (aRef < bRef) { + return -1; + } + if (aRef > bRef) { + return 1; + } + return 0; +}; + /** @public */ export const CatalogTable = (props: CatalogTableProps) => { const { columns, actions, tableOptions, subtitle, emptyContent } = props; @@ -177,7 +211,7 @@ export const CatalogTable = (props: CatalogTableProps) => { }, ]; - const rows = entities.map(entity => { + const rows = entities.sort(refCompare).map(entity => { const partOfSystemRelations = getEntityRelations(entity, RELATION_PART_OF, { kind: 'system', }); From cee0a7ec16b1d245ca8ae211f44d3947dbe97cf6 Mon Sep 17 00:00:00 2001 From: albertojuanL Date: Sat, 4 Feb 2023 16:52:08 +0100 Subject: [PATCH 155/423] Revert file dummy change Signed-off-by: albertojuanL --- packages/catalog-client/src/CatalogClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index d2d4d64d75..af4262b842 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -18,8 +18,8 @@ import { Entity, CompoundEntityRef, parseEntityRef, - stringifyLocationRef, stringifyEntityRef, + stringifyLocationRef, } from '@backstage/catalog-model'; import { ResponseError } from '@backstage/errors'; import crossFetch from 'cross-fetch'; From 16acf34bf2b7c14151c91afb96faf4428704e530 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Sat, 4 Feb 2023 13:21:37 -0500 Subject: [PATCH 156/423] improve Vault plugin catalog entry language * correct grammar * clarify that the plugin deals with HashiCorp Vault (and not another Vault, such as Ansible Vault) Signed-off-by: Mike Ball --- microsite/data/plugins/vault.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/data/plugins/vault.yaml b/microsite/data/plugins/vault.yaml index 822f5dcc90..bb8f799ba7 100644 --- a/microsite/data/plugins/vault.yaml +++ b/microsite/data/plugins/vault.yaml @@ -3,7 +3,7 @@ title: Vault author: Spread Group authorUrl: https://github.com/ivangonzalezacuna category: Vault -description: Visualize a list secrets stored in your vault instance. +description: Visualize a list of the secrets stored in your HashiCorp Vault instance. documentation: https://github.com/backstage/backstage/tree/master/plugins/vault iconUrl: img/vault.png npmPackageName: '@backstage/plugin-vault' From 9d9cdea1173223a6630e96d93dbc67fdf83bd119 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 30 Jan 2023 15:54:30 +0100 Subject: [PATCH 157/423] create backend-dev-utils with cli ipc client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Patrik Oldsberg --- .changeset/green-adults-retire.md | 5 + packages/backend-dev-utils/.eslintrc.js | 1 + packages/backend-dev-utils/README.md | 5 + packages/backend-dev-utils/package.json | 36 ++++++ packages/backend-dev-utils/src/index.ts | 21 ++++ packages/backend-dev-utils/src/ipcClient.ts | 120 +++++++++++++++++++ packages/backend-dev-utils/src/setupTests.ts | 16 +++ yarn.lock | 8 ++ 8 files changed, 212 insertions(+) create mode 100644 .changeset/green-adults-retire.md create mode 100644 packages/backend-dev-utils/.eslintrc.js create mode 100644 packages/backend-dev-utils/README.md create mode 100644 packages/backend-dev-utils/package.json create mode 100644 packages/backend-dev-utils/src/index.ts create mode 100644 packages/backend-dev-utils/src/ipcClient.ts create mode 100644 packages/backend-dev-utils/src/setupTests.ts diff --git a/.changeset/green-adults-retire.md b/.changeset/green-adults-retire.md new file mode 100644 index 0000000000..c13e8d664f --- /dev/null +++ b/.changeset/green-adults-retire.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-dev-utils': minor +--- + +Introduced a new package for backend development utilities. Similar to how `@backstage/dev-utils` is used in the frontend. diff --git a/packages/backend-dev-utils/.eslintrc.js b/packages/backend-dev-utils/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/backend-dev-utils/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/backend-dev-utils/README.md b/packages/backend-dev-utils/README.md new file mode 100644 index 0000000000..8acce94cf0 --- /dev/null +++ b/packages/backend-dev-utils/README.md @@ -0,0 +1,5 @@ +# backend-dev-utils + +Welcome to the backend-dev-utils package! + +_This package is experimental._ diff --git a/packages/backend-dev-utils/package.json b/packages/backend-dev-utils/package.json new file mode 100644 index 0000000000..735185e37f --- /dev/null +++ b/packages/backend-dev-utils/package.json @@ -0,0 +1,36 @@ +{ + "name": "@backstage/backend-dev-utils", + "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": "node-library" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/backend-dev-utils" + }, + "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" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + }, + "files": [ + "dist" + ] +} diff --git a/packages/backend-dev-utils/src/index.ts b/packages/backend-dev-utils/src/index.ts new file mode 100644 index 0000000000..bddecad73d --- /dev/null +++ b/packages/backend-dev-utils/src/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2023 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. + */ + +/** + * Local development helpers for backend. + * + * @packageDocumentation + */ diff --git a/packages/backend-dev-utils/src/ipcClient.ts b/packages/backend-dev-utils/src/ipcClient.ts new file mode 100644 index 0000000000..d3fa184a3f --- /dev/null +++ b/packages/backend-dev-utils/src/ipcClient.ts @@ -0,0 +1,120 @@ +/* + * Copyright 2023 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. + */ + +type SendMessage = Exclude; + +interface Request { + id: number; + method: string; + body: unknown; + type: string; +} + +type Response = + | { + type: string; + id: number; + body: unknown; + } + | { + type: string; + id: number; + error: Error; + }; + +const requestType = '@backstage/cli/channel/request'; +const responseType = '@backstage/cli/channel/response'; + +/** + * The client side of an IPC communication channel. + * + * @internal + */ +export class BackstageIpcClient { + #messageId = 0; + #sendMessage: SendMessage; + + /** + * Creates a new client if we're in a child process with IPC and BACKSTAGE_CLI_CHANNEL is set. + */ + static create(): BackstageIpcClient | undefined { + const sendMessage = process.send?.bind(process); + return sendMessage && process.env.BACKSTAGE_CLI_CHANNEL + ? new BackstageIpcClient(sendMessage) + : undefined; + } + + constructor(sendMessage: SendMessage) { + this.#sendMessage = sendMessage; + } + + /** + * Send a request to the parent process and wait for a response. + */ + async request( + method: string, + body: TRequestBody, + ): Promise { + return new Promise((resolve, reject) => { + const id = this.#messageId++; + + const request: Request = { + type: requestType, + id, + method, + body, + }; + + this.#sendMessage(request, (e: Error) => { + if (e) { + reject(e); + return; + } + + const timeout = setTimeout(() => { + reject(new Error('IPC request timed out')); + }, 1000); + timeout.unref(); + + const messageHandler = (response: Response) => { + if (response?.type !== responseType) { + return; + } + if (response.id !== id) { + return; + } + + if ('error' in response) { + const error = new Error(response.error.message); + if (response.error.name) { + error.name = response.error.name; + } + reject(error); + } else { + resolve(response.body as TResponseBody); + } + + clearTimeout(timeout); + process.removeListener('message', messageHandler); + }; + + process.addListener('message', messageHandler as () => void); + }); + }); + } +} + +export const ipcClient = BackstageIpcClient.create(); diff --git a/packages/backend-dev-utils/src/setupTests.ts b/packages/backend-dev-utils/src/setupTests.ts new file mode 100644 index 0000000000..4b9026cde5 --- /dev/null +++ b/packages/backend-dev-utils/src/setupTests.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 3d809a40c8..ecd381c8f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3519,6 +3519,14 @@ __metadata: languageName: unknown linkType: soft +"@backstage/backend-dev-utils@workspace:packages/backend-dev-utils": + version: 0.0.0-use.local + resolution: "@backstage/backend-dev-utils@workspace:packages/backend-dev-utils" + dependencies: + "@backstage/cli": "workspace:^" + languageName: unknown + linkType: soft + "@backstage/backend-plugin-api@workspace:^, @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" From a70806c3b09b851bc5785cc32700cb5b36f58f39 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 31 Jan 2023 12:08:55 +0100 Subject: [PATCH 158/423] backend-dev-utils: add DevDataStore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: blam Signed-off-by: Patrik Oldsberg --- packages/backend-dev-utils/api-report.md | 20 +++ .../src/DevDataStore.test.ts | 121 ++++++++++++++++++ .../backend-dev-utils/src/DevDataStore.ts | 99 ++++++++++++++ packages/backend-dev-utils/src/index.ts | 2 + 4 files changed, 242 insertions(+) create mode 100644 packages/backend-dev-utils/api-report.md create mode 100644 packages/backend-dev-utils/src/DevDataStore.test.ts create mode 100644 packages/backend-dev-utils/src/DevDataStore.ts diff --git a/packages/backend-dev-utils/api-report.md b/packages/backend-dev-utils/api-report.md new file mode 100644 index 0000000000..216311ccd8 --- /dev/null +++ b/packages/backend-dev-utils/api-report.md @@ -0,0 +1,20 @@ +## API Report File for "@backstage/backend-dev-utils" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +// @public +export class DevDataStore { + static get(): DevDataStore | undefined; + load(key: string): Promise<{ + loaded: boolean; + data: T; + }>; + save( + key: string, + data: T, + ): Promise<{ + saved: boolean; + }>; +} +``` diff --git a/packages/backend-dev-utils/src/DevDataStore.test.ts b/packages/backend-dev-utils/src/DevDataStore.test.ts new file mode 100644 index 0000000000..2bb3f221ae --- /dev/null +++ b/packages/backend-dev-utils/src/DevDataStore.test.ts @@ -0,0 +1,121 @@ +/* + * Copyright 2023 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 { Serializable, spawn } from 'child_process'; +import { DevDataStore } from './DevDataStore'; +import { BackstageIpcClient } from './ipcClient'; + +function applyIpcTransform(value: Serializable): Promise { + const child = spawn( + 'node', + [ + '--eval', + ` + const listener = msg => { + process.send(msg); + process.removeListener('message', listener); + } + process.addListener('message', listener); + `, + ], + { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'], + serialization: 'advanced', + }, + ); + + return new Promise(resolve => { + child.addListener('message', resolve); + child.send(value); + }); +} + +class MockIpcClient implements Pick { + #data = new Map(); + + async request(method: string, body: any): Promise { + if (method === 'DevDataStore.save') { + this.#data.set(body.key, body.data); + return { saved: true }; + } else if (method === 'DevDataStore.load') { + if (!this.#data.has(body.key)) { + return { loaded: false, data: undefined }; + } + const data = this.#data.get(body.key)!; + return { loaded: true, data: await applyIpcTransform(data) }; + } + throw new Error('Unknown message'); + } +} + +describe('DevDataStore', () => { + it('should save and load data', async () => { + const store = DevDataStore.forTest(new MockIpcClient()); + + await expect(store.save('test', { foo: 'bar' })).resolves.toEqual({ + saved: true, + }); + await expect(store.load('test')).resolves.toEqual({ + loaded: true, + data: { foo: 'bar' }, + }); + }); + + it('should save and load buffers', async () => { + const store = DevDataStore.forTest(new MockIpcClient()); + + await expect( + store.save('test', Buffer.from('abc', 'ascii')), + ).resolves.toEqual({ + saved: true, + }); + await expect(store.load('test')).resolves.toEqual({ + loaded: true, + data: Buffer.from('abc', 'ascii'), + }); + }); + + it('should save and load array buffers', async () => { + const store = DevDataStore.forTest(new MockIpcClient()); + + await expect( + store.save('test', new Uint8Array(Buffer.from('abc', 'ascii'))), + ).resolves.toEqual({ + saved: true, + }); + await expect(store.load('test')).resolves.toEqual({ + loaded: true, + data: new Uint8Array(Buffer.from('abc', 'ascii')), + }); + }); + + it('should save and load buffers nested in objects', async () => { + const store = DevDataStore.forTest(new MockIpcClient()); + + await expect( + store.save('test', { + x: Buffer.from('x', 'ascii'), + y: [Buffer.from('y', 'ascii')], + }), + ).resolves.toEqual({ + saved: true, + }); + await expect(store.load('test')).resolves.toEqual({ + loaded: true, + data: { x: Buffer.from('x', 'ascii'), y: [Buffer.from('y', 'ascii')] }, + }); + }); +}); diff --git a/packages/backend-dev-utils/src/DevDataStore.ts b/packages/backend-dev-utils/src/DevDataStore.ts new file mode 100644 index 0000000000..4069ab1bdb --- /dev/null +++ b/packages/backend-dev-utils/src/DevDataStore.ts @@ -0,0 +1,99 @@ +/* + * Copyright 2023 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 { BackstageIpcClient, ipcClient } from './ipcClient'; + +interface SaveRequest { + key: string; + data: unknown; +} + +interface SaveResponse { + saved: boolean; +} + +interface LoadRequest { + key: string; +} + +interface LoadResponse { + loaded: boolean; + data: unknown; +} + +/** + * A data store that can be used to store temporary data during development. + * + * @public + */ +export class DevDataStore { + static #instance?: DevDataStore; + + /** + * Tries to acquire a DevDataStore instance. This will only succeed when the backend + * process is being run through the `@backstage/cli` in development mode. + * + * @returns A DevDataStore instance, or undefined if not available. + */ + static get(): DevDataStore | undefined { + if (ipcClient) { + if (!this.#instance) { + this.#instance = new DevDataStore(ipcClient); + } + return this.#instance; + } + return undefined; + } + + /** @internal */ + static forTest(client: Pick): DevDataStore { + return new DevDataStore(client as BackstageIpcClient); + } + + #client: BackstageIpcClient; + + private constructor(client: BackstageIpcClient) { + this.#client = client; + } + + /** + * Save data to the data store. + * + * @param key - The key used to identify the data. + * @param data - The data to save. The data will be serialized using advanced IPC serialization. + * @returns A promise that resolves to a result object that indicates whether the data was saved. + */ + async save(key: string, data: T): Promise<{ saved: boolean }> { + return this.#client.request( + 'DevDataStore.save', + { key, data }, + ); + } + + /** + * Loads data from the data store. + * + * @param key - The key used to identify the data. + * @returns A promise that resolves to a result object that indicates whether the data was loaded, as well as the data. + */ + async load(key: string): Promise<{ loaded: boolean; data: T }> { + const result = await this.#client.request( + 'DevDataStore.load', + { key }, + ); + return result as { loaded: boolean; data: T }; + } +} diff --git a/packages/backend-dev-utils/src/index.ts b/packages/backend-dev-utils/src/index.ts index bddecad73d..9b707db029 100644 --- a/packages/backend-dev-utils/src/index.ts +++ b/packages/backend-dev-utils/src/index.ts @@ -19,3 +19,5 @@ * * @packageDocumentation */ + +export { DevDataStore } from './DevDataStore'; From 90616df9a8784703dabc093337343ceab5d473d0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 31 Jan 2023 16:28:40 +0100 Subject: [PATCH 159/423] cli: add experimental backend start Co-authored-by: blam Signed-off-by: Patrik Oldsberg --- .changeset/weak-radios-sing.md | 5 + packages/cli/package.json | 3 + .../cli/src/commands/start/startBackend.ts | 34 +++-- .../cli/src/lib/experimental/ChannelServer.ts | 102 +++++++++++++ .../src/lib/experimental/ServerDataStore.ts | 78 ++++++++++ .../experimental/startBackendExperimental.ts | 138 ++++++++++++++++++ packages/cli/src/types.d.ts | 2 + yarn.lock | 43 +++++- 8 files changed, 392 insertions(+), 13 deletions(-) create mode 100644 .changeset/weak-radios-sing.md create mode 100644 packages/cli/src/lib/experimental/ChannelServer.ts create mode 100644 packages/cli/src/lib/experimental/ServerDataStore.ts create mode 100644 packages/cli/src/lib/experimental/startBackendExperimental.ts diff --git a/.changeset/weak-radios-sing.md b/.changeset/weak-radios-sing.md new file mode 100644 index 0000000000..dff287b565 --- /dev/null +++ b/.changeset/weak-radios-sing.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Added an experimental mode for the `package start` command for backend packages. Enabled by setting `EXPERIMENTAL_BACKEND_START`. diff --git a/packages/cli/package.json b/packages/cli/package.json index 909ac8460c..e6b9b7a97e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -36,6 +36,7 @@ "@backstage/errors": "workspace:^", "@backstage/release-manifests": "workspace:^", "@backstage/types": "workspace:^", + "@esbuild-kit/cjs-loader": "^2.4.1", "@manypkg/get-packages": "^1.1.3", "@octokit/request": "^6.0.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", @@ -65,6 +66,7 @@ "chalk": "^4.0.0", "chokidar": "^3.3.1", "commander": "^9.1.0", + "cross-spawn": "^7.0.3", "css-loader": "^6.5.1", "diff": "^5.0.0", "esbuild": "^0.17.0", @@ -136,6 +138,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@backstage/theme": "workspace:^", + "@types/cross-spawn": "^6.0.2", "@types/diff": "^5.0.0", "@types/express": "^4.17.6", "@types/fs-extra": "^9.0.1", diff --git a/packages/cli/src/commands/start/startBackend.ts b/packages/cli/src/commands/start/startBackend.ts index 61ada7a291..3e6a13be96 100644 --- a/packages/cli/src/commands/start/startBackend.ts +++ b/packages/cli/src/commands/start/startBackend.ts @@ -17,6 +17,7 @@ import fs from 'fs-extra'; import { paths } from '../../lib/paths'; import { serveBackend } from '../../lib/bundler'; +import { startBackendExperimental } from '../../lib/experimental/startBackendExperimental'; interface StartBackendOptions { checksEnabled: boolean; @@ -25,17 +26,28 @@ interface StartBackendOptions { } export async function startBackend(options: StartBackendOptions) { - // Cleaning dist/ before we start the dev process helps work around an issue - // where we end up with the entrypoint executing multiple times, causing - // a port bind conflict among other things. - await fs.remove(paths.resolveTarget('dist')); + if (process.env.EXPERIMENTAL_BACKEND_START) { + const waitForExit = await startBackendExperimental({ + entry: 'src/index', + checksEnabled: false, // not supported + inspectEnabled: options.inspectEnabled, + inspectBrkEnabled: options.inspectBrkEnabled, + }); - const waitForExit = await serveBackend({ - entry: 'src/index', - checksEnabled: options.checksEnabled, - inspectEnabled: options.inspectEnabled, - inspectBrkEnabled: options.inspectBrkEnabled, - }); + await waitForExit(); + } else { + // Cleaning dist/ before we start the dev process helps work around an issue + // where we end up with the entrypoint executing multiple times, causing + // a port bind conflict among other things. + await fs.remove(paths.resolveTarget('dist')); - await waitForExit(); + const waitForExit = await serveBackend({ + entry: 'src/index', + checksEnabled: options.checksEnabled, + inspectEnabled: options.inspectEnabled, + inspectBrkEnabled: options.inspectBrkEnabled, + }); + + await waitForExit(); + } } diff --git a/packages/cli/src/lib/experimental/ChannelServer.ts b/packages/cli/src/lib/experimental/ChannelServer.ts new file mode 100644 index 0000000000..db949f95b8 --- /dev/null +++ b/packages/cli/src/lib/experimental/ChannelServer.ts @@ -0,0 +1,102 @@ +/* + * Copyright 2023 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 { serializeError } from '@backstage/errors'; +import { ChildProcess } from 'child_process'; + +interface RequestMeta { + generation: number; +} + +type MethodHandler = ( + req: TRequest, + meta: RequestMeta, +) => Promise; + +interface Request { + id: number; + method: string; + body: unknown; + type: string; +} + +const requestType = '@backstage/cli/channel/request'; +const responseType = '@backstage/cli/channel/response'; + +export class ChannelServer { + #generation = 1; + #methods = new Map>(); + + addChild(child: ChildProcess) { + const generation = this.#generation++; + const sendMessage = child.send?.bind(child); + if (!sendMessage) { + return; + } + + const messageListener = (request: Request) => { + if (request.type !== requestType) { + return; + } + + const handler = this.#methods.get(request.method); + if (!handler) { + sendMessage({ + type: responseType, + id: request.id, + error: { + name: 'NotFoundError', + message: `No handler registered for method ${request.method}`, + }, + }); + return; + } + + Promise.resolve() + .then(() => handler(request.body, { generation })) + .then(response => + sendMessage({ + type: responseType, + id: request.id, + body: response, + }), + ) + .catch(error => + sendMessage({ + type: responseType, + id: request.id, + error: serializeError(error), + }), + ); + }; + + child.addListener('message', messageListener as (req: unknown) => void); + + child.addListener('exit', () => { + child.removeListener('message', messageListener); + }); + } + + registerMethod( + method: string, + handler: MethodHandler, + ) { + if (this.#methods.has(method)) { + throw new Error(`A handler is already registered for method ${method}`); + } + this.#methods.set(method, handler); + } +} diff --git a/packages/cli/src/lib/experimental/ServerDataStore.ts b/packages/cli/src/lib/experimental/ServerDataStore.ts new file mode 100644 index 0000000000..29ac331de5 --- /dev/null +++ b/packages/cli/src/lib/experimental/ServerDataStore.ts @@ -0,0 +1,78 @@ +/* + * Copyright 2023 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 { ChannelServer } from './ChannelServer'; + +interface StorageItem { + generation: number; + data: unknown; +} + +interface SaveRequest { + key: string; + data: unknown; +} + +interface SaveResponse { + saved: boolean; +} + +interface LoadRequest { + key: string; +} + +interface LoadResponse { + loaded: boolean; + data: unknown; +} + +export class ServerDataStore { + static bind(server: ChannelServer): void { + const store = new Map(); + + server.registerMethod( + 'DevDataStore.save', + async (request, { generation }) => { + const { key, data } = request; + if (!key) { + throw new Error('Key is required in DevDataStore.save'); + } + + const item = store.get(key); + + if (!item) { + store.set(key, { generation, data }); + return { saved: true }; + } + + if (item.generation > generation) { + return { saved: false }; + } + + store.set(key, { generation, data }); + return { saved: true }; + }, + ); + + server.registerMethod( + 'DevDataStore.load', + async request => { + const item = store.get(request.key); + return { loaded: Boolean(item), data: item?.data }; + }, + ); + } +} diff --git a/packages/cli/src/lib/experimental/startBackendExperimental.ts b/packages/cli/src/lib/experimental/startBackendExperimental.ts new file mode 100644 index 0000000000..94bf066925 --- /dev/null +++ b/packages/cli/src/lib/experimental/startBackendExperimental.ts @@ -0,0 +1,138 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BackendServeOptions } from '../bundler/types'; +import type { ChildProcess } from 'child_process'; +import { fileURLToPath } from 'url'; +import { isAbsolute as isAbsolutePath } from 'path'; +import { FSWatcher, watch } from 'chokidar'; +import { ChannelServer } from './ChannelServer'; +import { ServerDataStore } from './ServerDataStore'; +import debounce from 'lodash/debounce'; +import spawn from 'cross-spawn'; +import { paths } from '../paths'; + +const loaderArgs = ['--require', require.resolve('@esbuild-kit/cjs-loader')]; + +export async function startBackendExperimental(options: BackendServeOptions) { + const envEnv = process.env as { NODE_ENV: string }; + if (!envEnv.NODE_ENV) { + envEnv.NODE_ENV = 'development'; + } + + // Set up the parent IPC server and bind the available services + const server = new ChannelServer(); + ServerDataStore.bind(server); + + let exiting = false; + let child: ChildProcess | undefined; + let watcher: FSWatcher | undefined = undefined; + let shutdownPromise: Promise | undefined = undefined; + + const restart = debounce(async () => { + // If a re-trigger happens during an existing shutdown, we just ignore it + if (shutdownPromise) { + return; + } + + if (child && !child.killed && child.exitCode === null) { + // We always wait for the existing process to exit, to make sure we don't get IPC conflicts + shutdownPromise = new Promise(resolve => child!.once('exit', resolve)); + child.kill(); + await shutdownPromise; + shutdownPromise = undefined; + } + + // We've received a shutdown signal + if (exiting) { + return; + } + + const optionArgs = new Array(); + if (options.inspectEnabled) { + optionArgs.push('--inspect'); + } else if (options.inspectBrkEnabled) { + optionArgs.push('--inspect-brk'); + } + + const userArgs = process.argv + .slice(['node', 'backstage-cli', 'package', 'start'].length) + .filter(arg => !optionArgs.includes(arg)); + + child = spawn( + process.execPath, + [...loaderArgs, ...optionArgs, options.entry, ...userArgs], + { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'], + env: { + ...process.env, + BACKSTAGE_CLI_CHANNEL: '1', + ESBK_TSCONFIG_PATH: paths.resolveTargetRoot('tsconfig.json'), + }, + serialization: 'advanced', + }, + ); + + server.addChild(child); + + // This captures messages sent by @esbuild-kit/cjs-loader + child.on('message', (data: { type?: string } | null) => { + if (typeof data === 'object' && data?.type === 'dependency') { + let path = (data as { path: string }).path; + if (path.startsWith('file:')) { + path = fileURLToPath(path); + } + + if (isAbsolutePath(path)) { + watcher?.add(path); + } + } + }); + }, 100); + + restart(); + + watcher = watch([paths.targetDir], { + cwd: process.cwd(), + ignored: ['**/.*/**', '**/node_modules/**'], + ignoreInitial: true, + ignorePermissionErrors: true, + }).on('all', restart); + + // Trigger restart on hitting enter in the terminal + process.stdin.on('data', restart); + + const exitPromise = new Promise(resolveExitPromise => { + async function handleSignal(signal: NodeJS.Signals) { + exiting = true; + + // Forward signals to child and wait for it to exit if still running + if (child && child.exitCode === null) { + await new Promise(resolve => { + child!.on('close', resolve); + child!.kill(signal); + }); + } + + resolveExitPromise(); + } + + process.once('SIGINT', handleSignal); + process.once('SIGTERM', handleSignal); + }); + + return () => exitPromise; +} diff --git a/packages/cli/src/types.d.ts b/packages/cli/src/types.d.ts index fedbe61f02..1222b2b4b8 100644 --- a/packages/cli/src/types.d.ts +++ b/packages/cli/src/types.d.ts @@ -258,3 +258,5 @@ declare module 'webpack-node-externals' { } } } + +declare module '@esbuild-kit/cjs-loader' {} diff --git a/yarn.lock b/yarn.lock index ecd381c8f8..7143443674 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3672,6 +3672,7 @@ __metadata: "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@backstage/types": "workspace:^" + "@esbuild-kit/cjs-loader": ^2.4.1 "@manypkg/get-packages": ^1.1.3 "@octokit/request": ^6.0.0 "@pmmmwh/react-refresh-webpack-plugin": ^0.5.7 @@ -3690,6 +3691,7 @@ __metadata: "@swc/core": ^1.3.9 "@swc/helpers": ^0.4.7 "@swc/jest": ^0.2.22 + "@types/cross-spawn": ^6.0.2 "@types/diff": ^5.0.0 "@types/express": ^4.17.6 "@types/fs-extra": ^9.0.1 @@ -3717,6 +3719,7 @@ __metadata: chalk: ^4.0.0 chokidar: ^3.3.1 commander: ^9.1.0 + cross-spawn: ^7.0.3 css-loader: ^6.5.1 del: ^6.0.0 diff: ^5.0.0 @@ -9196,6 +9199,26 @@ __metadata: languageName: node linkType: hard +"@esbuild-kit/cjs-loader@npm:^2.4.1": + version: 2.4.1 + resolution: "@esbuild-kit/cjs-loader@npm:2.4.1" + dependencies: + "@esbuild-kit/core-utils": ^3.0.0 + get-tsconfig: ^4.2.0 + checksum: a516065907be0ead76ac2199ccb08ff92659ba5e2edb4bb8772b6a63afe4faed7eb45a3b4d87266a68c7c135c3dba971cd087bc6f16c382356e835c7dd3440f5 + languageName: node + linkType: hard + +"@esbuild-kit/core-utils@npm:^3.0.0": + version: 3.0.0 + resolution: "@esbuild-kit/core-utils@npm:3.0.0" + dependencies: + esbuild: ~0.15.10 + source-map-support: ^0.5.21 + checksum: 0e89ec718e2211bf95c48a8085aaef88e8e416f42abd1c62d488d5458eecd3fbc144179a0c5570ad36fa7e2d3bbc411f8d3fb28802c37ced2154dc2c6ded9dfe + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.17.5": version: 0.17.5 resolution: "@esbuild/android-arm64@npm:0.17.5" @@ -13912,6 +13935,15 @@ __metadata: languageName: node linkType: hard +"@types/cross-spawn@npm:^6.0.2": + version: 6.0.2 + resolution: "@types/cross-spawn@npm:6.0.2" + dependencies: + "@types/node": "*" + checksum: fa9edd32178878cab3ea8d6d0260639e0fe4860ddb3887b8de53d6e8036e154fc5f313c653f690975aa25025aea8beb83fb0870b931bf8d9202c3ac530a24c9d + languageName: node + linkType: hard + "@types/d3-color@npm:*": version: 3.0.2 resolution: "@types/d3-color@npm:3.0.2" @@ -21335,7 +21367,7 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.15.6": +"esbuild@npm:^0.15.6, esbuild@npm:~0.15.10": version: 0.15.18 resolution: "esbuild@npm:0.15.18" dependencies: @@ -23493,6 +23525,13 @@ __metadata: languageName: node linkType: hard +"get-tsconfig@npm:^4.2.0": + version: 4.3.0 + resolution: "get-tsconfig@npm:4.3.0" + checksum: 2597aab99aa3a24db209e192a3e5874ac47fc5abc71703ee26346e0c5816cb346ca09fc813c739db5862d3a2905d89aeca1b0cbc46c2b272398d672309aaf414 + languageName: node + linkType: hard + "getopts@npm:2.3.0": version: 2.3.0 resolution: "getopts@npm:2.3.0" @@ -35146,7 +35185,7 @@ __metadata: languageName: node linkType: hard -"source-map-support@npm:^0.5.16, source-map-support@npm:~0.5.20": +"source-map-support@npm:^0.5.16, source-map-support@npm:^0.5.21, source-map-support@npm:~0.5.20": version: 0.5.21 resolution: "source-map-support@npm:0.5.21" dependencies: From ab2251564746e53a10759267dacdf83bb7d6769d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 31 Jan 2023 17:58:58 +0100 Subject: [PATCH 160/423] backend-app-api: move signal handlers to backend initializer + exit Signed-off-by: Patrik Oldsberg --- .changeset/red-kiwis-compare.md | 5 +++++ .../rootLifecycle/rootLifecycleFactory.ts | 5 +---- .../backend-app-api/src/wiring/BackendInitializer.ts | 12 ++++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 .changeset/red-kiwis-compare.md diff --git a/.changeset/red-kiwis-compare.md b/.changeset/red-kiwis-compare.md new file mode 100644 index 0000000000..6045367105 --- /dev/null +++ b/.changeset/red-kiwis-compare.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +The shutdown signal handlers are now installed as part of the backend instance rather than the lifecycle service, and explicitly cause the process to exit. diff --git a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts index 71ab76ae92..ebff53e9a6 100644 --- a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts @@ -22,11 +22,8 @@ import { LoggerService, } from '@backstage/backend-plugin-api'; -const CALLBACKS = ['SIGTERM', 'SIGINT', 'beforeExit']; export class BackendLifecycleImpl implements RootLifecycleService { - constructor(private readonly logger: LoggerService) { - CALLBACKS.map(signal => process.on(signal, () => this.shutdown())); - } + constructor(private readonly logger: LoggerService) {} #isCalled = false; #shutdownTasks: Array = []; diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index ce17398a79..d1139615f1 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -87,6 +87,18 @@ export class BackendInitializer { } this.#started = true; + for (const event of ['SIGTERM', 'SIGINT', 'beforeExit']) { + process.on(event, async () => { + try { + await this.stop(); + process.exit(0); + } catch (error) { + console.error(error); + process.exit(1); + } + }); + } + // Initialize all root scoped services for (const ref of this.#serviceHolder.getServiceRefs()) { if (ref.scope === 'root') { From f60cca9da1defe5786a0f16bb17fac2502fca043 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 1 Feb 2023 10:57:42 +0100 Subject: [PATCH 161/423] backend-common: add support for restoring database state via dev store Signed-off-by: Patrik Oldsberg --- .changeset/long-chefs-burn.md | 5 ++ .changeset/old-ways-know.md | 5 ++ .../database/databaseFactory.ts | 10 +++- packages/backend-common/api-report.md | 14 ++++- packages/backend-common/package.json | 1 + .../src/database/DatabaseManager.ts | 15 +++-- .../backend-common/src/database/connection.ts | 5 +- .../src/database/connectors/sqlite3.ts | 55 +++++++++++++++---- packages/backend-common/src/database/index.ts | 5 +- packages/backend-common/src/database/types.ts | 20 ++++++- yarn.lock | 3 +- 11 files changed, 115 insertions(+), 23 deletions(-) create mode 100644 .changeset/long-chefs-burn.md create mode 100644 .changeset/old-ways-know.md diff --git a/.changeset/long-chefs-burn.md b/.changeset/long-chefs-burn.md new file mode 100644 index 0000000000..03a7b76db9 --- /dev/null +++ b/.changeset/long-chefs-burn.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Updated database factory to pass service deps required for restoring database state during development. diff --git a/.changeset/old-ways-know.md b/.changeset/old-ways-know.md new file mode 100644 index 0000000000..60a1a923e8 --- /dev/null +++ b/.changeset/old-ways-know.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +The `DatabaseManager.forPlugin` method now accepts additional service dependencies. There is no need to update existing code to pass these dependencies. diff --git a/packages/backend-app-api/src/services/implementations/database/databaseFactory.ts b/packages/backend-app-api/src/services/implementations/database/databaseFactory.ts index 8baf84cb69..4d95f863db 100644 --- a/packages/backend-app-api/src/services/implementations/database/databaseFactory.ts +++ b/packages/backend-app-api/src/services/implementations/database/databaseFactory.ts @@ -26,7 +26,8 @@ export const databaseFactory = createServiceFactory({ service: coreServices.database, deps: { config: coreServices.config, - plugin: coreServices.pluginMetadata, + lifecycle: coreServices.lifecycle, + pluginMetadata: coreServices.pluginMetadata, }, async createRootContext({ config }) { return config.getOptional('backend.database') @@ -39,7 +40,10 @@ export const databaseFactory = createServiceFactory({ }), ); }, - async factory({ plugin }, databaseManager) { - return databaseManager.forPlugin(plugin.getId()); + async factory({ pluginMetadata, lifecycle }, databaseManager) { + return databaseManager.forPlugin(pluginMetadata.getId(), { + pluginMetadata, + lifecycle, + }); }, }); diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index b03d6ec866..8b6311f8b0 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -32,6 +32,7 @@ import { IdentityService } from '@backstage/backend-plugin-api'; import { isChildPath } from '@backstage/cli-common'; import { Knex } from 'knex'; import { KubeConfig } from '@kubernetes/client-node'; +import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoadConfigOptionsRemote } from '@backstage/config-loader'; import { Logger } from 'winston'; import { LoggerService } from '@backstage/backend-plugin-api'; @@ -40,6 +41,7 @@ import { PermissionsService } from '@backstage/backend-plugin-api'; import { CacheService as PluginCacheManager } from '@backstage/backend-plugin-api'; import { DatabaseService as PluginDatabaseManager } from '@backstage/backend-plugin-api'; import { DiscoveryService as PluginEndpointDiscovery } from '@backstage/backend-plugin-api'; +import { PluginMetadataService } from '@backstage/backend-plugin-api'; import { PushResult } from 'isomorphic-git'; import { Readable } from 'stream'; import { ReadCommitResult } from 'isomorphic-git'; @@ -232,6 +234,7 @@ export class Contexts { export function createDatabaseClient( dbConfig: Config, overrides?: Partial, + deps?: PluginDatabaseDependencies, ): Knex; // @public @@ -252,7 +255,10 @@ export function createStatusCheckRouter(options: { // @public export class DatabaseManager { - forPlugin(pluginId: string): PluginDatabaseManager; + forPlugin( + pluginId: string, + deps?: PluginDatabaseDependencies, + ): PluginDatabaseManager; static fromConfig( config: Config, options?: DatabaseManagerOptions, @@ -571,6 +577,12 @@ export function notFoundHandler(): RequestHandler; export { PluginCacheManager }; +// @public +export type PluginDatabaseDependencies = { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; +}; + export { PluginDatabaseManager }; export { PluginEndpointDiscovery }; diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index c950950680..9f1069f322 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -35,6 +35,7 @@ }, "dependencies": { "@backstage/backend-app-api": "workspace:^", + "@backstage/backend-dev-utils": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/cli-common": "workspace:^", "@backstage/config": "workspace:^", diff --git a/packages/backend-common/src/database/DatabaseManager.ts b/packages/backend-common/src/database/DatabaseManager.ts index 5a497fff29..d8205faec1 100644 --- a/packages/backend-common/src/database/DatabaseManager.ts +++ b/packages/backend-common/src/database/DatabaseManager.ts @@ -27,7 +27,7 @@ import { ensureSchemaExists, normalizeConnection, } from './connection'; -import { PluginDatabaseManager } from './types'; +import { PluginDatabaseDependencies, PluginDatabaseManager } from './types'; import path from 'path'; import { LoggerService } from '@backstage/backend-plugin-api'; import { stringifyError } from '@backstage/errors'; @@ -94,12 +94,15 @@ export class DatabaseManager { * should be unique as they are used to look up database config overrides under * `backend.database.plugin`. */ - forPlugin(pluginId: string): PluginDatabaseManager { + forPlugin( + pluginId: string, + deps?: PluginDatabaseDependencies, + ): PluginDatabaseManager { const _this = this; return { getClient(): Promise { - return _this.getDatabase(pluginId); + return _this.getDatabase(pluginId, deps); }, migrations: { skip: false, @@ -307,7 +310,10 @@ export class DatabaseManager { * @returns Promise which resolves to a scoped Knex database client for a * plugin */ - private async getDatabase(pluginId: string): Promise { + private async getDatabase( + pluginId: string, + deps?: PluginDatabaseDependencies, + ): Promise { if (this.databaseCache.has(pluginId)) { return this.databaseCache.get(pluginId)!; } @@ -351,6 +357,7 @@ export class DatabaseManager { const client = createDatabaseClient( pluginConfig, databaseClientOverrides, + deps, ); this.startKeepaliveLoop(pluginId, client); return client; diff --git a/packages/backend-common/src/database/connection.ts b/packages/backend-common/src/database/connection.ts index 5f487886b4..054ab7cfa8 100644 --- a/packages/backend-common/src/database/connection.ts +++ b/packages/backend-common/src/database/connection.ts @@ -19,7 +19,7 @@ import { JsonObject } from '@backstage/types'; import { InputError } from '@backstage/errors'; import knexFactory, { Knex } from 'knex'; import { mergeDatabaseConfig } from './config'; -import { DatabaseConnector } from './types'; +import { DatabaseConnector, PluginDatabaseDependencies } from './types'; import { mysqlConnector, pgConnector, sqlite3Connector } from './connectors'; @@ -55,11 +55,12 @@ const ConnectorMapping: Record = { export function createDatabaseClient( dbConfig: Config, overrides?: Partial, + deps?: PluginDatabaseDependencies, ) { const client: DatabaseClient = dbConfig.getString('client'); return ( - ConnectorMapping[client]?.createClient(dbConfig, overrides) ?? + ConnectorMapping[client]?.createClient(dbConfig, overrides, deps) ?? knexFactory(mergeDatabaseConfig(dbConfig.get(), overrides)) ); } diff --git a/packages/backend-common/src/database/connectors/sqlite3.ts b/packages/backend-common/src/database/connectors/sqlite3.ts index 6426005f0e..299e18a111 100644 --- a/packages/backend-common/src/database/connectors/sqlite3.ts +++ b/packages/backend-common/src/database/connectors/sqlite3.ts @@ -18,8 +18,9 @@ import { Config } from '@backstage/config'; import { ensureDirSync } from 'fs-extra'; import knexFactory, { Knex } from 'knex'; import path from 'path'; +import { DevDataStore } from '@backstage/backend-dev-utils'; import { mergeDatabaseConfig } from '../config'; -import { DatabaseConnector } from '../types'; +import { DatabaseConnector, PluginDatabaseDependencies } from '../types'; /** * Creates a knex SQLite3 database connection @@ -30,22 +31,56 @@ import { DatabaseConnector } from '../types'; export function createSqliteDatabaseClient( dbConfig: Config, overrides?: Knex.Config, + deps?: PluginDatabaseDependencies, ) { const knexConfig = buildSqliteDatabaseConfig(dbConfig, overrides); + const connConfig = knexConfig.connection as Knex.Sqlite3ConnectionConfig; // If storage on disk is used, ensure that the directory exists - if ( - (knexConfig.connection as Knex.Sqlite3ConnectionConfig).filename && - (knexConfig.connection as Knex.Sqlite3ConnectionConfig).filename !== - ':memory:' - ) { - const { filename } = knexConfig.connection as Knex.Sqlite3ConnectionConfig; - const directory = path.dirname(filename); - + if (connConfig.filename && connConfig.filename !== ':memory:') { + const directory = path.dirname(connConfig.filename); ensureDirSync(directory); } - const database = knexFactory(knexConfig); + let database: Knex; + + if (deps && connConfig.filename === ':memory:') { + // The dev store is used during watch mode to store and restore the database + // across reloads. It is only available when running the backend through + // `backstage-cli package start`. + const devStore = DevDataStore.get(); + const dataKey = `sqlite3-db-${deps.pluginMetadata.getId()}`; + + if (devStore) { + database = knexFactory({ + ...knexConfig, + connection: async () => { + // If seed data is available, use it to restore the database + const { data: seedData } = await devStore?.load(dataKey); + + return { + ...(knexConfig.connection as Knex.Sqlite3ConnectionConfig), + filename: seedData ?? ':memory:', + }; + }, + }); + } else { + database = knexFactory(knexConfig); + } + + if (devStore) { + // If the dev store is available we save the database state on shutdown + deps?.lifecycle?.addShutdownHook({ + async fn() { + const connection = await database.client.acquireConnection(); + const data = connection.serialize(); + await devStore.save(dataKey, data); + }, + }); + } + } else { + database = knexFactory(knexConfig); + } database.client.pool.on('createSuccess', (_eventId: any, resource: any) => { resource.run('PRAGMA foreign_keys = ON', () => {}); diff --git a/packages/backend-common/src/database/index.ts b/packages/backend-common/src/database/index.ts index 0dde1ec239..483dbd9e40 100644 --- a/packages/backend-common/src/database/index.ts +++ b/packages/backend-common/src/database/index.ts @@ -22,5 +22,8 @@ export * from './DatabaseManager'; */ export { createDatabaseClient, ensureDatabaseExists } from './connection'; -export type { PluginDatabaseManager } from './types'; +export type { + PluginDatabaseManager, + PluginDatabaseDependencies, +} from './types'; export { isDatabaseConflictError } from './util'; diff --git a/packages/backend-common/src/database/types.ts b/packages/backend-common/src/database/types.ts index 2d59cf636e..7e96c44071 100644 --- a/packages/backend-common/src/database/types.ts +++ b/packages/backend-common/src/database/types.ts @@ -14,11 +14,25 @@ * limitations under the License. */ +import { + LifecycleService, + PluginMetadataService, +} from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { Knex } from 'knex'; export type { DatabaseService as PluginDatabaseManager } from '@backstage/backend-plugin-api'; +/** + * Service dependencies for `PluginDatabaseManager`. + * + * @public + */ +export type PluginDatabaseDependencies = { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; +}; + /** * DatabaseConnector manages an underlying Knex database driver. */ @@ -26,7 +40,11 @@ export interface DatabaseConnector { /** * createClient provides an instance of a knex database connector. */ - createClient(dbConfig: Config, overrides?: Partial): Knex; + createClient( + dbConfig: Config, + overrides?: Partial, + deps?: PluginDatabaseDependencies, + ): Knex; /** * createNameOverride provides a partial knex config sufficient to override a * database name. diff --git a/yarn.lock b/yarn.lock index 7143443674..650cb4c95d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3423,6 +3423,7 @@ __metadata: resolution: "@backstage/backend-common@workspace:packages/backend-common" dependencies: "@backstage/backend-app-api": "workspace:^" + "@backstage/backend-dev-utils": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -3519,7 +3520,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/backend-dev-utils@workspace:packages/backend-dev-utils": +"@backstage/backend-dev-utils@workspace:^, @backstage/backend-dev-utils@workspace:packages/backend-dev-utils": version: 0.0.0-use.local resolution: "@backstage/backend-dev-utils@workspace:packages/backend-dev-utils" dependencies: From cd4d0365ac9feddd40abe820d3c9097f92575202 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 1 Feb 2023 11:08:32 +0100 Subject: [PATCH 162/423] backend-next: use experimental start script Signed-off-by: Patrik Oldsberg --- packages/backend-next/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index cc537ef514..fb821e19eb 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -18,7 +18,7 @@ "backstage" ], "scripts": { - "start": "backstage-cli package start", + "start": "EXPERIMENTAL_BACKEND_START=1 backstage-cli package start", "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", From bff35c4d98c80cfb77f65d53c9cfb5b9db280fc1 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Sun, 5 Feb 2023 08:00:07 -0500 Subject: [PATCH 163/423] fix github-actions plugin dev environment This ensures the mockGithubActionsApi used by the plugin in dev returns the necessary mock data to meaningfully render the plugin. Signed-off-by: Mike Ball --- plugins/github-actions/dev/index.tsx | 8 +- .../downloadJobLogsForWorkflowRun.ts | 315 ++++++++++++++++++ .../src/__fixtures__/list-workflow-runs.json | 223 +++++++++++++ 3 files changed, 544 insertions(+), 2 deletions(-) create mode 100644 plugins/github-actions/src/__fixtures__/downloadJobLogsForWorkflowRun.ts create mode 100644 plugins/github-actions/src/__fixtures__/list-workflow-runs.json diff --git a/plugins/github-actions/dev/index.tsx b/plugins/github-actions/dev/index.tsx index ee761b3504..93e6ee4f74 100644 --- a/plugins/github-actions/dev/index.tsx +++ b/plugins/github-actions/dev/index.tsx @@ -22,6 +22,8 @@ import { Entity } from '@backstage/catalog-model'; import { GithubActionsApi, githubActionsApiRef } from '../src'; import getWorkflowRunResponse from '../src/__fixtures__/get-workflow-run.json'; import listJobsForWorkflowRunResponse from '../src/__fixtures__/list-jobs-for-workflow-run.json'; +import listWorkflowRuns from '../src/__fixtures__/list-workflow-runs.json'; +import { downloadJobLogsForWorkflowRun } from '../src/__fixtures__/downloadJobLogsForWorkflowRun'; const mockEntity: Entity = { apiVersion: 'backstage.io/v1alpha1', @@ -41,7 +43,9 @@ const mockEntity: Entity = { }; const mockGithubActionsApi: GithubActionsApi = { - async downloadJobLogsForWorkflowRun() {}, + async downloadJobLogsForWorkflowRun() { + return downloadJobLogsForWorkflowRun; + }, async getWorkflow() { return {} as any; }, @@ -52,7 +56,7 @@ const mockGithubActionsApi: GithubActionsApi = { return listJobsForWorkflowRunResponse as any; }, async listWorkflowRuns() { - return {} as any; + return listWorkflowRuns as any; }, async reRunWorkflow() { return {} as any; diff --git a/plugins/github-actions/src/__fixtures__/downloadJobLogsForWorkflowRun.ts b/plugins/github-actions/src/__fixtures__/downloadJobLogsForWorkflowRun.ts new file mode 100644 index 0000000000..7b882d0719 --- /dev/null +++ b/plugins/github-actions/src/__fixtures__/downloadJobLogsForWorkflowRun.ts @@ -0,0 +1,315 @@ +/* + * 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 const downloadJobLogsForWorkflowRun = ` +2022-12-09T17:25:25.6542422Z Requested labels: ubuntu-latest +2022-12-09T17:25:25.6542470Z Job defined at: octo-org/octo-template/dynamic/pages/pages-build-deployment@refs/heads/main +2022-12-09T17:25:25.6542493Z Waiting for a runner to pick up this job... +2022-12-09T17:25:25.9157301Z Job is waiting for a hosted runner to come online. +2022-12-09T17:25:29.3998345Z Job is about to start running on the hosted runner: Hosted Agent (hosted) +2022-12-09T17:25:31.7099053Z Current runner version: '2.299.1' +2022-12-09T17:25:31.7123983Z ##[group]Operating System +2022-12-09T17:25:31.7124496Z Ubuntu +2022-12-09T17:25:31.7124859Z 22.04.1 +2022-12-09T17:25:31.7125085Z LTS +2022-12-09T17:25:31.7125353Z ##[endgroup] +2022-12-09T17:25:31.7125657Z ##[group]Runner Image +2022-12-09T17:25:31.7125963Z Image: ubuntu-22.04 +2022-12-09T17:25:31.7126295Z Version: 20221204.2 +2022-12-09T17:25:31.7127048Z Included Software: https://github.com/actions/runner-images/blob/ubuntu22/20221204.2/images/linux/Ubuntu2204-Readme.md +2022-12-09T17:25:31.7127614Z Image Release: https://github.com/actions/runner-images/releases/tag/ubuntu22%2F20221204.2 +2022-12-09T17:25:31.7128026Z ##[endgroup] +2022-12-09T17:25:31.7128400Z ##[group]Runner Image Provisioner +2022-12-09T17:25:31.7128722Z 2.0.91.1 +2022-12-09T17:25:31.7128945Z ##[endgroup] +2022-12-09T17:25:31.7129586Z ##[group]GITHUB_TOKEN Permissions +2022-12-09T17:25:31.7130130Z Contents: read +2022-12-09T17:25:31.7130387Z Metadata: read +2022-12-09T17:25:31.7130849Z Pages: write +2022-12-09T17:25:31.7131169Z ##[endgroup] +2022-12-09T17:25:31.7134756Z Secret source: Actions +2022-12-09T17:25:31.7135232Z Prepare workflow directory +2022-12-09T17:25:31.7951647Z Prepare all required actions +2022-12-09T17:25:31.8134091Z Getting action download info +2022-12-09T17:25:32.1190857Z Download action repository 'actions/checkout@v3' (SHA:93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8) +2022-12-09T17:25:32.4403240Z Download action repository 'actions/jekyll-build-pages@v1' (SHA:9b882383c88a22eef81e9c1a5a232c2ff9a6672b) +2022-12-09T17:25:32.7457755Z Download action repository 'actions/upload-pages-artifact@v1' (SHA:c8641e80048cf33d329c39df3bcc53196178335a) +2022-12-09T17:25:33.0262452Z Getting action download info +2022-12-09T17:25:33.1786870Z Download action repository 'actions/upload-artifact@main' (SHA:83fd05a356d7e2593de66fc9913b3002723633cb) +2022-12-09T17:25:33.4537715Z ##[group]Pull down action image 'ghcr.io/actions/jekyll-build-pages:v1.0.4' +2022-12-09T17:25:33.4611360Z ##[command]/usr/bin/docker pull ghcr.io/actions/jekyll-build-pages:v1.0.4 +2022-12-09T17:25:34.0231935Z v1.0.4: Pulling from actions/jekyll-build-pages +2022-12-09T17:25:34.0232298Z eff15d958d66: Pulling fs layer +2022-12-09T17:25:34.0232609Z 923e91ae3a1b: Pulling fs layer +2022-12-09T17:25:34.0232986Z 2aa5d3a4a151: Pulling fs layer +2022-12-09T17:25:34.0233248Z bc64adf2d0b2: Pulling fs layer +2022-12-09T17:25:34.0233543Z bfc5cca7d80e: Pulling fs layer +2022-12-09T17:25:34.0233827Z 61b6e3e25463: Pulling fs layer +2022-12-09T17:25:34.0234080Z 7c62fb63f605: Pulling fs layer +2022-12-09T17:25:34.0234380Z 0f68cc81f8f6: Pulling fs layer +2022-12-09T17:25:34.0234663Z 09f325326117: Pulling fs layer +2022-12-09T17:25:34.0234894Z a73a0a50c4db: Pulling fs layer +2022-12-09T17:25:34.0235171Z bc64adf2d0b2: Waiting +2022-12-09T17:25:34.0235470Z bfc5cca7d80e: Waiting +2022-12-09T17:25:34.0235840Z 61b6e3e25463: Waiting +2022-12-09T17:25:34.0236104Z 7c62fb63f605: Waiting +2022-12-09T17:25:34.0236314Z 0f68cc81f8f6: Waiting +2022-12-09T17:25:34.0236586Z 09f325326117: Waiting +2022-12-09T17:25:34.0236855Z a73a0a50c4db: Waiting +2022-12-09T17:25:34.1800756Z 2aa5d3a4a151: Verifying Checksum +2022-12-09T17:25:34.1801065Z 2aa5d3a4a151: Download complete +2022-12-09T17:25:34.4333121Z eff15d958d66: Verifying Checksum +2022-12-09T17:25:34.4335284Z eff15d958d66: Download complete +2022-12-09T17:25:34.5215161Z bc64adf2d0b2: Verifying Checksum +2022-12-09T17:25:34.5231169Z bc64adf2d0b2: Download complete +2022-12-09T17:25:34.5266358Z 923e91ae3a1b: Verifying Checksum +2022-12-09T17:25:34.5266637Z 923e91ae3a1b: Download complete +2022-12-09T17:25:34.6185999Z bfc5cca7d80e: Verifying Checksum +2022-12-09T17:25:34.6186341Z bfc5cca7d80e: Download complete +2022-12-09T17:25:34.6627434Z 7c62fb63f605: Verifying Checksum +2022-12-09T17:25:34.6629228Z 7c62fb63f605: Download complete +2022-12-09T17:25:34.8423112Z 09f325326117: Verifying Checksum +2022-12-09T17:25:34.8424383Z 09f325326117: Download complete +2022-12-09T17:25:35.0142784Z a73a0a50c4db: Verifying Checksum +2022-12-09T17:25:35.0143743Z a73a0a50c4db: Download complete +2022-12-09T17:25:35.2282893Z 0f68cc81f8f6: Verifying Checksum +2022-12-09T17:25:35.2283672Z 0f68cc81f8f6: Download complete +2022-12-09T17:25:35.8547685Z 61b6e3e25463: Verifying Checksum +2022-12-09T17:25:35.8547985Z 61b6e3e25463: Download complete +2022-12-09T17:25:36.3689873Z eff15d958d66: Pull complete +2022-12-09T17:25:38.9751393Z 923e91ae3a1b: Pull complete +2022-12-09T17:25:39.0574850Z 2aa5d3a4a151: Pull complete +2022-12-09T17:25:39.6785807Z bc64adf2d0b2: Pull complete +2022-12-09T17:25:39.7560781Z bfc5cca7d80e: Pull complete +2022-12-09T17:25:45.3145640Z 61b6e3e25463: Pull complete +2022-12-09T17:25:45.3626474Z 7c62fb63f605: Pull complete +2022-12-09T17:25:48.5182928Z 0f68cc81f8f6: Pull complete +2022-12-09T17:25:48.5924407Z 09f325326117: Pull complete +2022-12-09T17:25:48.6361139Z a73a0a50c4db: Pull complete +2022-12-09T17:25:48.6390662Z Digest: sha256:e56d7e4c5ac45aa2934b1d535f4c66769a442ef6538c7948f8b4e3b2950fd7b4 +2022-12-09T17:25:48.6435854Z Status: Downloaded newer image for ghcr.io/actions/jekyll-build-pages:v1.0.4 +2022-12-09T17:25:48.6436263Z ghcr.io/actions/jekyll-build-pages:v1.0.4 +2022-12-09T17:25:48.6444026Z ##[endgroup] +2022-12-09T17:25:48.6814585Z ##[group]Run actions/checkout@v3 +2022-12-09T17:25:48.6814842Z with: +2022-12-09T17:25:48.6815018Z ref: main +2022-12-09T17:25:48.6815204Z submodules: recursive +2022-12-09T17:25:48.6815442Z repository: octo-org/octo-template +2022-12-09T17:25:48.6815884Z token: *** +2022-12-09T17:25:48.6816068Z ssh-strict: true +2022-12-09T17:25:48.6816284Z persist-credentials: true +2022-12-09T17:25:48.6816500Z clean: true +2022-12-09T17:25:48.6816685Z fetch-depth: 1 +2022-12-09T17:25:48.6816872Z lfs: false +2022-12-09T17:25:48.6817076Z set-safe-directory: true +2022-12-09T17:25:48.6817275Z ##[endgroup] +2022-12-09T17:25:48.9194010Z Syncing repository: octo-org/octo-template +2022-12-09T17:25:48.9195798Z ##[group]Getting Git version info +2022-12-09T17:25:48.9196263Z Working directory is '/home/runner/work/octo-template/octo-template' +2022-12-09T17:25:48.9196777Z [command]/usr/bin/git version +2022-12-09T17:25:48.9267188Z git version 2.38.1 +2022-12-09T17:25:48.9293570Z ##[endgroup] +2022-12-09T17:25:48.9315385Z Temporarily overriding HOME='/home/runner/work/_temp/54730a3a-82b6-4069-a509-366e53e131cc' before making global git config changes +2022-12-09T17:25:48.9315845Z Adding repository directory to the temporary git global config as a safe directory +2022-12-09T17:25:48.9316365Z [command]/usr/bin/git config --global --add safe.directory /home/runner/work/octo-template/octo-template +2022-12-09T17:25:48.9362562Z Deleting the contents of '/home/runner/work/octo-template/octo-template' +2022-12-09T17:25:48.9366563Z ##[group]Initializing the repository +2022-12-09T17:25:48.9370913Z [command]/usr/bin/git init /home/runner/work/octo-template/octo-template +2022-12-09T17:25:48.9428579Z hint: Using 'master' as the name for the initial branch. This default branch name +2022-12-09T17:25:48.9429400Z hint: is subject to change. To configure the initial branch name to use in all +2022-12-09T17:25:48.9429828Z hint: of your new repositories, which will suppress this warning, call: +2022-12-09T17:25:48.9430089Z hint: +2022-12-09T17:25:48.9430525Z hint: git config --global init.defaultBranch +2022-12-09T17:25:48.9430769Z hint: +2022-12-09T17:25:48.9431094Z hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and +2022-12-09T17:25:48.9431510Z hint: 'development'. The just-created branch can be renamed via this command: +2022-12-09T17:25:48.9431770Z hint: +2022-12-09T17:25:48.9431994Z hint: git branch -m +2022-12-09T17:25:48.9442316Z Initialized empty Git repository in /home/runner/work/octo-template/octo-template/.git/ +2022-12-09T17:25:48.9454154Z [command]/usr/bin/git remote add origin https://github.com/octo-org/octo-template +2022-12-09T17:25:48.9490442Z ##[endgroup] +2022-12-09T17:25:48.9491112Z ##[group]Disabling automatic garbage collection +2022-12-09T17:25:48.9494676Z [command]/usr/bin/git config --local gc.auto 0 +2022-12-09T17:25:48.9524540Z ##[endgroup] +2022-12-09T17:25:48.9525308Z ##[group]Setting up auth +2022-12-09T17:25:48.9532488Z [command]/usr/bin/git config --local --name-only --get-regexp core\.sshCommand +2022-12-09T17:25:48.9563906Z [command]/usr/bin/git submodule foreach --recursive git config --local --name-only --get-regexp 'core\.sshCommand' && git config --local --unset-all 'core.sshCommand' || : +2022-12-09T17:25:48.9857748Z [command]/usr/bin/git config --local --name-only --get-regexp http\.https\:\/\/github\.com\/\.extraheader +2022-12-09T17:25:48.9892225Z [command]/usr/bin/git submodule foreach --recursive git config --local --name-only --get-regexp 'http\.https\:\/\/github\.com\/\.extraheader' && git config --local --unset-all 'http.https://github.com/.extraheader' || : +2022-12-09T17:25:49.0110192Z [command]/usr/bin/git config --local http.https://github.com/.extraheader AUTHORIZATION: basic *** +2022-12-09T17:25:49.0146631Z ##[endgroup] +2022-12-09T17:25:49.0147330Z ##[group]Fetching the repository +2022-12-09T17:25:49.0156010Z [command]/usr/bin/git -c protocol.version=2 fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 origin +refs/heads/main*:refs/remotes/origin/main* +refs/tags/main*:refs/tags/main* +2022-12-09T17:25:49.2837218Z remote: Enumerating objects: 3, done. +2022-12-09T17:25:49.2837524Z remote: Counting objects: 33% (1/3) +2022-12-09T17:25:49.2837809Z remote: Counting objects: 66% (2/3) +2022-12-09T17:25:49.2838044Z remote: Counting objects: 100% (3/3) +2022-12-09T17:25:49.2839733Z remote: Counting objects: 100% (3/3), done. +2022-12-09T17:25:49.2840661Z remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 +2022-12-09T17:25:49.2896737Z From https://github.com/octo-org/octo-template +2022-12-09T17:25:49.2897109Z * [new branch] main -> origin/main +2022-12-09T17:25:49.2924446Z ##[endgroup] +2022-12-09T17:25:49.2925129Z ##[group]Determining the checkout info +2022-12-09T17:25:49.2931526Z [command]/usr/bin/git branch --list --remote origin/main +2022-12-09T17:25:49.2958361Z origin/main +2022-12-09T17:25:49.2963283Z ##[endgroup] +2022-12-09T17:25:49.2964130Z ##[group]Checking out the ref +2022-12-09T17:25:49.2970560Z [command]/usr/bin/git checkout --progress --force -B main refs/remotes/origin/main +2022-12-09T17:25:49.3010381Z Switched to a new branch 'main' +2022-12-09T17:25:49.3014811Z branch 'main' set up to track 'origin/main'. +2022-12-09T17:25:49.3019861Z ##[endgroup] +2022-12-09T17:25:49.3022847Z ##[group]Setting up auth for fetching submodules +2022-12-09T17:25:49.3031486Z [command]/usr/bin/git config --global http.https://github.com/.extraheader AUTHORIZATION: basic *** +2022-12-09T17:25:49.3101009Z [command]/usr/bin/git config --global --unset-all url.https://github.com/.insteadOf +2022-12-09T17:25:49.3132496Z [command]/usr/bin/git config --global --add url.https://github.com/.insteadOf git@github.com: +2022-12-09T17:25:49.3159145Z ##[endgroup] +2022-12-09T17:25:49.3159671Z ##[group]Fetching submodules +2022-12-09T17:25:49.3163060Z [command]/usr/bin/git submodule sync --recursive +2022-12-09T17:25:49.3374628Z [command]/usr/bin/git -c protocol.version=2 submodule update --init --force --depth=1 --recursive +2022-12-09T17:25:49.3595435Z [command]/usr/bin/git submodule foreach --recursive git config --local gc.auto 0 +2022-12-09T17:25:49.3838526Z ##[endgroup] +2022-12-09T17:25:49.3839209Z ##[group]Persisting credentials for submodules +2022-12-09T17:25:49.3844491Z [command]/usr/bin/git submodule foreach --recursive git config --local --name-only --get-regexp 'url\.https\:\/\/github\.com\/\.insteadOf' && git config --local --unset-all 'url.https://github.com/.insteadOf' || : +2022-12-09T17:25:49.4113780Z [command]/usr/bin/git submodule foreach --recursive git config --local 'http.https://github.com/.extraheader' 'AUTHORIZATION: basic ***' && git config --local --show-origin --name-only --get-regexp remote.origin.url +2022-12-09T17:25:49.4324497Z [command]/usr/bin/git submodule foreach --recursive git config --local --add 'url.https://github.com/.insteadOf' 'git@github.com:' +2022-12-09T17:25:49.4536981Z ##[endgroup] +2022-12-09T17:25:49.4565161Z [command]/usr/bin/git log -1 --format='%H' +2022-12-09T17:25:49.4592051Z 'c85af0e5e5798047462143a13c1b455ee1275a64' +2022-12-09T17:25:49.4851246Z ##[group]Run actions/jekyll-build-pages@v1 +2022-12-09T17:25:49.4851491Z with: +2022-12-09T17:25:49.4851672Z source: . +2022-12-09T17:25:49.4851856Z destination: ./_site +2022-12-09T17:25:49.4852055Z future: false +2022-12-09T17:25:49.4852300Z build_revision: c85af0e5e5798047462143a13c1b455ee1275a64 +2022-12-09T17:25:49.4852525Z verbose: true +2022-12-09T17:25:49.4852887Z token: *** +2022-12-09T17:25:49.4853073Z ##[endgroup] +2022-12-09T17:25:49.5094807Z ##[command]/usr/bin/docker run --name ghcrioactionsjekyllbuildpagesv104_e36266 --label 290506 --workdir /github/workspace --rm -e "INPUT_SOURCE" -e "INPUT_DESTINATION" -e "INPUT_FUTURE" -e "INPUT_BUILD_REVISION" -e "INPUT_VERBOSE" -e "INPUT_TOKEN" -e "HOME" -e "GITHUB_JOB" -e "GITHUB_REF" -e "GITHUB_SHA" -e "GITHUB_REPOSITORY" -e "GITHUB_REPOSITORY_OWNER" -e "GITHUB_RUN_ID" -e "GITHUB_RUN_NUMBER" -e "GITHUB_RETENTION_DAYS" -e "GITHUB_RUN_ATTEMPT" -e "GITHUB_ACTOR" -e "GITHUB_TRIGGERING_ACTOR" -e "GITHUB_WORKFLOW" -e "GITHUB_HEAD_REF" -e "GITHUB_BASE_REF" -e "GITHUB_EVENT_NAME" -e "GITHUB_SERVER_URL" -e "GITHUB_API_URL" -e "GITHUB_GRAPHQL_URL" -e "GITHUB_REF_NAME" -e "GITHUB_REF_PROTECTED" -e "GITHUB_REF_TYPE" -e "GITHUB_WORKSPACE" -e "GITHUB_ACTION" -e "GITHUB_EVENT_PATH" -e "GITHUB_ACTION_REPOSITORY" -e "GITHUB_ACTION_REF" -e "GITHUB_PATH" -e "GITHUB_ENV" -e "GITHUB_STEP_SUMMARY" -e "GITHUB_STATE" -e "GITHUB_OUTPUT" -e "RUNNER_OS" -e "RUNNER_ARCH" -e "RUNNER_NAME" -e "RUNNER_TOOL_CACHE" -e "RUNNER_TEMP" -e "RUNNER_WORKSPACE" -e "ACTIONS_RUNTIME_URL" -e "ACTIONS_RUNTIME_TOKEN" -e "ACTIONS_CACHE_URL" -e "ACTIONS_ID_TOKEN_REQUEST_URL" -e "ACTIONS_ID_TOKEN_REQUEST_TOKEN" -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -v "/home/runner/work/_temp/_runner_file_commands":"/github/file_commands" -v "/home/runner/work/octo-template/octo-template":"/github/workspace" ghcr.io/actions/jekyll-build-pages:v1.0.4 +2022-12-09T17:25:50.5151506Z [33mConfiguration file: none[0m +2022-12-09T17:25:50.5313330Z Logging at level: debug +2022-12-09T17:25:50.5313941Z GitHub Pages: github-pages v227 +2022-12-09T17:25:50.5314484Z GitHub Pages: jekyll v3.9.2 +2022-12-09T17:25:50.5315560Z Theme: jekyll-theme-primer +2022-12-09T17:25:50.5316125Z Theme source: /usr/local/bundle/gems/jekyll-theme-primer-0.6.0 +2022-12-09T17:25:50.5316710Z Requiring: jekyll-github-metadata +2022-12-09T17:25:50.6063961Z To use retry middleware with Faraday v2.0+, install faraday-retry gem +2022-12-09T17:25:52.4164334Z Requiring: jekyll-seo-tag +2022-12-09T17:25:52.4165089Z Requiring: jekyll-coffeescript +2022-12-09T17:25:52.4166139Z Requiring: jekyll-commonmark-ghpages +2022-12-09T17:25:52.4166490Z Requiring: jekyll-gist +2022-12-09T17:25:52.4167025Z Requiring: jekyll-github-metadata +2022-12-09T17:25:52.4167363Z Requiring: jekyll-paginate +2022-12-09T17:25:52.4167663Z Requiring: jekyll-relative-links +2022-12-09T17:25:52.4167989Z Requiring: jekyll-optional-front-matter +2022-12-09T17:25:52.4168298Z Requiring: jekyll-readme-index +2022-12-09T17:25:52.4168589Z Requiring: jekyll-default-layout +2022-12-09T17:25:52.4168888Z Requiring: jekyll-titles-from-headings +2022-12-09T17:25:52.4169143Z GitHub Metadata: Initializing... +2022-12-09T17:25:52.4169392Z Source: /github/workspace/. +2022-12-09T17:25:52.4169651Z Destination: /github/workspace/./_site +2022-12-09T17:25:52.4169981Z Incremental build: disabled. Enable with --incremental +2022-12-09T17:25:52.4170230Z Generating... +2022-12-09T17:25:52.4183638Z Generating: JekyllOptionalFrontMatter::Generator finished in 0.000150897 seconds. +2022-12-09T17:25:52.4184136Z Generating: JekyllReadmeIndex::Generator finished in 0.00169567 seconds. +2022-12-09T17:25:52.4185038Z Generating: Jekyll::Paginate::Pagination finished in 4.8e-06 seconds. +2022-12-09T17:25:52.4185483Z Generating: JekyllRelativeLinks::Generator finished in 2.97e-05 seconds. +2022-12-09T17:25:52.4185914Z Generating: JekyllDefaultLayout::Generator finished in 7.7999e-05 seconds. +2022-12-09T17:25:52.4186258Z Requiring: kramdown-parser-gfm +2022-12-09T17:25:52.4186586Z Generating: JekyllTitlesFromHeadings::Generator finished in 0.008350253 seconds. +2022-12-09T17:25:52.4186888Z Rendering: assets/css/style.scss +2022-12-09T17:25:52.4187176Z Pre-Render Hooks: assets/css/style.scss +2022-12-09T17:25:52.4187437Z Rendering Markup: assets/css/style.scss +2022-12-09T17:25:52.4187672Z Rendering: README.md +2022-12-09T17:25:52.4187920Z Pre-Render Hooks: README.md +2022-12-09T17:25:52.4188141Z Rendering Markup: README.md +2022-12-09T17:25:52.4188360Z Rendering Layout: README.md +2022-12-09T17:25:52.4188568Z Layout source: theme +2022-12-09T17:25:52.4188886Z GitHub Metadata: Generating for octo-org/octo-template +2022-12-09T17:25:52.4189408Z GitHub Metadata: Calling @client.repository("octo-org/octo-template", {:accept=>"application/vnd.github.drax-preview+json"}) +2022-12-09T17:25:52.4189903Z GitHub Metadata: Calling @client.pages("octo-org/octo-template", {}) +2022-12-09T17:25:52.4190223Z Writing: /github/workspace/_site/assets/css/style.css +2022-12-09T17:25:52.4190520Z Writing: /github/workspace/_site/index.html +2022-12-09T17:25:52.4190772Z done in 1.524 seconds. +2022-12-09T17:25:52.4191074Z Auto-regeneration: disabled. Use --watch to enable. +2022-12-09T17:25:52.5460546Z ##[group]Run actions/upload-pages-artifact@v1 +2022-12-09T17:25:52.5460787Z with: +2022-12-09T17:25:52.5460968Z path: ./_site +2022-12-09T17:25:52.5461168Z name: github-pages +2022-12-09T17:25:52.5461361Z retention-days: 1 +2022-12-09T17:25:52.5461560Z ##[endgroup] +2022-12-09T17:25:52.5745795Z ##[group]Run chmod -c -R +rX . | while read line; do +2022-12-09T17:25:52.5746128Z [36;1mchmod -c -R +rX . | while read line; do[0m +2022-12-09T17:25:52.5746462Z [36;1m echo "::warning title=Invalid file permissions automatically fixed::$line"[0m +2022-12-09T17:25:52.5746740Z [36;1mdone[0m +2022-12-09T17:25:52.5746920Z [36;1mtar \[0m +2022-12-09T17:25:52.5747146Z [36;1m --dereference --hard-dereference \[0m +2022-12-09T17:25:52.5747410Z [36;1m --directory "$INPUT_PATH" \[0m +2022-12-09T17:25:52.5747668Z [36;1m -cvf "$RUNNER_TEMP/artifact.tar" \[0m +2022-12-09T17:25:52.5747896Z [36;1m --exclude=.git \[0m +2022-12-09T17:25:52.5748110Z [36;1m --exclude=.github \[0m +2022-12-09T17:25:52.5748352Z [36;1m .[0m +2022-12-09T17:25:52.5805770Z shell: /usr/bin/sh -e {0} +2022-12-09T17:25:52.5805980Z env: +2022-12-09T17:25:52.5806170Z INPUT_PATH: ./_site +2022-12-09T17:25:52.5806374Z ##[endgroup] +2022-12-09T17:25:52.5967973Z chmod: changing permissions of './_site': Operation not permitted +2022-12-09T17:25:52.5986749Z chmod: changing permissions of './_site/index.html': Operation not permitted +2022-12-09T17:25:52.5987217Z chmod: changing permissions of './_site/README.md': Operation not permitted +2022-12-09T17:25:52.5987625Z chmod: changing permissions of './_site/assets': Operation not permitted +2022-12-09T17:25:52.5988025Z chmod: changing permissions of './_site/assets/css': Operation not permitted +2022-12-09T17:25:52.5988455Z chmod: changing permissions of './_site/assets/css/style.css': Operation not permitted +2022-12-09T17:25:52.6003872Z ./ +2022-12-09T17:25:52.6004035Z ./index.html +2022-12-09T17:25:52.6004213Z ./README.md +2022-12-09T17:25:52.6004387Z ./assets/ +2022-12-09T17:25:52.6004556Z ./assets/css/ +2022-12-09T17:25:52.6004743Z ./assets/css/style.css +2022-12-09T17:25:52.6089697Z ##[group]Run actions/upload-artifact@main +2022-12-09T17:25:52.6089918Z with: +2022-12-09T17:25:52.6090104Z name: github-pages +2022-12-09T17:25:52.6090342Z path: /home/runner/work/_temp/artifact.tar +2022-12-09T17:25:52.6090677Z retention-days: 1 +2022-12-09T17:25:52.6090884Z if-no-files-found: warn +2022-12-09T17:25:52.6091085Z ##[endgroup] +2022-12-09T17:25:52.6745114Z With the provided path, there will be 1 file uploaded +2022-12-09T17:25:52.6748618Z Starting artifact upload +2022-12-09T17:25:52.6749367Z For more detailed logs during the artifact upload process, enable step-debugging: https://docs.github.com/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging#enabling-step-debug-logging +2022-12-09T17:25:52.6750012Z Artifact name is valid! +2022-12-09T17:25:52.7711407Z Container for artifact "github-pages" successfully created. Starting upload of file(s) +2022-12-09T17:25:52.8679144Z Total size of all the files uploaded is 12638 bytes +2022-12-09T17:25:52.8680162Z File upload process has finished. Finalizing the artifact upload +2022-12-09T17:25:52.8976033Z Artifact has been finalized. All files have been successfully uploaded! +2022-12-09T17:25:52.8976512Z +2022-12-09T17:25:52.8976816Z The raw size of all the files that were specified for upload is 92160 bytes +2022-12-09T17:25:52.8977329Z The size of all the files that were uploaded is 12638 bytes. This takes into account any gzip compression used to reduce the upload size, time and storage +2022-12-09T17:25:52.8977612Z +2022-12-09T17:25:52.8978179Z Note: The size of downloaded zips can differ significantly from the reported size. For more information see: https://github.com/actions/upload-artifact#zipped-artifact-downloads +2022-12-09T17:25:52.8978524Z +2022-12-09T17:25:52.8980509Z Artifact github-pages has been successfully uploaded! +2022-12-09T17:25:52.9084311Z Post job cleanup. +2022-12-09T17:25:53.0358449Z [command]/usr/bin/git version +2022-12-09T17:25:53.0407485Z git version 2.38.1 +2022-12-09T17:25:53.0465462Z Temporarily overriding HOME='/home/runner/work/_temp/52bccf8b-8b44-45e0-a383-0833ced20023' before making global git config changes +2022-12-09T17:25:53.0470560Z Adding repository directory to the temporary git global config as a safe directory +2022-12-09T17:25:53.0478850Z [command]/usr/bin/git config --global --add safe.directory /home/runner/work/octo-template/octo-template +2022-12-09T17:25:53.0517249Z [command]/usr/bin/git config --local --name-only --get-regexp core\.sshCommand +2022-12-09T17:25:53.0550835Z [command]/usr/bin/git submodule foreach --recursive git config --local --name-only --get-regexp 'core\.sshCommand' && git config --local --unset-all 'core.sshCommand' || : +2022-12-09T17:25:53.0769173Z [command]/usr/bin/git config --local --name-only --get-regexp http\.https\:\/\/github\.com\/\.extraheader +2022-12-09T17:25:53.0792441Z http.https://github.com/.extraheader +2022-12-09T17:25:53.0803756Z [command]/usr/bin/git config --local --unset-all http.https://github.com/.extraheader +2022-12-09T17:25:53.0838329Z [command]/usr/bin/git submodule foreach --recursive git config --local --name-only --get-regexp 'http\.https\:\/\/github\.com\/\.extraheader' && git config --local --unset-all 'http.https://github.com/.extraheader' || : +2022-12-09T17:25:53.1274888Z Cleaning up orphan processes +`; diff --git a/plugins/github-actions/src/__fixtures__/list-workflow-runs.json b/plugins/github-actions/src/__fixtures__/list-workflow-runs.json new file mode 100644 index 0000000000..4d1e1223ce --- /dev/null +++ b/plugins/github-actions/src/__fixtures__/list-workflow-runs.json @@ -0,0 +1,223 @@ +{ + "total_count": 1, + "workflow_runs": [ + { + "id": 30433642, + "name": "Build", + "node_id": "MDEyOldvcmtmbG93IFJ1bjI2OTI4OQ==", + "check_suite_id": 42, + "check_suite_node_id": "MDEwOkNoZWNrU3VpdGU0Mg==", + "head_branch": "master", + "head_sha": "acb5820ced9479c074f688cc328bf03f341a511d", + "run_number": 562, + "event": "push", + "status": "queued", + "conclusion": null, + "workflow_id": 159038, + "url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642", + "html_url": "https://github.com/octo-org/octo-repo/actions/runs/30433642", + "pull_requests": [], + "created_at": "2020-01-22T19:33:08Z", + "updated_at": "2020-01-22T19:33:08Z", + "actor": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "run_attempt": 1, + "run_started_at": "2020-01-22T19:33:08Z", + "triggering_actor": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "jobs_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/jobs", + "logs_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/logs", + "check_suite_url": "https://api.github.com/repos/octo-org/octo-repo/check-suites/414944374", + "artifacts_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/artifacts", + "cancel_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/cancel", + "rerun_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/rerun", + "workflow_url": "https://api.github.com/repos/octo-org/octo-repo/actions/workflows/159038", + "head_commit": { + "id": "acb5820ced9479c074f688cc328bf03f341a511d", + "tree_id": "d23f6eedb1e1b9610bbc754ddb5197bfe7271223", + "message": "Create linter.yaml", + "timestamp": "2020-01-22T19:33:05Z", + "author": { + "name": "Octo Cat", + "email": "octocat@github.com" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com" + } + }, + "repository": { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks" + }, + "head_repository": { + "id": 217723378, + "node_id": "MDEwOlJlcG9zaXRvcnkyMTc3MjMzNzg=", + "name": "octo-repo", + "full_name": "octo-org/octo-repo", + "private": true, + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/octo-org/octo-repo", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/octo-org/octo-repo", + "forks_url": "https://api.github.com/repos/octo-org/octo-repo/forks", + "keys_url": "https://api.github.com/repos/octo-org/octo-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/octo-org/octo-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/octo-org/octo-repo/teams", + "hooks_url": "https://api.github.com/repos/octo-org/octo-repo/hooks", + "issue_events_url": "https://api.github.com/repos/octo-org/octo-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/octo-org/octo-repo/events", + "assignees_url": "https://api.github.com/repos/octo-org/octo-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/octo-org/octo-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/octo-org/octo-repo/tags", + "blobs_url": "https://api.github.com/repos/octo-org/octo-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/octo-org/octo-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/octo-org/octo-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/octo-org/octo-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/octo-org/octo-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/octo-org/octo-repo/languages", + "stargazers_url": "https://api.github.com/repos/octo-org/octo-repo/stargazers", + "contributors_url": "https://api.github.com/repos/octo-org/octo-repo/contributors", + "subscribers_url": "https://api.github.com/repos/octo-org/octo-repo/subscribers", + "subscription_url": "https://api.github.com/repos/octo-org/octo-repo/subscription", + "commits_url": "https://api.github.com/repos/octo-org/octo-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/octo-org/octo-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/octo-org/octo-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/octo-org/octo-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/octo-org/octo-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/octo-org/octo-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/octo-org/octo-repo/merges", + "archive_url": "https://api.github.com/repos/octo-org/octo-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/octo-org/octo-repo/downloads", + "issues_url": "https://api.github.com/repos/octo-org/octo-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/octo-org/octo-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/octo-org/octo-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octo-org/octo-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/octo-org/octo-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/octo-org/octo-repo/releases{/id}", + "deployments_url": "https://api.github.com/repos/octo-org/octo-repo/deployments" + } + } + ] +} From 9ccf4bebd7872b64916f2540afd4d5d19b0ddd91 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Sun, 5 Feb 2023 08:02:39 -0500 Subject: [PATCH 164/423] remove errant and unnecessary 'await's Signed-off-by: Mike Ball --- .../src/components/Cards/RecentWorkflowRunsCard.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx index 5e0a5f3e15..f55cad8424 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx @@ -94,7 +94,7 @@ describe('', () => { ); it('renders a table with a row for each workflow', async () => { - const subject = await renderSubject(); + const subject = renderSubject(); workflowRuns.forEach(run => { expect(subject.getByText(run.message)).toBeInTheDocument(); @@ -102,7 +102,7 @@ describe('', () => { }); it('renders a workflow row correctly', async () => { - const subject = await renderSubject(); + const subject = renderSubject(); const [run] = workflowRuns; expect(subject.getByText(run.message).closest('a')).toHaveAttribute( 'href', From b623d1c8980a623cf04bd9ee44131536049bbd7a Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Sun, 5 Feb 2023 08:28:35 -0500 Subject: [PATCH 165/423] add changeset documenting github-actions plugin fix Signed-off-by: Mike Ball --- .changeset/neat-elephants-breathe.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/neat-elephants-breathe.md diff --git a/.changeset/neat-elephants-breathe.md b/.changeset/neat-elephants-breathe.md new file mode 100644 index 0000000000..d1f88556e1 --- /dev/null +++ b/.changeset/neat-elephants-breathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-github-actions': patch +--- + +`yarn start` now starts a functional dev environment using a mock GitHub API to properly render the `` component. From 03570c71e44b81f0da89d7cf244c79e4687e6046 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 5 Feb 2023 16:07:08 +0100 Subject: [PATCH 166/423] backend-common: inline plugin database deps type Signed-off-by: Patrik Oldsberg --- packages/backend-common/api-report.md | 16 ++++++++-------- .../src/database/DatabaseManager.ts | 18 ++++++++++++++---- .../backend-common/src/database/connection.ts | 11 +++++++++-- .../src/database/connectors/sqlite3.ts | 11 +++++++++-- packages/backend-common/src/database/index.ts | 5 +---- packages/backend-common/src/database/types.ts | 15 ++++----------- 6 files changed, 45 insertions(+), 31 deletions(-) diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index 8b6311f8b0..e77a58b34c 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -234,7 +234,10 @@ export class Contexts { export function createDatabaseClient( dbConfig: Config, overrides?: Partial, - deps?: PluginDatabaseDependencies, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, ): Knex; // @public @@ -257,7 +260,10 @@ export function createStatusCheckRouter(options: { export class DatabaseManager { forPlugin( pluginId: string, - deps?: PluginDatabaseDependencies, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, ): PluginDatabaseManager; static fromConfig( config: Config, @@ -577,12 +583,6 @@ export function notFoundHandler(): RequestHandler; export { PluginCacheManager }; -// @public -export type PluginDatabaseDependencies = { - lifecycle: LifecycleService; - pluginMetadata: PluginMetadataService; -}; - export { PluginDatabaseManager }; export { PluginEndpointDiscovery }; diff --git a/packages/backend-common/src/database/DatabaseManager.ts b/packages/backend-common/src/database/DatabaseManager.ts index d8205faec1..08979a92f8 100644 --- a/packages/backend-common/src/database/DatabaseManager.ts +++ b/packages/backend-common/src/database/DatabaseManager.ts @@ -27,9 +27,13 @@ import { ensureSchemaExists, normalizeConnection, } from './connection'; -import { PluginDatabaseDependencies, PluginDatabaseManager } from './types'; +import { PluginDatabaseManager } from './types'; import path from 'path'; -import { LoggerService } from '@backstage/backend-plugin-api'; +import { + LifecycleService, + LoggerService, + PluginMetadataService, +} from '@backstage/backend-plugin-api'; import { stringifyError } from '@backstage/errors'; /** @@ -96,7 +100,10 @@ export class DatabaseManager { */ forPlugin( pluginId: string, - deps?: PluginDatabaseDependencies, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, ): PluginDatabaseManager { const _this = this; @@ -312,7 +319,10 @@ export class DatabaseManager { */ private async getDatabase( pluginId: string, - deps?: PluginDatabaseDependencies, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, ): Promise { if (this.databaseCache.has(pluginId)) { return this.databaseCache.get(pluginId)!; diff --git a/packages/backend-common/src/database/connection.ts b/packages/backend-common/src/database/connection.ts index 054ab7cfa8..ff10d349dd 100644 --- a/packages/backend-common/src/database/connection.ts +++ b/packages/backend-common/src/database/connection.ts @@ -19,9 +19,13 @@ import { JsonObject } from '@backstage/types'; import { InputError } from '@backstage/errors'; import knexFactory, { Knex } from 'knex'; import { mergeDatabaseConfig } from './config'; -import { DatabaseConnector, PluginDatabaseDependencies } from './types'; +import { DatabaseConnector } from './types'; import { mysqlConnector, pgConnector, sqlite3Connector } from './connectors'; +import { + LifecycleService, + PluginMetadataService, +} from '@backstage/backend-plugin-api'; type DatabaseClient = | 'pg' @@ -55,7 +59,10 @@ const ConnectorMapping: Record = { export function createDatabaseClient( dbConfig: Config, overrides?: Partial, - deps?: PluginDatabaseDependencies, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, ) { const client: DatabaseClient = dbConfig.getString('client'); diff --git a/packages/backend-common/src/database/connectors/sqlite3.ts b/packages/backend-common/src/database/connectors/sqlite3.ts index 299e18a111..5a2dc46f18 100644 --- a/packages/backend-common/src/database/connectors/sqlite3.ts +++ b/packages/backend-common/src/database/connectors/sqlite3.ts @@ -20,7 +20,11 @@ import knexFactory, { Knex } from 'knex'; import path from 'path'; import { DevDataStore } from '@backstage/backend-dev-utils'; import { mergeDatabaseConfig } from '../config'; -import { DatabaseConnector, PluginDatabaseDependencies } from '../types'; +import { DatabaseConnector } from '../types'; +import { + LifecycleService, + PluginMetadataService, +} from '@backstage/backend-plugin-api'; /** * Creates a knex SQLite3 database connection @@ -31,7 +35,10 @@ import { DatabaseConnector, PluginDatabaseDependencies } from '../types'; export function createSqliteDatabaseClient( dbConfig: Config, overrides?: Knex.Config, - deps?: PluginDatabaseDependencies, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, ) { const knexConfig = buildSqliteDatabaseConfig(dbConfig, overrides); const connConfig = knexConfig.connection as Knex.Sqlite3ConnectionConfig; diff --git a/packages/backend-common/src/database/index.ts b/packages/backend-common/src/database/index.ts index 483dbd9e40..0dde1ec239 100644 --- a/packages/backend-common/src/database/index.ts +++ b/packages/backend-common/src/database/index.ts @@ -22,8 +22,5 @@ export * from './DatabaseManager'; */ export { createDatabaseClient, ensureDatabaseExists } from './connection'; -export type { - PluginDatabaseManager, - PluginDatabaseDependencies, -} from './types'; +export type { PluginDatabaseManager } from './types'; export { isDatabaseConflictError } from './util'; diff --git a/packages/backend-common/src/database/types.ts b/packages/backend-common/src/database/types.ts index 7e96c44071..621bcc676b 100644 --- a/packages/backend-common/src/database/types.ts +++ b/packages/backend-common/src/database/types.ts @@ -23,16 +23,6 @@ import { Knex } from 'knex'; export type { DatabaseService as PluginDatabaseManager } from '@backstage/backend-plugin-api'; -/** - * Service dependencies for `PluginDatabaseManager`. - * - * @public - */ -export type PluginDatabaseDependencies = { - lifecycle: LifecycleService; - pluginMetadata: PluginMetadataService; -}; - /** * DatabaseConnector manages an underlying Knex database driver. */ @@ -43,7 +33,10 @@ export interface DatabaseConnector { createClient( dbConfig: Config, overrides?: Partial, - deps?: PluginDatabaseDependencies, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, ): Knex; /** * createNameOverride provides a partial knex config sufficient to override a From cbeba4b6f38d7db41f5b9d1f90585af2debaf614 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 5 Feb 2023 16:07:49 +0100 Subject: [PATCH 167/423] backend-common: simplify SQLite setup + work around warning Signed-off-by: Patrik Oldsberg --- .../src/database/connectors/sqlite3.ts | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/packages/backend-common/src/database/connectors/sqlite3.ts b/packages/backend-common/src/database/connectors/sqlite3.ts index 5a2dc46f18..e1ed6b18e9 100644 --- a/packages/backend-common/src/database/connectors/sqlite3.ts +++ b/packages/backend-common/src/database/connectors/sqlite3.ts @@ -43,47 +43,53 @@ export function createSqliteDatabaseClient( const knexConfig = buildSqliteDatabaseConfig(dbConfig, overrides); const connConfig = knexConfig.connection as Knex.Sqlite3ConnectionConfig; + const filename = connConfig.filename ?? ':memory:'; + // If storage on disk is used, ensure that the directory exists - if (connConfig.filename && connConfig.filename !== ':memory:') { - const directory = path.dirname(connConfig.filename); + if (filename !== ':memory:') { + const directory = path.dirname(filename); ensureDirSync(directory); } let database: Knex; - if (deps && connConfig.filename === ':memory:') { + if (deps && filename === ':memory:') { // The dev store is used during watch mode to store and restore the database // across reloads. It is only available when running the backend through // `backstage-cli package start`. const devStore = DevDataStore.get(); - const dataKey = `sqlite3-db-${deps.pluginMetadata.getId()}`; if (devStore) { + const dataKey = `sqlite3-db-${deps.pluginMetadata.getId()}`; + + const connectionLoader = async () => { + // If seed data is available, use it tconnectionLoader restore the database + const { data: seedData } = await devStore.load(dataKey); + + return { + ...(knexConfig.connection as Knex.Sqlite3ConnectionConfig), + filename: seedData ?? ':memory:', + }; + }; + database = knexFactory({ ...knexConfig, - connection: async () => { - // If seed data is available, use it to restore the database - const { data: seedData } = await devStore?.load(dataKey); - - return { - ...(knexConfig.connection as Knex.Sqlite3ConnectionConfig), - filename: seedData ?? ':memory:', - }; - }, + connection: Object.assign(connectionLoader, { + // This is a workaround for the knex SQLite driver always warning when using a config loader + filename: ':memory:', + }), }); - } else { - database = knexFactory(knexConfig); - } - if (devStore) { // If the dev store is available we save the database state on shutdown - deps?.lifecycle?.addShutdownHook({ + deps.lifecycle.addShutdownHook({ async fn() { const connection = await database.client.acquireConnection(); const data = connection.serialize(); await devStore.save(dataKey, data); }, }); + } else { + database = knexFactory(knexConfig); } } else { database = knexFactory(knexConfig); From 4f5bf2835c43699d61d6313abde4ec9a2329d025 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 5 Feb 2023 16:11:23 +0100 Subject: [PATCH 168/423] backend-app-api: tweak backend initializer to wait for startup before shutdown Signed-off-by: Patrik Oldsberg --- .../src/wiring/BackendInitializer.ts | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index d1139615f1..4bdee8b085 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -28,7 +28,7 @@ import { } from './types'; export class BackendInitializer { - #started = false; + #startPromise?: Promise; #features = new Map(); #registerInits = new Array(); #extensionPoints = new Map, unknown>(); @@ -75,30 +75,40 @@ export class BackendInitializer { } add(feature: BackendFeature, options?: TOptions) { - if (this.#started) { + if (this.#startPromise) { throw new Error('feature can not be added after the backend has started'); } this.#features.set(feature, options); } async start(): Promise { - if (this.#started) { + if (this.#startPromise) { throw new Error('Backend has already started'); } - this.#started = true; - for (const event of ['SIGTERM', 'SIGINT', 'beforeExit']) { - process.on(event, async () => { - try { - await this.stop(); - process.exit(0); - } catch (error) { - console.error(error); - process.exit(1); - } - }); - } + const exitHandler = async () => { + process.removeListener('SIGTERM', exitHandler); + process.removeListener('SIGINT', exitHandler); + process.removeListener('beforeExit', exitHandler); + try { + await this.stop(); + process.exit(0); + } catch (error) { + console.error(error); + process.exit(1); + } + }; + + process.addListener('SIGTERM', exitHandler); + process.addListener('SIGINT', exitHandler); + process.addListener('beforeExit', exitHandler); + + this.#startPromise = this.#doStart(); + await this.#startPromise; + } + + async #doStart(): Promise { // Initialize all root scoped services for (const ref of this.#serviceHolder.getServiceRefs()) { if (ref.scope === 'root') { @@ -189,9 +199,10 @@ export class BackendInitializer { } async stop(): Promise { - if (!this.#started) { + if (!this.#startPromise) { return; } + await this.#startPromise; const lifecycleService = await this.#serviceHolder.get( coreServices.rootLifecycle, From 81c06d5a4ad0e4579e40526dcb73e5f7728b21a3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 5 Feb 2023 16:11:47 +0100 Subject: [PATCH 169/423] backend-dev-utils: remove message listener when IPC client reuqest times out Signed-off-by: Patrik Oldsberg --- packages/backend-dev-utils/src/ipcClient.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/backend-dev-utils/src/ipcClient.ts b/packages/backend-dev-utils/src/ipcClient.ts index d3fa184a3f..87c1596a39 100644 --- a/packages/backend-dev-utils/src/ipcClient.ts +++ b/packages/backend-dev-utils/src/ipcClient.ts @@ -84,10 +84,7 @@ export class BackstageIpcClient { return; } - const timeout = setTimeout(() => { - reject(new Error('IPC request timed out')); - }, 1000); - timeout.unref(); + let timeout: NodeJS.Timeout | undefined = undefined; const messageHandler = (response: Response) => { if (response?.type !== responseType) { @@ -111,6 +108,12 @@ export class BackstageIpcClient { process.removeListener('message', messageHandler); }; + timeout = setTimeout(() => { + reject(new Error(`IPC request '${method}' with ID ${id} timed out`)); + process.removeListener('message', messageHandler); + }, 5000); + timeout.unref(); + process.addListener('message', messageHandler as () => void); }); }); From 1e6f5fcfede627b980d8e627b94ed8b857219213 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 5 Feb 2023 16:12:53 +0100 Subject: [PATCH 170/423] cli: rename ChannelServer to IpcServer Signed-off-by: Patrik Oldsberg --- .../src/lib/experimental/{ChannelServer.ts => IpcServer.ts} | 2 +- packages/cli/src/lib/experimental/ServerDataStore.ts | 4 ++-- packages/cli/src/lib/experimental/startBackendExperimental.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename packages/cli/src/lib/experimental/{ChannelServer.ts => IpcServer.ts} (98%) diff --git a/packages/cli/src/lib/experimental/ChannelServer.ts b/packages/cli/src/lib/experimental/IpcServer.ts similarity index 98% rename from packages/cli/src/lib/experimental/ChannelServer.ts rename to packages/cli/src/lib/experimental/IpcServer.ts index db949f95b8..8ceb72b046 100644 --- a/packages/cli/src/lib/experimental/ChannelServer.ts +++ b/packages/cli/src/lib/experimental/IpcServer.ts @@ -36,7 +36,7 @@ interface Request { const requestType = '@backstage/cli/channel/request'; const responseType = '@backstage/cli/channel/response'; -export class ChannelServer { +export class IpcServer { #generation = 1; #methods = new Map>(); diff --git a/packages/cli/src/lib/experimental/ServerDataStore.ts b/packages/cli/src/lib/experimental/ServerDataStore.ts index 29ac331de5..c0232157cb 100644 --- a/packages/cli/src/lib/experimental/ServerDataStore.ts +++ b/packages/cli/src/lib/experimental/ServerDataStore.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ChannelServer } from './ChannelServer'; +import { IpcServer } from './IpcServer'; interface StorageItem { generation: number; @@ -40,7 +40,7 @@ interface LoadResponse { } export class ServerDataStore { - static bind(server: ChannelServer): void { + static bind(server: IpcServer): void { const store = new Map(); server.registerMethod( diff --git a/packages/cli/src/lib/experimental/startBackendExperimental.ts b/packages/cli/src/lib/experimental/startBackendExperimental.ts index 94bf066925..c08fbda0da 100644 --- a/packages/cli/src/lib/experimental/startBackendExperimental.ts +++ b/packages/cli/src/lib/experimental/startBackendExperimental.ts @@ -19,7 +19,7 @@ import type { ChildProcess } from 'child_process'; import { fileURLToPath } from 'url'; import { isAbsolute as isAbsolutePath } from 'path'; import { FSWatcher, watch } from 'chokidar'; -import { ChannelServer } from './ChannelServer'; +import { IpcServer } from './IpcServer'; import { ServerDataStore } from './ServerDataStore'; import debounce from 'lodash/debounce'; import spawn from 'cross-spawn'; @@ -34,7 +34,7 @@ export async function startBackendExperimental(options: BackendServeOptions) { } // Set up the parent IPC server and bind the available services - const server = new ChannelServer(); + const server = new IpcServer(); ServerDataStore.bind(server); let exiting = false; From 9f52a76778074d1d9405ac804c9aca9f5c0c5d53 Mon Sep 17 00:00:00 2001 From: ivgo Date: Fri, 3 Feb 2023 16:01:53 +0100 Subject: [PATCH 171/423] Remove node package, update api-report & props Signed-off-by: ivgo --- plugins/entity-validation/api-report.md | 9 +-- plugins/entity-validation/package.json | 2 +- .../EntityValidationOutput.tsx | 2 +- .../EntityValidationPage.tsx | 21 +++--- .../entity-validation/src/processingResult.ts | 73 +++++++++++++++++++ plugins/entity-validation/src/types.ts | 54 +++++++++++++- .../src/{utils => }/utils.ts | 6 +- plugins/entity-validation/src/utils/index.ts | 16 ---- yarn.lock | 2 +- 9 files changed, 146 insertions(+), 39 deletions(-) create mode 100644 plugins/entity-validation/src/processingResult.ts rename plugins/entity-validation/src/{utils => }/utils.ts (95%) delete mode 100644 plugins/entity-validation/src/utils/index.ts diff --git a/plugins/entity-validation/api-report.md b/plugins/entity-validation/api-report.md index 1a3b92a7c1..2fccbf9471 100644 --- a/plugins/entity-validation/api-report.md +++ b/plugins/entity-validation/api-report.md @@ -9,12 +9,9 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { RouteRef } from '@backstage/core-plugin-api'; // @public (undocumented) -export const EntityValidationPage: ({ - defaultPreviewCatalog, - locationPlaceholder, -}: { - defaultPreviewCatalog?: string | undefined; - locationPlaceholder?: string | undefined; +export const EntityValidationPage: (props: { + defaultYaml?: string | undefined; + defaultLocation?: string | undefined; }) => JSX.Element; // @public (undocumented) diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index a6ea724473..3ff4f0ad5c 100644 --- a/plugins/entity-validation/package.json +++ b/plugins/entity-validation/package.json @@ -31,8 +31,8 @@ "@backstage/catalog-model": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", + "@backstage/errors": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", - "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/theme": "workspace:^", "@codemirror/language": "^6.0.0", diff --git a/plugins/entity-validation/src/components/EntityValidationOutput/EntityValidationOutput.tsx b/plugins/entity-validation/src/components/EntityValidationOutput/EntityValidationOutput.tsx index f58fc90559..bc7e22ef54 100644 --- a/plugins/entity-validation/src/components/EntityValidationOutput/EntityValidationOutput.tsx +++ b/plugins/entity-validation/src/components/EntityValidationOutput/EntityValidationOutput.tsx @@ -15,7 +15,6 @@ */ import React from 'react'; import { identityApiRef, useApi } from '@backstage/core-plugin-api'; -import { CatalogProcessorResult } from '@backstage/plugin-catalog-node'; import { catalogApiRef, humanizeEntityRef, @@ -25,6 +24,7 @@ import useAsync from 'react-use/lib/useAsync'; import { InfoCard, Progress } from '@backstage/core-components'; import Alert from '@material-ui/lab/Alert'; import { + CatalogProcessorResult, ValidationOutput, ValidationOutputError, ValidationOutputOk, diff --git a/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx b/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx index d39b234342..dc86af8763 100644 --- a/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx +++ b/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx @@ -17,7 +17,7 @@ import React, { useState } from 'react'; import { Button, Content, Header, Page } from '@backstage/core-components'; import { EntityTextArea } from '../EntityTextArea'; import { Grid, TextField } from '@material-ui/core'; -import { CatalogProcessorResult } from '@backstage/plugin-catalog-node'; +import { CatalogProcessorResult } from '../../types'; import { parseEntityYaml } from '../../utils'; import { EntityValidationOutput } from '../EntityValidationOutput'; @@ -36,14 +36,16 @@ spec: owner: owner `; -export const EntityValidationPage = ({ - defaultPreviewCatalog = EXAMPLE_CATALOG_INFO_YAML, - locationPlaceholder = 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', -}: { - defaultPreviewCatalog?: string; - locationPlaceholder?: string; +export const EntityValidationPage = (props: { + defaultYaml?: string; + defaultLocation?: string; }) => { - const [catalogYaml, setCatalogYaml] = useState(defaultPreviewCatalog); + const { + defaultYaml = EXAMPLE_CATALOG_INFO_YAML, + defaultLocation = 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', + } = props; + + const [catalogYaml, setCatalogYaml] = useState(defaultYaml); const [yamlFiles, setYamlFiles] = useState(); const [locationUrl, setLocationUrl] = useState(''); @@ -72,7 +74,8 @@ export const EntityValidationPage = ({ margin="normal" variant="outlined" required - placeholder={locationPlaceholder} + value={defaultLocation} + placeholder={defaultLocation} helperText="Location where you catalog-info.yaml file is, or will be, located" onChange={e => setLocationUrl(e.target.value)} /> diff --git a/plugins/entity-validation/src/processingResult.ts b/plugins/entity-validation/src/processingResult.ts new file mode 100644 index 0000000000..de9d8adbbd --- /dev/null +++ b/plugins/entity-validation/src/processingResult.ts @@ -0,0 +1,73 @@ +/* + * 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. + */ + +// File copied from https://github.com/backstage/backstage/blob/master/plugins/catalog-node/src/api/processingResult.ts +import { InputError, NotFoundError } from '@backstage/errors'; +import { Entity } from '@backstage/catalog-model'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; +import { CatalogProcessorResult, EntityRelationSpec } from './types'; + +/** + * Factory functions for the standard processing result types. + * + * @public + */ +export const processingResult = Object.freeze({ + notFoundError( + atLocation: LocationSpec, + message: string, + ): CatalogProcessorResult { + return { + type: 'error', + location: atLocation, + error: new NotFoundError(message), + }; + }, + + inputError( + atLocation: LocationSpec, + message: string, + ): CatalogProcessorResult { + return { + type: 'error', + location: atLocation, + error: new InputError(message), + }; + }, + + generalError( + atLocation: LocationSpec, + message: string, + ): CatalogProcessorResult { + return { type: 'error', location: atLocation, error: new Error(message) }; + }, + + location(newLocation: LocationSpec): CatalogProcessorResult { + return { type: 'location', location: newLocation }; + }, + + entity(atLocation: LocationSpec, newEntity: Entity): CatalogProcessorResult { + return { type: 'entity', location: atLocation, entity: newEntity }; + }, + + relation(spec: EntityRelationSpec): CatalogProcessorResult { + return { type: 'relation', relation: spec }; + }, + + refresh(key: string): CatalogProcessorResult { + return { type: 'refresh', key }; + }, +} as const); diff --git a/plugins/entity-validation/src/types.ts b/plugins/entity-validation/src/types.ts index 69caf79e33..7ecc27bb25 100644 --- a/plugins/entity-validation/src/types.ts +++ b/plugins/entity-validation/src/types.ts @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; +import { CompoundEntityRef, Entity } from '@backstage/catalog-model'; import { ValidateEntityResponse } from '@backstage/catalog-client'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; export type ValidationOutputError = { type: 'error'; @@ -28,3 +29,54 @@ export type ValidationOutputOk = { }; export type ValidationOutput = ValidationOutputOk | ValidationOutputError; + +export type EntityRelationSpec = { + /** + * The source entity of this relation. + */ + source: CompoundEntityRef; + + /** + * The type of the relation. + */ + type: string; + + /** + * The target entity of this relation. + */ + target: CompoundEntityRef; +}; + +type CatalogProcessorLocationResult = { + type: 'location'; + location: LocationSpec; +}; + +type CatalogProcessorEntityResult = { + type: 'entity'; + entity: Entity; + location: LocationSpec; +}; + +type CatalogProcessorRelationResult = { + type: 'relation'; + relation: EntityRelationSpec; +}; + +type CatalogProcessorErrorResult = { + type: 'error'; + error: Error; + location: LocationSpec; +}; + +type CatalogProcessorRefreshKeysResult = { + type: 'refresh'; + key: string; +}; + +export type CatalogProcessorResult = + | CatalogProcessorLocationResult + | CatalogProcessorEntityResult + | CatalogProcessorRelationResult + | CatalogProcessorErrorResult + | CatalogProcessorRefreshKeysResult; diff --git a/plugins/entity-validation/src/utils/utils.ts b/plugins/entity-validation/src/utils.ts similarity index 95% rename from plugins/entity-validation/src/utils/utils.ts rename to plugins/entity-validation/src/utils.ts index dde50d2f9c..d81de6f6c9 100644 --- a/plugins/entity-validation/src/utils/utils.ts +++ b/plugins/entity-validation/src/utils.ts @@ -17,10 +17,8 @@ import { Entity, stringifyLocationRef } from '@backstage/catalog-model'; import lodash from 'lodash'; import yaml from 'yaml'; import { LocationSpec } from '@backstage/plugin-catalog-common'; -import { - CatalogProcessorResult, - processingResult, -} from '@backstage/plugin-catalog-node'; +import { CatalogProcessorResult } from './types'; +import { processingResult } from './processingResult'; // Copy from: https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/modules/util/parse.ts export function* parseEntityYaml( diff --git a/plugins/entity-validation/src/utils/index.ts b/plugins/entity-validation/src/utils/index.ts deleted file mode 100644 index 8d45a67a36..0000000000 --- a/plugins/entity-validation/src/utils/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2023 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 './utils'; diff --git a/yarn.lock b/yarn.lock index a3e9612ca6..7e53aaf8bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5770,8 +5770,8 @@ __metadata: "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" + "@backstage/errors": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" - "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" From db10b6ef6583677fa492bb4a8b79aa5d06c16eb9 Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Mon, 6 Feb 2023 08:54:01 +0100 Subject: [PATCH 172/423] feat(auth): add auth provider for Bitbucket Server Signed-off-by: Katharina Sick --- .changeset/pretty-jars-peel.md | 9 + docs/auth/bitbucket/provider.md | 2 +- docs/auth/bitbucketServer/provider.md | 52 +++ docs/auth/index.md | 1 + packages/app-defaults/src/defaults/apis.ts | 15 + packages/app/src/identityProviders.ts | 7 + packages/backend/src/plugins/auth.ts | 7 + .../BitbucketServerAuth.test.ts | 51 +++ .../bitbucketServer/BitbucketServerAuth.ts | 66 +++ .../auth/bitbucketServer/index.ts | 18 + .../auth/bitbucketServer/types.ts | 35 ++ .../src/apis/implementations/auth/index.ts | 1 + .../src/apis/definitions/auth.ts | 15 + .../src/providers/bitbucketServer/index.ts | 18 + .../bitbucketServer/provider.test.ts | 377 ++++++++++++++++++ .../src/providers/bitbucketServer/provider.ts | 297 ++++++++++++++ plugins/auth-backend/src/providers/index.ts | 1 + .../auth-backend/src/providers/providers.ts | 3 + .../AuthProviders/DefaultProviderSettings.tsx | 9 + 19 files changed, 983 insertions(+), 1 deletion(-) create mode 100644 .changeset/pretty-jars-peel.md create mode 100644 docs/auth/bitbucketServer/provider.md create mode 100644 packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.test.ts create mode 100644 packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.ts create mode 100644 packages/core-app-api/src/apis/implementations/auth/bitbucketServer/index.ts create mode 100644 packages/core-app-api/src/apis/implementations/auth/bitbucketServer/types.ts create mode 100644 plugins/auth-backend/src/providers/bitbucketServer/index.ts create mode 100644 plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts create mode 100644 plugins/auth-backend/src/providers/bitbucketServer/provider.ts diff --git a/.changeset/pretty-jars-peel.md b/.changeset/pretty-jars-peel.md new file mode 100644 index 0000000000..639d4565ed --- /dev/null +++ b/.changeset/pretty-jars-peel.md @@ -0,0 +1,9 @@ +--- +'@backstage/core-plugin-api': minor +'@backstage/app-defaults': minor +'@backstage/core-app-api': minor +'@backstage/plugin-user-settings': minor +'@backstage/plugin-auth-backend': minor +--- + +Added a Bitbucket Server Auth Provider and added its API to the app defaults diff --git a/docs/auth/bitbucket/provider.md b/docs/auth/bitbucket/provider.md index 36859dab45..b03201893c 100644 --- a/docs/auth/bitbucket/provider.md +++ b/docs/auth/bitbucket/provider.md @@ -61,7 +61,7 @@ how this is done. Note that for the Bitbucket provider, you'll want to use factory. The `@backstage/plugin-auth-backend` plugin also comes with two built-in -resolves that can be used if desired. The first one is the +resolvers that can be used if desired. The first one is the `bitbucketUsernameSignInResolver`, which identifies users by matching their Bitbucket username to `bitbucket.org/username` annotations of `User` entities in the catalog. Note that you must populate your catalog with matching entities or diff --git a/docs/auth/bitbucketServer/provider.md b/docs/auth/bitbucketServer/provider.md new file mode 100644 index 0000000000..96c7db263e --- /dev/null +++ b/docs/auth/bitbucketServer/provider.md @@ -0,0 +1,52 @@ +--- +id: provider +title: Bitbucket Server Authentication Provider +sidebar_label: Bitbucket Server +description: Adding Bitbucket Server OAuth as an authentication provider in Backstage +--- + +The Backstage `core-plugin-api` package comes with a Bitbucket Server authentication provider that can authenticate +users using Bitbucket Server. This does **NOT** work with Bitbucket Cloud. + +## Create an Application Link in Bitbucket Server + +To add Bitbucket Server authentication, you must create an outgoing application link. Follow the steps described in +the [Bitbucket Server documentation](https://confluence.atlassian.com/bitbucketserver/configure-an-outgoing-link-1108483656.html) +to create one. + +## Configuration + +The provider configuration can then be added to your `app-config.yaml` under the root `auth` configuration: + +```yaml +auth: + environment: development + providers: + bitbucketServer: + development: + host: bitbucket.org + clientId: ${AUTH_BITBUCKET_SERVER_CLIENT_ID} + clientSecret: ${AUTH_BITBUCKET_SERVER_CLIENT_SECRET} +``` + +The Bitbucket Server provider is a structure with two configuration keys: + +- `clientId`: The client ID that was generated by Bitbucket, e.g. `b0f868455c15dcdff5c5fb5d173ae684`. +- `clientSecret`: The client secret tied to the generated client ID. + +## Adding the provider to the Backstage frontend + +To add the provider to the frontend, add the `bitbucketServerAuthApi` reference and `SignInPage` component as shown +in [Adding the provider to the sign-in page](../index.md#adding-the-provider-to-the-sign-in-page). + +## Using Bitbucket Server for sign-in + +In order to use the Bitbucket Server provider for sign-in, you must configure it with a `signIn.resolver`. See +the [Sign-In Resolver documentation](../identity-resolver.md) for more details on how this is done. Note that for the +Bitbucket Server provider, you'll want to use `bitbucketServer` as the provider ID, +and `providers.bitbucketServer.create` for the provider factory. + +The `@backstage/plugin-auth-backend` plugin also comes with a built-in resolver that can be used if desired. +The `emailMatchingUserEntityProfileEmail` identifies users by matching their Bitbucket Server email address to the email +address of `User` entities in the catalog. Note that you must populate your catalog with matching entities or users will +not be able to sign in with this resolver. diff --git a/docs/auth/index.md b/docs/auth/index.md index fa185c0c23..8e15830aa8 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -18,6 +18,7 @@ Backstage comes with many common authentication providers in the core library: - [Auth0](auth0/provider.md) - [Azure](microsoft/provider.md) - [Bitbucket](bitbucket/provider.md) +- [Bitbucket Server](bitbucketServer/provider.md) - [Cloudflare Access](cloudflare/access.md) - [GitHub](github/provider.md) - [GitLab](gitlab/provider.md) diff --git a/packages/app-defaults/src/defaults/apis.ts b/packages/app-defaults/src/defaults/apis.ts index 3f5cfc1c58..d3ebddfb84 100644 --- a/packages/app-defaults/src/defaults/apis.ts +++ b/packages/app-defaults/src/defaults/apis.ts @@ -25,6 +25,7 @@ import { GitlabAuth, MicrosoftAuth, BitbucketAuth, + BitbucketServerAuth, OAuthRequestManager, WebStorage, UrlPatternDiscovery, @@ -53,6 +54,7 @@ import { configApiRef, oneloginAuthApiRef, bitbucketAuthApiRef, + bitbucketServerAuthApiRef, atlassianAuthApiRef, } from '@backstage/core-plugin-api'; import { @@ -219,6 +221,19 @@ export const apis = [ environment: configApi.getOptionalString('auth.environment'), }), }), + createApiFactory({ + api: bitbucketServerAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + BitbucketServerAuth.create({ + discoveryApi, + oauthRequestApi, + defaultScopes: ['REPO_READ'], + }), + }), createApiFactory({ api: atlassianAuthApiRef, deps: { diff --git a/packages/app/src/identityProviders.ts b/packages/app/src/identityProviders.ts index 5f8c0faf47..66f1460210 100644 --- a/packages/app/src/identityProviders.ts +++ b/packages/app/src/identityProviders.ts @@ -22,6 +22,7 @@ import { microsoftAuthApiRef, oneloginAuthApiRef, bitbucketAuthApiRef, + bitbucketServerAuthApiRef, } from '@backstage/core-plugin-api'; export const providers = [ @@ -67,4 +68,10 @@ export const providers = [ message: 'Sign In using Bitbucket', apiRef: bitbucketAuthApiRef, }, + { + id: 'bitbucket-server-auth-provider', + title: 'Bitbucket Server', + message: 'Sign In using Bitbucket Server', + apiRef: bitbucketServerAuthApiRef, + }, ]; diff --git a/packages/backend/src/plugins/auth.ts b/packages/backend/src/plugins/auth.ts index 8beda6f3fb..0d92315f92 100644 --- a/packages/backend/src/plugins/auth.ts +++ b/packages/backend/src/plugins/auth.ts @@ -114,6 +114,13 @@ export default async function createPlugin( }, }), + bitbucketServer: providers.bitbucketServer.create({ + signIn: { + resolver: + providers.bitbucketServer.resolvers.emailMatchingUserEntityProfileEmail(), + }, + }), + // This is an example of how to configure the OAuth2Proxy provider as well // as how to sign a user in without a matching user entity in the catalog. // You can try it out using `` diff --git a/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.test.ts b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.test.ts new file mode 100644 index 0000000000..32e7755a00 --- /dev/null +++ b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.test.ts @@ -0,0 +1,51 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import MockOAuthApi from '../../OAuthRequestApi/MockOAuthApi'; +import { UrlPatternDiscovery } from '../../DiscoveryApi'; +import BitbucketServerAuth from './BitbucketServerAuth'; + +const getSession = jest.fn(); + +jest.mock('../../../../lib/AuthSessionManager', () => ({ + ...(jest.requireActual('../../../../lib/AuthSessionManager') as any), + RefreshingAuthSessionManager: class { + getSession = getSession; + }, +})); + +describe('BitbucketServerAuth', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + it.each([ + ['PUBLIC_REPOS', ['PUBLIC_REPOS']], + ['PROJECT_ADMIN REPO_READ', ['PROJECT_ADMIN', 'REPO_READ']], + [ + 'PROJECT_ADMIN REPO_READ ACCOUNT_WRITE', + ['PROJECT_ADMIN', 'REPO_READ', 'ACCOUNT_WRITE'], + ], + ])(`should normalize scopes correctly - %p`, (scope, scopes) => { + const bitbucketServerAuth = BitbucketServerAuth.create({ + oauthRequestApi: new MockOAuthApi(), + discoveryApi: UrlPatternDiscovery.compile('http://example.com'), + }); + + bitbucketServerAuth.getAccessToken(scope); + expect(getSession).toHaveBeenCalledWith({ scopes: new Set(scopes) }); + }); +}); diff --git a/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.ts b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.ts new file mode 100644 index 0000000000..dc50eff6ab --- /dev/null +++ b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.ts @@ -0,0 +1,66 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BackstageIdentityResponse, + bitbucketServerAuthApiRef, + ProfileInfo, +} from '@backstage/core-plugin-api'; + +import { OAuthApiCreateOptions } from '../types'; +import { OAuth2 } from '../oauth2'; + +export type BitbucketServerAuthResponse = { + providerInfo: { + accessToken: string; + scope: string; + expiresInSeconds: number; + }; + profile: ProfileInfo; + backstageIdentity: BackstageIdentityResponse; +}; + +const DEFAULT_PROVIDER = { + id: 'bitbucketServer', + title: 'Bitbucket Server', + icon: () => null, +}; + +/** + * Implements the OAuth flow to Bitbucket Server. + * @public + */ +export default class BitbucketServerAuth { + static create( + options: OAuthApiCreateOptions, + ): typeof bitbucketServerAuthApiRef.T { + const { + discoveryApi, + environment = 'development', + provider = DEFAULT_PROVIDER, + oauthRequestApi, + defaultScopes = ['PROJECT_ADMIN'], + } = options; + + return OAuth2.create({ + discoveryApi, + oauthRequestApi, + provider, + environment, + defaultScopes, + }); + } +} diff --git a/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/index.ts b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/index.ts new file mode 100644 index 0000000000..5fcb8f72f2 --- /dev/null +++ b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/index.ts @@ -0,0 +1,18 @@ +/* + * 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 * from './types'; +export { default as BitbucketServerAuth } from './BitbucketServerAuth'; diff --git a/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/types.ts b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/types.ts new file mode 100644 index 0000000000..1041aa8110 --- /dev/null +++ b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/types.ts @@ -0,0 +1,35 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ProfileInfo, + BackstageIdentityResponse, +} from '@backstage/core-plugin-api'; + +/** + * Session information for Bitbucket Server auth. + * + * @public + */ +export type BitbucketServerSession = { + providerInfo: { + accessToken: string; + scopes: Set; + expiresAt?: Date; + }; + profile: ProfileInfo; + backstageIdentity: BackstageIdentityResponse; +}; diff --git a/packages/core-app-api/src/apis/implementations/auth/index.ts b/packages/core-app-api/src/apis/implementations/auth/index.ts index c4cf520db5..b54e0424da 100644 --- a/packages/core-app-api/src/apis/implementations/auth/index.ts +++ b/packages/core-app-api/src/apis/implementations/auth/index.ts @@ -23,5 +23,6 @@ export * from './saml'; export * from './microsoft'; export * from './onelogin'; export * from './bitbucket'; +export * from './bitbucketServer'; export * from './atlassian'; export type { OAuthApiCreateOptions, AuthApiCreateOptions } from './types'; diff --git a/packages/core-plugin-api/src/apis/definitions/auth.ts b/packages/core-plugin-api/src/apis/definitions/auth.ts index 163ae74806..43597639b6 100644 --- a/packages/core-plugin-api/src/apis/definitions/auth.ts +++ b/packages/core-plugin-api/src/apis/definitions/auth.ts @@ -412,6 +412,21 @@ export const bitbucketAuthApiRef: ApiRef< id: 'core.auth.bitbucket', }); +/** + * Provides authentication towards Bitbucket Server APIs. + * + * @public + * @remarks + * + * See {@link https://confluence.atlassian.com/bitbucketserver/bitbucket-oauth-2-0-provider-api-1108483661.html#BitbucketOAuth2.0providerAPI-scopes} + * for a full list of supported scopes. + */ +export const bitbucketServerAuthApiRef: ApiRef< + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi +> = createApiRef({ + id: 'core.auth.bitbucket-server', +}); + /** * Provides authentication towards Atlassian APIs. * diff --git a/plugins/auth-backend/src/providers/bitbucketServer/index.ts b/plugins/auth-backend/src/providers/bitbucketServer/index.ts new file mode 100644 index 0000000000..cef12cd50d --- /dev/null +++ b/plugins/auth-backend/src/providers/bitbucketServer/index.ts @@ -0,0 +1,18 @@ +/* + * 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 { bitbucketServer } from './provider'; +export type { BitbucketServerOAuthResult } from './provider'; diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts new file mode 100644 index 0000000000..127ca71a17 --- /dev/null +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts @@ -0,0 +1,377 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as helpers from '../../lib/passport/PassportStrategyHelper'; +import { makeProfileInfo } from '../../lib/passport/PassportStrategyHelper'; +import { AuthResolverContext } from '../types'; +import { + BitbucketServerAuthProvider, + BitbucketServerOAuthResult, +} from './provider'; +import { commonByEmailResolver } from '../resolvers'; + +jest.mock('../../lib/passport/PassportStrategyHelper', () => { + return { + ...jest.requireActual('../../lib/passport/PassportStrategyHelper'), + executeFrameHandlerStrategy: jest.fn(), + executeRefreshTokenStrategy: jest.fn(), + executeFetchUserProfileStrategy: jest.fn(), + }; +}); + +const mockFrameHandler = jest.spyOn( + helpers, + 'executeFrameHandlerStrategy', +) as unknown as jest.MockedFunction< + () => Promise<{ + result: BitbucketServerOAuthResult; + privateInfo: { refreshToken?: string }; + }> +>; + +const passportProfile = { + id: '123', + username: 'john.doe', + provider: 'bitubcketServer', + displayName: 'John Doe', + emails: [{ value: 'john@doe.com' }], + photos: [{ value: 'https://bitbucket.org/user/123/avatar' }], +}; + +const mockFetchUserRequests = ( + failOnWhoAmI: boolean = false, + whoAmIValue: string = passportProfile.username, + failOnGetUser: boolean = false, + getUserOk: boolean = true, + avatarUrl: string = '/user/123/avatar', + setDisplayName: boolean = true, + setUserName: boolean = true, +) => { + const fetchMock = global.fetch as jest.Mock; + if (failOnWhoAmI) { + fetchMock.mockRejectedValueOnce(() => {}); + } else { + fetchMock.mockResolvedValueOnce({ + headers: { get: jest.fn(() => whoAmIValue) }, + }); + } + if (failOnGetUser) { + fetchMock.mockRejectedValueOnce(() => {}); + } else { + fetchMock.mockResolvedValueOnce({ + ok: getUserOk, + json: () => ({ + name: setUserName ? 'john.doe' : undefined, + emailAddress: 'john@doe.com', + id: 123, + displayName: setDisplayName ? 'John Doe' : undefined, + active: true, + slug: 'john.doe', + type: 'NORMAL', + links: { + self: [ + { + href: 'https://bitbucket.org/users/john.doe', + }, + ], + }, + avatarUrl: avatarUrl, + }), + }); + } +}; + +describe('BitbucketServerAuthProvider', () => { + const originalFetch = global.fetch; + + beforeEach(() => { + global.fetch = jest.fn(); + }); + + afterEach(() => { + global.fetch = originalFetch; + }); + + const provider = new BitbucketServerAuthProvider({ + resolverContext: { + signInWithCatalogUser: jest.fn(info => { + return { + token: `token-for-user:${info.filter['spec.profile.email']}`, + }; + }), + } as unknown as AuthResolverContext, + signInResolver: commonByEmailResolver, + authHandler: async ({ fullProfile }) => ({ + profile: makeProfileInfo(fullProfile), + }), + callbackUrl: 'mock', + clientId: 'mock', + clientSecret: 'mock', + host: 'bitbucket.org', + authorizationUrl: 'mock', + tokenUrl: 'mock', + }); + + describe('when transforming to type OAuthResponse', () => { + it('should map to a valid response', async () => { + mockFetchUserRequests(); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + + const expected = { + backstageIdentity: { + token: 'token-for-user:john@doe.com', + }, + providerInfo: { + accessToken: '19xasczxcm9n7gacn9jdgm19me', + scope: 'REPO_READ', + }, + profile: { + email: 'john@doe.com', + displayName: 'John Doe', + picture: 'https://bitbucket.org/user/123/avatar', + }, + }; + + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + const { response } = await provider.handler({} as any); + expect(response).toEqual(expected); + }); + it('should throw if whoami fails', async () => { + mockFetchUserRequests(true); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + + await expect(provider.handler({} as any)).rejects.toThrow( + `Failed to retrieve the username of the logged in user`, + ); + }); + it('should throw if whoami returns an invalid response', async () => { + mockFetchUserRequests(false, ''); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + + await expect(provider.handler({} as any)).rejects.toThrow( + `Failed to retrieve the username of the logged in user`, + ); + }); + it('should throw if get user fails', async () => { + mockFetchUserRequests(false, passportProfile.username, true); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + + await expect(provider.handler({} as any)).rejects.toThrow( + `Failed to retrieve the user '${passportProfile.username}'`, + ); + }); + it('should throw if get user is not ok', async () => { + mockFetchUserRequests(false, passportProfile.username, false, false); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + + await expect(provider.handler({} as any)).rejects.toThrow( + `Failed to retrieve the user '${passportProfile.username}'`, + ); + }); + it('should not set an avatar url if not given', async () => { + mockFetchUserRequests(false, passportProfile.username, false, true, ''); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + + const expected = { + backstageIdentity: { + token: 'token-for-user:john@doe.com', + }, + providerInfo: { + accessToken: '19xasczxcm9n7gacn9jdgm19me', + scope: 'REPO_READ', + }, + profile: { + email: 'john@doe.com', + displayName: 'John Doe', + }, + }; + + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + const { response } = await provider.handler({} as any); + expect(response).toEqual(expected); + }); + it('should fallback to the username if no displayName is given', async () => { + mockFetchUserRequests( + false, + passportProfile.username, + false, + true, + '/user/123/avatar', + false, + ); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + + const expected = { + backstageIdentity: { + token: 'token-for-user:john@doe.com', + }, + providerInfo: { + accessToken: '19xasczxcm9n7gacn9jdgm19me', + scope: 'REPO_READ', + }, + profile: { + email: 'john@doe.com', + displayName: 'john.doe', + picture: 'https://bitbucket.org/user/123/avatar', + }, + }; + + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + const { response } = await provider.handler({} as any); + expect(response).toEqual(expected); + }); + it('should fallback to the user id if no name is given', async () => { + mockFetchUserRequests( + false, + passportProfile.username, + false, + true, + '/user/123/avatar', + false, + false, + ); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + + const expected = { + backstageIdentity: { + token: 'token-for-user:john@doe.com', + }, + providerInfo: { + accessToken: '19xasczxcm9n7gacn9jdgm19me', + scope: 'REPO_READ', + }, + profile: { + email: 'john@doe.com', + displayName: '123', + picture: 'https://bitbucket.org/user/123/avatar', + }, + }; + + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + const { response } = await provider.handler({} as any); + expect(response).toEqual(expected); + }); + }); + + describe('when authenticating', () => { + it('should forward the refresh token', async () => { + mockFetchUserRequests(); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: { refreshToken: 'refresh-token' }, + }); + + const response = await provider.handler({} as any); + + const expected = { + response: { + backstageIdentity: { + token: 'token-for-user:john@doe.com', + }, + providerInfo: { + accessToken: '19xasczxcm9n7gacn9jdgm19me', + scope: 'REPO_READ', + }, + profile: { + email: 'john@doe.com', + displayName: 'John Doe', + picture: 'https://bitbucket.org/user/123/avatar', + }, + }, + refreshToken: 'refresh-token', + }; + + expect(response).toEqual(expected); + }); + it('should forward a new refresh token on refresh', async () => { + mockFetchUserRequests(); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + const mockRefreshToken = jest.spyOn( + helpers, + 'executeRefreshTokenStrategy', + ) as unknown as jest.MockedFunction<() => Promise<{}>>; + mockRefreshToken.mockResolvedValueOnce({ + accessToken, + refreshToken: 'dont-forget-to-send-refresh', + params, + }); + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: { refreshToken: 'refresh-token' }, + }); + + const expected = { + response: { + backstageIdentity: { + token: 'token-for-user:john@doe.com', + }, + providerInfo: { + accessToken: '19xasczxcm9n7gacn9jdgm19me', + scope: 'REPO_READ', + }, + profile: { + email: 'john@doe.com', + displayName: 'John Doe', + picture: 'https://bitbucket.org/user/123/avatar', + }, + }, + refreshToken: 'dont-forget-to-send-refresh', + }; + const response = await provider.refresh({ scope: 'REPO_WRITE' } as any); + + expect(response).toEqual(expected); + }); + }); +}); diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts new file mode 100644 index 0000000000..397f63733f --- /dev/null +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts @@ -0,0 +1,297 @@ +/* + * Copyright 2023 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 { + encodeState, + OAuthAdapter, + OAuthEnvironmentHandler, + OAuthHandlers, + OAuthProviderOptions, + OAuthRefreshRequest, + OAuthResponse, + OAuthStartRequest, +} from '../../lib/oauth'; +import { Strategy as OAuth2Strategy, VerifyCallback } from 'passport-oauth2'; +import { + executeFetchUserProfileStrategy, + executeFrameHandlerStrategy, + executeRedirectStrategy, + executeRefreshTokenStrategy, + makeProfileInfo, +} from '../../lib/passport'; +import { + AuthHandler, + AuthResolverContext, + OAuthStartResponse, + SignInResolver, +} from '../types'; +import express from 'express'; +import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; +import { PassportProfile } from '../../lib/passport/types'; +import { commonByEmailResolver } from '../resolvers'; + +type PrivateInfo = { + refreshToken: string; +}; + +export type BitbucketServerOAuthResult = { + fullProfile: PassportProfile; + params: { + scope: string; + access_token?: string; + token_type?: string; + expires_in?: number; + }; + accessToken: string; + refreshToken?: string; +}; + +export type BitbucketServerAuthProviderOptions = OAuthProviderOptions & { + host: string; + authorizationUrl: string; + tokenUrl: string; + authHandler: AuthHandler; + signInResolver?: SignInResolver; + resolverContext: AuthResolverContext; +}; + +export class BitbucketServerAuthProvider implements OAuthHandlers { + private readonly signInResolver?: SignInResolver; + private readonly authHandler: AuthHandler; + private readonly resolverContext: AuthResolverContext; + private readonly strategy: OAuth2Strategy; + private readonly host: string; + + constructor(options: BitbucketServerAuthProviderOptions) { + this.signInResolver = options.signInResolver; + this.authHandler = options.authHandler; + this.resolverContext = options.resolverContext; + this.strategy = new OAuth2Strategy( + { + authorizationURL: options.authorizationUrl, + tokenURL: options.tokenUrl, + clientID: options.clientId, + clientSecret: options.clientSecret, + callbackURL: options.callbackUrl, + }, + ( + accessToken: string, + refreshToken: string, + params: any, + fullProfile: PassportProfile, + done: VerifyCallback, + ) => { + done(undefined, { fullProfile, params, accessToken }, { refreshToken }); + }, + ); + this.host = options.host; + } + + async start(req: OAuthStartRequest): Promise { + return await executeRedirectStrategy(req, this.strategy, { + accessType: 'offline', + prompt: 'consent', + scope: req.scope, + state: encodeState(req.state), + }); + } + + async handler( + req: express.Request, + ): Promise<{ response: OAuthResponse; refreshToken?: string }> { + const { result, privateInfo } = await executeFrameHandlerStrategy< + BitbucketServerOAuthResult, + PrivateInfo + >(req, this.strategy); + + return { + response: await this.handleResult(result), + refreshToken: privateInfo.refreshToken, + }; + } + + async refresh( + req: OAuthRefreshRequest, + ): Promise<{ response: OAuthResponse; refreshToken?: string }> { + const { accessToken, refreshToken, params } = + await executeRefreshTokenStrategy( + this.strategy, + req.refreshToken, + req.scope, + ); + const fullProfile = await executeFetchUserProfileStrategy( + this.strategy, + accessToken, + ); + return { + response: await this.handleResult({ + fullProfile, + params, + accessToken, + }), + refreshToken, + }; + } + + private async handleResult( + result: BitbucketServerOAuthResult, + ): Promise { + // The OAuth2 strategy does not return a user profile -> let's fetch it before calling the auth handler + result.fullProfile = await this.fetchProfile(result); + const { profile } = await this.authHandler(result, this.resolverContext); + + let backstageIdentity = undefined; + if (this.signInResolver) { + backstageIdentity = await this.signInResolver( + { result, profile }, + this.resolverContext, + ); + } + + return { + providerInfo: { + accessToken: result.accessToken, + scope: result.params.scope, + expiresInSeconds: result.params.expires_in, + }, + profile, + backstageIdentity, + }; + } + + private async fetchProfile( + result: BitbucketServerOAuthResult, + ): Promise { + // Get current user name + let whoAmIResponse; + try { + whoAmIResponse = await fetch( + `https://${this.host}/plugins/servlet/applinks/whoami`, + { + headers: { + Authorization: `Bearer ${result.accessToken}`, + }, + }, + ); + } catch (e) { + throw new Error(`Failed to retrieve the username of the logged in user`); + } + + // A response.ok check here would be worthless as the Bitbucket API always returns 200 OK for this call + const username = whoAmIResponse.headers.get('X-Ausername'); + if (!username) { + throw new Error(`Failed to retrieve the username of the logged in user`); + } + + let userResponse; + try { + userResponse = await fetch( + `https://${this.host}/rest/api/latest/users/${username}?avatarSize=256`, + { + headers: { + Authorization: `Bearer ${result.accessToken}`, + }, + }, + ); + } catch (e) { + throw new Error(`Failed to retrieve the user '${username}'`); + } + + if (!userResponse.ok) { + throw new Error(`Failed to retrieve the user '${username}'`); + } + + const user = await userResponse.json(); + + return { + provider: 'bitbucketServer', + id: user.id.toString(), + displayName: user.displayName, + username: user.name, + emails: [ + { + value: user.emailAddress, + }, + ], + avatarUrl: user.avatarUrl + ? `https://${this.host}${user.avatarUrl}` + : undefined, + }; + } +} + +export const bitbucketServer = createAuthProviderIntegration({ + create(options?: { + /** + * The profile transformation function used to verify and convert the auth response + * into the profile that will be presented to the user. + */ + authHandler?: AuthHandler; + + /** + * Configure sign-in for this provider, without it the provider can not be used to sign users in. + */ + signIn?: { + /** + * Maps an auth result to a Backstage identity for the user. + */ + resolver: SignInResolver; + }; + }) { + return ({ providerId, globalConfig, config, resolverContext }) => + OAuthEnvironmentHandler.mapConfig(config, envConfig => { + const clientId = envConfig.getString('clientId'); + const clientSecret = envConfig.getString('clientSecret'); + const host = envConfig.getString('host'); + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const authorizationUrl = `https://${host}/rest/oauth2/latest/authorize`; + const tokenUrl = `https://${host}/rest/oauth2/latest/token`; + + const authHandler: AuthHandler = + options?.authHandler + ? options.authHandler + : async ({ fullProfile }) => ({ + profile: makeProfileInfo(fullProfile), + }); + + const provider = new BitbucketServerAuthProvider({ + callbackUrl, + clientId, + clientSecret, + host, + authorizationUrl, + tokenUrl, + authHandler, + signInResolver: options?.signIn?.resolver, + resolverContext, + }); + + return OAuthAdapter.fromConfig(globalConfig, provider, { + providerId, + callbackUrl, + }); + }); + }, + resolvers: { + /** + * Looks up the user by matching their email to the entity email. + */ + emailMatchingUserEntityProfileEmail: () => commonByEmailResolver, + }, +}); diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index 67d3a62990..a922065fd8 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -19,6 +19,7 @@ export type { BitbucketOAuthResult, BitbucketPassportProfile, } from './bitbucket'; +export type { BitbucketServerOAuthResult } from './bitbucketServer'; export type { CloudflareAccessClaims, CloudflareAccessGroup, diff --git a/plugins/auth-backend/src/providers/providers.ts b/plugins/auth-backend/src/providers/providers.ts index b2795c25f0..aa630b7481 100644 --- a/plugins/auth-backend/src/providers/providers.ts +++ b/plugins/auth-backend/src/providers/providers.ts @@ -31,6 +31,7 @@ import { okta } from './okta'; import { onelogin } from './onelogin'; import { saml } from './saml'; import { AuthProviderFactory } from './types'; +import { bitbucketServer } from './bitbucketServer'; /** * All built-in auth provider integrations. @@ -42,6 +43,7 @@ export const providers = Object.freeze({ auth0, awsAlb, bitbucket, + bitbucketServer, cfAccess, gcpIap, github, @@ -76,5 +78,6 @@ export const defaultAuthProviderFactories: { onelogin: onelogin.create(), awsalb: awsAlb.create(), bitbucket: bitbucket.create(), + bitbucketServer: bitbucketServer.create(), atlassian: atlassian.create(), }; diff --git a/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx b/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx index f8e1fb190c..772ec80982 100644 --- a/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx +++ b/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx @@ -24,6 +24,7 @@ import { oktaAuthApiRef, microsoftAuthApiRef, bitbucketAuthApiRef, + bitbucketServerAuthApiRef, atlassianAuthApiRef, oneloginAuthApiRef, } from '@backstage/core-plugin-api'; @@ -99,6 +100,14 @@ export const DefaultProviderSettings = (props: { icon={Star} /> )} + {configuredProviders.includes('bitbucketServer') && ( + + )} ); }; From 04f8ef30a6804d9e8048b8d7e591c3b644d40889 Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Mon, 6 Feb 2023 12:01:47 +0100 Subject: [PATCH 173/423] Update slow-moles-sin.md Signed-off-by: Ben Lambert --- .changeset/slow-moles-sin.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/slow-moles-sin.md b/.changeset/slow-moles-sin.md index 13527b509e..140d9e7435 100644 --- a/.changeset/slow-moles-sin.md +++ b/.changeset/slow-moles-sin.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-circleci': minor +'@backstage/plugin-circleci': patch --- -Making workflow a link +Making workflow a link From 8940c2727986cf51f818571075f9ecf66c4329c1 Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Mon, 6 Feb 2023 12:04:37 +0100 Subject: [PATCH 174/423] Add API report Signed-off-by: Katharina Sick --- plugins/auth-backend/api-report.md | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 88cb33863e..e25ed18dfe 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -16,6 +16,7 @@ import { GetEntitiesRequest } from '@backstage/catalog-client'; import { IncomingHttpHeaders } from 'http'; import { JsonValue } from '@backstage/types'; import { Logger } from 'winston'; +import passport from 'passport'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Profile } from 'passport'; @@ -132,6 +133,21 @@ export type BitbucketPassportProfile = Profile & { }; }; +// Warning: (ae-missing-release-tag) "BitbucketServerOAuthResult" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type BitbucketServerOAuthResult = { + fullProfile: PassportProfile; + params: { + scope: string; + access_token?: string; + token_type?: string; + expires_in?: number; + }; + accessToken: string; + refreshToken?: string; +}; + // @public export class CatalogIdentityClient { constructor(options: { catalogApi: CatalogApi; tokenManager: TokenManager }); @@ -480,6 +496,23 @@ export const providers: Readonly<{ userIdMatchingUserEntityAnnotation(): SignInResolver; }>; }>; + bitbucketServer: Readonly<{ + create: ( + options?: + | { + authHandler?: AuthHandler | undefined; + signIn?: + | { + resolver: SignInResolver; + } + | undefined; + } + | undefined, + ) => AuthProviderFactory; + resolvers: Readonly<{ + emailMatchingUserEntityProfileEmail: () => SignInResolver; + }>; + }>; cfAccess: Readonly<{ create: (options: { authHandler?: AuthHandler | undefined; @@ -730,4 +763,8 @@ export type WebMessageResponse = type: 'authorization_response'; error: Error; }; + +// Warnings were encountered during analysis: +// +// src/providers/bitbucketServer/provider.d.ts:6:5 - (ae-forgotten-export) The symbol "PassportProfile" needs to be exported by the entry point index.d.ts ``` From 7ad74fba7309282468b366610fcea56a69e6e6fc Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Mon, 6 Feb 2023 13:41:18 +0100 Subject: [PATCH 175/423] Added a missing validator check for items in an array Signed-off-by: bnechyporenko --- .../TemplatePage/createValidator.test.ts | 59 ++++++++++++++++++- .../TemplatePage/createValidator.ts | 26 +++++++- 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts index 177697eda0..da7a79b1b9 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts @@ -17,14 +17,32 @@ import { createValidator } from './createValidator'; import { CustomFieldValidator } from '@backstage/plugin-scaffolder-react'; import { ApiHolder } from '@backstage/core-plugin-api'; -import { FormValidation } from '@rjsf/core'; +import { FieldValidation, FormValidation } from '@rjsf/core'; describe('createValidator', () => { const validators: Record> = { - CustomPicker: (value, validation, _context) => { + CustomPicker: ( + value: unknown, + fieldValidation: FieldValidation, + _context: { apiHolder: ApiHolder }, + ) => { if (!value || !(value as { value?: unknown }).value) { - validation.addError('Error !'); + fieldValidation.addError('Error !'); + } + }, + TagPicker: ( + value: unknown, + fieldValidation: FieldValidation, + _context: { apiHolder: ApiHolder }, + ) => { + if (!value) { + fieldValidation.addError('A tag name can not be empty'); + } + if (!/^[a-z0-9-]+$/.test(value as string)) { + fieldValidation.addError( + 'A tag name can only contain lowercase letters, numeric characters or dashes', + ); } }, }; @@ -70,4 +88,39 @@ describe('createValidator', () => { expect(result).not.toBeNull(); expect(result.p1.addError).toHaveBeenCalledTimes(1); }); + + it('Should call validator for array property from a custom field extension', () => { + /* GIVEN */ + const rootSchema = { + title: 'My form', + properties: { + tags: { + title: 'Tags', + type: 'array', + items: { + type: 'string', + 'ui:field': 'TagPicker', + }, + }, + }, + }; + const validator = createValidator(rootSchema, validators, context); + + const formData = { + tags: ['invalid-tag$$'], + }; + const errors = { + addError: jest.fn(), + tags: { + addError: jest.fn(), + } as unknown as FormValidation, + } as unknown as FormValidation; + + /* WHEN */ + const result = validator(formData, errors); + + /* THEN */ + expect(result).not.toBeNull(); + expect(result.tags.addError).toHaveBeenCalledTimes(1); + }); }); diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts index 4a64481fc3..98273da43a 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts @@ -23,6 +23,10 @@ function isObject(obj: unknown): obj is JsonObject { return typeof obj === 'object' && obj !== null && !Array.isArray(obj); } +function isArray(obj: unknown): obj is JsonObject { + return typeof obj === 'object' && obj !== null && Array.isArray(obj); +} + export const createValidator = ( rootSchema: JsonObject, validators: Record>, @@ -46,8 +50,8 @@ export const createValidator = ( for (const [key, propData] of Object.entries(formData)) { const propValidation = errors[key]; + const propSchemaProps = schemaProps[key]; if (isObject(propData)) { - const propSchemaProps = schemaProps[key]; if (isObject(propSchemaProps)) { validate( propSchemaProps, @@ -55,10 +59,26 @@ export const createValidator = ( propValidation as FormValidation, ); } + } else if (isArray(propData)) { + if (isObject(propSchemaProps)) { + const { items } = propSchemaProps; + if (isObject(items)) { + for (const propItem of propData as JsonObject[]) { + const fieldName = items['ui:field'] as string; + if (fieldName && typeof validators[fieldName] === 'function') { + validators[fieldName]!( + propItem as JsonValue, + propValidation, + context, + ); + } + } + } + } } else { - const propSchema = schemaProps[key]; const fieldName = - isObject(propSchema) && (propSchema['ui:field'] as string); + isObject(propSchemaProps) && + (propSchemaProps['ui:field'] as string); if (fieldName && typeof validators[fieldName] === 'function') { validators[fieldName]!( propData as JsonValue, From 074f7e81b5033ed68f75eec17a9ebc6c7f4a02fd Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Mon, 6 Feb 2023 13:49:44 +0100 Subject: [PATCH 176/423] Added a changeset Signed-off-by: bnechyporenko --- .changeset/lucky-papayas-allow.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/lucky-papayas-allow.md diff --git a/.changeset/lucky-papayas-allow.md b/.changeset/lucky-papayas-allow.md new file mode 100644 index 0000000000..5a896efd0b --- /dev/null +++ b/.changeset/lucky-papayas-allow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': minor +--- + +Added a missing validator check for items in an array From acf6c8c10b2c9f5206456f3216280019a00e3df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C5=A0neberger?= Date: Mon, 6 Feb 2023 13:49:48 +0100 Subject: [PATCH 177/423] [TechRadar] Deprecate RadarEntry.url MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Šneberger --- .changeset/hip-chairs-double.md | 5 +++++ .changeset/slow-moles-sin.md | 2 +- plugins/tech-radar/src/api.ts | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .changeset/hip-chairs-double.md diff --git a/.changeset/hip-chairs-double.md b/.changeset/hip-chairs-double.md new file mode 100644 index 0000000000..73e939ba21 --- /dev/null +++ b/.changeset/hip-chairs-double.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-tech-radar': minor +--- + +Deprecate `RadarEntry.url` - use `RadarEntry.links` instead diff --git a/.changeset/slow-moles-sin.md b/.changeset/slow-moles-sin.md index 140d9e7435..02e1952312 100644 --- a/.changeset/slow-moles-sin.md +++ b/.changeset/slow-moles-sin.md @@ -2,4 +2,4 @@ '@backstage/plugin-circleci': patch --- -Making workflow a link +Making workflow a link diff --git a/plugins/tech-radar/src/api.ts b/plugins/tech-radar/src/api.ts index 0fbc88255a..bf90cf0750 100644 --- a/plugins/tech-radar/src/api.ts +++ b/plugins/tech-radar/src/api.ts @@ -133,6 +133,8 @@ export interface RadarEntry { * @remarks * * You can use `#` if you don't want to provide any other url + * + * @deprecated Use {@link RadarEntry.links} instead */ url: string; /** From 3c5c6807fb81ad7aec78f097d92e71834ce88a19 Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Mon, 6 Feb 2023 07:55:44 -0500 Subject: [PATCH 178/423] Remove title so it doesn't show up twice Signed-off-by: Taras Mankovski --- microsite/blog/2023-01-31-incremental-entity-provider.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/microsite/blog/2023-01-31-incremental-entity-provider.md b/microsite/blog/2023-01-31-incremental-entity-provider.md index ff5f346ccd..c14c3fc15d 100644 --- a/microsite/blog/2023-01-31-incremental-entity-provider.md +++ b/microsite/blog/2023-01-31-incremental-entity-provider.md @@ -4,8 +4,6 @@ author: Paul Cowan & Taras Mankovski authorURL: https://frontside.com/ --- -# Scaling Backstage Ingestion with Incremental Entity Providers - At the heart of [Backstage](https://backstage.io/) is the [Backstage Software Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview), which is a data store that allows an organization to centralize and visualize its many software services and components. Backstage inspects and transforms an organization's disparate software services and parts into a centralized data store. ![catalog pipeline](assets/2023-01-31/catalog-pipeline.png) From 8c63cebe70106a17efa3c7a3f3f2859591b6be6a Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Mon, 6 Feb 2023 14:05:02 +0100 Subject: [PATCH 179/423] Incorporated a feedback Signed-off-by: bnechyporenko --- .changeset/slow-moles-sin.md | 2 +- .../TemplatePage/createValidator.test.ts | 15 +++++++++------ .../components/TemplatePage/createValidator.ts | 16 +++++++--------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/.changeset/slow-moles-sin.md b/.changeset/slow-moles-sin.md index 140d9e7435..02e1952312 100644 --- a/.changeset/slow-moles-sin.md +++ b/.changeset/slow-moles-sin.md @@ -2,4 +2,4 @@ '@backstage/plugin-circleci': patch --- -Making workflow a link +Making workflow a link diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts index da7a79b1b9..d9b9d1c0c3 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts @@ -32,17 +32,20 @@ describe('createValidator', () => { } }, TagPicker: ( - value: unknown, + values: unknown, fieldValidation: FieldValidation, _context: { apiHolder: ApiHolder }, ) => { - if (!value) { + const input = values as string[]; + if (input.length === 0) { fieldValidation.addError('A tag name can not be empty'); } - if (!/^[a-z0-9-]+$/.test(value as string)) { - fieldValidation.addError( - 'A tag name can only contain lowercase letters, numeric characters or dashes', - ); + for (const item of input) { + if (!/^[a-z0-9-]+$/.test(item)) { + fieldValidation.addError( + 'A tag name can only contain lowercase letters, numeric characters or dashes', + ); + } } }, }; diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts index 98273da43a..123a7e800e 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts @@ -63,15 +63,13 @@ export const createValidator = ( if (isObject(propSchemaProps)) { const { items } = propSchemaProps; if (isObject(items)) { - for (const propItem of propData as JsonObject[]) { - const fieldName = items['ui:field'] as string; - if (fieldName && typeof validators[fieldName] === 'function') { - validators[fieldName]!( - propItem as JsonValue, - propValidation, - context, - ); - } + const fieldName = items['ui:field'] as string; + if (fieldName && typeof validators[fieldName] === 'function') { + validators[fieldName]!( + propData as JsonObject[], + propValidation, + context, + ); } } } From 9a58b4127e6a4a5fad3000a84aa71135fa40ca13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C5=A0neberger?= Date: Mon, 6 Feb 2023 14:17:47 +0100 Subject: [PATCH 180/423] Build API report MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Šneberger --- plugins/tech-radar/api-report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/tech-radar/api-report.md b/plugins/tech-radar/api-report.md index e2744872d8..2836e04461 100644 --- a/plugins/tech-radar/api-report.md +++ b/plugins/tech-radar/api-report.md @@ -25,6 +25,7 @@ export interface RadarEntry { quadrant: string; timeline: Array; title: string; + // @deprecated url: string; } From 28f9883440f254856b08d35812772295262f527a Mon Sep 17 00:00:00 2001 From: LauraMoraB Date: Mon, 6 Feb 2023 14:55:39 +0100 Subject: [PATCH 181/423] fix(catalog/msgraph): read user.select from config Signed-off-by: LauraMoraB --- .changeset/silly-buckets-joke.md | 5 +++++ .../src/microsoftGraph/config.test.ts | 4 ++++ .../src/microsoftGraph/config.ts | 2 ++ 3 files changed, 11 insertions(+) create mode 100644 .changeset/silly-buckets-joke.md diff --git a/.changeset/silly-buckets-joke.md b/.changeset/silly-buckets-joke.md new file mode 100644 index 0000000000..bd77f2ed05 --- /dev/null +++ b/.changeset/silly-buckets-joke.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-msgraph': patch +--- + +Fixed bug in readProviderConfig as it wasn't reading the user.select field expected from the app-config.yaml configuration 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 68c174665d..b02894dfd9 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts @@ -52,6 +52,7 @@ describe('readMicrosoftGraphConfig', () => { authority: 'https://login.example.com/', userExpand: 'manager', userFilter: 'accountEnabled eq true', + userSelect: ['id', 'displayName', 'department'], groupExpand: 'member', groupSelect: ['id', 'displayName', 'description'], groupFilter: 'securityEnabled eq false', @@ -69,6 +70,7 @@ describe('readMicrosoftGraphConfig', () => { authority: 'https://login.example.com/', userExpand: 'manager', userFilter: 'accountEnabled eq true', + userSelect: ['id', 'displayName', 'department'], groupExpand: 'member', groupSelect: ['id', 'displayName', 'description'], groupFilter: 'securityEnabled eq false', @@ -167,6 +169,7 @@ describe('readProviderConfigs', () => { user: { expand: 'manager', filter: 'accountEnabled eq true', + select: ['id', 'displayName', 'department'], }, group: { expand: 'member', @@ -196,6 +199,7 @@ describe('readProviderConfigs', () => { queryMode: 'advanced', userExpand: 'manager', userFilter: 'accountEnabled eq true', + userSelect: ['id', 'displayName', 'department'], groupExpand: 'member', groupSelect: ['id', 'displayName', 'description'], groupFilter: 'securityEnabled eq false', diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts index 506951ff10..cf4ec646a2 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts @@ -264,6 +264,7 @@ export function readProviderConfig( const userExpand = config.getOptionalString('user.expand'); const userFilter = config.getOptionalString('user.filter'); + const userSelect = config.getOptionalStringArray('user.select'); const groupExpand = config.getOptionalString('group.expand'); const groupFilter = config.getOptionalString('group.filter'); @@ -318,6 +319,7 @@ export function readProviderConfig( tenantId, userExpand, userFilter, + userSelect, groupExpand, groupFilter, groupSearch, From 4382e0c7a2ce78db27d668d936f5c3aae41d286d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C5=A0neberger?= Date: Mon, 6 Feb 2023 15:24:33 +0100 Subject: [PATCH 182/423] Remove deprecated url from `sample.ts` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Šneberger --- plugins/tech-radar/src/sample.ts | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/plugins/tech-radar/src/sample.ts b/plugins/tech-radar/src/sample.ts index 1c4f7a1a01..0dc647ac54 100644 --- a/plugins/tech-radar/src/sample.ts +++ b/plugins/tech-radar/src/sample.ts @@ -45,12 +45,16 @@ entries.push({ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua', }, ], - url: 'https://www.javascript.com/', + url: '#', key: 'javascript', id: 'javascript', title: 'JavaScript', quadrant: 'languages', links: [ + { + url: 'https://www.javascript.com/', + title: 'Learn more', + }, { url: 'https://www.typescriptlang.org/', title: 'TypeScript', @@ -87,7 +91,13 @@ entries.push({ 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur', }, ], - url: 'https://webpack.js.org/', + url: '#', + links: [ + { + url: 'https://webpack.js.org/', + title: 'Learn more', + }, + ], key: 'webpack', id: 'webpack', title: 'Webpack', @@ -101,7 +111,13 @@ entries.push({ date: new Date('2020-08-06'), }, ], - url: 'https://reactjs.org/', + url: '#', + links: [ + { + url: 'https://reactjs.org/', + title: 'Learn more', + }, + ], key: 'react', id: 'react', title: 'React', @@ -170,7 +186,13 @@ entries.push({ description: 'long description', }, ], - url: 'https://github.com', + url: '#', + links: [ + { + url: 'https://reactjs.org/', + title: 'Learn more', + }, + ], key: 'github-actions', id: 'github-actions', title: 'GitHub Actions', From 8179f9df3eb0264537f798b4c875f1534a3093e5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 14:25:09 +0000 Subject: [PATCH 183/423] chore(deps): update dependency @types/node to v16.18.12 Signed-off-by: Renovate Bot --- yarn.lock | 164 +++++++++++++++++++++++++++--------------------------- 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/yarn.lock b/yarn.lock index 15cc1e24a9..259b321cd5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3362,7 +3362,7 @@ __metadata: "@material-ui/icons": ^4.9.1 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/react": ^16.13.1 || ^17.0.0 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -3702,7 +3702,7 @@ __metadata: "@types/jest": ^29.0.0 "@types/minimatch": ^5.0.0 "@types/mock-fs": ^4.13.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/npm-packlist": ^3.0.0 "@types/recursive-readdir": ^2.2.0 "@types/rollup-plugin-peer-deps-external": ^2.2.0 @@ -3804,7 +3804,7 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" "@types/jscodeshift": ^0.11.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 chalk: ^4.0.0 commander: ^9.1.0 jscodeshift: ^0.14.0 @@ -3827,7 +3827,7 @@ __metadata: "@types/json-schema": ^7.0.6 "@types/json-schema-merge-allof": ^0.6.0 "@types/mock-fs": ^4.10.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/yup": ^0.29.13 ajv: ^8.10.0 chokidar: ^3.5.2 @@ -3870,7 +3870,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/prop-types": ^15.7.3 "@types/zen-observable": ^0.8.0 cross-fetch: ^3.1.5 @@ -3968,7 +3968,7 @@ __metadata: "@types/d3-zoom": ^3.0.1 "@types/dagre": ^0.7.44 "@types/google-protobuf": ^3.7.2 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/react-helmet": ^6.1.0 "@types/react-sparklines": ^1.7.0 "@types/react-syntax-highlighter": ^15.0.0 @@ -4025,7 +4025,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/prop-types": ^15.7.3 "@types/zen-observable": ^0.8.0 cross-fetch: ^3.1.5 @@ -4049,7 +4049,7 @@ __metadata: "@types/command-exists": ^1.2.0 "@types/fs-extra": ^9.0.1 "@types/inquirer": ^8.1.3 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/recursive-readdir": ^2.2.0 chalk: ^4.0.0 commander: ^9.1.0 @@ -4174,7 +4174,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4266,7 +4266,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/git-url-parse": ^9.0.0 - "@types/node": "*" + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-markdown: ^8.0.0 @@ -4318,7 +4318,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4347,7 +4347,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4375,7 +4375,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-ga: ^3.3.0 @@ -4401,7 +4401,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 qs: ^6.10.1 @@ -4445,7 +4445,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/swagger-ui-react": ^4.1.1 cross-fetch: ^3.1.5 graphiql: ^1.8.8 @@ -4480,7 +4480,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4656,7 +4656,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 humanize-duration: ^3.27.0 luxon: ^3.0.0 @@ -4718,7 +4718,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -4770,7 +4770,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4862,7 +4862,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 lodash: ^4.17.21 @@ -5560,7 +5560,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.25.1 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 circleci-api: ^4.0.0 cross-fetch: ^3.1.5 humanize-duration: ^3.27.0 @@ -5593,7 +5593,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -5625,7 +5625,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.27.1 "@types/luxon": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 humanize-duration: ^3.27.1 luxon: ^3.0.0 @@ -5687,7 +5687,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/highlightjs": ^10.1.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 highlight.js: ^10.6.0 @@ -5720,7 +5720,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 rc-progress: 3.4.1 @@ -5751,7 +5751,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 jsonschema: ^1.2.6 msw: ^0.49.0 @@ -5792,7 +5792,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/pluralize": ^0.0.29 "@types/recharts": ^1.8.14 "@types/regression": ^2.0.0 @@ -5834,7 +5834,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.0.0 express: ^4.18.1 msw: ^0.49.0 react-use: ^17.2.4 @@ -6017,7 +6017,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 languageName: unknown @@ -6048,7 +6048,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 classnames: ^2.2.6 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -6078,7 +6078,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6108,7 +6108,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6140,7 +6140,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/dompurify": ^2.3.3 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/sanitize-html": ^2.6.2 classnames: ^2.3.1 cross-fetch: ^3.1.5 @@ -6173,7 +6173,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 peerDependencies: @@ -6202,7 +6202,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6238,7 +6238,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6272,7 +6272,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6304,7 +6304,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6336,7 +6336,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6366,7 +6366,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -6398,7 +6398,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/lodash": ^4.14.173 "@types/luxon": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 lodash: ^4.17.21 luxon: ^3.0.0 @@ -6428,7 +6428,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/codemirror": ^5.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 graphiql: ^1.5.12 graphql: ^16.0.0 @@ -6484,7 +6484,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 graphql-voyager: ^1.0.0-rc.31 msw: ^0.49.0 @@ -6538,7 +6538,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 lodash: ^4.17.21 msw: ^0.49.0 @@ -6572,7 +6572,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 humanize-duration: ^3.26.0 luxon: ^3.0.0 @@ -6640,7 +6640,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/testing-library__jest-dom": ^5.9.1 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6696,7 +6696,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 jest-when: ^3.1.0 msw: ^0.49.0 @@ -6784,7 +6784,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/react": ^16.13.1 || ^17.0.0 cronstrue: ^2.2.0 cross-fetch: ^3.1.5 @@ -6846,7 +6846,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -6897,7 +6897,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -6926,7 +6926,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -6955,7 +6955,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 p-limit: ^3.1.0 @@ -6988,7 +6988,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 classnames: ^2.2.6 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -7042,7 +7042,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -7203,7 +7203,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 lodash: ^4.17.21 msw: ^0.49.0 @@ -7290,7 +7290,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 lodash: ^4.17.21 @@ -7342,7 +7342,7 @@ __metadata: "@types/command-exists": ^1.2.0 "@types/fs-extra": ^9.0.1 "@types/mock-fs": ^4.13.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 command-exists: ^1.2.9 fs-extra: ^10.0.1 jest-when: ^3.1.0 @@ -7556,7 +7556,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.18.1 "@types/json-schema": ^7.0.9 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@uiw/react-codemirror": ^4.9.3 classnames: ^2.2.6 cross-fetch: ^3.1.5 @@ -7761,7 +7761,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 qs: ^6.9.4 @@ -7794,7 +7794,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -7825,7 +7825,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/zen-observable": ^0.8.2 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -7893,7 +7893,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 rc-progress: 3.4.1 @@ -7923,7 +7923,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 classnames: ^2.2.6 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -7997,7 +7997,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 lodash: ^4.17.21 msw: ^0.49.0 @@ -8109,7 +8109,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 qs: ^6.9.4 @@ -8140,7 +8140,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/color": ^3.0.1 "@types/d3-force": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/react": ^16.13.1 || ^17.0.0 color: ^4.0.1 cross-fetch: ^3.1.5 @@ -8175,7 +8175,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -8243,7 +8243,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 git-url-parse: ^13.0.0 @@ -8356,7 +8356,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/dompurify": ^2.2.2 "@types/event-source-polyfill": ^1.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 canvas: ^2.10.2 cross-fetch: ^3.1.5 dompurify: ^2.2.9 @@ -8418,7 +8418,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -8471,7 +8471,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -8530,7 +8530,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -8558,7 +8558,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 lodash: ^4.17.21 luxon: ^3.0.0 @@ -8633,7 +8633,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 zen-observable: ^0.10.0 @@ -10546,7 +10546,7 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/test-utils": "workspace:^" - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 languageName: unknown @@ -10569,7 +10569,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 msw: ^0.49.0 react-use: ^17.2.4 peerDependencies: @@ -13491,7 +13491,7 @@ __metadata: "@types/dockerode": ^3.3.0 "@types/fs-extra": ^9.0.6 "@types/http-proxy": ^1.17.4 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/serve-handler": ^6.1.0 "@types/webpack-env": ^1.15.3 commander: ^9.1.0 @@ -14841,7 +14841,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^16.0.0, @types/node@npm:^16.11.26, @types/node@npm:^16.9.2": +"@types/node@npm:^16.0.0, @types/node@npm:^16.9.2": version: 16.18.11 resolution: "@types/node@npm:16.18.11" checksum: 2a3b1da13063debe6e26f732defb5f03ef4ef732c3e08daba838d8850433bd00e537ce1a97ce9bcfc4b15db5218d701d1265fae94e0d6926906bec157e6b46e0 @@ -20874,7 +20874,7 @@ __metadata: "@backstage/cli-common": "workspace:^" "@backstage/errors": "workspace:^" "@types/fs-extra": ^9.0.1 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/puppeteer": ^5.4.4 chalk: ^4.0.0 commander: ^9.1.0 @@ -22194,7 +22194,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/jquery": ^3.3.34 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/react": "*" "@types/react-dom": "*" "@types/zen-observable": ^0.8.0 @@ -34251,7 +34251,7 @@ __metadata: "@spotify/eslint-plugin": ^14.1.3 "@spotify/prettier-config": ^14.0.0 "@techdocs/cli": "workspace:*" - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/webpack": ^5.28.0 command-exists: ^1.2.9 concurrently: ^7.0.0 @@ -36275,7 +36275,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": ^16.0.0 "@types/react-dom": "*" cross-env: ^7.0.0 cypress: ^10.0.0 From 5b5d7d416ffca72ce84d0bf844a3938a9aacf777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C5=A0neberger?= Date: Mon, 6 Feb 2023 15:27:22 +0100 Subject: [PATCH 184/423] Update changeset with migration diff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Šneberger --- .changeset/hip-chairs-double.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.changeset/hip-chairs-double.md b/.changeset/hip-chairs-double.md index 73e939ba21..722795d80d 100644 --- a/.changeset/hip-chairs-double.md +++ b/.changeset/hip-chairs-double.md @@ -3,3 +3,18 @@ --- Deprecate `RadarEntry.url` - use `RadarEntry.links` instead + +```diff +- url: 'https://www.javascript.com/', ++ url: '#', + key: 'javascript', + id: 'javascript', + title: 'JavaScript', + quadrant: 'languages', + links: [ ++ { ++ url: 'https://www.javascript.com/', ++ title: 'Learn more', ++ }, + ], +``` From a6aff183ba79ebb4531d30a2a6d89b9ae3013ce1 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 6 Feb 2023 15:28:43 +0100 Subject: [PATCH 185/423] chore: updating the breaking changes Signed-off-by: blam --- .github/workflows/automate_changeset_feedback.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index 11fef75b9b..aaf0bb1294 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -31,10 +31,10 @@ jobs: - uses: backstage/actions/changeset-feedback@v0.6.0 name: Generate feedback with: - diffRef: 'origin/master' + diff-ref: 'origin/master' marker: issue-number: ${{ github.event.pull_request.number }} - botUsername: backstage-goalie[bot] + bot-username: backstage-goalie[bot] app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} installation-id: ${{ secrets.BACKSTAGE_GOALIE_INSTALLATION_ID }} From cd065df85f7814e3d586e868e01cf37f39f5cc77 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 14:35:46 +0000 Subject: [PATCH 186/423] chore(deps): update dependency @types/node to v18.11.19 Signed-off-by: Renovate Bot --- yarn.lock | 160 +++++++++++++++++++++++++++--------------------------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/yarn.lock b/yarn.lock index 15cc1e24a9..a3e4f754b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3362,7 +3362,7 @@ __metadata: "@material-ui/icons": ^4.9.1 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/react": ^16.13.1 || ^17.0.0 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -3652,7 +3652,7 @@ __metadata: resolution: "@backstage/cli-common@workspace:packages/cli-common" dependencies: "@backstage/cli": "workspace:^" - "@types/node": ^16.0.0 + "@types/node": "*" languageName: unknown linkType: soft @@ -3702,7 +3702,7 @@ __metadata: "@types/jest": ^29.0.0 "@types/minimatch": ^5.0.0 "@types/mock-fs": ^4.13.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/npm-packlist": ^3.0.0 "@types/recursive-readdir": ^2.2.0 "@types/rollup-plugin-peer-deps-external": ^2.2.0 @@ -3804,7 +3804,7 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" "@types/jscodeshift": ^0.11.0 - "@types/node": ^16.11.26 + "@types/node": "*" chalk: ^4.0.0 commander: ^9.1.0 jscodeshift: ^0.14.0 @@ -3827,7 +3827,7 @@ __metadata: "@types/json-schema": ^7.0.6 "@types/json-schema-merge-allof": ^0.6.0 "@types/mock-fs": ^4.10.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/yup": ^0.29.13 ajv: ^8.10.0 chokidar: ^3.5.2 @@ -3851,7 +3851,7 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" - "@types/node": ^16.0.0 + "@types/node": "*" lodash: ^4.17.21 languageName: unknown linkType: soft @@ -3870,7 +3870,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/prop-types": ^15.7.3 "@types/zen-observable": ^0.8.0 cross-fetch: ^3.1.5 @@ -3968,7 +3968,7 @@ __metadata: "@types/d3-zoom": ^3.0.1 "@types/dagre": ^0.7.44 "@types/google-protobuf": ^3.7.2 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/react-helmet": ^6.1.0 "@types/react-sparklines": ^1.7.0 "@types/react-syntax-highlighter": ^15.0.0 @@ -4025,7 +4025,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/prop-types": ^15.7.3 "@types/zen-observable": ^0.8.0 cross-fetch: ^3.1.5 @@ -4049,7 +4049,7 @@ __metadata: "@types/command-exists": ^1.2.0 "@types/fs-extra": ^9.0.1 "@types/inquirer": ^8.1.3 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/recursive-readdir": ^2.2.0 chalk: ^4.0.0 commander: ^9.1.0 @@ -4085,7 +4085,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": "*" react-use: ^17.2.4 zen-observable: ^0.10.0 peerDependencies: @@ -4174,7 +4174,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4318,7 +4318,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4347,7 +4347,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4375,7 +4375,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-ga: ^3.3.0 @@ -4401,7 +4401,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 qs: ^6.10.1 @@ -4445,7 +4445,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/swagger-ui-react": ^4.1.1 cross-fetch: ^3.1.5 graphiql: ^1.8.8 @@ -4656,7 +4656,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 humanize-duration: ^3.27.0 luxon: ^3.0.0 @@ -4718,7 +4718,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -4770,7 +4770,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4862,7 +4862,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 lodash: ^4.17.21 @@ -5560,7 +5560,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.25.1 - "@types/node": ^16.11.26 + "@types/node": "*" circleci-api: ^4.0.0 cross-fetch: ^3.1.5 humanize-duration: ^3.27.0 @@ -5593,7 +5593,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -5625,7 +5625,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.27.1 "@types/luxon": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 humanize-duration: ^3.27.1 luxon: ^3.0.0 @@ -5687,7 +5687,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/highlightjs": ^10.1.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 highlight.js: ^10.6.0 @@ -5751,7 +5751,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 jsonschema: ^1.2.6 msw: ^0.49.0 @@ -5792,7 +5792,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/pluralize": ^0.0.29 "@types/recharts": ^1.8.14 "@types/regression": ^2.0.0 @@ -6017,7 +6017,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 languageName: unknown @@ -6048,7 +6048,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" classnames: ^2.2.6 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -6078,7 +6078,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6108,7 +6108,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6140,7 +6140,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/dompurify": ^2.3.3 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/sanitize-html": ^2.6.2 classnames: ^2.3.1 cross-fetch: ^3.1.5 @@ -6173,7 +6173,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 peerDependencies: @@ -6202,7 +6202,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6238,7 +6238,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6272,7 +6272,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6336,7 +6336,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6366,7 +6366,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -6398,7 +6398,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/lodash": ^4.14.173 "@types/luxon": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 lodash: ^4.17.21 luxon: ^3.0.0 @@ -6428,7 +6428,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/codemirror": ^5.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 graphiql: ^1.5.12 graphql: ^16.0.0 @@ -6538,7 +6538,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 lodash: ^4.17.21 msw: ^0.49.0 @@ -6572,7 +6572,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 humanize-duration: ^3.26.0 luxon: ^3.0.0 @@ -6640,7 +6640,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/testing-library__jest-dom": ^5.9.1 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6696,7 +6696,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 jest-when: ^3.1.0 msw: ^0.49.0 @@ -6784,7 +6784,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/react": ^16.13.1 || ^17.0.0 cronstrue: ^2.2.0 cross-fetch: ^3.1.5 @@ -6846,7 +6846,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -6897,7 +6897,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -6955,7 +6955,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 p-limit: ^3.1.0 @@ -6988,7 +6988,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" classnames: ^2.2.6 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -7042,7 +7042,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -7290,7 +7290,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 lodash: ^4.17.21 @@ -7342,7 +7342,7 @@ __metadata: "@types/command-exists": ^1.2.0 "@types/fs-extra": ^9.0.1 "@types/mock-fs": ^4.13.0 - "@types/node": ^16.11.26 + "@types/node": "*" command-exists: ^1.2.9 fs-extra: ^10.0.1 jest-when: ^3.1.0 @@ -7556,7 +7556,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.18.1 "@types/json-schema": ^7.0.9 - "@types/node": ^16.11.26 + "@types/node": "*" "@uiw/react-codemirror": ^4.9.3 classnames: ^2.2.6 cross-fetch: ^3.1.5 @@ -7761,7 +7761,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 qs: ^6.9.4 @@ -7794,7 +7794,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -7825,7 +7825,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/zen-observable": ^0.8.2 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -7893,7 +7893,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 rc-progress: 3.4.1 @@ -7923,7 +7923,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" classnames: ^2.2.6 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -7997,7 +7997,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 lodash: ^4.17.21 msw: ^0.49.0 @@ -8109,7 +8109,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 qs: ^6.9.4 @@ -8140,7 +8140,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/color": ^3.0.1 "@types/d3-force": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/react": ^16.13.1 || ^17.0.0 color: ^4.0.1 cross-fetch: ^3.1.5 @@ -8175,7 +8175,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -8243,7 +8243,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 git-url-parse: ^13.0.0 @@ -8356,7 +8356,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/dompurify": ^2.2.2 "@types/event-source-polyfill": ^1.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" canvas: ^2.10.2 cross-fetch: ^3.1.5 dompurify: ^2.2.9 @@ -8418,7 +8418,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -8471,7 +8471,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -8558,7 +8558,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 lodash: ^4.17.21 luxon: ^3.0.0 @@ -8576,7 +8576,7 @@ __metadata: dependencies: "@backstage/cli": "workspace:^" "@backstage/test-utils": "workspace:^" - "@types/node": ^16.0.0 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 languageName: unknown @@ -8633,7 +8633,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 zen-observable: ^0.10.0 @@ -10546,7 +10546,7 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/test-utils": "workspace:^" - "@types/node": ^16.11.26 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 languageName: unknown @@ -10569,7 +10569,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" msw: ^0.49.0 react-use: ^17.2.4 peerDependencies: @@ -13491,7 +13491,7 @@ __metadata: "@types/dockerode": ^3.3.0 "@types/fs-extra": ^9.0.6 "@types/http-proxy": ^1.17.4 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/serve-handler": ^6.1.0 "@types/webpack-env": ^1.15.3 commander: ^9.1.0 @@ -14800,9 +14800,9 @@ __metadata: linkType: hard "@types/node@npm:*, @types/node@npm:>= 8, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0, @types/node@npm:^18.11.17": - version: 18.11.18 - resolution: "@types/node@npm:18.11.18" - checksum: 03f17f9480f8d775c8a72da5ea7e9383db5f6d85aa5fefde90dd953a1449bd5e4ffde376f139da4f3744b4c83942166d2a7603969a6f8ea826edfb16e6e3b49d + version: 18.11.19 + resolution: "@types/node@npm:18.11.19" + checksum: d7cd19fcfc59cbdd3f9ba0b4072cb7adc21bd575bd8eb7d7e698975e63564aaa83f03434f32b12331f84f73d0b369d9cbe2371e359d9d7f5c3361f4987f4f7da languageName: node linkType: hard @@ -14841,7 +14841,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^16.0.0, @types/node@npm:^16.11.26, @types/node@npm:^16.9.2": +"@types/node@npm:^16.9.2": version: 16.18.11 resolution: "@types/node@npm:16.18.11" checksum: 2a3b1da13063debe6e26f732defb5f03ef4ef732c3e08daba838d8850433bd00e537ce1a97ce9bcfc4b15db5218d701d1265fae94e0d6926906bec157e6b46e0 @@ -20874,7 +20874,7 @@ __metadata: "@backstage/cli-common": "workspace:^" "@backstage/errors": "workspace:^" "@types/fs-extra": ^9.0.1 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/puppeteer": ^5.4.4 chalk: ^4.0.0 commander: ^9.1.0 @@ -22194,7 +22194,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/jquery": ^3.3.34 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/react": "*" "@types/react-dom": "*" "@types/zen-observable": ^0.8.0 @@ -34251,7 +34251,7 @@ __metadata: "@spotify/eslint-plugin": ^14.1.3 "@spotify/prettier-config": ^14.0.0 "@techdocs/cli": "workspace:*" - "@types/node": ^16.11.26 + "@types/node": "*" "@types/webpack": ^5.28.0 command-exists: ^1.2.9 concurrently: ^7.0.0 @@ -36275,7 +36275,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.11.26 + "@types/node": "*" "@types/react-dom": "*" cross-env: ^7.0.0 cypress: ^10.0.0 From 6c54bf08a5a040dce86758e51a193615a5d68b34 Mon Sep 17 00:00:00 2001 From: Lee Mills Date: Mon, 6 Feb 2023 10:49:28 +0000 Subject: [PATCH 187/423] Adding whats ahead blog post and image asset Signed-off-by: Lee Mills --- .../blog/2023-02-06-whats-ahead-in-2023.md | 58 ++++++++++++++++++ .../blog/assets/2023-02-06/whats-ahead.png | Bin 0 -> 150199 bytes 2 files changed, 58 insertions(+) create mode 100644 microsite/blog/2023-02-06-whats-ahead-in-2023.md create mode 100644 microsite/blog/assets/2023-02-06/whats-ahead.png diff --git a/microsite/blog/2023-02-06-whats-ahead-in-2023.md b/microsite/blog/2023-02-06-whats-ahead-in-2023.md new file mode 100644 index 0000000000..a9f06d9ea0 --- /dev/null +++ b/microsite/blog/2023-02-06-whats-ahead-in-2023.md @@ -0,0 +1,58 @@ +--- +title: What’s Ahead in 2023? +author: Lee Mills +authorURL: https://github.com/leemills83 +--- + +# What’s Ahead in 2023? + +![Fewer “vibes” and more climbs (up the contribution ladder)](assets/2023-02-06/whats-ahead.png) + +Okay, everyone. Time to move on from all the 2022 reflections, Top 10 lists, and Wrapped(s), and turn our gaze in the other direction — towards 2023. As the Backstage team moves into the new year, we find ourselves asking those perennial questions: How can we continue to grow and enhance the Backstage community? How can we improve the experience for those adopting Backstage? How can we give the best support to Backstage contributors? + +Well, we don’t have all the answers, but we do have some. So we wanted to share more on three ongoing initiatives aimed at moving the needle forward for these three distinct, yet interrelated, questions. + +- Grow your influence by climbing the contribution ladder +- Come join our SIGs (and push for new ones) +- Work with us to drive a better experience for Backstage adopters + +# Climb the contribution ladder + +Truth be told, we’ve been wanting to grow the maintainer team for some time, and have had multiple requests from contributors and contributing organizations wanting to become maintainers. But, so far, we just haven’t managed to get anything off the ground. What we see is that becoming a maintainer is too hard and the current ownership model doesn’t work. In short, we need to update Backstage governance. + +To address this, we are proposing (RFC links below) the following three initiatives: + +- Introduce more steps in between first-time contributor and maintainer in the form of a contributor ladder (loosely based on the [CNCF Project Template](https://github.com/cncf/project-template/blob/main/CONTRIBUTOR_LADDER.md)). The ladder might look as follows: Contributor, Org Member, Reviewer, Maintainer, Project Maintainer. +- Change the ownership model, for example, divide the project up into several project areas, each covering particular parts of the project. +- Introduce a new process for large contributions in the form of Backstage Enhancement Proposals (BEPs). + +Read more and join the already rich discussion in [RFC: Updated Backstage Governance](https://github.com/backstage/backstage/issues/15317) and [RFC: Backstage Enhancement Proposals](https://github.com/backstage/backstage/issues/15318). The RFC will be open until 13/02/2023. + +# Come join our SIGs (and push for new ones) + +As many of you know, SIG stands for Special Interest Group. The purpose of a SIG is to bring together maintainers and interested contributors within a certain specialist area to discuss, debate, spread knowledge, brainstorm - and drive the overall project forward. They’re also a lot of fun! + +We currently have two SIGs up and running: + +- [Catalog](https://github.com/backstage/community/tree/main/sigs/sig-catalog?utm_campaign=Newsletters%20Sent&utm_medium=email&_hsmi=241130993&_hsenc=p2ANqtz-9fx-nTmQga2j12NqzZaL-lYPq-xQjDoXcWKe_JUoa2RGlK65R9j0CIygfYILr0tGEQSvRVN9xzhiJ6LmVxBthKnStfSA&utm_content=241130993&utm_source=hs_email) started up last June and covers all aspects of the systems and components related to the Software Catalog. The group runs every second Tuesday between 16:00 and 17:00 CET. Just show up or hop into [#catalog](https://discord.com/channels/687207715902193673/923144214580191282) (Discord), if you want to talk to us first. Here are the [notes from our sessions so far](https://docs.google.com/document/d/1xg57CDfX2R5jTGbbWANzifm2szEb664kuTwfEEvKgZU/edit#heading=h.iw0hjv6xfb9e). +- [Adoption](https://github.com/backstage/community/tree/main/sigs/sig-adoption?utm_campaign=Newsletters%20Sent&utm_medium=email&_hsmi=241130993&_hsenc=p2ANqtz-9CAxtT8JSeJZPh41o3ZnDBi0VBFpbL6fEqXInr9HHOFhU3JAo8HekKg1JzE5rhGP5zOaHcsYDd1YxJWNHw-eSk5mLWkA&utm_content=241130993&utm_source=hs_email) kicked off in December and covers all aspects of the Backstage adoption journey including documentation and tutorials. In the first two meetups, we discussed adoption challenges based on user persona, collecting data about those challenges, and bootstrapping the Catalog to improve metadata quality for adopters. This one runs every second Thursday between 16:00 and 17:00 CET. Again just show up or, if you want to talk to us first, you can do so in [#adoption](https://discord.com/channels/687207715902193673/1045031039061479536) (Discord). Here are the [notes from our sessions](https://docs.google.com/document/d/1zeYSzXYgh897bxPQmwy2btOwCFlEjlUDLf00riySLRc/edit?_hsmi=241130993&_hsenc=p2ANqtz-_nPuE5hW4fnbhJ5-uK8r5HisSTU7rkslKirvqu0g-vdynbitPVYF2AVLAatos2dLoxb2Bgx_g4LBgH02kXoq7_Acd43Q#heading=h.iw0hjv6xfb9e) so far. + +So that’s SIGs. Get involved and join the ones we have up and running. And/or feel free to propose new ones. + +# Help drive a better experience for all adopters + +Throughout all stages of adopting Backstage in an organization — initial discovery, evaluation and POC, and scaling to the wider org — we have identified opportunities where we want to make the journey for Backstage adopters faster and smoother. + +We’ll go step-by-step, but initial plans are to: + +- Make it easier to install, customize, and maintain Backstage +- Provide Golden Paths for adoption +- Improve the experience and the content on [backstage.io](https://backstage.io/docs/overview/what-is-backstage) + +As we move forward, we’d love you to be part of it. Here are some ways that you can contribute to this initiative: + +- Simply give us feedback. [Tell us about your adoption journey](https://spotify.co1.qualtrics.com/jfe/form/SV_cuxhYPB6oQDu7gW). +- Contribute to the pages and documentation on [backstage.io](https://backstage.io/docs/overview/what-is-backstage) +- Pay it forward by making code contributions even during your adoption journey (if you are on one) +- Join the [Adoption](https://github.com/backstage/community/tree/main/sigs/sig-adoption?utm_campaign=Newsletters%20Sent&utm_medium=email&_hsmi=241130993&_hsenc=p2ANqtz-9CAxtT8JSeJZPh41o3ZnDBi0VBFpbL6fEqXInr9HHOFhU3JAo8HekKg1JzE5rhGP5zOaHcsYDd1YxJWNHw-eSk5mLWkA&utm_content=241130993&utm_source=hs_email) SIG +- Chat with us on [#adoption](https://discord.com/channels/687207715902193673/1045031039061479536) (Discord) diff --git a/microsite/blog/assets/2023-02-06/whats-ahead.png b/microsite/blog/assets/2023-02-06/whats-ahead.png new file mode 100644 index 0000000000000000000000000000000000000000..e49f68149d7cf72acf5d06b008b4cd3b74660d18 GIT binary patch literal 150199 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

    Y=)q0dY> zT?F`?fpgw&xi^+o{Gu-a=Uw~5i{?23e2}oZ-p~SFv!4BfZj*^uD|LXUW3oM22Be9( z{qrmpkOosbRh2u1lm}|Q1El@Ryg~8o2=7>XZ-SdJQ@pe#snRU$Uc8XlYg3@c^gox@ zMtdH;cvJt^-yr}+U5*531yB4{|=2_WGZh0PXNpyUxShu31t7hvzmtrcMG$Jfy z=Nv6NP%u=3tS`4J6>3LEFK3`RC{ zOrz8S{6o`a`D=8!(Uzu7*mjqtFUfot*X*6y9}BD{ak0!qqf1LzvXw!q8E$P$UX$*d z)yO1SQ%Qt=`J>}e<*?Vzm()iPEaf0 zYBh`hWZ~w1g75la(cL|L0HM3-gl8X{24uz?;T6FD6}0mvt2`|eQYwOH05Z%5R{~?x zCpK_p{P$ESa{}=5E6%K-b@^`uao^^qs;nyaujmBEN|3JtrlrLOy*_8{sIwoSxcj1f zySRkKR1a$@PlqopC2&bpepVMw!HKhO?(Qz2VfEaZo`iwh1RSSIeZKf=s9Q0=-zs~BC&b@(HnjG!&e68n6p9CQh zX(omPPE53f4nh0>&xeG3!G;4c<3fM)=l5Z`JIab65Q58grCGLi-I9S$C43YPhpQLn zJ_FfZm|(02vfOmRB3m#Uv@~w2ecAh6DRg3&1LehZnriDd$f^QWo9no3$bm7$#e^Fl zHt&A&D*?n+;Cj1PDax$7I-!&Aw-z>!sCvX_u&Khsx0edtO=1=*?qST(otMek(iHC+Z}yI=M`mUXK9QhB zRyu~OKM0w#C)u@(W?y;p%0Fw>XX#upqALtiMQ>Ma@Ds??HA$XH{HFx~rAO*hzT9kj z2;~VzrI-IXz+QPN_yB|)07Sm>N^2oImjN3pRpQ zqZ*MTQPI(==yB0M4EV%h>6P|Fd8(GK}mRZXP>`CaK_gz7Iv0_3FE(46DP`-mbwMkACqZGEGx%g6n1J#A|Mrx-mLa z%_%JFJiqn#zxhKrYFNK)4g7MmPyTC1z|jHG1<0-#ZHvXubY?xxlr3d6GpyiRa0LHR zVuOA57Ed+M8^$3jSP0ZZFCI$Z?yxLyslX$BE3l>`E1jyHmeUb){zvLZ8&-Y zL3o_{;ja^fJpF4GWNazBz{F_ED!MXlO}3X8G*keW`(L4~NenAWx2{IGn`kPxcT;}N zeK)`cx|^538uXP{CiLmJw-+6KOzSM2wHGi)68dmcw4&2}y>myj! z9d2Rcxh6K%FJ{{=G2Lwjf^Qih3HEt&tRoVl6?u>yW8(iIb8lxh!1KE@jV9*YO#g#_ zX*V;oS~b6bkX1R6v)?uVDv0!HW4T%^{c9HGpymj1Ic}hUR|mLMPF!z2){&%LR`(9L&G8{Sk)jX5L09_;_a1U8F-riz_vb=y7O{~A6+m$4;T z`8ZLF*+QMA7Mh^w?Y6-I4V00qH~ZBei-0Hwj`&wF@FF!O(kf1(_|qVbs7y1`_AU=> zzOx*F0WiB;**HseQs;;H)#XZ|!`bxiNvg_B=srXHx>gp)IYz4netw^=@($$Qk0Ql(tQQ zjpS;Vn1io-Rl}3wY>Nip`I^K`t>3!FSr8Qn$@+bBK}&h2)pkXV|1lvrP;4{uLs+-k zQj5)vRzm=>lD4`Ycy3PnoTVpCmHk@Er6T;~c?8F^++YE2Ij4ZeX@7mB8|VxzjDM-wsgj_Qyrs3@kS8?uRIF+bPOys}5^@p*)8TbX|45c*$<$ zhr{*3;{vHwxHX>*MLpc}PC&BM_JiOiPikNFa z;2ocsIkd^GedY?P6UvqD1?{qHz-9}j9U%dSlE=|5z>-K#BU+Wi4>Mhk zcZ*Asowpb+d#`YQVdq3VWjIgm(Iottet5snxzuUkz~A($W>+L#gY9k=tGX$THWygu7??^{KZPjeV`4RE1KaM!>-eykO| zi@{pp!h6uZJ?$S4`vfu`UddAF-F3@S)<{1ax>gl`MvNY`A=2m{np+QCa*_*B&|hC= zp9R1qypvM)f(s2n*_bU@mM#^vp%i`C8J^|`g*O_JW8}2W5O>;OVB2C%~NvU+=uF;udz{0rH)SI=I<$cpbV7lt&jOlX7 z$IV#s^B6l$Ar$rh5B>Cx9&7xaB1Ks*lS(~cu~&Ojr#@T2aTa9HIW@9>eh0!TFT?ucY8bxfQ{L?+G)tbH1 zAC)`)RkcQNHUQQ)0Yrj16mp;_x(gO{#V&XgQTd{vMvkBJ|8(?>W-lgBd{Va_`wsA6 zf3o9DZ#2LxMH@Z02wX&bPlMZJ=yYjOg(J%qNbOa%KiW&_d04~!B6!(;fP+83A4rp3 z^?`L0AiEN$v-%_7Ufn+i&gHJj{Y$XDM8LTxu7p#%u!2^dTgd4X335Q0<_y_p%ufIZ z@%Lz?-bEH*VVA}yfVjv0w?TFJYO;*9uO?4s+5-G{;Yw@1TL-F6syc}VZWaT!s@q-o z1HIAmTr)45b2?QYi95~-|Kz3_(RT_ z*?X_GK6&5wTKkU5Zi6)Uy-4_?@qXbjXf?oO9kx%`c7PaKEgs~(l zQ(cfj+;B^43(&d`Y23WrP?maWD~D#BLD?3eEOHr&MbF@K6;T!&SZCTMT>V<%h_E+PbNz{D1#!2rLK*&Ir3$q)t4XqN9~$;PVrY z1qLvA4E0JvMppsU3Nm5trXlIW=wkKucZw)rxufr3!!Ma`gS)ksJTjOl_kok4#~iop z2#-DY08g5X{_sx$=I&KXKYG4_3>$*UG$Ce6&n$EMYYoeAWe~VC`=>5UANaO4%GyfV z{krxYfR30+S1AK+Lwl!utZO!`CwdC&RgstNYQ4UzsKJkZxUYBgvaubpotFQKjt!dj zfX8@t0}lq(U~9pYGWQ-sT66;U$yVYT1sZuKZ+e z0Ui-JG3=NC19Z)xO9Cttgzfg>VSRH8lb0_Ap3%Zq!`b$*B--8f4N9Orfj{LiO5OYn zJ6N3(L`+>SshN5uzroPyd&)0&nE%25m+m*0nPC-zaq;VzU+*Sv6(G%QnIx=&DYd%Ad1b*;l=P^LpfC%7C0Yy21PY zEN*TjLAP&{-2?}wBbrh!jX-4o=>8&FBFy|1>)F33uxQ?pfCxj=0>tHA#^=w?wx*iW zt9!(z&xiE5A|xBeKImK6SBfvv(Xh`8XZB;?{yMTC{*d&uWCO0emKH-&T;-bZKKWTWT|g;*Igz)aG&C)B`+kr4{jSrK zB522rnII9)H6BjX)>2{0l{hzTgo|m{nH2T7CqSs~aN}*Y$esIw$Uj-7+|wH!zN^cr%sj z7h^r8?kNWEnw|OHGWW(Nuz%eaU;;K75k46zP{#88}xuA;v>YA$s;F)uO^Gvb@KbnSnN9} zdkKfaI(3+nmL-%nkz2Q=@ya>pbW)M+;D|8lWruNJe6Y!1BzOI?MvF%g(H*Bf9>Z>S zlOa6E8;WK+!ZVs-;~T|pOefRFD0l)-R#W(VONTb?fXA(;*#Ry`A9_;`!XYmC=d!1v z+0w)n{T6wN(vi)-q?zn}ptK6jQkek|@3e2CN|6&aGS|(dh zF2B(pm~r;;;*U5xT=RWmw+CO-WOaMp|9k6H_#j_bpSR!4Byp(5e)-TRr5?f`7-rfJ z^~+jG8Ox=9&bPl~kU-R)99pgSgf*$YW<&R&R4|!9>JF+t=TO_Pu5V|Q#?!8~T4N4X zA9vk1%7&~cp)X_h?1%?_rm+Ei6#=YVTIxv5odj6H>~_b*HAgG7PRC-mdWBDtP=}5Ma54*r zVPC(wbLRjk(me5el*XfQ^kEf4Yv26gZ9i&_){Y{gqY6!Q|H<5DPmi1@{s3jq z%h|15>VhaVf6I`eqf{y3jRybimwKfzk011Qm0FH=jq_C5%uAIl3&Xt6aXUQx?UiP| zECWv9SN__}Z%wb$u7{iCh3o#C6U>AKT!`D*jR$*Drk`zC^#uC#4?jHGZ5j4Do9=Kp z?s<$)kbL9Znf{q;w@3Q4x*nvMuqvLF@7UiXKzCEjjy1Q{a zTp7`Y%m|2Yv7md|qwc<`6KAEFL?n9LjMD3-bgo$`POXb#yR8^mZ{+=mr>4_ju58d% z!dRa1=uRqUG9i;NyEhSCf>ZnxNUjG|h(iHd*5B-En{(1kBxTY0qC zuQ@l^c)MzQK6Z=ZTsvIW(gB*GrRqb}Wuq%w9l`hd=Z_7|fZ5nfm+`ZtUCAkSN6XW< z64ml8%@?ioep=~0wHp*Gz7)>#qaRiptxoIx1G-eVm(}xSkFG*1a^Oow{0Z66%h>zD z;%KLvrwHGl{{%y;;&-MJgqv~^km|tWM?$$d$q>;I;hmY=_K!Wz(mAsO)~3+v^mI`y zS*u%+Zg;ykJSqpOZlOnFb(6YDj|&O+Dy;g(^Q!wS=4$1x%~&MTZ1A$OQ?BGt#c4Z3 ztuNOd$n0{*GxMX^yrumfYVjM8;M*l9q95GZ;5|Ki*Cgt{?b2Q6_4A9pY>v&n5AxjL zOwK$iHhNzvZ=wcxQrp+NCMowL`;6yTwrt;e|7}94H~jlkn=Uq5}$oz`ei^6`v=hz^pW=niOx2}SuR zd++)1-zaYC5 zC?YN#Vj9^ezQF!0BS70NJHYF>LNMf3arzfg>tCX&r&rN$x`Jxts_hCZjO?Zz*(Mr< ztq*IKepAbDS9)gfAGZHX+dL87F?^OI=KSpAV-A7e?OR^j&Lk;~3-;z&M@NAvPL=uv zpSPzhOBhriON2?-=EiLs4b4bDh1&pntR^I)Q*FN(mHfUIZuOZ*#3-?cJ*+ zq9Ca)IG8%Jk?Z)lpGeBvO5X{GL`EI>p~n{-__+Ev!vaxth(h>dPf}S#oc7Vnu2t$n zak`ho5YIs}pK;(b+O)ICs8`TFeAqFmXhzAXb%6>Wv$)R8$-Rt#>lTKRnDJlfYyKSE z-`qcvD$Sq~H>SF#8x!-Ifr~oy=K8po**Q12>!)C^xlP`x?g5u&d5y`@SzEb5hR&^$ z_VP>DXm?9O#YItzx~5wtE)Sx+Ogqh}EMdo?--t5;Y#k7cdNOx2+PYfpnx%>LAqj&p zsP|d3a%BXQbfj+7wjY}Rqco&yKeN9OPIkAsv@u%!U&KV`$;knv zgCuA;+cxF98pgeX-pmLfQ@Y6+>ibErzZryGW4{;S=F?h=q5NWq`_jamea*p8c2F>6 zw9!)%aT@S+x=ua?f5v16WV&M%r9YkBbQ3}p>x+5NzyF07*`GF@#X!KFq>NpSe`a>` zpDk^7nAF?kHt`eQ|oa{7ba*NiYsd-N&=fn z8f;vN7T0%o37x2ty9Jxsu5$D`ObM+v8LmEPQJ1*<2K~XTry~^G2)|X5Vh85|Ss8HM#A7fFTx!UgDS6F1jl!R-rSr{yKD_AJ$f@c?*f*ma?mlS=F=LC9`m^4V$g6*l>E#lRSM=K{{?DRBk~U#Thh zM$|eZwsVQQ6NnMTwR{&GhxL!K@Z$&l0~5+&t3BfzQ+3)dp5h+VTzGW|S=74v2EB0Q z(%J&E0`_}f@LGVl_pRalaqGiku`klVD@)IV>kW!(^g+-X7%$?vQyCFk6L{;4kL^IM zRA_=bS_Tyu;Pc*gT5%X6#skZIu!^TBS zZG#_4i5*o}(Cxltclv0Ut21&j13I`FNUAw^OYos~2C<{?+qPVA@2kIf^x0V(8|UuN(NsQnIeMQje-+nVZQLU~CcpPR z#Eg%w>ER_dr^N%IyN|OZ|JItF@t=6{BK{rxc;`3?hrQv47y>br$n7Ex&CZi*rkYFx z;jtuqUvHu(c22cl(vmCbuq-7N9$P9>-Soo#^{IrE?e1glMYFqx>k9T4XB}+G6FD>ZHbG4q3 zrWM|6F$E4J{WI{wd@5~l19_ia^eL+h1X$9l@@zHOA!!$^@?{d}Jswhrl9Y}XbOs?E zPe5w|?Niz4hhK?B{)=G5WB+xoM<0%uHY0^Tle{P{;1$BpovsKc|FNtQ=Tgj z8U8i;`!8TQ%GZ3Rw6IqHRumgP9z^CBizZEiHf=-kvKYqS(Kq;I-75xC1W!M65k}$r zMx@hPQOn_{C%1zML;g6%$6B4TId-~@5k<~b`Rxxu@S&Fy8xBkC8||-?>7&MYOEjHHG{1`*HN>8)z}Vbgr@Ls@O}J(~ z{L#cy8*ccPk zT&}JU7Fwr_g=eM0PX?7~1Dxl7{`s8(`xG&``lwdTg>Vq-BGNx84+FC`-hsG;XxR$% zv%miNaknV5_lz^%T;BGkkC8R4K%XNYb?En7S6o=AL#5BhaM|(*>v&)J2w)q*Wx1u9 z-KUooKavIoVFaKvjh_MT@_Q!HSw#cZ_g2n#J zP$u0P6LV0G9ITQ-ZPf$IVR-z^)%Itm;;0ICDLa{~j9j?QvF22F8unFV2n>#?AmK5)&S;kp}E1vAn$zb`u@X`vEPSr&M$VT-9Kjk4{jxMEOpi`tUpru zNJwH*Bx!-y$bSY!GCtDBF~tqSyhW`N>?YMSdY(HIF|N;4=`TF@qYHK%pMR>ERt&63 zRjW08tbejsJ}_Ki8%xz_ERUAB%~#~)z74g-4&yK5n*5b9e%!<$(cYdtkzuq}IQ#ds#=j~2j82ec;m$%1SE*dW~yjtpoumQrDC z9cr{r(7A)=+Xv~?SPE-VB7fm7`rtnUm(E#>n~DL=PxP)Wa@#(m!l-baQK;>?*C=;3 z`FPfqo@BE=yYL&Jys8~|%#Tf_c=$osMEqCR^O}kOOkCQQttX-&1E2QF{s!A`(;C9i z*Bu0(loL6vCQDAy2pLpM@Lw3s1|FUSHaanq434Sp`3%DAYV*-j;eSB9xjMD zK^IuYa-SoAQ8#T*xhhr(>#G>$b5VGVM99D~N+ZZ?Cjh z@`9?TCG6r>PPkiL;~K}*@)w0pLxZE3zMqK{JA)D2q{b%K(KJ81=wH}9uh=i|@BhM{ zaHf2*cFMV|T->hz!eY_3NMU!hHaKHUgXw-?jGf?M+-^rXQo{e@Mw!?feHR{6l~ef> zlx)SG@#s{Y03(q{hx}9U&()r`TUSi)g{2sO#Y%}p9%C);cUbv=s=7m@T>7aQ$U&nj zB;NV$YSDSw94i&B%}wFNx^gVI3NQ|WbqlvFQ{7e2YROfzI)Tumny80v2)7-jC6T=q z=^4}$ZdcAgXH=YynJ~Pss90lc>iJmMrP=%9i`)<%>x20GkxvdZ?DLmSwoeh1?8_dL7O9`ez&n91EOQkLqKe zg0ROSK*w`Gx}_=nVOUuku1?3}#ohFl4Kg!F{OSq0YQsmB!6%&E@nxH%o^U}BDkfg2 zw`yX`6TE1wO@F5VbFT>IK4z z{DK}^X?&!a8ZsTFeePX8Ku5B&2^<%ABT;L{^v}_qcgdbr4LP7fOLTSM*TvO2A{d)~ zKnOA?7#^nG9xct>cU}h;^F5Rg!wU0dSQGhhWB?@Ik?Wn>WT>A3_`iavka8v zhU)8!1$qY6HW)`fF>Q@`<+vKG=eVjoJcBKY)a?z|_KV}+;zkF>jxO#A@C^`DFqPc$ z+K6tbxX5u8K-qJcdcJ)G{7XroOzcmHyp4VSevoQ@LAk$&HsZJS zDr1_OCo7Yxu<2@j=WCbM3;45#O1b$x%0&G^y?7!Cy%zw=K4Oz3>|SHMiNA2y;4o6i z!_L8qY&9zvfV`#>{zXW!$HtG{BIYM1Tpw3*w4AzpwTJ3t)yRbRj2z<~Z&$GS-hPR) zek|7{2mnDo^X8103M*DXr?DopzGw%yJjul1Qir4eE2n-#T@#;F-ZDIp1p^*csNuG6 z{nW&|*k)oclh(e__YF)i?b6-*IPqe01Xs?RNU7K(Uwj{#EKeNC72q6tGCT~;UQ`jF zJZjUTQKRL;JPKarCER5`<`<_`%LJ4U$U{jt&wT2iOirrK%}CpQGXPB|{eTmcIHWC< z?i^IbnY>)69NZ?uUu{^2nfOFz6+50Q0IaC-PvHXU%o$&&;-)IGOUL_Cm`w08yfb9G zSBsz>Tn56GE$J(j;j2av>QNFRi!C4VQr=?X`&X*p<=h>Zx?PR9CNsvCfr~>RP3NIe zMhy=LiOwWPTEOa>w3snDe87V1$wy+{im=_p7%FU=geQUR*1jhFD(B`m8v?C1KDM%> z_qKP-!`K^tB0r{Qy-gNLvu}L%DPTq%$Gn@4xa3c`PugTej&>eI<##Wn)$4x6_Tp9Y6w2DP?8GRN_~W;3_)V>q(eUTaj&A#bkqQbxzo0m6I!t;QL~C{zyyJ z&PKZK(qep1igHx+$SV1Uu;Wpi86~HsH&Jq{@9y3g&4umLnWoEco>@IJ8yYHrtzx6R^3(gp1-6WY{&XkP0V5f#!ScfEiwAehRvkiFns%pgTF3I~$nEt6Ngy zenU>d67)@T0aRg;G!;bo1#RJ0;CJyj;2d2HP)oZ5&%kz2zR#%Dp?h87Yx`0Lr$y`j zf$H|ZCjO7x5@1ty%HZS7gL4~1-T92lJ!9mjsS7t~0>Y6Cqe zQ4^BG1#YI&*5sGnqq$H89_7lI*8}hSE4&~hons2Ss~WFCN+9suD+=qtxxpXL^d;vS z1Ga`WmOJ?w!0FJ*?lVK<`F7H*iO7m-$#avZyDsOGIkl^lDcht^pXC8d%teq&9rs+L z1#on??jBK-XBQ~+(4+l5su!UrbkrF0k}G8n5Ws#jHo|iO{%7>jI-nd4pMN_ID#xXh z7d3P!@ut0plUnDC(J~ksV9`M~;L+CR(Od|C2Qb}~^L!Ea=nP3X09!zC{%{cm`f))% z7qB_eRPQAkC+pCLGibj_uFPT7eSnm#@>$on2#$Mg!E8atrK2gW3fi=H`!xT+cypAj zNku{X=K&Do1<7caawerowXl^nkhxO6s1&FI?>>_}J}|i`O52P&K|%CY{V~TJ4=;J2 zUshnTxm+1Qd7jtkm2u<}(P0Uv&cj{+uoUIN0Zj@j?K|mAL`p_YV4a75)DH!- z_sZPM&s~zS4FC^)Pz&4Tf{hhu&z^qe*$mtI2sg6rnUkQkoB3t+8c!$dU+>RQLcgDn z(@?r=baknHz%D$yB<^6Bk8Hsh2}Il-3Cyz3Y{Hgix=9}+CU_F?d34^s?tr`e=HpS2jd24zw2wB$=ic+&mS8EsZ`czO~d-Z zGy2;UF5&zvCJ?aEUFUnB-AcD2qN64C5W&FYd?}*+y?c=U~C%`4GZS zX91<1c%sD}edn@tB$<`&j+2(elL+Q~R;C77O94s%vA|$Ghrh*EcQaORAj2 zU?Wu<4?A)qZEMT3If+A}yEtpJ%6MNrPNfM1AQM2G0PO}m+#Ym+0J0fINq)Q+DO8qO zG8)ysRq`Y@Ms~%@uPIy_5-muIAbL_EN3SM&t%gXuMlhV81Alhb7tBIjA_OQP;-jdd zpa8tb%u1(pqznX}qjkday05HIoFiW4(7aNikfL!R_}gF|qh&udwqFLZ+-Wh(Vvl$} z7N6_olA8AF>^%?Rv`cA8+N=8h74>r0%^y(K$SOcxhuEd$ju&art0`uyfvKvTc;cRE zwjbsU*y3OMYpAqL)pk#{o-B)fJw&Jbo`j%+@l}S9WQY@g`Km<(RT#hiD)p_3>_&r? z_=DA;jDTba7jx{I#cZ;07?eFbKyC*5iZ_W{N#b3fI0)0ASOZQ_|D=Ts1*dY~`zsqH z8#1f*48B9;uCKZygVQK+n3sdtDt&_%fx%?IcHA=kFZkT;^sw5ks(TnVjY8=YXx&cR zhU??M$>tI@uDsTSb`Qf8naP*N@1Ff#so!6!zFM#c)Bd$MGb%i0Qn(8SH2Sa1+-p7w zj?5INiOGFd*2q^m=;j}&bA#Sz=k@7HZxA^XWG^yg=Ek!jed05bj@dwfVBa%V=18Z| zXVK>ky$x6xy=448aWh5YQ`M?=i?oE@Pg4cJ~HJ@l5H6fBAXumSI!g})^brL8>N0DuRAav9K?aH#)Q9AqJnAP*D zqHxyHaT>h&xE=qK>Er}gdKUOw=(uTXbYio;hppR#DB$$BmZj&>cd!=nL+5o{-Onr9 z4d(K-_kJ9Ec|9WzH8#Eq@!?g_I~d|OLl>O)vpe-StEm+IbOeVPqnn_-`L>9WKC<(J zdfgIBUW>HswxzQbR0KryT6Vwo4ytr$%R^Qva^6m=by_If8ZlC$?TDy7nCq4o2#%tSy3)l{ZL)*HLt~*sRhC@t6I*Xd~*01 z3ZHgBV9kES`ia+M?Iq#jVb{r9j+8FPjZ){@qse%FMD)0}Z2i7EJ$_K}9{Q>V+^H1*V5BW2F98yN(;^LU-gCAovlevtC!gx)<*WA> zsw>Vel@-D#_fYU7m-?NheR8|avEh&H!}XX2UZEMP?VwRVVo_I$bn`k-ONMOvR$W#g zzV4pY_@Z#To#2x{5)H?fpG9b}@&ALzzyjN17*q(_d9Bp)Wa9J&yvQ8B(sc+ItoS#p zNh?qE(W}y}&P-usL*igrOC#CfgZlYf7$yN$lfkv_`0EpOkI8%g!I?7OBX{D0#~ zbnTNB5KbHSU3ToQeyb$%PUg8Q5zB`BU5xhV&_^yh1(rx40w)t3;`ktPRr~7Pf|psy~X^B zKJv$2Bm8;4r4?&k-+ZOpkE+=kONw#G4O;K680pL?LDI#^7N7bf579}53>o5*gudn# z>1N_~>Ki+ov+sd043rFF@A`~Ei#N?f9e;L8f)Y6<+%0Hk2(tz6Y_I_xtYBfm8Dc7J z37`db=jH46_{-?*sE>DK&aJObp)AW+jU^cmRGb z=vCZ1;#T?^)O3Guco|U^+@1D%GvnL0R?Q8nMNs*M=(x^|aCOzXk7i{1Sq4LIi<%Qi z34Gc-{tWT%m?3H%^vZrnt#$A^3d-)t3zT@(cQI4_xhqDwtbj#2G6Aa|2!_UcTfs~h zOO!vIlobZbDsflTcx%p3_iVgQPn9X8$Otg8FtjntB_gBUW&NvIG^1GiE=u42tb$@V!bYv+}dpY&$|LVR-`;CtEtPCVvz+up{x1OR0Zh)jSU!`hIMG5i7P#>EyqeVlcz@B-EqSK-Y$g^aJT%u(2a8@(0#8HG^VSWAl5jyB8n{^hTbx`R`2m+;$!uEZ%D^j`S;Vy0Qi_Kq`X=0@B^$Q z;35I-(?9ZnJ$c*^bT`LZ;{}^5!LJYSY43y=rFd*4wAiaZ`V@?18AMdDoZzos0Oy$a zz3`ETW(~)96W!p6>I@;pd#vhL4OVMiPmIGU4cc=+7Y+CYS}X=Z1E?vL zGWh^9aD-g$Fih*_UIy|Qbls~rl#Iki)$0K(3IHpllKv2@`|LJD0?%EIwR!qCFS!uz zbZ|<)!XY=8e4@sjDnwABrgJ3#FKf(>Ls-=TQ6zjc#pI5*;j_# z8A`}ivjT8q;5sDBGXOP_{we!z(*t4n;U0w5Ho6cp4Dbiwq{I8K$-}q?oLqC(egU}$ z+r*cG)Q~YigLoX2MV6*vZCv>TYvb~ZzXoIeh1)U(3w=k&WENjZoO%b4=U|;wjD+Bp zDT1SSWKb|^QLzjBU)b27!4H_FHfx!CJTCHp98QT{5-(Tb6c%t=V1s8|9-x!qn04R;E@!d zHQibTKqPq03$m^Eqg(aoFB!CVD>!(nJQJmVwttmN0x}tVTD>XD>C+pQrh{v!$LE)L zLjESGcYHz}dW{xTHUWfm>PlGLgAoTR+s^(PBu`+AsQ^B**8-@cNuV}qkOv4ft`i10 z3(csGLjlbSffE%MPe#GWpitrK)lnv}$yM@=VwitFIt<=Z_uyhX--RZ^Hmy5&+I+fj zx23T!9=u9DlMkn=B3LR1S@wM)C6ot~a6s(aSAA@XC0X%ue6i570!jQf#Rh-6i)3}} zU}hh&g{@rvaS-iWI;_;|rxqi`&*M#RRyZJC+!_u@dcJ#&n;<_7g2`2~$gPM)Wm! zI_)l@6e#|Xg>q@ET*M&&ht?M!vzeIHg?hDYI>YAv4!Ahw=chA{bV>agJPqPTTZnNW zhA#ayshSQq101)xt+f7r^Be#g=zVc#D!t_w!|+2d-dl2df`A@j9u@5O5I{m}Yjk#U zUE)TdB9U|qLB0Po>^s5uo50in=@>U8n0T+JBZ!5JiR3-fjbr>pTM z8dQ+Ajste=5iFg9EAZyW%EP6169nig(HKTfbqs<1w1@AajY0go%L8Bq~PYb zZGIP%>m+KI1W&`i-i2?l7EfYq2yo>lU@nXD>eOWiaQBO&!v^=p{+woCvVI{nW=pI{eS*`!I`=z)!ly6VHGhpqL=EhV~^Icv`W zf4-d#SZol20r+Srjk_5mRwX9l1Q2k;@!%4XRy2fLo)u&i%+i50f}tR6pNjgA{PfA| zamjj5`~S0F4oS>7a|&cb$_EZJ->O_=IqMz(aNGV@S~x4b0z(h2@;RTHSG>BhDdO(` zM+~>$|sif|z1M;1GTg^8m2%VAWHC+>lkO9Nh{9DKi(7*X3?x|m3 zF?bOR0+N=M-{MqIn;obw0c#{#?H;1*5wutcoW@G;0W&@BtIvZm z)}*Yn$H8EF0vHM4lAwoOHaocjVqZ`4@NkOuI1_`f`E-1q`@WfN@R~62d?2ApyO?AV zE{vbQ?Ng86POy^OV?}HgY`5Q9RJ*m{ECcc)gr$U1cLDo5Nad`wSQc^;tvmFPa-C{ zU56mqc!b=Tzp{e_I?s&y9G(4|7{O&Qzs$~MJ9lkeIr_s+_lZ!Y#yE32c{6BsbvLzkGOQ1USw+_$r^p;I}kNoy^6E*9vD zS{;&*j#{Mdc?&h)Kuwl^wBcPH3StkL@S9U7*hrBAh=p5q*zgHvC<|M=Dn~7OGK{H4 zrhmeStb$OSdxo~Hc6-H*wr1{DVygi1ePT7PI`zkjD)q5*lLo@Im35rXbaCl-W*;C^ z0hH8=m7SI2J8D2~{TJ>oBI)COSx(%Ne8vVN#@uS;m%1>C#*wE^)SR9^fOiA2G`lyK z+50&NcEAXjesf%W!x&rism~{GRA{&Xs?x{&T-+>omeUiEOu#5`h0ecIG+31e9-heu ztks3nae||0FxsfYJYSy#Olom->Nx{_;am*R2v1FvGoZq-g$CZ+-`IExUQutDTlCWM zdTA!9X{#Mb2G!a9<~?^s2P#-Fn${NB#W9&8>^MitkY*oTmfx!&acAF~oCt>XoVpzk z%3Df?w%;9N#U9c`-iWfHZ-Kq`uNk$#)(mDWRY@LeF zc|3IQ)E5+)0fv@?P}39N3rhk{inHOP){C#1V!x(CGWwK@mt6L;7`l3$Uu`b-Z%mm- z(Tq%Prn*&=?{%M|)_(6uG5s&CYel$5gT!sS z^8O*v5ffZYAQT(1Embn(5aUnF{xLn-pV$wc{$I!pvgX=(h}zC}T=nBm+#IBGW7mhaV0S~V`3 z@P;{Do%MDMTTp9&eiSIMFaiV+JDYBSJt_O$>gjQ-hjFkjzzKdTNQdGS1b8C&*g@S* zZap^kdvV#Qwa~8D1EW`bn!;ord{k$`KaR!86z5P6z2j;ej_$eqmm%?RvVQefR#gQo zaLoKwWa86e%+;_jZd#WD=(H?TDpqOp{y$HbQ~c7h0E89Q^_Bs^u-Drk3MFm>B%%@! zFrK_GCOBLce&4Mb3qo~V9F?`;hqVVEx)$~Ho4h+`moafVd^&Xb#?mC16VL?$rR5x( z>mNH}!gV!o9k4=5#s)#%d@_`Qm;Uw^D>-#CV-}#2LA&yvjRusePuyP56_>OAHy_w? zLF9U1X=cobFS5$e@=%@aPh4aa#d^UVJ;$hJ`4AXld3~3Q^f(yya#bE^$6G@{UiAR# z-apq$y^pm=S!L7Ct-?JCi`Q9;`|^WFK(bv_Q%B$a)#U3!z9L4zc9AF6t&1_s_~pIs zyKaC^G6KVZ#fr;tfbImd=i#i(s4zx+WTC-D*bl2?!TZ_Yi#aW#J;jnDYp8++*dqy7 zg-zArn2bxvK@fkro7rFo!G$@+VKX(OS77I%!aTQpk~ZCG5{SV%80k80hXUT)u$DL& z$mVBy_??G$MVr}_NYvJJWnVPmYHPgIL##c8+C5Ump9>xRlMI=e`WNtz09XJ zS4D<;V#jrS5qR<3uzYe9FDQQ2i9WyRJlyNWN%QgW=C5PiLU|FSnS}37S?E#RF_d_C z--$6snc7)J61UCVnS=~^jXl;J%+1lo)qn&Rl!3GukzS`UhDOHxe0+pi9+7ypmpucn zwylL7x*HhX+C{=owZ^W-f;IXCVchJkLsp|N5>w1whOFU)F z(5irNhyeQ^h;7-zP>4kFav-wR7YVSj1dx_Y3M*+-zqUh6N`NW ztWaOGHYteP?j?)k2E*CCbEL$8d3lR$dU2K%qqGWY}BZ zKWYrM4q!}Y0io>=7u+V;zPgwUNZy*sWa&)$)`zhj3w;jf@V;iSg=@aK*M4LpKwWm! z2*XBOM1WmIfWpm?2@QwDTXVB|E1R|!7QJNppv!(2^kYDZ3pQNjpPTn2rHpg2Mt3ot zI;`6J%LArk#-VlYdKImVvC!I=8{tlT#Mhm|d^=`-I4Iq$$zmwcHeq{hDO#DR7(O&@ z4CEr94q7xEDSROnpWiLBQpZd9$EmT zQK5c+;WhmonSkx@PW@$ULZ9P>Kfl^o1B}CQ6T-*Ba3v0wkTuG+0r*D?k7ISfCo+*Q z@k9Fy_1Os&IzqphZH!eN@?9VQdCJ@XMRg%0CQ+vAvIh@w}L+BOvV`Dq_LKlLMp zU??!TSqs$)BW4RglT_(*_lP3~Hb!z?5hF5@lzxvDHu=XacGN4GCctLO)`iy*5I#YL zT%8z1zj&`vIG|%gtYBcrcVLVxv-?Iza?QSp$8$%%B+Q3b90KJfy(Z%TpG+6|s+vTI zJhGo&0`WW&GDNE8LnJz|;Q@HhvSHV)$uhNTpEd&q%xX1Q<+jFteIZH%`<}}vhOTR% zPHg+3;fm8c^K%8-d!qjCW7Ob9piyu`dD%!bmC|+ED8cAreo8=AM?&agA@yApcCy5y zDs6^}#KWK8wDgO2n92}OHrL3EW4^yVt=P$?@v^n>>0LGWL4SN;*j-A2gVoi-J+MjP zRggk|?unC=*Y=X=wc*cbaI1SOrNv7x=#q0LzZ8Hc67{d)7SJnks1h5@OGN8ho`weW z_f{t#M6r*jZu(X zNB~jWfIbEFP=9lU8^$P?q1aW+mI1Wnst$iB8R1(i_Vnq$dgH_w9{Cc9I*z#Uu=j_F&}qqQ7q zx7K8EzJx%7&1j_uZw_(A!tg9$Scx;bUp$r|Y=IPzO++h%&$b|QYoRzDDm!*Z@h_A)8@7-J{r$dn|2*R3bxF)EG>e) zwy3dfQS>QcgoTC@b0kv!Y1GMve_a;jWDMCW$Yw^h|C;Y1KMOAqoCQqeQvD4&=i&D!ND&0R?XÇHS?RntQ1I!I9``-y(E;j&0z9)hLcgCb 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 S6#*Toaz$QMF6*-4!~X+pLLrC% literal 0 HcmV?d00001 From 922c7f85347e5d467d260f5fe7e3f29de3f54ced Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 6 Feb 2023 15:52:11 +0100 Subject: [PATCH 188/423] chore: add BEP's and sort Signed-off-by: blam --- .github/vale/Vocab/Backstage/accept.txt | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index 9e7cf7aa98..d933d2889a 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -9,6 +9,8 @@ Airbrake Airbrakes Alaria Alef +allowlisted +allowlisted Anddddd Apdex api @@ -23,6 +25,7 @@ Avro backend's backported backporting +BEPs Bigtable Billett bitbucket @@ -95,6 +98,8 @@ dockerfiles Dockerize dockerode Docusaurus +Dominik +Dominik DOMPurify don'ts dynatrace @@ -119,6 +124,8 @@ Firekube Firestore Fiverr Francesco +Frontside +Frontside gerrit Gerrit gitbeaker @@ -138,6 +145,8 @@ Hackathons haproxy hardcoded Helidon +Henneke +Henneke Heroku hoc horizontalpodautoscalers @@ -167,12 +176,18 @@ jsonnet jsx JWTs Kaewkasi +Kaswell +Kaswell Keyv Knex KPIs +Kuang +Kuang kubectl kubernetes kubernetes +Lainfiesta +Lainfiesta ldap learnings Leasot @@ -413,10 +428,3 @@ zod Zolotusky zoomable zsh -Lainfiesta -allowlisted -Dominik -Henneke -Kuang -Frontside -Kaswell From 3ee310ce1ff48e4c8642718ea8f09c20a67af249 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 6 Feb 2023 15:54:51 +0100 Subject: [PATCH 189/423] chore: fix duplication and bad merge Signed-off-by: blam --- .github/vale/Vocab/Backstage/accept.txt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index d933d2889a..e6380a17f0 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -10,7 +10,6 @@ Airbrakes Alaria Alef allowlisted -allowlisted Anddddd Apdex api @@ -99,7 +98,6 @@ Dockerize dockerode Docusaurus Dominik -Dominik DOMPurify don'ts dynatrace @@ -125,7 +123,6 @@ Firestore Fiverr Francesco Frontside -Frontside gerrit Gerrit gitbeaker @@ -146,7 +143,6 @@ haproxy hardcoded Helidon Henneke -Henneke Heroku hoc horizontalpodautoscalers @@ -177,16 +173,12 @@ jsx JWTs Kaewkasi Kaswell -Kaswell Keyv Knex KPIs Kuang -Kuang kubectl kubernetes -kubernetes -Lainfiesta Lainfiesta ldap learnings From bfd441b9d5f4dbba84ca30749e0822d38df110bf Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 6 Feb 2023 16:05:28 +0100 Subject: [PATCH 190/423] chore: fixing bad changeset ] Signed-off-by: blam --- .changeset/slow-moles-sin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/slow-moles-sin.md b/.changeset/slow-moles-sin.md index 140d9e7435..02e1952312 100644 --- a/.changeset/slow-moles-sin.md +++ b/.changeset/slow-moles-sin.md @@ -2,4 +2,4 @@ '@backstage/plugin-circleci': patch --- -Making workflow a link +Making workflow a link From e6b80909385fe5b7ab03c32e95e43d0f8d9ea4d0 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 6 Feb 2023 16:50:42 +0100 Subject: [PATCH 191/423] chore: fix yarn install Signed-off-by: blam --- yarn.lock | 170 +++++++++++++++++++++++++++--------------------------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/yarn.lock b/yarn.lock index 259b321cd5..04738e5b2b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3362,7 +3362,7 @@ __metadata: "@material-ui/icons": ^4.9.1 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -3702,7 +3702,7 @@ __metadata: "@types/jest": ^29.0.0 "@types/minimatch": ^5.0.0 "@types/mock-fs": ^4.13.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/npm-packlist": ^3.0.0 "@types/recursive-readdir": ^2.2.0 "@types/rollup-plugin-peer-deps-external": ^2.2.0 @@ -3804,7 +3804,7 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" "@types/jscodeshift": ^0.11.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 chalk: ^4.0.0 commander: ^9.1.0 jscodeshift: ^0.14.0 @@ -3827,7 +3827,7 @@ __metadata: "@types/json-schema": ^7.0.6 "@types/json-schema-merge-allof": ^0.6.0 "@types/mock-fs": ^4.10.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/yup": ^0.29.13 ajv: ^8.10.0 chokidar: ^3.5.2 @@ -3870,7 +3870,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/prop-types": ^15.7.3 "@types/zen-observable": ^0.8.0 cross-fetch: ^3.1.5 @@ -3968,7 +3968,7 @@ __metadata: "@types/d3-zoom": ^3.0.1 "@types/dagre": ^0.7.44 "@types/google-protobuf": ^3.7.2 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/react-helmet": ^6.1.0 "@types/react-sparklines": ^1.7.0 "@types/react-syntax-highlighter": ^15.0.0 @@ -4025,7 +4025,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/prop-types": ^15.7.3 "@types/zen-observable": ^0.8.0 cross-fetch: ^3.1.5 @@ -4049,7 +4049,7 @@ __metadata: "@types/command-exists": ^1.2.0 "@types/fs-extra": ^9.0.1 "@types/inquirer": ^8.1.3 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/recursive-readdir": ^2.2.0 chalk: ^4.0.0 commander: ^9.1.0 @@ -4174,7 +4174,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4266,7 +4266,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/git-url-parse": ^9.0.0 - "@types/node": ^16.0.0 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-markdown: ^8.0.0 @@ -4318,7 +4318,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4347,7 +4347,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4375,7 +4375,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-ga: ^3.3.0 @@ -4401,7 +4401,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 qs: ^6.10.1 @@ -4445,7 +4445,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/swagger-ui-react": ^4.1.1 cross-fetch: ^3.1.5 graphiql: ^1.8.8 @@ -4480,7 +4480,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4656,7 +4656,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 humanize-duration: ^3.27.0 luxon: ^3.0.0 @@ -4718,7 +4718,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -4770,7 +4770,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4862,7 +4862,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 lodash: ^4.17.21 @@ -5560,7 +5560,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.25.1 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 circleci-api: ^4.0.0 cross-fetch: ^3.1.5 humanize-duration: ^3.27.0 @@ -5593,7 +5593,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -5625,7 +5625,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.27.1 "@types/luxon": ^3.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 humanize-duration: ^3.27.1 luxon: ^3.0.0 @@ -5687,7 +5687,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/highlightjs": ^10.1.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 highlight.js: ^10.6.0 @@ -5720,7 +5720,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 rc-progress: 3.4.1 @@ -5751,7 +5751,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 jsonschema: ^1.2.6 msw: ^0.49.0 @@ -5792,7 +5792,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/pluralize": ^0.0.29 "@types/recharts": ^1.8.14 "@types/regression": ^2.0.0 @@ -5834,7 +5834,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": "*" express: ^4.18.1 msw: ^0.49.0 react-use: ^17.2.4 @@ -6017,7 +6017,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 languageName: unknown @@ -6048,7 +6048,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 classnames: ^2.2.6 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -6078,7 +6078,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6108,7 +6108,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6140,7 +6140,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/dompurify": ^2.3.3 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/sanitize-html": ^2.6.2 classnames: ^2.3.1 cross-fetch: ^3.1.5 @@ -6173,7 +6173,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 peerDependencies: @@ -6202,7 +6202,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6238,7 +6238,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6272,7 +6272,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6304,7 +6304,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": "*" "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6336,7 +6336,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6366,7 +6366,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -6398,7 +6398,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/lodash": ^4.14.173 "@types/luxon": ^3.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 lodash: ^4.17.21 luxon: ^3.0.0 @@ -6428,7 +6428,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/codemirror": ^5.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 graphiql: ^1.5.12 graphql: ^16.0.0 @@ -6484,7 +6484,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": "*" cross-fetch: ^3.1.5 graphql-voyager: ^1.0.0-rc.31 msw: ^0.49.0 @@ -6538,7 +6538,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 lodash: ^4.17.21 msw: ^0.49.0 @@ -6572,7 +6572,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 humanize-duration: ^3.26.0 luxon: ^3.0.0 @@ -6640,7 +6640,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/testing-library__jest-dom": ^5.9.1 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6696,7 +6696,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 jest-when: ^3.1.0 msw: ^0.49.0 @@ -6784,7 +6784,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cronstrue: ^2.2.0 cross-fetch: ^3.1.5 @@ -6846,7 +6846,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -6897,7 +6897,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -6926,7 +6926,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -6955,7 +6955,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 p-limit: ^3.1.0 @@ -6988,7 +6988,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 classnames: ^2.2.6 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -7042,7 +7042,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -7203,7 +7203,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": "*" cross-fetch: ^3.1.5 lodash: ^4.17.21 msw: ^0.49.0 @@ -7290,7 +7290,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 lodash: ^4.17.21 @@ -7342,7 +7342,7 @@ __metadata: "@types/command-exists": ^1.2.0 "@types/fs-extra": ^9.0.1 "@types/mock-fs": ^4.13.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 command-exists: ^1.2.9 fs-extra: ^10.0.1 jest-when: ^3.1.0 @@ -7556,7 +7556,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.18.1 "@types/json-schema": ^7.0.9 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@uiw/react-codemirror": ^4.9.3 classnames: ^2.2.6 cross-fetch: ^3.1.5 @@ -7761,7 +7761,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 qs: ^6.9.4 @@ -7794,7 +7794,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -7825,7 +7825,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/zen-observable": ^0.8.2 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -7893,7 +7893,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 rc-progress: 3.4.1 @@ -7923,7 +7923,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 classnames: ^2.2.6 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -7997,7 +7997,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 lodash: ^4.17.21 msw: ^0.49.0 @@ -8109,7 +8109,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 qs: ^6.9.4 @@ -8140,7 +8140,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/color": ^3.0.1 "@types/d3-force": ^3.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 color: ^4.0.1 cross-fetch: ^3.1.5 @@ -8175,7 +8175,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -8243,7 +8243,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 git-url-parse: ^13.0.0 @@ -8356,7 +8356,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/dompurify": ^2.2.2 "@types/event-source-polyfill": ^1.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 canvas: ^2.10.2 cross-fetch: ^3.1.5 dompurify: ^2.2.9 @@ -8418,7 +8418,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -8471,7 +8471,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -8530,7 +8530,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": "*" cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -8558,7 +8558,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 lodash: ^4.17.21 luxon: ^3.0.0 @@ -8633,7 +8633,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 zen-observable: ^0.10.0 @@ -10546,7 +10546,7 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/test-utils": "workspace:^" - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 languageName: unknown @@ -10569,7 +10569,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 msw: ^0.49.0 react-use: ^17.2.4 peerDependencies: @@ -13491,7 +13491,7 @@ __metadata: "@types/dockerode": ^3.3.0 "@types/fs-extra": ^9.0.6 "@types/http-proxy": ^1.17.4 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/serve-handler": ^6.1.0 "@types/webpack-env": ^1.15.3 commander: ^9.1.0 @@ -14841,10 +14841,10 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^16.0.0, @types/node@npm:^16.9.2": - version: 16.18.11 - resolution: "@types/node@npm:16.18.11" - checksum: 2a3b1da13063debe6e26f732defb5f03ef4ef732c3e08daba838d8850433bd00e537ce1a97ce9bcfc4b15db5218d701d1265fae94e0d6926906bec157e6b46e0 +"@types/node@npm:^16.0.0, @types/node@npm:^16.11.26, @types/node@npm:^16.9.2": + version: 16.18.12 + resolution: "@types/node@npm:16.18.12" + checksum: fc3271182414f8593018ef8f00b4718116a92f463f619081bd399d9460e7861e1dd7eebc7cf94c23567e418ff397babed077011711aae8d47171b5a81c5bd71d languageName: node linkType: hard @@ -20874,7 +20874,7 @@ __metadata: "@backstage/cli-common": "workspace:^" "@backstage/errors": "workspace:^" "@types/fs-extra": ^9.0.1 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/puppeteer": ^5.4.4 chalk: ^4.0.0 commander: ^9.1.0 @@ -22194,7 +22194,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/jquery": ^3.3.34 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/react": "*" "@types/react-dom": "*" "@types/zen-observable": ^0.8.0 @@ -34251,7 +34251,7 @@ __metadata: "@spotify/eslint-plugin": ^14.1.3 "@spotify/prettier-config": ^14.0.0 "@techdocs/cli": "workspace:*" - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/webpack": ^5.28.0 command-exists: ^1.2.9 concurrently: ^7.0.0 @@ -36275,7 +36275,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": ^16.0.0 + "@types/node": ^16.11.26 "@types/react-dom": "*" cross-env: ^7.0.0 cypress: ^10.0.0 From 3264529162871c77a6b4c40b8499702e18834518 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 6 Feb 2023 16:55:59 +0100 Subject: [PATCH 192/423] chore: fix yarn install Signed-off-by: blam --- yarn.lock | 160 +++++++++++++++++++++++++++--------------------------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/yarn.lock b/yarn.lock index a3e4f754b2..83503fb359 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3362,7 +3362,7 @@ __metadata: "@material-ui/icons": ^4.9.1 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -3652,7 +3652,7 @@ __metadata: resolution: "@backstage/cli-common@workspace:packages/cli-common" dependencies: "@backstage/cli": "workspace:^" - "@types/node": "*" + "@types/node": ^16.0.0 languageName: unknown linkType: soft @@ -3702,7 +3702,7 @@ __metadata: "@types/jest": ^29.0.0 "@types/minimatch": ^5.0.0 "@types/mock-fs": ^4.13.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/npm-packlist": ^3.0.0 "@types/recursive-readdir": ^2.2.0 "@types/rollup-plugin-peer-deps-external": ^2.2.0 @@ -3804,7 +3804,7 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" "@types/jscodeshift": ^0.11.0 - "@types/node": "*" + "@types/node": ^16.11.26 chalk: ^4.0.0 commander: ^9.1.0 jscodeshift: ^0.14.0 @@ -3827,7 +3827,7 @@ __metadata: "@types/json-schema": ^7.0.6 "@types/json-schema-merge-allof": ^0.6.0 "@types/mock-fs": ^4.10.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/yup": ^0.29.13 ajv: ^8.10.0 chokidar: ^3.5.2 @@ -3851,7 +3851,7 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" - "@types/node": "*" + "@types/node": ^16.0.0 lodash: ^4.17.21 languageName: unknown linkType: soft @@ -3870,7 +3870,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/prop-types": ^15.7.3 "@types/zen-observable": ^0.8.0 cross-fetch: ^3.1.5 @@ -3968,7 +3968,7 @@ __metadata: "@types/d3-zoom": ^3.0.1 "@types/dagre": ^0.7.44 "@types/google-protobuf": ^3.7.2 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/react-helmet": ^6.1.0 "@types/react-sparklines": ^1.7.0 "@types/react-syntax-highlighter": ^15.0.0 @@ -4025,7 +4025,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/prop-types": ^15.7.3 "@types/zen-observable": ^0.8.0 cross-fetch: ^3.1.5 @@ -4049,7 +4049,7 @@ __metadata: "@types/command-exists": ^1.2.0 "@types/fs-extra": ^9.0.1 "@types/inquirer": ^8.1.3 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/recursive-readdir": ^2.2.0 chalk: ^4.0.0 commander: ^9.1.0 @@ -4085,7 +4085,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.0.0 react-use: ^17.2.4 zen-observable: ^0.10.0 peerDependencies: @@ -4174,7 +4174,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4318,7 +4318,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4347,7 +4347,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4375,7 +4375,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-ga: ^3.3.0 @@ -4401,7 +4401,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 qs: ^6.10.1 @@ -4445,7 +4445,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/swagger-ui-react": ^4.1.1 cross-fetch: ^3.1.5 graphiql: ^1.8.8 @@ -4656,7 +4656,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 humanize-duration: ^3.27.0 luxon: ^3.0.0 @@ -4718,7 +4718,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -4770,7 +4770,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -4862,7 +4862,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 lodash: ^4.17.21 @@ -5560,7 +5560,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.25.1 - "@types/node": "*" + "@types/node": ^16.11.26 circleci-api: ^4.0.0 cross-fetch: ^3.1.5 humanize-duration: ^3.27.0 @@ -5593,7 +5593,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -5625,7 +5625,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.27.1 "@types/luxon": ^3.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 humanize-duration: ^3.27.1 luxon: ^3.0.0 @@ -5687,7 +5687,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/highlightjs": ^10.1.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 highlight.js: ^10.6.0 @@ -5751,7 +5751,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 jsonschema: ^1.2.6 msw: ^0.49.0 @@ -5792,7 +5792,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/pluralize": ^0.0.29 "@types/recharts": ^1.8.14 "@types/regression": ^2.0.0 @@ -6017,7 +6017,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 languageName: unknown @@ -6048,7 +6048,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 classnames: ^2.2.6 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -6078,7 +6078,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6108,7 +6108,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6140,7 +6140,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/dompurify": ^2.3.3 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/sanitize-html": ^2.6.2 classnames: ^2.3.1 cross-fetch: ^3.1.5 @@ -6173,7 +6173,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 peerDependencies: @@ -6202,7 +6202,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6238,7 +6238,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6272,7 +6272,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -6336,7 +6336,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6366,7 +6366,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -6398,7 +6398,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/lodash": ^4.14.173 "@types/luxon": ^3.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 lodash: ^4.17.21 luxon: ^3.0.0 @@ -6428,7 +6428,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/codemirror": ^5.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 graphiql: ^1.5.12 graphql: ^16.0.0 @@ -6538,7 +6538,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 lodash: ^4.17.21 msw: ^0.49.0 @@ -6572,7 +6572,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 humanize-duration: ^3.26.0 luxon: ^3.0.0 @@ -6640,7 +6640,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/testing-library__jest-dom": ^5.9.1 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -6696,7 +6696,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 jest-when: ^3.1.0 msw: ^0.49.0 @@ -6784,7 +6784,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cronstrue: ^2.2.0 cross-fetch: ^3.1.5 @@ -6846,7 +6846,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -6897,7 +6897,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -6955,7 +6955,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 p-limit: ^3.1.0 @@ -6988,7 +6988,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 classnames: ^2.2.6 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -7042,7 +7042,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 msw: ^0.49.0 @@ -7290,7 +7290,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 lodash: ^4.17.21 @@ -7342,7 +7342,7 @@ __metadata: "@types/command-exists": ^1.2.0 "@types/fs-extra": ^9.0.1 "@types/mock-fs": ^4.13.0 - "@types/node": "*" + "@types/node": ^16.11.26 command-exists: ^1.2.9 fs-extra: ^10.0.1 jest-when: ^3.1.0 @@ -7556,7 +7556,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/humanize-duration": ^3.18.1 "@types/json-schema": ^7.0.9 - "@types/node": "*" + "@types/node": ^16.11.26 "@uiw/react-codemirror": ^4.9.3 classnames: ^2.2.6 cross-fetch: ^3.1.5 @@ -7761,7 +7761,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 qs: ^6.9.4 @@ -7794,7 +7794,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -7825,7 +7825,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/zen-observable": ^0.8.2 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -7893,7 +7893,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 rc-progress: 3.4.1 @@ -7923,7 +7923,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 classnames: ^2.2.6 cross-fetch: ^3.1.5 luxon: ^3.0.0 @@ -7997,7 +7997,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 lodash: ^4.17.21 msw: ^0.49.0 @@ -8109,7 +8109,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 qs: ^6.9.4 @@ -8140,7 +8140,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/color": ^3.0.1 "@types/d3-force": ^3.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 color: ^4.0.1 cross-fetch: ^3.1.5 @@ -8175,7 +8175,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -8243,7 +8243,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 git-url-parse: ^13.0.0 @@ -8356,7 +8356,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/dompurify": ^2.2.2 "@types/event-source-polyfill": ^1.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 canvas: ^2.10.2 cross-fetch: ^3.1.5 dompurify: ^2.2.9 @@ -8418,7 +8418,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 react-use: ^17.2.4 @@ -8471,7 +8471,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 @@ -8558,7 +8558,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/luxon": ^3.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 lodash: ^4.17.21 luxon: ^3.0.0 @@ -8576,7 +8576,7 @@ __metadata: dependencies: "@backstage/cli": "workspace:^" "@backstage/test-utils": "workspace:^" - "@types/node": "*" + "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.49.0 languageName: unknown @@ -8633,7 +8633,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 zen-observable: ^0.10.0 @@ -10546,7 +10546,7 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/test-utils": "workspace:^" - "@types/node": "*" + "@types/node": ^16.11.26 cross-fetch: ^3.1.5 msw: ^0.49.0 languageName: unknown @@ -10569,7 +10569,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 msw: ^0.49.0 react-use: ^17.2.4 peerDependencies: @@ -13491,7 +13491,7 @@ __metadata: "@types/dockerode": ^3.3.0 "@types/fs-extra": ^9.0.6 "@types/http-proxy": ^1.17.4 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/serve-handler": ^6.1.0 "@types/webpack-env": ^1.15.3 commander: ^9.1.0 @@ -14841,10 +14841,10 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^16.9.2": - version: 16.18.11 - resolution: "@types/node@npm:16.18.11" - checksum: 2a3b1da13063debe6e26f732defb5f03ef4ef732c3e08daba838d8850433bd00e537ce1a97ce9bcfc4b15db5218d701d1265fae94e0d6926906bec157e6b46e0 +"@types/node@npm:^16.0.0, @types/node@npm:^16.11.26, @types/node@npm:^16.9.2": + version: 16.18.12 + resolution: "@types/node@npm:16.18.12" + checksum: fc3271182414f8593018ef8f00b4718116a92f463f619081bd399d9460e7861e1dd7eebc7cf94c23567e418ff397babed077011711aae8d47171b5a81c5bd71d languageName: node linkType: hard @@ -20874,7 +20874,7 @@ __metadata: "@backstage/cli-common": "workspace:^" "@backstage/errors": "workspace:^" "@types/fs-extra": ^9.0.1 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/puppeteer": ^5.4.4 chalk: ^4.0.0 commander: ^9.1.0 @@ -22194,7 +22194,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/jquery": ^3.3.34 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/react": "*" "@types/react-dom": "*" "@types/zen-observable": ^0.8.0 @@ -34251,7 +34251,7 @@ __metadata: "@spotify/eslint-plugin": ^14.1.3 "@spotify/prettier-config": ^14.0.0 "@techdocs/cli": "workspace:*" - "@types/node": "*" + "@types/node": ^16.11.26 "@types/webpack": ^5.28.0 command-exists: ^1.2.9 concurrently: ^7.0.0 @@ -36275,7 +36275,7 @@ __metadata: "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 - "@types/node": "*" + "@types/node": ^16.11.26 "@types/react-dom": "*" cross-env: ^7.0.0 cypress: ^10.0.0 From 8657e0f05c1a8fa0e94153f8e6a0c948eb745db6 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Wed, 1 Feb 2023 17:31:08 -0500 Subject: [PATCH 193/423] Expose all props available to underlying EntityRelationsGraph. Signed-off-by: Aramis Sennyey --- .../CatalogGraphCard/CatalogGraphCard.tsx | 27 +++++++------------ .../EntityRelationsGraph.tsx | 16 ++++++----- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx index b9a15eb569..0266693696 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx @@ -36,8 +36,8 @@ import { Direction, EntityNode, EntityRelationsGraph, - RelationPairs, } from '../EntityRelationsGraph'; +import { EntityRelationsGraphProps } from '../EntityRelationsGraph/EntityRelationsGraph'; const useStyles = makeStyles( { @@ -55,27 +55,19 @@ const useStyles = makeStyles( { name: 'PluginCatalogGraphCatalogGraphCard' }, ); -export const CatalogGraphCard = (props: { - variant?: InfoCardVariants; - relationPairs?: RelationPairs; - maxDepth?: number; - unidirectional?: boolean; - mergeRelations?: boolean; - kinds?: string[]; - relations?: string[]; - direction?: Direction; - height?: number; - title?: string; - zoom?: 'enabled' | 'disabled' | 'enable-on-click'; -}) => { +export const CatalogGraphCard = ( + props: Omit & { + variant?: InfoCardVariants; + height?: number; + title?: string; + }, +) => { const { variant = 'gridItem', relationPairs = ALL_RELATION_PAIRS, maxDepth = 1, unidirectional = true, mergeRelations = true, - kinds, - relations, direction = Direction.LEFT_RIGHT, height, title = 'Relations', @@ -133,12 +125,11 @@ export const CatalogGraphCard = (props: { }} > ; renderLabel?: DependencyGraphTypes.RenderLabelFunction; curve?: 'curveStepBefore' | 'curveMonotoneX'; -}) => { +} + +/** + * Core building block for custom entity relations diagrams. + * + * @public + */ +export const EntityRelationsGraph = (props: EntityRelationsGraphProps) => { const { rootEntityNames, maxDepth = 2, From 4365ae46e4dcb43c0688491d9ec3dbe55d1bfbb7 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Wed, 1 Feb 2023 17:37:50 -0500 Subject: [PATCH 194/423] Remove items that are overriden in passed props. Signed-off-by: Aramis Sennyey --- .../src/components/CatalogGraphCard/CatalogGraphCard.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx index 0266693696..e646cc7cfa 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx @@ -56,7 +56,10 @@ const useStyles = makeStyles( ); export const CatalogGraphCard = ( - props: Omit & { + props: Omit< + EntityRelationsGraphProps, + 'rootEntityNames' | 'onNodeClick' | 'className' + > & { variant?: InfoCardVariants; height?: number; title?: string; From 18277101362b9f51bd7a7598d44436fa07ed7e46 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Wed, 1 Feb 2023 17:41:45 -0500 Subject: [PATCH 195/423] Add changeset. Signed-off-by: Aramis Sennyey --- .changeset/slow-sloths-do.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/slow-sloths-do.md diff --git a/.changeset/slow-sloths-do.md b/.changeset/slow-sloths-do.md new file mode 100644 index 0000000000..7d9cc263de --- /dev/null +++ b/.changeset/slow-sloths-do.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-graph': minor +--- + +Expose additional props on the CatalogGraphCard to allow for custom node & label rendering or kind/relation filtering. From a6dba7dde1f9e6619fd071a021119888815907d1 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Thu, 2 Feb 2023 15:28:25 -0500 Subject: [PATCH 196/423] Add back destructured kinds and relations. Signed-off-by: Aramis Sennyey --- .../src/components/CatalogGraphCard/CatalogGraphCard.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx index e646cc7cfa..03b346e5ec 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx @@ -72,6 +72,8 @@ export const CatalogGraphCard = ( unidirectional = true, mergeRelations = true, direction = Direction.LEFT_RIGHT, + kinds, + relations, height, title = 'Relations', zoom = 'enable-on-click', From 21c31d742a4da3860f9f7f6b450ea77ddb9fe2e1 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Fri, 3 Feb 2023 10:18:19 -0500 Subject: [PATCH 197/423] Prefer type and expose in public API. Signed-off-by: Aramis Sennyey --- plugins/catalog-graph/api-report.md | 62 +++++++++---------- .../CatalogGraphCard/CatalogGraphCard.tsx | 4 +- .../EntityRelationsGraph.tsx | 7 ++- .../components/EntityRelationsGraph/index.ts | 1 + 4 files changed, 38 insertions(+), 36 deletions(-) diff --git a/plugins/catalog-graph/api-report.md b/plugins/catalog-graph/api-report.md index 95f497fe95..0f4b4170ad 100644 --- a/plugins/catalog-graph/api-report.md +++ b/plugins/catalog-graph/api-report.md @@ -65,19 +65,16 @@ export enum Direction { } // @public -export const EntityCatalogGraphCard: (props: { - variant?: InfoCardVariants | undefined; - relationPairs?: RelationPairs | undefined; - maxDepth?: number | undefined; - unidirectional?: boolean | undefined; - mergeRelations?: boolean | undefined; - kinds?: string[] | undefined; - relations?: string[] | undefined; - direction?: Direction | undefined; - height?: number | undefined; - title?: string | undefined; - zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined; -}) => JSX.Element; +export const EntityCatalogGraphCard: ( + props: Omit< + EntityRelationsGraphProps, + 'className' | 'onNodeClick' | 'rootEntityNames' + > & { + variant?: InfoCardVariants | undefined; + height?: number | undefined; + title?: string | undefined; + }, +) => JSX.Element; // @public export type EntityEdge = DependencyGraphTypes.DependencyEdge; @@ -103,26 +100,27 @@ export type EntityNodeData = { }; // @public -export const EntityRelationsGraph: (props: { +export const EntityRelationsGraph: ( + props: EntityRelationsGraphProps, +) => JSX.Element; + +// @public (undocumented) +export type EntityRelationsGraphProps = { rootEntityNames: CompoundEntityRef | CompoundEntityRef[]; - maxDepth?: number | undefined; - unidirectional?: boolean | undefined; - mergeRelations?: boolean | undefined; - kinds?: string[] | undefined; - relations?: string[] | undefined; - direction?: Direction | undefined; - onNodeClick?: - | ((value: EntityNode, event: MouseEvent_2) => void) - | undefined; - relationPairs?: RelationPairs | undefined; - className?: string | undefined; - zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined; - renderNode?: DependencyGraphTypes.RenderNodeFunction | undefined; - renderLabel?: - | DependencyGraphTypes.RenderLabelFunction - | undefined; - curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined; -}) => JSX.Element; + maxDepth?: number; + unidirectional?: boolean; + mergeRelations?: boolean; + kinds?: string[]; + relations?: string[]; + direction?: Direction; + onNodeClick?: (value: EntityNode, event: MouseEvent_2) => void; + relationPairs?: RelationPairs; + className?: string; + zoom?: 'enabled' | 'disabled' | 'enable-on-click'; + renderNode?: DependencyGraphTypes.RenderNodeFunction; + renderLabel?: DependencyGraphTypes.RenderLabelFunction; + curve?: 'curveStepBefore' | 'curveMonotoneX'; +}; // @public export type RelationPairs = [string, string][]; diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx index 03b346e5ec..a97be534f8 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx @@ -132,12 +132,12 @@ export const CatalogGraphCard = ( diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx index a9fc9960ff..2451f4913a 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx @@ -66,7 +66,10 @@ const useStyles = makeStyles( { name: 'PluginCatalogGraphEntityRelationsGraph' }, ); -export interface EntityRelationsGraphProps { +/** + * @public + */ +export type EntityRelationsGraphProps = { rootEntityNames: CompoundEntityRef | CompoundEntityRef[]; maxDepth?: number; unidirectional?: boolean; @@ -81,7 +84,7 @@ export interface EntityRelationsGraphProps { renderNode?: DependencyGraphTypes.RenderNodeFunction; renderLabel?: DependencyGraphTypes.RenderLabelFunction; curve?: 'curveStepBefore' | 'curveMonotoneX'; -} +}; /** * Core building block for custom entity relations diagrams. diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/index.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/index.ts index b86c8f05ae..06227babe3 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/index.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/index.ts @@ -14,6 +14,7 @@ * limitations under the License. */ export { EntityRelationsGraph } from './EntityRelationsGraph'; +export type { EntityRelationsGraphProps } from './EntityRelationsGraph'; export { ALL_RELATION_PAIRS } from './relations'; export type { RelationPairs } from './relations'; export { Direction } from './types'; From 8fbc10c1f87de83b0f82f9a81ab303aa713e713a Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Mon, 6 Feb 2023 10:54:42 -0500 Subject: [PATCH 198/423] Make all original props optional. Signed-off-by: Aramis Sennyey --- .../CatalogGraphCard/CatalogGraphCard.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx index a97be534f8..8f6d02d1f1 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx @@ -56,10 +56,7 @@ const useStyles = makeStyles( ); export const CatalogGraphCard = ( - props: Omit< - EntityRelationsGraphProps, - 'rootEntityNames' | 'onNodeClick' | 'className' - > & { + props: Partial & { variant?: InfoCardVariants; height?: number; title?: string; @@ -75,6 +72,9 @@ export const CatalogGraphCard = ( kinds, relations, height, + className, + rootEntityNames, + onNodeClick, title = 'Relations', zoom = 'enable-on-click', } = props; @@ -87,7 +87,7 @@ export const CatalogGraphCard = ( const classes = useStyles({ height }); const analytics = useAnalytics(); - const onNodeClick = useCallback( + const defaultOnNodeClick = useCallback( (node: EntityNode, _: MouseEvent) => { const nodeEntityName = parseEntityRef(node.id); const path = catalogEntityRoute({ @@ -131,9 +131,9 @@ export const CatalogGraphCard = ( > Date: Mon, 6 Feb 2023 15:54:19 +0100 Subject: [PATCH 199/423] backend-plugin-api: separate out hook in addShutdownHook Signed-off-by: Patrik Oldsberg --- .changeset/bright-plums-cough.md | 5 ++++ .changeset/green-guests-flow.md | 8 +++++ docs/backend-system/core-services/01-index.md | 29 +++++++++---------- .../lifecycle/lifecycleFactory.ts | 12 ++++---- .../rootHttpRouter/rootHttpRouterFactory.ts | 7 +---- .../rootLifecycleFactory.test.ts | 20 +++++++------ .../rootLifecycle/rootLifecycleFactory.ts | 19 ++++++++---- .../src/database/connectors/sqlite3.ts | 10 +++---- packages/backend-plugin-api/api-report.md | 13 ++++++--- .../services/definitions/LifecycleService.ts | 14 ++++++--- .../src/services/definitions/index.ts | 1 + .../src/next/wiring/TestBackend.test.ts | 8 ++--- .../src/next/wiring/TestBackend.ts | 7 +---- .../src/service/CatalogPlugin.ts | 6 +--- 14 files changed, 88 insertions(+), 71 deletions(-) create mode 100644 .changeset/bright-plums-cough.md create mode 100644 .changeset/green-guests-flow.md diff --git a/.changeset/bright-plums-cough.md b/.changeset/bright-plums-cough.md new file mode 100644 index 0000000000..9af30f002e --- /dev/null +++ b/.changeset/bright-plums-cough.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +**BREAKING**: Split out the hook for both lifecycle services so that the first parameter of `addShutdownHook` is the hook function, and the second is the options. diff --git a/.changeset/green-guests-flow.md b/.changeset/green-guests-flow.md new file mode 100644 index 0000000000..688ff17dd9 --- /dev/null +++ b/.changeset/green-guests-flow.md @@ -0,0 +1,8 @@ +--- +'@backstage/backend-test-utils': patch +'@backstage/backend-app-api': patch +'@backstage/backend-common': patch +'@backstage/plugin-catalog-backend': patch +--- + +Updated usage of the lifecycle service. diff --git a/docs/backend-system/core-services/01-index.md b/docs/backend-system/core-services/01-index.md index b394391480..711357df61 100644 --- a/docs/backend-system/core-services/01-index.md +++ b/docs/backend-system/core-services/01-index.md @@ -479,10 +479,7 @@ createBackendPlugin({ // do some other stuff. }, 1000); - lifecycle.addShutdownHook({ - fn: () => clearInterval(interval), - logger, - }); + lifecycle.addShutdownHook(() => clearInterval(interval)); }, }); }, @@ -499,17 +496,19 @@ The following example shows how to override the default implementation of the li ```ts class MyCustomLifecycleService implements RootLifecycleService { - constructor(private readonly logger: LoggerService) { - ['SIGKILL', 'SIGTERM'].map(signal => - process.on(signal, () => this.shutdown()), - ); - } + constructor(private readonly logger: LoggerService) {} #isCalled = false; - #shutdownTasks: Array = []; + #shutdownTasks: Array<{ + hook: LifecycleServiceShutdownHook; + options?: LifecycleServiceShutdownOptions; + }> = []; - addShutdownHook(options: LifecycleServiceShutdownHook): void { - this.#shutdownTasks.push(options); + addShutdownHook( + hook: LifecycleServiceShutdownHook, + options?: LifecycleServiceShutdownOptions, + ): void { + this.#shutdownTasks.push({ hook, options }); } async shutdown(): Promise { @@ -520,10 +519,10 @@ class MyCustomLifecycleService implements RootLifecycleService { this.logger.info(`Running ${this.#shutdownTasks.length} shutdown tasks...`); await Promise.all( - this.#shutdownTasks.map(async hook => { - const { logger = this.logger } = hook; + this.#shutdownTasks.map(async ({ hook, options }) => { + const logger = options?.logger ?? this.logger; try { - await hook.fn(); + await hook(); logger.info(`Shutdown hook succeeded`); } catch (error) { logger.error(`Shutdown hook failed, ${error}`); diff --git a/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts b/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts index 299022079b..27c1a139fd 100644 --- a/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts +++ b/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts @@ -17,6 +17,7 @@ import { createServiceFactory, coreServices, LifecycleServiceShutdownHook, + LifecycleServiceShutdownOptions, } from '@backstage/backend-plugin-api'; /** @@ -33,11 +34,12 @@ export const lifecycleFactory = createServiceFactory({ async factory({ rootLifecycle, logger, pluginMetadata }) { const plugin = pluginMetadata.getId(); return { - addShutdownHook(options: LifecycleServiceShutdownHook): void { - rootLifecycle.addShutdownHook({ - ...options, - - logger: options.logger?.child({ plugin }) ?? logger, + addShutdownHook( + hook: LifecycleServiceShutdownHook, + options?: LifecycleServiceShutdownOptions, + ): void { + rootLifecycle.addShutdownHook(hook, { + logger: options?.logger?.child({ plugin }) ?? logger, }); }, }; diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts index 58f8cc2db1..f46f92741b 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts @@ -104,12 +104,7 @@ export const rootHttpRouterFactory = createServiceFactory({ { logger }, ); - lifecycle.addShutdownHook({ - async fn() { - await server.stop(); - }, - logger, - }); + lifecycle.addShutdownHook(() => server.stop()); await server.start(); diff --git a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.test.ts b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.test.ts index fc1c266775..3a93cacc8d 100644 --- a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.test.ts @@ -21,11 +21,7 @@ describe('lifecycleService', () => { it('should execute registered shutdown hook', async () => { const service = new BackendLifecycleImpl(getVoidLogger()); const hook = jest.fn(); - service.addShutdownHook({ - fn: async () => { - hook(); - }, - }); + service.addShutdownHook(() => hook()); // should not execute the hook more than once. await service.shutdown(); await service.shutdown(); @@ -35,10 +31,16 @@ describe('lifecycleService', () => { it('should not throw errors', async () => { const service = new BackendLifecycleImpl(getVoidLogger()); - service.addShutdownHook({ - fn: async () => { - throw new Error('oh no'); - }, + service.addShutdownHook(() => { + throw new Error('oh no'); + }); + await expect(service.shutdown()).resolves.toBeUndefined(); + }); + + it('should not throw async errors', async () => { + const service = new BackendLifecycleImpl(getVoidLogger()); + service.addShutdownHook(async () => { + throw new Error('oh no'); }); await expect(service.shutdown()).resolves.toBeUndefined(); }); diff --git a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts index ebff53e9a6..2b6f7eeafe 100644 --- a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts @@ -18,6 +18,7 @@ import { createServiceFactory, coreServices, LifecycleServiceShutdownHook, + LifecycleServiceShutdownOptions, RootLifecycleService, LoggerService, } from '@backstage/backend-plugin-api'; @@ -26,10 +27,16 @@ export class BackendLifecycleImpl implements RootLifecycleService { constructor(private readonly logger: LoggerService) {} #isCalled = false; - #shutdownTasks: Array = []; + #shutdownTasks: Array<{ + hook: LifecycleServiceShutdownHook; + options?: LifecycleServiceShutdownOptions; + }> = []; - addShutdownHook(options: LifecycleServiceShutdownHook): void { - this.#shutdownTasks.push(options); + addShutdownHook( + hook: LifecycleServiceShutdownHook, + options?: LifecycleServiceShutdownOptions, + ): void { + this.#shutdownTasks.push({ hook, options }); } async shutdown(): Promise { @@ -40,10 +47,10 @@ export class BackendLifecycleImpl implements RootLifecycleService { this.logger.info(`Running ${this.#shutdownTasks.length} shutdown tasks...`); await Promise.all( - this.#shutdownTasks.map(async hook => { - const { logger = this.logger } = hook; + this.#shutdownTasks.map(async ({ hook, options }) => { + const logger = options?.logger ?? this.logger; try { - await hook.fn(); + await hook(); logger.info(`Shutdown hook succeeded`); } catch (error) { logger.error(`Shutdown hook failed, ${error}`); diff --git a/packages/backend-common/src/database/connectors/sqlite3.ts b/packages/backend-common/src/database/connectors/sqlite3.ts index e1ed6b18e9..3cb0f57de6 100644 --- a/packages/backend-common/src/database/connectors/sqlite3.ts +++ b/packages/backend-common/src/database/connectors/sqlite3.ts @@ -81,12 +81,10 @@ export function createSqliteDatabaseClient( }); // If the dev store is available we save the database state on shutdown - deps.lifecycle.addShutdownHook({ - async fn() { - const connection = await database.client.acquireConnection(); - const data = connection.serialize(); - await devStore.save(dataKey, data); - }, + deps.lifecycle.addShutdownHook(async () => { + const connection = await database.client.acquireConnection(); + const data = connection.serialize(); + await devStore.save(dataKey, data); }); } else { database = knexFactory(knexConfig); diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index a7700d81ac..1add61348c 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -294,14 +294,19 @@ export interface IdentityService extends IdentityApi {} // @public (undocumented) export interface LifecycleService { - addShutdownHook(options: LifecycleServiceShutdownHook): void; + addShutdownHook( + hook: LifecycleServiceShutdownHook, + options?: LifecycleServiceShutdownOptions, + ): void; } // @public (undocumented) -export type LifecycleServiceShutdownHook = { - fn: () => void | Promise; +export type LifecycleServiceShutdownHook = () => void | Promise; + +// @public (undocumented) +export interface LifecycleServiceShutdownOptions { logger?: LoggerService; -}; +} // @public export interface LoggerService { diff --git a/packages/backend-plugin-api/src/services/definitions/LifecycleService.ts b/packages/backend-plugin-api/src/services/definitions/LifecycleService.ts index 59d14aa61d..89351194e6 100644 --- a/packages/backend-plugin-api/src/services/definitions/LifecycleService.ts +++ b/packages/backend-plugin-api/src/services/definitions/LifecycleService.ts @@ -19,14 +19,17 @@ import { LoggerService } from './LoggerService'; /** * @public */ -export type LifecycleServiceShutdownHook = { - fn: () => void | Promise; +export type LifecycleServiceShutdownHook = () => void | Promise; +/** + * @public + */ +export interface LifecycleServiceShutdownOptions { /** * Optional {@link LoggerService} that will be used for logging instead of the default logger. */ logger?: LoggerService; -}; +} /** * @public @@ -35,5 +38,8 @@ export interface LifecycleService { /** * Register a function to be called when the backend is shutting down. */ - addShutdownHook(options: LifecycleServiceShutdownHook): void; + addShutdownHook( + hook: LifecycleServiceShutdownHook, + options?: LifecycleServiceShutdownOptions, + ): void; } diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index c5af0967bd..720b4d634d 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -28,6 +28,7 @@ export type { HttpRouterService } from './HttpRouterService'; export type { LifecycleService, LifecycleServiceShutdownHook, + LifecycleServiceShutdownOptions, } from './LifecycleService'; export type { LoggerService, LogMeta } from './LoggerService'; export type { PermissionsService } from './PermissionsService'; diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts index dca463a9ae..9bda3f3f5b 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts @@ -40,10 +40,8 @@ beforeAll(async () => { env.registerInit({ deps: { lifecycle: coreServices.lifecycle }, async init({ lifecycle }) { - lifecycle.addShutdownHook({ - fn() { - globalTestBackendHasBeenStopped = true; - }, + lifecycle.addShutdownHook(() => { + globalTestBackendHasBeenStopped = true; }); }, }); @@ -145,7 +143,7 @@ describe('TestBackend', () => { lifecycle: coreServices.lifecycle, }, async init({ lifecycle }) { - lifecycle.addShutdownHook({ fn: shutdownSpy }); + lifecycle.addShutdownHook(shutdownSpy); }, }); }, diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.ts index db1016fcb6..27a8c5bceb 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.ts @@ -129,12 +129,7 @@ export async function startTestBackend< { logger }, ); - lifecycle.addShutdownHook({ - async fn() { - await server.stop(); - }, - logger, - }); + lifecycle.addShutdownHook(() => server.stop(), { logger }); await server.start(); diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts index effed7f8f1..a726d3261b 100644 --- a/plugins/catalog-backend/src/service/CatalogPlugin.ts +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -97,11 +97,7 @@ export const catalogPlugin = createBackendPlugin({ const { processingEngine, router } = await builder.build(); await processingEngine.start(); - lifecycle.addShutdownHook({ - fn: async () => { - await processingEngine.stop(); - }, - }); + lifecycle.addShutdownHook(() => processingEngine.stop()); httpRouter.use(router); }, }); From 000fd3f4a8a57311c5301d0de0fd6621f50fe607 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 6 Feb 2023 17:24:10 +0100 Subject: [PATCH 200/423] eslint-plugin: fix no-undeclared-imports test on windows Signed-off-by: Patrik Oldsberg --- .../src/no-undeclared-imports.test.ts | 142 ++++++++++++------ 1 file changed, 94 insertions(+), 48 deletions(-) diff --git a/packages/eslint-plugin/src/no-undeclared-imports.test.ts b/packages/eslint-plugin/src/no-undeclared-imports.test.ts index c156558e8d..1b5cbee853 100644 --- a/packages/eslint-plugin/src/no-undeclared-imports.test.ts +++ b/packages/eslint-plugin/src/no-undeclared-imports.test.ts @@ -15,11 +15,11 @@ */ import { RuleTester } from 'eslint'; -import path from 'path'; +import { join as joinPath } from 'path'; import rule from '../rules/no-undeclared-imports'; const RULE = 'no-undeclared-imports'; -const FIXTURE = path.resolve(__dirname, '__fixtures__/monorepo'); +const FIXTURE = joinPath(__dirname, '__fixtures__/monorepo'); const ERR_UNDECLARED = ( name: string, @@ -27,7 +27,10 @@ const ERR_UNDECLARED = ( path: string, flag?: string, ) => ({ - message: `${name} must be declared in ${field} of ${path}/package.json, run 'yarn --cwd ${path} add${ + message: `${name} must be declared in ${field} of ${joinPath( + path, + 'package.json', + )}, run 'yarn --cwd ${path} add${ flag ? ` ${flag}` : '' } ${name}' from the project root.`, }); @@ -37,7 +40,10 @@ const ERR_SWITCHED = ( field: string, path: string, ) => ({ - message: `${name} is declared in ${old}, but should be moved to ${field} in ${path}/package.json.`, + message: `${name} is declared in ${old}, but should be moved to ${field} in ${joinPath( + path, + 'package.json', + )}.`, }); process.chdir(FIXTURE); @@ -53,141 +59,181 @@ ruleTester.run(RULE, rule, { valid: [ { code: `import '@internal/foo'`, - filename: path.join(FIXTURE, 'packages/foo/src/index.ts'), + filename: joinPath(FIXTURE, 'packages/foo/src/index.ts'), }, { code: `import '@internal/bar'`, - filename: path.join(FIXTURE, 'packages/foo/src/index.ts'), + filename: joinPath(FIXTURE, 'packages/foo/src/index.ts'), }, { code: `import 'react'`, - filename: path.join(FIXTURE, 'packages/foo/src/index.ts'), + filename: joinPath(FIXTURE, 'packages/foo/src/index.ts'), }, { code: `import '@internal/foo'`, - filename: path.join(FIXTURE, 'packages/foo/src/index.test.ts'), + filename: joinPath(FIXTURE, 'packages/foo/src/index.test.ts'), }, { code: `import '@internal/bar'`, - filename: path.join(FIXTURE, 'packages/foo/src/index.test.ts'), + filename: joinPath(FIXTURE, 'packages/foo/src/index.test.ts'), }, { code: `import 'lodash'`, - filename: path.join(FIXTURE, 'packages/foo/src/index.test.ts'), + filename: joinPath(FIXTURE, 'packages/foo/src/index.test.ts'), }, { code: `import 'react'`, - filename: path.join(FIXTURE, 'packages/foo/src/index.test.ts'), + filename: joinPath(FIXTURE, 'packages/foo/src/index.test.ts'), }, { // We're only able to validate literals code: `require('lod' + 'ash')`, - filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), }, ], invalid: [ { code: `import 'lodash'`, - filename: path.join(FIXTURE, 'packages/foo/src/index.ts'), + filename: joinPath(FIXTURE, 'packages/foo/src/index.ts'), errors: [ ERR_SWITCHED( 'lodash', 'devDependencies', 'dependencies', - 'packages/foo', + joinPath('packages', 'foo'), ), ], }, { code: `import 'react-router'`, - filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), errors: [ ERR_SWITCHED( 'react-router', 'dependencies', 'peerDependencies', - 'packages/bar', + joinPath('packages', 'bar'), ), ], }, { code: `import 'react-router-dom'`, - filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), errors: [ ERR_SWITCHED( 'react-router-dom', 'devDependencies', 'peerDependencies', - 'packages/bar', + joinPath('packages', 'bar'), ), ], }, { code: `import 'lodash'`, - filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), - errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], }, { code: `import { debounce } from 'lodash'`, - filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), - errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], }, { code: `import * as _ from 'lodash'`, - filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), - errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], }, { code: `import _ from 'lodash'`, - filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), - errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], }, { code: `import('lodash')`, - filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), - errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], }, { code: `require('lodash')`, - filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), - errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], - }, - { - code: `import 'lodash'`, - filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), - errors: [ERR_UNDECLARED('lodash', 'dependencies', 'packages/bar')], - }, - { - code: `import 'lodash'`, - filename: path.join(FIXTURE, 'packages/bar/src/index.test.ts'), + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), errors: [ - ERR_UNDECLARED('lodash', 'devDependencies', 'packages/bar', '--dev'), + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], + }, + { + code: `import 'lodash'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], + }, + { + code: `import 'lodash'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.test.ts'), + errors: [ + ERR_UNDECLARED( + 'lodash', + 'devDependencies', + joinPath('packages', 'bar'), + '--dev', + ), ], }, { code: `import 'react'`, - filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), errors: [ - ERR_UNDECLARED('react', 'peerDependencies', 'packages/bar', '--peer'), + ERR_UNDECLARED( + 'react', + 'peerDependencies', + joinPath('packages', 'bar'), + '--peer', + ), ], }, { code: `import 'react'`, - filename: path.join(FIXTURE, 'packages/bar/src/index.test.ts'), + filename: joinPath(FIXTURE, 'packages/bar/src/index.test.ts'), errors: [ - ERR_UNDECLARED('react', 'peerDependencies', 'packages/bar', '--peer'), + ERR_UNDECLARED( + 'react', + 'peerDependencies', + joinPath('packages', 'bar'), + '--peer', + ), ], }, { code: `import 'react-dom'`, - filename: path.join(FIXTURE, 'packages/foo/src/index.ts'), - errors: [ERR_UNDECLARED('react-dom', 'dependencies', 'packages/foo')], + filename: joinPath(FIXTURE, 'packages/foo/src/index.ts'), + errors: [ + ERR_UNDECLARED( + 'react-dom', + 'dependencies', + joinPath('packages', 'foo'), + ), + ], }, { code: `import 'react-dom'`, - filename: path.join(FIXTURE, 'packages/foo/src/index.test.ts'), + filename: joinPath(FIXTURE, 'packages/foo/src/index.test.ts'), errors: [ - ERR_UNDECLARED('react-dom', 'devDependencies', 'packages/foo', '--dev'), + ERR_UNDECLARED( + 'react-dom', + 'devDependencies', + joinPath('packages', 'foo'), + '--dev', + ), ], }, ], From f1adb2e36b460b5c996504d1a6ed897d04968c4d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 6 Feb 2023 17:34:26 +0100 Subject: [PATCH 201/423] backend-test-utils: remove mock service refs Signed-off-by: Patrik Oldsberg --- .changeset/thin-donkeys-attack.md | 5 ++++ packages/backend-test-utils/api-report.md | 27 ------------------- .../src/next/services/mockServices.ts | 24 +++++------------ 3 files changed, 12 insertions(+), 44 deletions(-) create mode 100644 .changeset/thin-donkeys-attack.md diff --git a/.changeset/thin-donkeys-attack.md b/.changeset/thin-donkeys-attack.md new file mode 100644 index 0000000000..2fd0aebb6a --- /dev/null +++ b/.changeset/thin-donkeys-attack.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Removed the `ref` from all `mockServices`. diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index 232f7e8136..6e0edde88b 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -20,7 +20,6 @@ import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoggerService } from '@backstage/backend-plugin-api'; import { PermissionsService } from '@backstage/backend-plugin-api'; import { RootLifecycleService } from '@backstage/backend-plugin-api'; -import { RootLoggerService } from '@backstage/backend-plugin-api'; import { SchedulerService } from '@backstage/backend-plugin-api'; import { ServiceFactory } from '@backstage/backend-plugin-api'; import { ServiceRef } from '@backstage/backend-plugin-api'; @@ -34,8 +33,6 @@ export function isDockerDisabledForTests(): boolean; export namespace mockServices { // (undocumented) export namespace cache { - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: () => ServiceFactory; } @@ -47,22 +44,16 @@ export namespace mockServices { export type Options = { data?: JsonObject; }; - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: (options?: Options | undefined) => ServiceFactory; } // (undocumented) export namespace database { - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: () => ServiceFactory; } // (undocumented) export namespace httpRouter { - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: ( options?: HttpRouterFactoryOptions | undefined, @@ -72,36 +63,26 @@ export namespace mockServices { export function identity(): IdentityService; // (undocumented) export namespace identity { - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: () => ServiceFactory; } // (undocumented) export namespace lifecycle { - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: () => ServiceFactory; } // (undocumented) export namespace logger { - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: () => ServiceFactory; } // (undocumented) export namespace permissions { - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: () => ServiceFactory; } // (undocumented) export namespace rootLifecycle { - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: () => ServiceFactory; } @@ -120,15 +101,11 @@ export namespace mockServices { debug: boolean; }; }; - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: (options?: Options | undefined) => ServiceFactory; } // (undocumented) export namespace scheduler { - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: () => ServiceFactory; } @@ -136,15 +113,11 @@ export namespace mockServices { export function tokenManager(): TokenManagerService; // (undocumented) export namespace tokenManager { - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: () => ServiceFactory; } // (undocumented) export namespace urlReader { - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: () => ServiceFactory; } diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index f86d8bac55..ef32993611 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -62,8 +62,7 @@ export namespace mockServices { export namespace config { export type Options = { data?: JsonObject }; - export const ref = coreServices.config; - export const factory = simpleFactory(ref, config); + export const factory = simpleFactory(coreServices.config, config); } export function rootLogger(options?: rootLogger.Options): LoggerService { @@ -76,8 +75,7 @@ export namespace mockServices { | { error: boolean; warn: boolean; info: boolean; debug: boolean }; }; - export const ref = coreServices.rootLogger; - export const factory = simpleFactory(ref, rootLogger); + export const factory = simpleFactory(coreServices.rootLogger, rootLogger); } export function tokenManager(): TokenManagerService { @@ -93,55 +91,47 @@ export namespace mockServices { }; } export namespace tokenManager { - export const ref = coreServices.tokenManager; - export const factory = simpleFactory(ref, tokenManager); + export const factory = simpleFactory( + coreServices.tokenManager, + tokenManager, + ); } export function identity(): IdentityService { return new MockIdentityService(); } export namespace identity { - export const ref = coreServices.identity; - export const factory = simpleFactory(ref, identity); + export const factory = simpleFactory(coreServices.identity, identity); } // TODO(Rugvip): Not all core services have implementations available here yet. // some may need a bit more refactoring for it to be simpler to // re-implement functioning mock versions here. export namespace cache { - export const ref = coreServices.cache; export const factory = cacheFactory; } export namespace database { - export const ref = coreServices.database; export const factory = databaseFactory; } export namespace httpRouter { - export const ref = coreServices.httpRouter; export const factory = httpRouterFactory; } export namespace lifecycle { - export const ref = coreServices.lifecycle; export const factory = lifecycleFactory; } export namespace logger { - export const ref = coreServices.logger; export const factory = loggerFactory; } export namespace permissions { - export const ref = coreServices.permissions; export const factory = permissionsFactory; } export namespace rootLifecycle { - export const ref = coreServices.rootLifecycle; export const factory = rootLifecycleFactory; } export namespace scheduler { - export const ref = coreServices.scheduler; export const factory = schedulerFactory; } export namespace urlReader { - export const ref = coreServices.urlReader; export const factory = urlReaderFactory; } } From 1835311713c3ee767376250f4e5252d06a554c67 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 6 Feb 2023 17:36:22 +0100 Subject: [PATCH 202/423] backend-test-utils: explicit return type for mockServices.config() Signed-off-by: Patrik Oldsberg --- .changeset/four-tables-fix.md | 5 +++++ packages/backend-test-utils/api-report.md | 3 +-- .../backend-test-utils/src/next/services/mockServices.ts | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 .changeset/four-tables-fix.md diff --git a/.changeset/four-tables-fix.md b/.changeset/four-tables-fix.md new file mode 100644 index 0000000000..f17f57e253 --- /dev/null +++ b/.changeset/four-tables-fix.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Added explicit return type signature for `mockServices.config()`. diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index 6e0edde88b..672c574cb2 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -6,7 +6,6 @@ import { Backend } from '@backstage/backend-app-api'; import { BackendFeature } from '@backstage/backend-plugin-api'; import { CacheService } from '@backstage/backend-plugin-api'; -import { ConfigReader } from '@backstage/config'; import { ConfigService } from '@backstage/backend-plugin-api'; import { DatabaseService } from '@backstage/backend-plugin-api'; import { ExtendedHttpServer } from '@backstage/backend-app-api'; @@ -37,7 +36,7 @@ export namespace mockServices { factory: () => ServiceFactory; } // (undocumented) - export function config(options?: config.Options): ConfigReader; + export function config(options?: config.Options): ConfigService; // (undocumented) export namespace config { // (undocumented) diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index ef32993611..5f771f13c5 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -15,6 +15,7 @@ */ import { + ConfigService, coreServices, createServiceFactory, IdentityService, @@ -56,7 +57,7 @@ function simpleFactory( * @alpha */ export namespace mockServices { - export function config(options?: config.Options) { + export function config(options?: config.Options): ConfigService { return new ConfigReader(options?.data, 'mock-config'); } export namespace config { From 1d4692fb3ddfcfdd31181d41e6e3def90b06f052 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 16:42:10 +0000 Subject: [PATCH 203/423] fix(deps): update dependency @esbuild-kit/cjs-loader to v2.4.2 Signed-off-by: Renovate Bot --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 83503fb359..ecb0826a83 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9212,12 +9212,12 @@ __metadata: linkType: hard "@esbuild-kit/cjs-loader@npm:^2.4.1": - version: 2.4.1 - resolution: "@esbuild-kit/cjs-loader@npm:2.4.1" + version: 2.4.2 + resolution: "@esbuild-kit/cjs-loader@npm:2.4.2" dependencies: "@esbuild-kit/core-utils": ^3.0.0 - get-tsconfig: ^4.2.0 - checksum: a516065907be0ead76ac2199ccb08ff92659ba5e2edb4bb8772b6a63afe4faed7eb45a3b4d87266a68c7c135c3dba971cd087bc6f16c382356e835c7dd3440f5 + get-tsconfig: ^4.4.0 + checksum: e346e339bfc7eff5c52c270fd0ec06a7f2341b624adfb69f84b7d83f119c35070420906f2761a0b4604e0a0ec90e35eaf12544585476c428ed6d6ee3b250c0fe languageName: node linkType: hard @@ -23525,10 +23525,10 @@ __metadata: languageName: node linkType: hard -"get-tsconfig@npm:^4.2.0": - version: 4.3.0 - resolution: "get-tsconfig@npm:4.3.0" - checksum: 2597aab99aa3a24db209e192a3e5874ac47fc5abc71703ee26346e0c5816cb346ca09fc813c739db5862d3a2905d89aeca1b0cbc46c2b272398d672309aaf414 +"get-tsconfig@npm:^4.4.0": + version: 4.4.0 + resolution: "get-tsconfig@npm:4.4.0" + checksum: e193558b4f0c84c81ae9688cf5b9950dc0b341e44f91b002713fd0c37cfb73108e1cd9998ed540bcc423f193fde32cc58a15e99dd469f5158a2eb4a148611176 languageName: node linkType: hard From a1e4a3e842f76e37e19ad7a76c44f8594e88975f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 16:42:41 +0000 Subject: [PATCH 204/423] fix(deps): update dependency @google-cloud/storage to v6.9.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 83503fb359..c3c0faab14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9602,8 +9602,8 @@ __metadata: linkType: hard "@google-cloud/storage@npm:^6.0.0": - version: 6.9.1 - resolution: "@google-cloud/storage@npm:6.9.1" + version: 6.9.2 + resolution: "@google-cloud/storage@npm:6.9.2" dependencies: "@google-cloud/paginator": ^3.0.7 "@google-cloud/projectify": ^3.0.0 @@ -9622,7 +9622,7 @@ __metadata: retry-request: ^5.0.0 teeny-request: ^8.0.0 uuid: ^8.0.0 - checksum: 9967bc0e80d1531f91030d27fc46cef0242f70dde2064b051104d8d261f1d3cba38b51789b0ae0850bf99b13d093365f85c85c43a2d9468d81f0f98238f76e78 + checksum: e4962be29ca3dd722019db95f99b095993534915d663a82b41c95beaf284d878de5b1357102441e4e375de838299f6d82eff55a2c4e9f610f9a12feac21e2735 languageName: node linkType: hard From 0ff03319be02103dea4bcb36ffcfeba272c31af6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 6 Feb 2023 17:49:57 +0100 Subject: [PATCH 205/423] backend-plugin-api: switch createBackendPlugin id -> pluginId Signed-off-by: Patrik Oldsberg --- .changeset/bright-teachers-compete.md | 5 ++++ .changeset/little-jars-lay.md | 18 ++++++++++++++ .../backend-system/architecture/04-plugins.md | 4 ++-- .../architecture/05-extension-points.md | 2 +- .../architecture/07-naming-patterns.md | 4 ++-- .../building-plugins-and-modules/01-index.md | 6 ++--- .../08-migrating.md | 6 ++--- docs/backend-system/core-services/01-index.md | 24 +++++++++---------- .../02-adding-a-basic-permission-check.md | 2 +- docs/plugins/new-backend-system.md | 4 ++-- .../scheduler/schedulerFactory.test.ts | 2 +- packages/backend-common/src/legacy.ts | 2 +- .../src/CreateBackend.test.ts | 2 +- packages/backend-plugin-api/api-report.md | 2 +- .../src/wiring/factories.test.ts | 10 ++++---- .../src/wiring/factories.ts | 16 +++++++++---- .../src/next/wiring/TestBackend.test.ts | 4 ++-- plugins/app-backend/src/service/appPlugin.ts | 2 +- plugins/bazaar-backend/src/plugin.ts | 2 +- .../src/service/CatalogPlugin.ts | 2 +- .../src/service/EventsPlugin.ts | 2 +- .../example-todo-list-backend/src/plugin.ts | 2 +- plugins/kafka-backend/src/plugin.ts | 2 +- plugins/periskop-backend/src/plugin.ts | 2 +- plugins/proxy-backend/src/plugin.ts | 2 +- .../src/ScaffolderPlugin.ts | 2 +- plugins/user-settings-backend/src/plugin.ts | 2 +- 27 files changed, 82 insertions(+), 51 deletions(-) create mode 100644 .changeset/bright-teachers-compete.md create mode 100644 .changeset/little-jars-lay.md diff --git a/.changeset/bright-teachers-compete.md b/.changeset/bright-teachers-compete.md new file mode 100644 index 0000000000..3cc900d613 --- /dev/null +++ b/.changeset/bright-teachers-compete.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +**BREAKING**: The plugin ID option passed to `createBackendPlugin` is now `pluginId`, rather than just `id`. This is to make it match `createBackendModule` more closely. diff --git a/.changeset/little-jars-lay.md b/.changeset/little-jars-lay.md new file mode 100644 index 0000000000..161dc099e9 --- /dev/null +++ b/.changeset/little-jars-lay.md @@ -0,0 +1,18 @@ +--- +'@internal/plugin-todo-list-backend': patch +'@backstage/plugin-user-settings-backend': patch +'@backstage/backend-test-utils': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/backend-defaults': patch +'@backstage/backend-app-api': patch +'@backstage/plugin-periskop-backend': patch +'@backstage/backend-common': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-bazaar-backend': patch +'@backstage/plugin-events-backend': patch +'@backstage/plugin-kafka-backend': patch +'@backstage/plugin-proxy-backend': patch +'@backstage/plugin-app-backend': patch +--- + +Updated usage of `createBackendPlugin`. diff --git a/docs/backend-system/architecture/04-plugins.md b/docs/backend-system/architecture/04-plugins.md index 7721b1c9f7..e73f086c43 100644 --- a/docs/backend-system/architecture/04-plugins.md +++ b/docs/backend-system/architecture/04-plugins.md @@ -22,7 +22,7 @@ import { } from '@backstage/backend-plugin-api'; export const examplePlugin = createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -53,7 +53,7 @@ export interface ExamplePluginOptions { export const examplePlugin = createBackendPlugin( (options?: ExamplePluginOptions) => ({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { diff --git a/docs/backend-system/architecture/05-extension-points.md b/docs/backend-system/architecture/05-extension-points.md index d16a773c0c..278c565472 100644 --- a/docs/backend-system/architecture/05-extension-points.md +++ b/docs/backend-system/architecture/05-extension-points.md @@ -44,7 +44,7 @@ class ActionsExtension implements ScaffolderActionsExtensionPoint { export const scaffolderPlugin = createBackendPlugin( { - id: 'scaffolder', + pluginId: 'scaffolder', register(env) { const actionsExtensions = new ActionsExtension(); env.registerExtensionPoint( diff --git a/docs/backend-system/architecture/07-naming-patterns.md b/docs/backend-system/architecture/07-naming-patterns.md index dc781a61ac..b4b4c6c70f 100644 --- a/docs/backend-system/architecture/07-naming-patterns.md +++ b/docs/backend-system/architecture/07-naming-patterns.md @@ -21,7 +21,7 @@ Example: ```ts export const catalogPlugin = createBackendPlugin({ - id: 'catalog', + pluginId: 'catalog', ... }) ``` @@ -36,7 +36,7 @@ export const catalogPlugin = createBackendPlugin({ Example: ```ts -export const catalogModuleGithubEntityProvider = createBackendPlugin({ +export const catalogModuleGithubEntityProvider = createBackendModule({ pluginId: 'catalog', moduleId: 'githubEntityProvider', ... diff --git a/docs/backend-system/building-plugins-and-modules/01-index.md b/docs/backend-system/building-plugins-and-modules/01-index.md index 5fefb3ff16..cae5052d04 100644 --- a/docs/backend-system/building-plugins-and-modules/01-index.md +++ b/docs/backend-system/building-plugins-and-modules/01-index.md @@ -36,7 +36,7 @@ import { import { createExampleRouter } from './router'; export const examplePlugin = createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -183,7 +183,7 @@ that needs to be different across environments. import { coreServices } from '@backstage/backend-plugin-api'; export const examplePlugin = createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { config: coreServices.config }, @@ -216,7 +216,7 @@ export interface ExampleOptions { export const examplePlugin = createBackendPlugin( (options?: ExampleOptions) => ({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { diff --git a/docs/backend-system/building-plugins-and-modules/08-migrating.md b/docs/backend-system/building-plugins-and-modules/08-migrating.md index ec5836a126..687f4c1d5e 100644 --- a/docs/backend-system/building-plugins-and-modules/08-migrating.md +++ b/docs/backend-system/building-plugins-and-modules/08-migrating.md @@ -46,7 +46,7 @@ import { Router } from 'express'; import { KubernetesBuilder } from './KubernetesBuilder'; export const kubernetesPlugin = createBackendPlugin({ - id: 'kubernetes', + pluginId: 'kubernetes', register(env) { env.registerInit({ deps: { @@ -95,7 +95,7 @@ export interface KubernetesOptions { } const kubernetesPlugin = createBackendPlugin((options: KubernetesOptions) => ({ - id: 'kubernetes', + pluginId: 'kubernetes', register(env) { env.registerInit({ deps: { @@ -182,7 +182,7 @@ class ClusterSupplier implements KubernetesClusterSupplierExtensionPoint { } export const kubernetesPlugin = createBackendPlugin({ - id: 'kubernetes', + pluginId: 'kubernetes', register(env) { const extensionPoint = new ClusterSupplier(); // We register the extension point with the backend, which allows modules to diff --git a/docs/backend-system/core-services/01-index.md b/docs/backend-system/core-services/01-index.md index b394391480..18c7b1079f 100644 --- a/docs/backend-system/core-services/01-index.md +++ b/docs/backend-system/core-services/01-index.md @@ -33,7 +33,7 @@ import { import { Router } from 'express'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { http: coreServices.httpRouter }, @@ -86,7 +86,7 @@ import { import { Router } from 'express'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -157,7 +157,7 @@ import { } from '@backstage/backend-plugin-api'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -215,7 +215,7 @@ import { } from '@backstage/backend-plugin-api'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -288,7 +288,7 @@ import { } from '@backstage/backend-plugin-api'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -327,7 +327,7 @@ import { import { resolvePackagePath } from '@backstage/backend-common'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -366,7 +366,7 @@ import { import { fetch } from 'node-fetch'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -397,7 +397,7 @@ import { import { Router } from 'express'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -465,7 +465,7 @@ import { } from '@backstage/backend-plugin-api'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -564,7 +564,7 @@ import { import { Router } from 'express'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -613,7 +613,7 @@ import { import { fetch } from 'node-fetch'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -652,7 +652,7 @@ import { import os from 'os'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { diff --git a/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md b/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md index 551e48f91a..2ceb8057f4 100644 --- a/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md +++ b/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md @@ -301,7 +301,7 @@ Finally, we need to update `plugins/todo-list-backend/src/plugin.ts`: * @alpha */ export const exampleTodoListPlugin = createBackendPlugin({ - id: 'exampleTodoList', + pluginId: 'exampleTodoList', register(env) { env.registerInit({ deps: { diff --git a/docs/plugins/new-backend-system.md b/docs/plugins/new-backend-system.md index bfc6f79661..785d364ae2 100644 --- a/docs/plugins/new-backend-system.md +++ b/docs/plugins/new-backend-system.md @@ -84,7 +84,7 @@ import { // export type ExamplePluginOptions = { exampleOption: boolean }; export const examplePlugin = createBackendPlugin({ // unique id for the plugin - id: 'example', + pluginId: 'example', // It's possible to provide options to the plugin // register(env, options: ExamplePluginOptions) { register(env) { @@ -111,7 +111,7 @@ If we wanted our plugin to accept options as well, we'd accept the options as th ```ts export const examplePlugin = createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env, options?: { silent?: boolean }) { env.registerInit({ deps: { logger: coreServices.logger }, diff --git a/packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.test.ts b/packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.test.ts index 1aaf4ec71d..15ec364ac5 100644 --- a/packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.test.ts @@ -28,7 +28,7 @@ describe('schedulerFactory', () => { const subject = schedulerFactory(); const plugin = createBackendPlugin({ - id: 'example', + pluginId: 'example', register(reg) { reg.registerInit({ deps: { diff --git a/packages/backend-common/src/legacy.ts b/packages/backend-common/src/legacy.ts index 30e7dd9dc5..214e65e0c7 100644 --- a/packages/backend-common/src/legacy.ts +++ b/packages/backend-common/src/legacy.ts @@ -60,7 +60,7 @@ export function makeLegacyPlugin< }>, ) => { const compatPlugin = createBackendPlugin({ - id: name, + pluginId: name, register(env) { env.registerInit({ deps: { ...envMapping, _router: coreServices.httpRouter }, diff --git a/packages/backend-defaults/src/CreateBackend.test.ts b/packages/backend-defaults/src/CreateBackend.test.ts index 2cfb92c3a6..8d56cd0986 100644 --- a/packages/backend-defaults/src/CreateBackend.test.ts +++ b/packages/backend-defaults/src/CreateBackend.test.ts @@ -143,7 +143,7 @@ describe('createBackend', () => { expect.assertions(3); backend.add( createBackendPlugin({ - id: 'test', + pluginId: 'test', register(reg) { reg.registerInit({ deps: { diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index a7700d81ac..9a6f05babe 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -47,7 +47,7 @@ export interface BackendModuleRegistrationPoints { // @public export interface BackendPluginConfig { - id: string; + pluginId: string; // (undocumented) register(reg: BackendPluginRegistrationPoints): void; } diff --git a/packages/backend-plugin-api/src/wiring/factories.test.ts b/packages/backend-plugin-api/src/wiring/factories.test.ts index dbdf0ead14..8e1b30ea53 100644 --- a/packages/backend-plugin-api/src/wiring/factories.test.ts +++ b/packages/backend-plugin-api/src/wiring/factories.test.ts @@ -33,7 +33,7 @@ describe('createExtensionPoint', () => { describe('createBackendPlugin', () => { it('should create a BackendPlugin', () => { const plugin = createBackendPlugin((_options: { a: string }) => ({ - id: 'x', + pluginId: 'x', register() {}, })); expect(plugin).toBeDefined(); @@ -47,7 +47,7 @@ describe('createBackendPlugin', () => { it('should create plugins with optional options', () => { const plugin = createBackendPlugin((_options?: { a: string }) => ({ - id: 'x', + pluginId: 'x', register() {}, })); expect(plugin).toBeDefined(); @@ -59,7 +59,7 @@ describe('createBackendPlugin', () => { it('should create plugins without options', () => { const plugin = createBackendPlugin({ - id: 'x', + pluginId: 'x', register() {}, }); expect(plugin).toBeDefined(); @@ -74,7 +74,7 @@ describe('createBackendPlugin', () => { a: string; } const plugin = createBackendPlugin((_options: TestOptions) => ({ - id: 'x', + pluginId: 'x', register() {}, })); expect(plugin).toBeDefined(); @@ -91,7 +91,7 @@ describe('createBackendPlugin', () => { a: string; } const plugin = createBackendPlugin((_options?: TestOptions) => ({ - id: 'x', + pluginId: 'x', register() {}, })); expect(plugin).toBeDefined(); diff --git a/packages/backend-plugin-api/src/wiring/factories.ts b/packages/backend-plugin-api/src/wiring/factories.ts index d281335a8e..6f37efabfe 100644 --- a/packages/backend-plugin-api/src/wiring/factories.ts +++ b/packages/backend-plugin-api/src/wiring/factories.ts @@ -72,7 +72,7 @@ export interface BackendPluginConfig { * * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns} */ - id: string; + pluginId: string; register(reg: BackendPluginRegistrationPoints): void; } @@ -87,10 +87,18 @@ export function createBackendPlugin( config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig), ): (...params: TOptions) => BackendFeature { if (typeof config === 'function') { - return config; + return (...options: TOptions) => { + const c = config(...options); + return { + ...c, + id: c.pluginId, + }; + }; } - - return () => config; + return () => ({ + ...config, + id: config.pluginId, + }); } /** diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts index dca463a9ae..eca003c70b 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts @@ -165,7 +165,7 @@ describe('TestBackend', () => { expect.assertions(2); const testPlugin = createBackendPlugin({ - id: 'test', + pluginId: 'test', register(env) { env.registerInit({ deps: { @@ -201,7 +201,7 @@ describe('TestBackend', () => { it('should allow making requests via supertest', async () => { const testPlugin = createBackendPlugin({ - id: 'test', + pluginId: 'test', register(env) { env.registerInit({ deps: { diff --git a/plugins/app-backend/src/service/appPlugin.ts b/plugins/app-backend/src/service/appPlugin.ts index b12a8d6877..a29f8fd5a8 100644 --- a/plugins/app-backend/src/service/appPlugin.ts +++ b/plugins/app-backend/src/service/appPlugin.ts @@ -71,7 +71,7 @@ export type AppPluginOptions = { * @alpha */ export const appPlugin = createBackendPlugin((options: AppPluginOptions) => ({ - id: 'app', + pluginId: 'app', register(env) { env.registerInit({ deps: { diff --git a/plugins/bazaar-backend/src/plugin.ts b/plugins/bazaar-backend/src/plugin.ts index 03491950e8..62622717c8 100644 --- a/plugins/bazaar-backend/src/plugin.ts +++ b/plugins/bazaar-backend/src/plugin.ts @@ -27,7 +27,7 @@ import { createRouter } from './service/router'; * @alpha */ export const bazaarPlugin = createBackendPlugin({ - id: 'bazaar', + pluginId: 'bazaar', register(env) { env.registerInit({ deps: { diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts index effed7f8f1..aadaf99a10 100644 --- a/plugins/catalog-backend/src/service/CatalogPlugin.ts +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -56,7 +56,7 @@ class CatalogExtensionPointImpl implements CatalogProcessingExtensionPoint { * @alpha */ export const catalogPlugin = createBackendPlugin({ - id: 'catalog', + pluginId: 'catalog', register(env) { const processingExtensions = new CatalogExtensionPointImpl(); // plugins depending on this API will be initialized before this plugins init method is executed. diff --git a/plugins/events-backend/src/service/EventsPlugin.ts b/plugins/events-backend/src/service/EventsPlugin.ts index 29456d71f7..402104b56c 100644 --- a/plugins/events-backend/src/service/EventsPlugin.ts +++ b/plugins/events-backend/src/service/EventsPlugin.ts @@ -80,7 +80,7 @@ class EventsExtensionPointImpl implements EventsExtensionPoint { * @alpha */ export const eventsPlugin = createBackendPlugin({ - id: 'events', + pluginId: 'events', register(env) { const extensionPoint = new EventsExtensionPointImpl(); env.registerExtensionPoint(eventsExtensionPoint, extensionPoint); diff --git a/plugins/example-todo-list-backend/src/plugin.ts b/plugins/example-todo-list-backend/src/plugin.ts index ba25ed7218..42985f6e88 100644 --- a/plugins/example-todo-list-backend/src/plugin.ts +++ b/plugins/example-todo-list-backend/src/plugin.ts @@ -27,7 +27,7 @@ import { createRouter } from './service/router'; * @alpha */ export const exampleTodoListPlugin = createBackendPlugin({ - id: 'exampleTodoList', + pluginId: 'exampleTodoList', register(env) { env.registerInit({ deps: { diff --git a/plugins/kafka-backend/src/plugin.ts b/plugins/kafka-backend/src/plugin.ts index f627e5a0bd..2442eddbaa 100644 --- a/plugins/kafka-backend/src/plugin.ts +++ b/plugins/kafka-backend/src/plugin.ts @@ -27,7 +27,7 @@ import { createRouter } from './service/router'; * @alpha */ export const kafkaPlugin = createBackendPlugin({ - id: 'kafka', + pluginId: 'kafka', register(env) { env.registerInit({ deps: { diff --git a/plugins/periskop-backend/src/plugin.ts b/plugins/periskop-backend/src/plugin.ts index b5dcfb1425..933c864d50 100644 --- a/plugins/periskop-backend/src/plugin.ts +++ b/plugins/periskop-backend/src/plugin.ts @@ -27,7 +27,7 @@ import { createRouter } from './service/router'; * @alpha */ export const periskopPlugin = createBackendPlugin({ - id: 'periskop', + pluginId: 'periskop', register(env) { env.registerInit({ deps: { diff --git a/plugins/proxy-backend/src/plugin.ts b/plugins/proxy-backend/src/plugin.ts index e9d6d515c1..d095bee527 100644 --- a/plugins/proxy-backend/src/plugin.ts +++ b/plugins/proxy-backend/src/plugin.ts @@ -28,7 +28,7 @@ import { createRouter } from './service/router'; */ export const proxyPlugin = createBackendPlugin( (options?: { skipInvalidProxies?: boolean }) => ({ - id: 'proxy', + pluginId: 'proxy', register(env) { env.registerInit({ deps: { diff --git a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts index 43b8d30f99..3b0d26be21 100644 --- a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts +++ b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts @@ -64,7 +64,7 @@ class ScaffolderActionsExtensionPointImpl */ export const scaffolderPlugin = createBackendPlugin( (options: ScaffolderPluginOptions) => ({ - id: 'scaffolder', + pluginId: 'scaffolder', register(env) { const actionsExtensions = new ScaffolderActionsExtensionPointImpl(); diff --git a/plugins/user-settings-backend/src/plugin.ts b/plugins/user-settings-backend/src/plugin.ts index 83120cc180..e200d22ffe 100644 --- a/plugins/user-settings-backend/src/plugin.ts +++ b/plugins/user-settings-backend/src/plugin.ts @@ -26,7 +26,7 @@ import { createRouter } from './service/router'; * @alpha */ export const userSettingsPlugin = createBackendPlugin({ - id: 'userSettings', + pluginId: 'userSettings', register(env) { env.registerInit({ deps: { From 181c03edb528d094ff15d5e637b60b27bace002b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 6 Feb 2023 17:59:48 +0100 Subject: [PATCH 206/423] backend-plugin-api: align opaque type markers Signed-off-by: Patrik Oldsberg --- .changeset/itchy-chairs-punch.md | 5 +++++ packages/backend-plugin-api/api-report.md | 4 ++-- packages/backend-plugin-api/src/services/system/types.ts | 4 ++-- .../src/wiring/createSharedEnvironment.test.ts | 2 +- .../backend-plugin-api/src/wiring/createSharedEnvironment.ts | 4 ++-- packages/backend-plugin-api/src/wiring/factories.ts | 2 +- packages/backend-plugin-api/src/wiring/types.ts | 2 +- 7 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 .changeset/itchy-chairs-punch.md diff --git a/.changeset/itchy-chairs-punch.md b/.changeset/itchy-chairs-punch.md new file mode 100644 index 0000000000..034a9bbdae --- /dev/null +++ b/.changeset/itchy-chairs-punch.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': patch +--- + +Aligned opaque type markers to all use a `$$type` property with namespacing. diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index a7700d81ac..baa2b1b7dc 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -275,7 +275,7 @@ export type ExtensionPoint = { id: string; T: T; toString(): string; - $$ref: 'extension-point'; + $$type: '@backstage/ExtensionPoint'; }; // @public @@ -490,7 +490,7 @@ export type ServiceRef< scope: TScope; T: TService; toString(): string; - $$ref: 'service'; + $$type: '@backstage/ServiceRef'; }; // @public (undocumented) diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index 2615c5e3a3..3e68e9349d 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -44,7 +44,7 @@ export type ServiceRef< toString(): string; - $$ref: 'service'; + $$type: '@backstage/ServiceRef'; }; /** @public */ @@ -119,7 +119,7 @@ export function createServiceRef( toString() { return `serviceRef{${config.id}}`; }, - $$ref: 'service', // TODO: declare + $$type: '@backstage/ServiceRef', __defaultFactory: defaultFactory, } as ServiceRef & { __defaultFactory?: ( diff --git a/packages/backend-plugin-api/src/wiring/createSharedEnvironment.test.ts b/packages/backend-plugin-api/src/wiring/createSharedEnvironment.test.ts index ec2cf1fe49..381a4799d2 100644 --- a/packages/backend-plugin-api/src/wiring/createSharedEnvironment.test.ts +++ b/packages/backend-plugin-api/src/wiring/createSharedEnvironment.test.ts @@ -48,7 +48,7 @@ describe('createSharedEnvironment', () => { expect(env).toBeDefined(); const internalEnv = env() as unknown as InternalSharedBackendEnvironment; expect(internalEnv).toEqual({ - $$type: 'SharedBackendEnvironment', + $$type: '@backstage/SharedBackendEnvironment', version: 'v1', services: undefined, }); diff --git a/packages/backend-plugin-api/src/wiring/createSharedEnvironment.ts b/packages/backend-plugin-api/src/wiring/createSharedEnvironment.ts index 2eb2cdec6a..57f0533523 100644 --- a/packages/backend-plugin-api/src/wiring/createSharedEnvironment.ts +++ b/packages/backend-plugin-api/src/wiring/createSharedEnvironment.ts @@ -31,7 +31,7 @@ export interface SharedBackendEnvironmentConfig { * @public */ export interface SharedBackendEnvironment { - $$type: 'SharedBackendEnvironment'; + $$type: '@backstage/SharedBackendEnvironment'; // NOTE: This type is opaque in order to allow for future API evolution without // cluttering the external API. For example we might want to add support @@ -93,7 +93,7 @@ export function createSharedEnvironment< // Here to ensure type safety in this internal implementation. const env: SharedBackendEnvironment & InternalSharedBackendEnvironment = { - $$type: 'SharedBackendEnvironment', + $$type: '@backstage/SharedBackendEnvironment', version: 'v1', services, }; diff --git a/packages/backend-plugin-api/src/wiring/factories.ts b/packages/backend-plugin-api/src/wiring/factories.ts index d281335a8e..0326080b11 100644 --- a/packages/backend-plugin-api/src/wiring/factories.ts +++ b/packages/backend-plugin-api/src/wiring/factories.ts @@ -55,7 +55,7 @@ export function createExtensionPoint( toString() { return `extensionPoint{${config.id}}`; }, - $$ref: 'extension-point', // TODO: declare + $$type: '@backstage/ExtensionPoint', }; } diff --git a/packages/backend-plugin-api/src/wiring/types.ts b/packages/backend-plugin-api/src/wiring/types.ts index 6e081f57e5..ab8ce07284 100644 --- a/packages/backend-plugin-api/src/wiring/types.ts +++ b/packages/backend-plugin-api/src/wiring/types.ts @@ -32,7 +32,7 @@ export type ExtensionPoint = { toString(): string; - $$ref: 'extension-point'; + $$type: '@backstage/ExtensionPoint'; }; /** From 0d0cb65e5e4ae7cde89a444a236433abf099d22f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C5=A0neberger?= Date: Mon, 6 Feb 2023 19:08:21 +0100 Subject: [PATCH 207/423] Release this change as a patch version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Šneberger --- .changeset/hip-chairs-double.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/hip-chairs-double.md b/.changeset/hip-chairs-double.md index 722795d80d..52cdde3588 100644 --- a/.changeset/hip-chairs-double.md +++ b/.changeset/hip-chairs-double.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-tech-radar': minor +'@backstage/plugin-tech-radar': patch --- Deprecate `RadarEntry.url` - use `RadarEntry.links` instead From 5b9a1e7dc00a25f474162b73ba606673df23eefc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C5=A0neberger?= Date: Mon, 6 Feb 2023 19:16:04 +0100 Subject: [PATCH 208/423] Make RadarEntry.url optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Šneberger --- plugins/tech-radar/api-report.md | 2 +- plugins/tech-radar/src/api.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/tech-radar/api-report.md b/plugins/tech-radar/api-report.md index 2836e04461..3b84990d85 100644 --- a/plugins/tech-radar/api-report.md +++ b/plugins/tech-radar/api-report.md @@ -26,7 +26,7 @@ export interface RadarEntry { timeline: Array; title: string; // @deprecated - url: string; + url?: string; } // @public diff --git a/plugins/tech-radar/src/api.ts b/plugins/tech-radar/src/api.ts index bf90cf0750..c0b8fb8852 100644 --- a/plugins/tech-radar/src/api.ts +++ b/plugins/tech-radar/src/api.ts @@ -136,7 +136,7 @@ export interface RadarEntry { * * @deprecated Use {@link RadarEntry.links} instead */ - url: string; + url?: string; /** * History of the Entry moving through {@link RadarRing} */ From 8060b73e5ed74f053289df62717264f2fd588564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C5=A0neberger?= Date: Mon, 6 Feb 2023 19:16:27 +0100 Subject: [PATCH 209/423] Remove deprecated url attribute from sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Šneberger --- plugins/tech-radar/src/sample.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/plugins/tech-radar/src/sample.ts b/plugins/tech-radar/src/sample.ts index 0dc647ac54..1a6f372f64 100644 --- a/plugins/tech-radar/src/sample.ts +++ b/plugins/tech-radar/src/sample.ts @@ -45,7 +45,6 @@ entries.push({ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua', }, ], - url: '#', key: 'javascript', id: 'javascript', title: 'JavaScript', @@ -73,7 +72,6 @@ entries.push({ 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat', }, ], - url: '#', key: 'typescript', id: 'typescript', title: 'TypeScript', @@ -91,7 +89,6 @@ entries.push({ 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur', }, ], - url: '#', links: [ { url: 'https://webpack.js.org/', @@ -111,7 +108,6 @@ entries.push({ date: new Date('2020-08-06'), }, ], - url: '#', links: [ { url: 'https://reactjs.org/', @@ -131,7 +127,6 @@ entries.push({ date: new Date('2020-08-06'), }, ], - url: '#', key: 'code-reviews', id: 'code-reviews', title: 'Code Reviews', @@ -145,7 +140,6 @@ entries.push({ date: new Date('2020-08-06'), }, ], - url: '#', key: 'mob-programming', id: 'mob-programming', title: 'Mob Programming', @@ -159,7 +153,6 @@ entries.push({ date: new Date('2020-08-06'), }, ], - url: '#', key: 'docs-like-code', id: 'docs-like-code', title: 'Docs-like-code', @@ -172,7 +165,6 @@ entries.push({ date: new Date('2020-08-06'), }, ], - url: '#', key: 'force-push', id: 'force-push', title: 'Force push to master', @@ -186,7 +178,6 @@ entries.push({ description: 'long description', }, ], - url: '#', links: [ { url: 'https://reactjs.org/', From 8784b505af2ccef161a479ce3b099468e8c45a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C5=A0neberger?= Date: Mon, 6 Feb 2023 19:17:51 +0100 Subject: [PATCH 210/423] Remove url attribute from the diff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Šneberger --- .changeset/hip-chairs-double.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/hip-chairs-double.md b/.changeset/hip-chairs-double.md index 52cdde3588..e2b03f2e66 100644 --- a/.changeset/hip-chairs-double.md +++ b/.changeset/hip-chairs-double.md @@ -6,7 +6,6 @@ Deprecate `RadarEntry.url` - use `RadarEntry.links` instead ```diff - url: 'https://www.javascript.com/', -+ url: '#', key: 'javascript', id: 'javascript', title: 'JavaScript', From b3f650b1a8546f05779a2d43f8dc61a8658d136e Mon Sep 17 00:00:00 2001 From: Justin De Burgo Date: Mon, 6 Feb 2023 12:36:57 -0600 Subject: [PATCH 211/423] adding dot option to minimatch Signed-off-by: Justin De Burgo --- .../src/ingestion/CatalogRules.test.ts | 20 +++++++++++++++++++ .../src/ingestion/CatalogRules.ts | 5 ++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts b/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts index 34e89fad29..592b1dda21 100644 --- a/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts +++ b/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts @@ -35,6 +35,10 @@ const entity = { }; const location: Record = { + v: { + type: 'url', + target: 'https://github.com/b/c/blob/master/.folder/v.yaml', + }, w: { type: 'url', target: 'https://github.com/b/c/blob/master/w.yaml', @@ -263,4 +267,20 @@ describe('DefaultCatalogRulesEnforcer', () => { expect(enforcer.isAllowed(entity.component, location.z)).toBe(false); }); }); + + it('should allow locations with a hidden folder', () => { + const enforcer = DefaultCatalogRulesEnforcer.fromConfig( + new ConfigReader({ + catalog: { + rules: [ + { + allow: ['Component'], + locations: [{ type: 'url', pattern: 'https://github.com/b/**' }], + }, + ], + }, + }), + ); + expect(enforcer.isAllowed(entity.component, location.v)).toBe(true); + }); }); diff --git a/plugins/catalog-backend/src/ingestion/CatalogRules.ts b/plugins/catalog-backend/src/ingestion/CatalogRules.ts index 677649d4b2..21b2d05a46 100644 --- a/plugins/catalog-backend/src/ingestion/CatalogRules.ts +++ b/plugins/catalog-backend/src/ingestion/CatalogRules.ts @@ -186,7 +186,10 @@ export class DefaultCatalogRulesEnforcer implements CatalogRulesEnforcer { } if ( matcher.pattern && - !minimatch(location?.target, matcher.pattern, { nocase: true }) + !minimatch(location?.target, matcher.pattern, { + nocase: true, + dot: true, + }) ) { continue; } From 0a32911d8a1ac9e6cd5f84da81aa5d5d4291ae13 Mon Sep 17 00:00:00 2001 From: David Weber Date: Sun, 29 Jan 2023 01:30:46 +0100 Subject: [PATCH 212/423] feat: improve navigation of adr plugin Signed-off-by: David Weber --- .changeset/light-crabs-drum.md | 6 ++ .../src/search/createMadrParser.ts | 42 ++----------- plugins/adr-backend/src/search/madrParser.ts | 59 ++++++++++++++++++ .../adr-backend/src/service/router.test.ts | 8 +-- plugins/adr-backend/src/service/router.ts | 22 ++++--- plugins/adr/README.md | 2 + plugins/adr/api-report.md | 3 + plugins/adr/docs/adr-tab.png | Bin 0 -> 773895 bytes plugins/adr/src/api/types.ts | 9 +++ .../EntityAdrContent/EntityAdrContent.tsx | 41 +++++++++--- 10 files changed, 136 insertions(+), 56 deletions(-) create mode 100644 .changeset/light-crabs-drum.md create mode 100644 plugins/adr-backend/src/search/madrParser.ts create mode 100644 plugins/adr/docs/adr-tab.png diff --git a/.changeset/light-crabs-drum.md b/.changeset/light-crabs-drum.md new file mode 100644 index 0000000000..ebc0b3fa5a --- /dev/null +++ b/.changeset/light-crabs-drum.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-adr-backend': minor +'@backstage/plugin-adr': minor +--- + +Display title, status and date in ADR navigation, sourced from ADR content and reverse order. diff --git a/plugins/adr-backend/src/search/createMadrParser.ts b/plugins/adr-backend/src/search/createMadrParser.ts index 6b77ec2fa7..1bc3c852e9 100644 --- a/plugins/adr-backend/src/search/createMadrParser.ts +++ b/plugins/adr-backend/src/search/createMadrParser.ts @@ -14,12 +14,11 @@ * limitations under the License. */ -import { DateTime } from 'luxon'; -import { marked } from 'marked'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { MADR_DATE_FORMAT } from '@backstage/plugin-adr-common'; import { AdrParser } from './types'; +import { madrParser } from './madrParser'; const applyArgsToFormat = ( format: string, @@ -65,43 +64,12 @@ export const createMadrParser = ( const dateFormat = options.dateFormat ?? MADR_DATE_FORMAT; return async ({ entity, content, path }) => { - const tokens = marked.lexer(content); - if (!tokens.length) { - throw new Error('ADR has no content'); - } - - // First h1 header should contain ADR title - const adrTitle = ( - tokens.find( - t => t.type === 'heading' && t.depth === 1, - ) as marked.Tokens.Heading - )?.text; - - // First list should contain status & date metadata (if defined) - const listTokens = ( - tokens.find(t => t.type === 'list') as marked.Tokens.List - )?.items; - const adrStatus = listTokens - .find(t => /^status:/i.test(t.text)) - ?.text.replace(/^status:/i, '') - .trim() - .toLocaleLowerCase('en-US'); - const adrDateTime = DateTime.fromFormat( - listTokens - .find(t => /^date:/i.test(t.text)) - ?.text.replace(/^date:/i, '') - .trim() ?? '', - dateFormat, - ); - const adrDate = adrDateTime.isValid - ? adrDateTime.toFormat(MADR_DATE_FORMAT) - : undefined; - + const madr = madrParser(content, dateFormat); return { - title: adrTitle ?? path.replace(/\.md$/, ''), + title: madr.title ?? path.replace(/\.md$/, ''), text: content, - status: adrStatus, - date: adrDate, + status: madr.status, + date: madr.date, entityRef: stringifyEntityRef(entity), entityTitle: entity.metadata.title, location: applyArgsToFormat(locationTemplate, { diff --git a/plugins/adr-backend/src/search/madrParser.ts b/plugins/adr-backend/src/search/madrParser.ts new file mode 100644 index 0000000000..30672028fe --- /dev/null +++ b/plugins/adr-backend/src/search/madrParser.ts @@ -0,0 +1,59 @@ +/* + * Copyright 2023 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 { DateTime } from 'luxon'; +import { marked } from 'marked'; +import { MADR_DATE_FORMAT } from '@backstage/plugin-adr-common'; + +export const madrParser = (content: string, dateFormat = MADR_DATE_FORMAT) => { + const tokens = marked.lexer(content); + if (!tokens.length) { + throw new Error('ADR has no content'); + } + + // First h1 header should contain ADR title + const adrTitle = ( + tokens.find( + t => t.type === 'heading' && t.depth === 1, + ) as marked.Tokens.Heading + )?.text; + + // First list should contain status & date metadata (if defined) + const listTokens = (tokens.find(t => t.type === 'list') as marked.Tokens.List) + ?.items; + const adrStatus = listTokens + ?.find(t => /^status:/i.test(t.text)) + ?.text.replace(/^status:/i, '') + .trim() + .toLocaleLowerCase('en-US'); + + const adrDateTime = DateTime.fromFormat( + listTokens + ?.find(t => /^date:/i.test(t.text)) + ?.text.replace(/^date:/i, '') + .trim() ?? '', + dateFormat, + ); + const adrDate = adrDateTime?.isValid + ? adrDateTime.toFormat(MADR_DATE_FORMAT) + : undefined; + + return { + title: adrTitle, + status: adrStatus, + date: adrDate, + }; +}; diff --git a/plugins/adr-backend/src/service/router.test.ts b/plugins/adr-backend/src/service/router.test.ts index fbbd6e8532..1ae9076bb5 100644 --- a/plugins/adr-backend/src/service/router.test.ts +++ b/plugins/adr-backend/src/service/router.test.ts @@ -156,8 +156,8 @@ describe('createRouter', () => { data: [ { type: 'file', - name: 'testFile001.txt', - path: 'folder/testFile001.txt', + name: 'testFile002.txt', + path: 'testFile002.txt', }, { type: 'file', @@ -166,8 +166,8 @@ describe('createRouter', () => { }, { type: 'file', - name: 'testFile002.txt', - path: 'testFile002.txt', + name: 'testFile001.txt', + path: 'folder/testFile001.txt', }, ], }; diff --git a/plugins/adr-backend/src/service/router.ts b/plugins/adr-backend/src/service/router.ts index e6603ab346..ed02a76e13 100644 --- a/plugins/adr-backend/src/service/router.ts +++ b/plugins/adr-backend/src/service/router.ts @@ -19,6 +19,7 @@ import { NotModifiedError, stringifyError } from '@backstage/errors'; import { Logger } from 'winston'; import express from 'express'; import Router from 'express-promise-router'; +import { madrParser } from '../search/madrParser'; /** @public */ export type AdrRouterOptions = { @@ -59,13 +60,20 @@ export async function createRouter( etag: cachedTree?.etag, }); const files = await treeGetResponse.files(); - const data = files.map(file => { - return { - type: 'file', - name: file.path.substring(file.path.lastIndexOf('/') + 1), - path: file.path, - }; - }); + const data = await Promise.all( + files + .map(async file => { + const fileContent = await file.content(); + const adrInfo = madrParser(fileContent.toString()); + return { + type: 'file', + name: file.path.substring(file.path.lastIndexOf('/') + 1), + path: file.path, + ...adrInfo, + }; + }) + .reverse(), + ); await cacheClient.set(urlToProcess, { data, diff --git a/plugins/adr/README.md b/plugins/adr/README.md index b9cc5d84ba..a669762dad 100644 --- a/plugins/adr/README.md +++ b/plugins/adr/README.md @@ -4,6 +4,8 @@ Welcome to the ADR plugin! This plugin allows you to browse ADRs associated with your entities as well as a way to discover ADRs across others entities via Backstage Search. Use this to learn from the past experience of other projects to guide your own architecture decisions. +![ADR tab](./docs/adr-tab.png) + ## Setup 1. Install this plugin: diff --git a/plugins/adr/api-report.md b/plugins/adr/api-report.md index d6480cd090..4005e1625e 100644 --- a/plugins/adr/api-report.md +++ b/plugins/adr/api-report.md @@ -51,6 +51,9 @@ export type AdrFileInfo = { type: string; path: string; name: string; + title?: string; + status?: string; + date?: string; }; // @public diff --git a/plugins/adr/docs/adr-tab.png b/plugins/adr/docs/adr-tab.png new file mode 100644 index 0000000000000000000000000000000000000000..d9dd728221c502861fe144843adde3390292f50a GIT binary patch literal 773895 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

    g`hbf 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℘PtM_kX%m~DZD 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

    t>}bvjw0L$N#rP9mAW`dSC`6oW@5Cs1WTHF zBNKjwoeEWXR2rf2p9KfR{%dRDtt`$gCOr{Fdb0GT+vTHreh^$U6Lhm}&zlp|o3hD2 zy#PG1Ki!8_lfB;+t^MUc8VF#}c|f&-&5(M(g{);i;f`6*JDZ6JI)&^{mAm-#)M<6Z zXuatVU4U?&av*?2N2~Cejg>2}IyK#@kqmSiYHje7?3Iw*)mZR|_)Va#4Ajg0^yG1iL)fr|} zpGlO7?@?IN^Au|R@>uh%@-RbKo_r|Dge<_WNI*%5R(N8~p5VO{eS{ijhou%bSXLR4 z^_3c^UmRa$f3iz5AY!nur*TA2}=eZ?Kv%_F}|0tic&0b}t`$6vlr*kehwTYlctH z@`Sekn#%}pD}oo}LC2v<)|ii-$|k`9NBMn{$~|YRkupz(Y}Sp+qgfCi)%|%= z?R=B23{Z^Et;&EvG zvT%V{A|cUPfjF4HI5}@;ud3s;6}55YH0TNaLpe=OkJWn^viSDvWvrGR9xDT<(1%1P zsKVA(dL{x-<62|)SQjYe2}IKRXo(c&D~`<HYG* zg-eJJ2IRTMDQ(J*2(Q9;7fLRc_^lJTZZwlk&fZSol`P2VmsUh^cUr1&eBTIGZG}D)<5tc^S z37QwhgH2;^J&*w6S$xGd;)?ofBqL0m*rTmV*yGBO15lzvHtd#iZxQg%)CXp0>`X;P#Ta(Soc!beGC= zwLd_30&s^bA63jxOt^zlRXh!wz? z1;UlA^r~W(jUMgHnY{AqrzWxU0ig?vRehNn(CGYi7X8c$IKK7DReBmO*O9-iTIHUa ze)5GOY>m0$_kG%g*}g~7b$5aeI`CSY8qKyZzg+K5YZEyEKI{8SjTNUtl=&dwiDnbL zbA2DU7adA8=4@Z0X*>0?cEa5|soeQ5j~|e1lk7M@KYfIM`VS6MlQSjD;)3?nj^l-0 z*Ew7E)&}0V)8gJ|!@iZX@zMgv8@F9e=vDY2e;Z?2>qUo!-agj0qHa&^uU{M2mLC=e z(Sl*ZgnCEixyFfJ;@&8Nlb2lXezUP0;9Y$u(5W?!#>>kr zM^wNJt~XFJy-*sLsEg~Lw5zz7E#;c8W7}OaF;?}7c?t=LdtgL*wB0VEB}>)7Lg$x@ zXx8o|+C|kTJT2O4e9t{^U8wHqQ3pzxb{=v)Lb(wMFDNQ0i>x~3<2dLdCV{n;c;ez? zoqD@BRRcRk&Z|2 zW?xaSr3EF}b`TDrbx#=052Mlg*4P7oyK1-rlI6*!FaA$^y<+I)q1eyV%Pl=Zr%OT5 z{TrZv=%eUS+PQ%K8g?!->jikr-V|illykfBTw)&eA%)tG<0gsRLUV6uiqjdL??oBv ze>?`%z|kr=9c!-y_y_T#76Ip&{E)reIKhY+;{f# zESjtj+b%*{>QuEpr~c_tHWiISyrb0_xHlZ#a#8Kj^~BxwT6zZ1u6<{ZgD*n|NgT(T ze-y4%Q#;t#AB~_b@8HT#16Kz7)%z{t91)xjiTm8E_hl2+!z^+sW_Z3F_)vP|56vsy z;oO-owbFl)*{{@SyGdsSGNI?)E`#?b=rv)odgI-p*G~tMkv6`LmSGTECf2-h7@i1M zk9u$saj3kq4MJCy^p4{dkHxOmjOJCs`4sP%%r9nJk;w>}JUs9x9-x1L`4gp+^qcwz zM|im4fsdc$)T+1oJ3GC-C#5sTY?hnclkeMz63xsN)y|bVD6GHIE#Q``Ifl@+y) z^fX>#bL5p|y?N$t#VMcIbT^4r7BZvl@BzhrrGeb2s5+z3|mczYVqZH`6X0M)xkX`pRv< zHc}@zsTbv2jofW{+)mW-zzq@rbM>#fkf@tI6&iO*Cos1 zu{h@I-w8rGj9j~kBWgBrW2>iD;#Nv!2syTBCa@Cr(vyv%xsP#H6n~--U*sMRZt71w zPG(JV?RO1w7wG9g#J?>=Vtc+SVb+<%(&My}AeWW`y2gUGfd%HW3CaZ`5(crkZp*0{gJ z5^0W3bCKch$f{XjeUcSmnLsSoAOpu7zd;VT76g>L2DYR6OKM03Gc!^u~hrj}+UWSbkT zNhQccjpoG{F3Bz~-@=$$7+mo~@M%WtLzj#PcR(oZBO`+ePvA)sd0i+&>eiif$)$U- zE9A{Lk3RB=FYI;9Ni8S`^u}~dubUJ^|LZI$k*m~iAc;Qv!?l67EvBpFszCS@U$dv=XsM#)+kCq5Z_I#fyW=lG_ zR{n1~8PN~rg7%)q>(2P?WIN@j;Tt6Io)wAqCx%#4?5-Z(qp-#HHsCr- z7zRtB^k?VMYuRV>lUIhFUgqGjW!pZx(C%)+eP9DDF`R^{wtcLibE49V<=-`&n#RX8rh-iq< zd@u_{3^@4ti-+QPY3aQ!l4O6bK}(;$6z5Uw#lrXiMoSPIk|x;s1=CYT6Qa`3#^U8o zB4$C$(TRlbJd@0VjZ-q*BA|AktrXD~brex7TP}9tlCBsETJkr#ZSJUN85mw<2;*kz5(J}3 zIoj|xKVU{|9ujWO#@an(pmxh7$DwxGlgTzye~ohY#^F5esb!WrAo#K)yOui`|;3g!pw`*K43wi1g9#6fg|w&)+Z2^#!J9vBf| zm`=66ak3C#I5wSC_BYh?Nu!V~?=#fsNuJt#Bz$S(YiFgaPNnZK2~Lej_^A;H%)zBh zZ@DQF0R*a=xv!Qew=`zi^~b<1X1KCthwt_V$A>{~o43QKDZ3{ZDTM6_GFhr_0K4K7 zC+ddWO7Mz?Hd{fuMm*#SS&2^g`5iGp-1RDA~}D@7Uj5~dF^ z+T1DKs=Ic+D{7G#Sm6@s^xvvHGGZ$v^~R823n@GXzO=jQmBB0HPt-XS*G9%(nCdXd zu%CeWsQR>1DX8(Vn9#PVD}|C*UygAruWhHLx(lq zEIkuqBozSd-EsnwqqCo`c}pj~;ym%!0k>WOeWyRC2_@V@@*_fE5C(A?z8)IVKkU}y zcsL$h?yfO&Z|_mi2Eo>%uEr(l(?`KBj2ow??kJMTF8Zwv{A@9KzNKK6qyUuJ1MlNb zfz5f{aYt!YjYF!8F7;*Iu~tQ=lqUcrMMSqy-|K@~aHRt^1t_cb>{!76hwu;KZ4s1?1;?kP*B=w=0fmbuOM-vO$qoKbusd_fH{V8Z(dk0Zy(D) zTCGaqAyg@NT!;J1yhO)iu{o0K#dcaTggOCno)4GVibua$q+Ia-3M}$sm7WWA$gaWP zcKyj%ci}r#qR($2w<7A7Bt4gNHDKd;wGup~qx$llb;H)r)D}Q@WdBkM+}#V&h()2W zG)SK4??~)dJ;eTe1oPr9A*(zjfu_noa~2?P-8YLnz4!07gwc`*MTwt&!R}G!@o_tU z(OB}XXyutml*68iEF*42ehqX}56_x=TlFRF%e^OP&>MxGJO&S#g0j-{&v9&-3NIXJ zmuL4+j^8%J5hVxj}y{xm;JWgNnQPAS%xZcO*6a<5Z&JpamnNU}N4X=3O?^u-;s zgOz}v#lY*yV~3D>S;W=&svqAD>NmyXmy%79SuHE{r~H0|Gd!vvAhO2_pw?9fQ`GFU3?VE&=s>W`&xAN9T{%($Lc*3?JQp6QOQPyK9hVna4Xq*GIxrkKOL; zk;my%&8S57$9VDEmptyxGTR=~%#Cm6zw|P5XzLTFHb%Al_da_BJ5XQoT}1_+n5-4{ zmPzwQW#&Ym#OJyFF4ai4eIjVy=y9m&Fjn-^WV$bjz$Y9}>rHBf!C0X&v8Kn_vi%8d z1yF0H&?djcvqt+mC|nadC}f&ycUVtQ8*@<Lx4Zj7 znyxWnF(aDqaSuVi5WV3G&L~wptIDycc6PmO?pU$_D#>~R;hufr$5&Jxbz~l=^9H*g zoR~%iSQs>nQJRN>eo#!%bs!OH^Eo(Nta}V(Unt}6SG9mK{{HXZHUF@$5#feMX>psq z#E|uYd@Bw6Ba6+86`s&`uI+sF-X(T`H_GXj{|0@_u=grb(6R3K!n23OGAVlyyZ^_&aPOk6jKN~Tb*4`EzcIj_o4R@sC`1k?e+1a^VvC32UFhYA_ zjAVM@xmEPMnS~yR5{O+M0d!-d(iPfYfbzTOCz1q(?X`)x;Cg|v@P02d22K04=grl< zRETfbB-|(ZL+J2WiNet`HO+T06xM5=g`18CP=6xBy+PM%pr_WJd1f$&nlj}CrjCf| z&q2e&!K$%ktskh8^pv#Vx>95zeVLTo*WNTn`2lMe*ifg2oN8NDx63C9xLCY?mVq?hQ`34f;WJ8|xz_VduHQp)z-OhiOf($1wBP-D(0`S8n@BZ?i zUk=azxMFM-WrNuqkDJ0{Na#@9pqG(CW}(CQz@Ke_ClkB%es;3QIf^rYV~eVJpZSRA z3LOj2m~|{r44*wC#OF!fX}X8;4y3F+A5~Z~eBuFQy0!X%JO`C*;WB~{N`I&No0CGI zbt?>ao0G4#YfE$+R!g=&@USUQ?cZ?j856du8Wn8lW^Ml3K1nJ(E3e}kn%dO>%dV7b#{Hkgj^I*4En(+@iB4-=qghQl0?%ge@=` zj&z&6qFrYN2a-@kneUbgagVu95Khywt+S_~xT4$g-rdWg?bnBh;Cc?>rP zCBOwV23ffLm3$x_lDu@0e~`rC|73Z18wQX``#*;Pd<06feg(vauNd@sMc({?RHI6l zcy<6}r|&R?PE+9a**tWnUib0d901FymLB@TO&(Ett|AC1C#7(VP&K#DR+F6ocRRTj zI2*KXfozf=paW=PmE^M0y|1@60cNo4U_kxeX+0;KFXAf*DLN*fs{lW%?y8sck2}K{ ziojKO>9l@>W2CmtYPD0eB)fXS>$KlZ zQwujLe^w7H+-of>r$^v4^hfC}pr!kPe=&f4N>x!1cUvDIqgDAYK6YB}uV>rH=IwL{ z_2fnHFo6@$5OX+79?e%ZU@L*{2z*LL@JPpib`{k)iIf}o=XGPE6oFv;#V6V1qj8yc1Sn;@i;qp;AMsN-A6#tqJO!7 z56@lLK$8D&^)bQ#E7mM$BT373kNobu@Y~991Niz zH1npk%=2;ehn(O`o*)`L1VbIXS~fu+)H=8ueG3frUi3ZK=W*;t@D%NaE53`N-EVCr zkoo-+{cQt(zwhOjrWC9>K^&jOzVD7N`DV{YD)|CnM&GsnyfD{D8vqiv0~jQbg^`1h z0q&F7!S~c>`OLSwBo6*R2GlGav3c!)FLUlZA-&U(%0$KY>5rCw-5+ z0ZKnI=>AU><`~s2sMU(H!fd*rzEwLQtV8d_ENTe5Tn_{n7*IKW!hLB2cc!1XGXj1F zxa?Mce8fi!vu{DAp+q7C_87ZBOj!+}d(u#29-e(*_f||BLDoYDcz|00uGek+6wO7G z2_W*)ny6sqS^XWn*c3y(+h;aw-za=ZWOXe+VrPB1{o`JAbac|Cz0@#lRQ_ElbHiLy zW}!N&>z4kFrl`8jPRYa7~2GQC_e!TfeE<8-wGZM0(zYiA)^F?auHy)cwJ-OMlgZkCW0BVT~g88 z5BwX%fXRL_klV-Mpc$D=XBqR1Py&INAmQ|YUo|OC<6AM zk+JI^RwM=t@C4KAs0nfcv8K5@G~Q_pWmm_OwTr>R4Uh-SOIxs9`og-Qd@wlmyMaqN zo?HOY=(2$=APn59(O{!FP()Hdm9C!xN)sGJ*&Sd)OsT8Z5E9*rAuK@qpngMl#||#U zhdAc$=Ux6|SFvC_8&BtKf2t*Qu&z2Bw(?>eA*{-q;Won_bv@$b9(1*~r=L1)Z^+mY z20}xvo1JCINt=nj@KZDA?IE&S8Yf<=HqNst#hOn-*IpBQLY~WmQ`VLIKl(XMBu-W) z74k_2QUt)c@KFUz#`o`%-utb5-9iOXy_3oemo69~rq zND;*I1T`112jDSfi6F6VJ_82iw(3Hx^WXq==P{YjjMlS@w(!mxra>Udv9l*wp>=FWt8vtkP)Q^EHAzgbExtE7p2mFO3e!$F%1k@8mxJq|A*D z<~!r*ksNfMCS0u2ED&e1E+Q|N5o&Yc?ry{NStSYIk_&HgiFsUcGBK z*uWHOxi2GK4puO|A^3Qme+Fo)q7o;c)nBguU=6EvxJSo*k;&n*<=g2_hsB8XQlN3k z%q^GRUhYH`h4n4}WZl#3m7AxT*@E(KNeJm`^TS>Syb=~m z;7#mcHd>H4e*91@M!=;+y~qoRG(pIH0>;FkQ6!RglH`LMK+LNW$8EjM>G;YUveFkz zadmORebtvNtp80dcjZ@hVPdK2pp3Dxai6$Ny2)IVS6VYQ zz9bY%H3REer{%7;GZhPGb-GKP_zcHr!@)rmQ54^q7{&`^ck=sg6;W75ZW$YH5)iSP z26s8q|K-yd3cUk76Q&rvAyc-dFW^to>jhpBUV8R^(ZiF<58!cpM8=3BWPdGXV^hSS z-=O1M{=5rVKL)ruh*Kma{ESPlLqz$%IY2&eS| zpn}X|PL%BoA~8DJ$kV8{%Y3)~vs;s7wE>B{%yN=zfQ$Iqo&UUSHt(j2TBM$FvJvS| zXW~=~L449R8M1DVde^9O<;kkGxkDH}9dzx*&i1agdrBSNFiBUBGml^CPq|ACyswoU zxG9!TW7dlz=2nkP2sH0PSCg5r%nM9c#h315&I-$XBh)?ptwGJQkvfBUgOWsb)xmH} z!Ed5S+uPo!7k&AQ^h{7crTLoJOLpF~ynmFL^6prB@exe~%fKZrJC*nNMgGI+~lfI*{Yi*fqXPw6t)14=av2d&vTi z&V|f^fyR_MdOBDKgN9zPyl`n_frMdY{5kogX;eYfRz7n4*$W+kCn2gs7DV2Vq0M~5 zSAVPn`1<@;--R?IqKMh7`e4E4g80*)!2h$167c!vJlrN2*dm8@bxHkb@&dOv38Cv# zqt4BRnXT`sAM>=zdpNY}oQq%NX|N8E!*+LV=+p}m&Qw#y?&s*$*PyEIa?60F97HPk zH1IKJSZ_4*m!Q3V?pY}*sn3m2xvLE6aO1<@KWr;(Nhwj9=~{&T^Jcm+n*`XQmd znB`C_iDHh+=oR3+Q6C>)Q5*I}q9=AS^^hBD+IcO^BOv!SG0waq*uCh*@o^&MXd07C zFg`Y$lEoW*y36X~(7NmCNYr_~yoOkw4=ZlF9qITF z?)z2MSBw_ZKUeJatO<@B{!&2XLi$tW^CiYC(}kY%>Kpi~3G7NDlkVzupy_nJbTNrou zeS?E{e?(yXVhTsqQ#^Aa>>??iik9KU;ndfoT6y>8r2NdbG1BARYi|hF@aQr{wz29_ z=kog6LDr29Il6bN(e6; zwp`&rk}>u)2H&+rAJC6mM+OAmwwjiQ_`B_`87C?6DtOh!*Wg2jV-Uauo5VA-jXC+ zp34_{V!}f7c8Cuo|L+gYDn z^xIEON);j3`VAEp38TYxr3fW0t+f5YL$U8cExA!)Y-C5#yN^xe8r6f6!UEN5dw;Rx zQ;zC7WNzkpVZ9fR;l*=5^WR+OP*HF%SE1yQ`j(%}!2N>ub!FNLm%sdua(*C$8+3e9EjZNhQRw zDk@#Of8w}ThvN{AH4A-fM$;w|rone2iO9=DlP;H6rK06{HgH{~P%+K>y{uQO;Oh$= zKCu>m{Gvhrvv$Rf)^AclVCN(hzK9{;XAu2mUMib}YdCBRk4@!2|v|z{_M&^dqi<;zI z?yzQg4mLgtycXja6ZwKfWz4Am)1ng>R#bj=hqv;5`kNHdqd-+T4R7AHokoTC*WsJn z0z;dTXLG#Wz{P(2ViSjV|5!j({Wu(-YVcm5fFkSUq&7wryR3S=r8lI`1x0N4*Z|{y zd0IlG=-_)*hHKjcRqXSmZ~84P6F$4G9Vo#;dd|-G7gUQ(A$YEsQ;ZHsNG}zSV}-E` zY5aj&{BV64fR6_pyliF-n_CA3IbhczqI+w^HwGfEqC{(Tnsz>B7F2`4 zLXx)e?El^){|er`4jFDYUGTr#bVT${;a_Soq>sQ_Ha|;~j*B;ih=t-$%Km^R)}K#m z`a?{8WQ!$$42*$f=ME$O$aX}C0Pic3gSP~w*a=%mpyVS`-J(Z81Z8^8hYf7@VMvpLqDI5y6MU4qUn$MlvJ(g zAMDC7a@v{299i0X%>j-o_h%(hOvV*g_o2U=kEr;1;F~AS#WJU8S8Z6Rq0!Ody{^K5 z9upQ0CFhCzlhiYcSBWJ%?PhkT{k&O1yxx#U^{m>*80Sqer8i0vu1w%mU#$hnL;q^o z|Aijpf~dEr`jh|RR0r$r5ybKDUpN%e1g~E`Nl7T+^{ic~zRb|n0-6|)z&!oY2GdQdXw zQ8y;6sI)&f?d0oWnJJZi=WD&i%t{ilfhI|e8vb7I|LVICz1s~m@b5Oz+|W$=>pf4K ziaeE#Hsa8flxKs?4dgKMn_9~FZ^BG`uirEzycYE+;J5N8RHb~o=xMAtSh;j*t=)gB z_A)5k!r^I*B^*q*Ho7v-N-76yvt|?IDKh(z2W6t3xGZ~WpLC~&mOlFkEyMZ!Lq#TN z$E@P0FmcPL8`SbKS9YaH(gTxk3BSz|&%fT*UKeEip1^CIBEmnqDkobqw+bwU?LNu6NNUbyqXFRyP2P)0_D#Sk(WBuh`=~hWqxtzhcbG3RGJ$dOWZEmn`0=Pp>RZCBw0b z>U_aOH5-bO>SEWkEIzu5g^68Z(9fPDibB(nehnoAiO-Doxlt+xUX>i_S8(H_CK zvp>@P-c0yZK9Ll-ds4Z2cp*aHtl~QnhujFTDh%XLG1xIqknZ?AXwT?Mc@$PDu3D?W zeF@;H7NX)uJFeL{ZkeSpysoR8BUWvADdg#<5E8DR z9|3B`KGs2U#C$kfU!KHD+u4qa+E1O+n})}w%|8M|eFpsNDY~0Ap_ge~*Uu@>Yb2C3 zzT#}pzO2ry?Csil+*!D znhOuaiYAaIqJPb})*sGNV3jX7hEaJkbw9>#gJ6aB^DSL)Qs>R}6c0avLb2kwvj@2V z8by9ZuYKnIQKFTk1gCqWG|_bV*YN6cON}m80%NXmZE@Zk0x`QtG;^mOa2b^F_Rd(j zR;1+6e`e>fr6mjsTgkzuzu(!v`YxpVj|(>Tzd7<%{_Ng_Rk~x-9T?tlus=sf(a
    %Jd^>-9R%^EjTz^Z7iE)6Cdv_Ws#& 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
    X*Q>nMzD?8KA#f{uXZ2-xGBJrxEmvD+J_QnZ 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
    + + + + + + + + + + ); +}; diff --git a/plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx b/plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx new file mode 100644 index 0000000000..fb24a8a832 --- /dev/null +++ b/plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx @@ -0,0 +1,63 @@ +/* + * 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 { + Stepper as MuiStepper, + Step as MuiStep, + StepButton as MuiStepButton, + StepLabel as MuiStepLabel, +} from '@material-ui/core'; +import { TaskStep } from '@backstage/plugin-scaffolder-common'; +import { Step } from '../../../components/hooks/useEventStream'; + +interface StepperProps { + steps: (TaskStep & Step)[]; + activeStep?: number; + setActiveStep?: (step: number) => void; +} + +export const TaskSteps = (props: StepperProps) => { + return ( + + {props.steps.map((step, index) => { + const isCompleted = step.status === 'completed'; + const isFailed = step.status === 'failed'; + const isActive = step.status === 'processing'; + const isSkipped = step.status === 'skipped'; + + return ( + + + + {step.name} + + + + ); + })} + + ); +}; diff --git a/plugins/scaffolder/src/next/TaskPage/TaskSteps/index.ts b/plugins/scaffolder/src/next/TaskPage/TaskSteps/index.ts new file mode 100644 index 0000000000..28724ba512 --- /dev/null +++ b/plugins/scaffolder/src/next/TaskPage/TaskSteps/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 { TaskSteps } from './TaskSteps'; diff --git a/plugins/scaffolder/src/next/TaskPage/index.ts b/plugins/scaffolder/src/next/TaskPage/index.ts new file mode 100644 index 0000000000..9b6e502fed --- /dev/null +++ b/plugins/scaffolder/src/next/TaskPage/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 { TaskPage } from './TaskPage'; diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index d24482a583..b71d0bd7a3 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -28,12 +28,17 @@ import { Workflow, type LayoutOptions, } from '@backstage/plugin-scaffolder-react'; -import { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; +import { + NextFieldExtensionOptions, + FormProps, +} from '@backstage/plugin-scaffolder-react'; import { JsonValue } from '@backstage/types'; -import { type FormProps } from '../types'; -import { nextRouteRef } from '../routes'; -import { scaffolderTaskRouteRef, selectedTemplateRouteRef } from '../../routes'; import { Header, Page } from '@backstage/core-components'; +import { + nextRouteRef, + nextScaffolderTaskRouteRef, + nextSelectedTemplateRouteRef, +} from '../routes'; export type TemplateWizardPageProps = { customFieldExtensions: NextFieldExtensionOptions[]; @@ -43,12 +48,12 @@ export type TemplateWizardPageProps = { export const TemplateWizardPage = (props: TemplateWizardPageProps) => { const rootRef = useRouteRef(nextRouteRef); - const taskRoute = useRouteRef(scaffolderTaskRouteRef); + const taskRoute = useRouteRef(nextScaffolderTaskRouteRef); const { secrets } = useTemplateSecrets(); const scaffolderApi = useApi(scaffolderApiRef); const navigate = useNavigate(); const { templateName, namespace } = useRouteRefParams( - selectedTemplateRouteRef, + nextSelectedTemplateRouteRef, ); const templateRef = stringifyEntityRef({ From 29feff150ed9b13d6d94e8c0e4358ff83a0e7aa2 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 17 Jan 2023 15:49:02 +0100 Subject: [PATCH 257/423] chore: added some more things for enabling testing Signed-off-by: blam --- app-config.yaml | 6 +++ packages/backend/src/plugins/scaffolder.ts | 28 +++++++++++++- packages/backend/test-template.yaml | 37 +++++++++++++++++++ .../default-app/app-config.local.yaml | 4 ++ .../scaffolder/src/next/TaskPage/TaskPage.tsx | 4 +- .../src/next/TaskPage/TaskSteps/TaskSteps.tsx | 19 ++++++---- 6 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 packages/backend/test-template.yaml diff --git a/app-config.yaml b/app-config.yaml index dd72051189..2eed4762ce 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -255,6 +255,12 @@ catalog: # Backstage example entities - type: file target: ../catalog-model/examples/all.yaml + + - type: file + target: ./test-template.yaml + rules: + - allow: [Template] + # Backstage example groups and users - type: file target: ../catalog-model/examples/acme-corp.yaml diff --git a/packages/backend/src/plugins/scaffolder.ts b/packages/backend/src/plugins/scaffolder.ts index d079b64c28..b6275e9883 100644 --- a/packages/backend/src/plugins/scaffolder.ts +++ b/packages/backend/src/plugins/scaffolder.ts @@ -15,7 +15,12 @@ */ import { CatalogClient } from '@backstage/catalog-client'; -import { createRouter } from '@backstage/plugin-scaffolder-backend'; +import { ScmIntegrations } from '@backstage/integration'; +import { + createRouter, + createTemplateAction, + createBuiltinActions, +} from '@backstage/plugin-scaffolder-backend'; import { Router } from 'express'; import type { PluginEnvironment } from '../types'; @@ -26,6 +31,26 @@ export default async function createPlugin( discoveryApi: env.discovery, }); + const defaultActions = createBuiltinActions({ + catalogClient, + reader: env.reader, + config: env.config, + integrations: ScmIntegrations.fromConfig(env.config), + }); + + const delayAction = createTemplateAction({ + id: 'mock:delay', + async handler(ctx) { + const interval = setInterval( + () => ctx.logger.info('Writing something', new Date().toISOString()), + 1000, + ); + + await new Promise(resolve => setTimeout(resolve, 5000)); + clearTimeout(interval); + }, + }); + return await createRouter({ logger: env.logger, config: env.config, @@ -34,5 +59,6 @@ export default async function createPlugin( reader: env.reader, identity: env.identity, scheduler: env.scheduler, + actions: [...defaultActions, delayAction], }); } diff --git a/packages/backend/test-template.yaml b/packages/backend/test-template.yaml new file mode 100644 index 0000000000..13a002e0b9 --- /dev/null +++ b/packages/backend/test-template.yaml @@ -0,0 +1,37 @@ +apiVersion: scaffolder.backstage.io/v1beta3 +# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-template +kind: Template +metadata: + name: example-delay-tempalte + title: Delay template + description: An example template for the scaffolder that creates a simple Node.js service +spec: + type: service + + parameters: [] + + steps: + - id: delay1 + name: Delay 1 + action: mock:delay + + - id: delay2 + name: Delay 2 + action: mock:delay + + - id: delay3 + name: Delay 3 + action: mock:delay + + - id: delay4 + name: Delay 4 + action: mock:delay + + - id: delay5 + if: true + name: Delay 5 + action: mock:delay + + - id: delay6 + name: Delay 6 + action: mock:delay diff --git a/packages/create-app/templates/default-app/app-config.local.yaml b/packages/create-app/templates/default-app/app-config.local.yaml index 976293b546..6b4dcd0327 100644 --- a/packages/create-app/templates/default-app/app-config.local.yaml +++ b/packages/create-app/templates/default-app/app-config.local.yaml @@ -1 +1,5 @@ # Backstage override configuration for your local development environment +catalog: + locations: + - type: file + target: ./test-template.yaml diff --git a/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx index f259231e4d..f9a84d2355 100644 --- a/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx +++ b/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx @@ -52,7 +52,9 @@ export const TaskPage = () => { /> - + {!taskStream.completed && ( + + )} diff --git a/plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx b/plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx index fb24a8a832..4095872465 100644 --- a/plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx +++ b/plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx @@ -19,9 +19,11 @@ import { Step as MuiStep, StepButton as MuiStepButton, StepLabel as MuiStepLabel, + StepIconProps, } from '@material-ui/core'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; import { Step } from '../../../components/hooks/useEventStream'; +import RemoveCircleOutlineIcon from '@material-ui/icons/RemoveCircleOutline'; interface StepperProps { steps: (TaskStep & Step)[]; @@ -41,17 +43,20 @@ export const TaskSteps = (props: StepperProps) => { const isFailed = step.status === 'failed'; const isActive = step.status === 'processing'; const isSkipped = step.status === 'skipped'; + const stepIconProps: Partial = { + completed: isCompleted, + error: isFailed, + active: isActive, + }; + + if (isSkipped) { + stepIconProps.icon = ; + } return ( - + {step.name} From 07c675f7ebd4fe3b72a808ff6cfd35c3f4b15af6 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 25 Jan 2023 10:14:48 +0100 Subject: [PATCH 258/423] chore: added times to the dropdown box Signed-off-by: blam --- plugins/scaffolder/src/next/Router/Router.tsx | 1 - .../scaffolder/src/next/TaskPage/TaskPage.tsx | 5 +- .../src/next/TaskPage/TaskSteps/StepIcon.tsx | 71 +++++++++++++++++++ .../src/next/TaskPage/TaskSteps/StepTime.tsx | 53 ++++++++++++++ .../src/next/TaskPage/TaskSteps/TaskSteps.tsx | 17 +++-- 5 files changed, 136 insertions(+), 11 deletions(-) create mode 100644 plugins/scaffolder/src/next/TaskPage/TaskSteps/StepIcon.tsx create mode 100644 plugins/scaffolder/src/next/TaskPage/TaskSteps/StepTime.tsx diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index f5e186eb67..8de9ac57e4 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -29,7 +29,6 @@ import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups'; import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default'; -import { FormProps } from '../types'; import { nextScaffolderTaskRouteRef, nextSelectedTemplateRouteRef, diff --git a/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx index f9a84d2355..138c6ac24e 100644 --- a/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx +++ b/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx @@ -52,11 +52,10 @@ export const TaskPage = () => { /> - {!taskStream.completed && ( - - )} + {!taskStream.completed && } + {/* */} diff --git a/plugins/scaffolder/src/next/TaskPage/TaskSteps/StepIcon.tsx b/plugins/scaffolder/src/next/TaskPage/TaskSteps/StepIcon.tsx new file mode 100644 index 0000000000..39ef37c771 --- /dev/null +++ b/plugins/scaffolder/src/next/TaskPage/TaskSteps/StepIcon.tsx @@ -0,0 +1,71 @@ +/* + * Copyright 2023 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 { BackstageTheme } from '@backstage/theme'; +import { CircularProgress, makeStyles, StepIconProps } from '@material-ui/core'; +import RemoveCircleOutline from '@material-ui/icons/RemoveCircleOutline'; +import FiberManualRecordIcon from '@material-ui/icons/FiberManualRecord'; +import classNames from 'classnames'; +import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline'; +import DeleteOutline from '@material-ui/icons/DeleteOutline'; + +const useStepIconStyles = makeStyles((theme: BackstageTheme) => ({ + root: { + color: theme.palette.text.disabled, + }, + completed: { + color: theme.palette.status.ok, + }, + error: { + color: theme.palette.status.error, + }, +})); + +export const StepIcon = (props: StepIconProps & { skipped: boolean }) => { + const classes = useStepIconStyles(); + const { active, completed, error, skipped } = props; + + const getMiddle = () => { + if (active) { + return ; + } + if (completed) { + return ; + } + + if (error) { + return ; + } + + if (skipped) { + return ; + } + + return ; + }; + + return ( +
    + {getMiddle()} +
    + ); +}; diff --git a/plugins/scaffolder/src/next/TaskPage/TaskSteps/StepTime.tsx b/plugins/scaffolder/src/next/TaskPage/TaskSteps/StepTime.tsx new file mode 100644 index 0000000000..f2d3116854 --- /dev/null +++ b/plugins/scaffolder/src/next/TaskPage/TaskSteps/StepTime.tsx @@ -0,0 +1,53 @@ +/* + * Copyright 2023 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, { useState } from 'react'; +import useInterval from 'react-use/lib/useInterval'; +import { DateTime, Interval } from 'luxon'; +import humanizeDuration from 'humanize-duration'; +import { Typography } from '@material-ui/core'; + +export const StepTime = ({ + step, +}: { + step: { + id: string; + name: string; + startedAt?: string; + endedAt?: string; + }; +}) => { + const [time, setTime] = useState(''); + + useInterval(() => { + if (!step.startedAt) { + setTime(''); + return; + } + + const end = step.endedAt + ? DateTime.fromISO(step.endedAt) + : DateTime.local(); + + const startedAt = DateTime.fromISO(step.startedAt); + const formatted = Interval.fromDateTimes(startedAt, end) + .toDuration() + .valueOf(); + + setTime(humanizeDuration(formatted, { round: true })); + }, 1000); + + return {time}; +}; diff --git a/plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx b/plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx index 4095872465..40f9f9c189 100644 --- a/plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx +++ b/plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx @@ -23,7 +23,8 @@ import { } from '@material-ui/core'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; import { Step } from '../../../components/hooks/useEventStream'; -import RemoveCircleOutlineIcon from '@material-ui/icons/RemoveCircleOutline'; +import { StepIcon } from './StepIcon'; +import { StepTime } from './StepTime'; interface StepperProps { steps: (TaskStep & Step)[]; @@ -43,21 +44,23 @@ export const TaskSteps = (props: StepperProps) => { const isFailed = step.status === 'failed'; const isActive = step.status === 'processing'; const isSkipped = step.status === 'skipped'; - const stepIconProps: Partial = { + const stepIconProps: Partial = { completed: isCompleted, error: isFailed, active: isActive, + skipped: isSkipped, }; - if (isSkipped) { - stepIconProps.icon = ; - } - return ( - + {step.name} +
    +
    From 66948f1a99dd676ad0f602de66b9f96e8f1308e2 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 25 Jan 2023 14:19:50 +0100 Subject: [PATCH 259/423] chore: make a little clearer when a task has failed Signed-off-by: blam --- .../src/next/TaskPage/TaskBorder.tsx | 51 +++++++++++++++++++ .../scaffolder/src/next/TaskPage/TaskPage.tsx | 8 ++- 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 plugins/scaffolder/src/next/TaskPage/TaskBorder.tsx diff --git a/plugins/scaffolder/src/next/TaskPage/TaskBorder.tsx b/plugins/scaffolder/src/next/TaskPage/TaskBorder.tsx new file mode 100644 index 0000000000..1bf09bf207 --- /dev/null +++ b/plugins/scaffolder/src/next/TaskPage/TaskBorder.tsx @@ -0,0 +1,51 @@ +/* + * Copyright 2023 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 { LinearProgress, makeStyles } from '@material-ui/core'; +import { BackstageTheme } from '@backstage/theme'; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + failed: { + backgroundColor: theme.palette.error.main, + }, + success: { + backgroundColor: theme.palette.success.main, + }, +})); + +export const TaskBorder = ({ + isComplete, + isError, +}: { + isComplete: boolean; + isError: boolean; +}) => { + const styles = useStyles(); + + if (!isComplete) { + return ; + } + + if (isError) { + return ( + + ); + } + + return ( + + ); +}; diff --git a/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx index 138c6ac24e..87d5d35453 100644 --- a/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx +++ b/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx @@ -17,8 +17,9 @@ import React, { useMemo } from 'react'; import { Page, Header, Content } from '@backstage/core-components'; import { useTaskEventStream } from '../../components/hooks/useEventStream'; import { useParams } from 'react-router-dom'; -import { Box, LinearProgress, Paper } from '@material-ui/core'; +import { Box, Paper } from '@material-ui/core'; import { TaskSteps } from './TaskSteps'; +import { TaskBorder } from './TaskBorder'; export const TaskPage = () => { const { taskId } = useParams(); @@ -52,7 +53,10 @@ export const TaskPage = () => { /> - {!taskStream.completed && } + {/* */} From 2b27e58084815f9a88fea94d19f5bb71e13e0ed7 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 25 Jan 2023 15:29:21 +0100 Subject: [PATCH 260/423] chore: change order of hooks Signed-off-by: blam --- .../scaffolder-react/src/next/components/Stepper/Stepper.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index 9242ef0086..f802121597 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -127,6 +127,8 @@ export const Stepper = (stepperProps: StepperProps) => { [setFormState], ); + const currentStep = useTransformSchemaToProps(steps[activeStep], { layouts }); + const handleNext = async ({ formData = {}, }: { @@ -151,8 +153,6 @@ export const Stepper = (stepperProps: StepperProps) => { setFormState(current => ({ ...current, ...formData })); }; - const currentStep = useTransformSchemaToProps(steps[activeStep], { layouts }); - return ( <> From 5cc6278ddc52d8f72ae0cd46f18766484cf4a6cb Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 25 Jan 2023 16:26:01 +0100 Subject: [PATCH 261/423] chore: moving some files around and making them pretty Signed-off-by: blam --- .../src/components/LogViewer/LogLine.tsx | 7 ++-- .../OngoingTask.tsx} | 18 ++++++--- .../{TaskPage => OngoingTask}/TaskBorder.tsx | 0 .../src/next/OngoingTask/TaskLogStream.tsx | 39 +++++++++++++++++++ .../TaskSteps/StepIcon.tsx | 0 .../TaskSteps/StepTime.tsx | 10 +++-- .../TaskSteps/TaskSteps.tsx | 0 .../TaskSteps/index.ts | 0 .../next/{TaskPage => OngoingTask}/index.ts | 2 +- plugins/scaffolder/src/next/Router/Router.tsx | 4 +- 10 files changed, 65 insertions(+), 15 deletions(-) rename plugins/scaffolder/src/next/{TaskPage/TaskPage.tsx => OngoingTask/OngoingTask.tsx} (82%) rename plugins/scaffolder/src/next/{TaskPage => OngoingTask}/TaskBorder.tsx (100%) create mode 100644 plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx rename plugins/scaffolder/src/next/{TaskPage => OngoingTask}/TaskSteps/StepIcon.tsx (100%) rename plugins/scaffolder/src/next/{TaskPage => OngoingTask}/TaskSteps/StepTime.tsx (85%) rename plugins/scaffolder/src/next/{TaskPage => OngoingTask}/TaskSteps/TaskSteps.tsx (100%) rename plugins/scaffolder/src/next/{TaskPage => OngoingTask}/TaskSteps/index.ts (100%) rename plugins/scaffolder/src/next/{TaskPage => OngoingTask}/index.ts (93%) diff --git a/packages/core-components/src/components/LogViewer/LogLine.tsx b/packages/core-components/src/components/LogViewer/LogLine.tsx index 8f3a2ce65c..c8ff5cbceb 100644 --- a/packages/core-components/src/components/LogViewer/LogLine.tsx +++ b/packages/core-components/src/components/LogViewer/LogLine.tsx @@ -15,7 +15,6 @@ */ import React, { useMemo } from 'react'; -import Typography from '@material-ui/core/Typography'; import { AnsiChunk, AnsiLine, ChunkModifiers } from './AnsiProcessor'; import startCase from 'lodash/startCase'; import classnames from 'classnames'; @@ -159,8 +158,8 @@ export function LogLine({ const elements = useMemo( () => chunks.map(({ text, modifiers, highlight }, index) => ( - {text} - + )), [chunks, highlightResultIndex, classes], ); diff --git a/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx similarity index 82% rename from plugins/scaffolder/src/next/TaskPage/TaskPage.tsx rename to plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx index 87d5d35453..feed582745 100644 --- a/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx @@ -20,8 +20,9 @@ import { useParams } from 'react-router-dom'; import { Box, Paper } from '@material-ui/core'; import { TaskSteps } from './TaskSteps'; import { TaskBorder } from './TaskBorder'; +import { TaskLogStream } from './TaskLogStream'; -export const TaskPage = () => { +export const OngoingTask = () => { const { taskId } = useParams(); // check that task Id actually exists, and that it's valid. otherwise redirect to something more useful. const taskStream = useTaskEventStream(taskId!); @@ -44,12 +45,19 @@ export const TaskPage = () => { return 0; }, [steps]); + const templateName = + taskStream.task?.spec.templateInfo?.entity?.metadata.name; + return (
    + Run of {templateName} + + } + subtitle={`Task ${taskId}`} /> @@ -59,7 +67,7 @@ export const TaskPage = () => { /> - {/* */} + diff --git a/plugins/scaffolder/src/next/TaskPage/TaskBorder.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx similarity index 100% rename from plugins/scaffolder/src/next/TaskPage/TaskBorder.tsx rename to plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx new file mode 100644 index 0000000000..0060a9c9be --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx @@ -0,0 +1,39 @@ +/* + * Copyright 2023 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 { LogViewer } from '@backstage/core-components'; +import { makeStyles } from '@material-ui/core/styles'; + +const useStyles = makeStyles({ + root: { + width: '100%', + height: '200px', + position: 'relative', + }, +}); + +export const TaskLogStream = (opts: { logs: { [k: string]: string[] } }) => { + const styles = useStyles(); + return ( +
    + l.join('\n')) + .join('\n')} + /> +
    + ); +}; diff --git a/plugins/scaffolder/src/next/TaskPage/TaskSteps/StepIcon.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepIcon.tsx similarity index 100% rename from plugins/scaffolder/src/next/TaskPage/TaskSteps/StepIcon.tsx rename to plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepIcon.tsx diff --git a/plugins/scaffolder/src/next/TaskPage/TaskSteps/StepTime.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx similarity index 85% rename from plugins/scaffolder/src/next/TaskPage/TaskSteps/StepTime.tsx rename to plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx index f2d3116854..746007a7d3 100644 --- a/plugins/scaffolder/src/next/TaskPage/TaskSteps/StepTime.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import useInterval from 'react-use/lib/useInterval'; import { DateTime, Interval } from 'luxon'; import humanizeDuration from 'humanize-duration'; @@ -31,7 +31,7 @@ export const StepTime = ({ }) => { const [time, setTime] = useState(''); - useInterval(() => { + const calculate = useCallback(() => { if (!step.startedAt) { setTime(''); return; @@ -47,7 +47,11 @@ export const StepTime = ({ .valueOf(); setTime(humanizeDuration(formatted, { round: true })); - }, 1000); + }, [step.endedAt, step.startedAt]); + + useMemo(() => calculate(), [calculate]); + + useInterval(() => !step.endedAt && calculate(), 1000); return {time}; }; diff --git a/plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.tsx similarity index 100% rename from plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx rename to plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.tsx diff --git a/plugins/scaffolder/src/next/TaskPage/TaskSteps/index.ts b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/index.ts similarity index 100% rename from plugins/scaffolder/src/next/TaskPage/TaskSteps/index.ts rename to plugins/scaffolder/src/next/OngoingTask/TaskSteps/index.ts diff --git a/plugins/scaffolder/src/next/TaskPage/index.ts b/plugins/scaffolder/src/next/OngoingTask/index.ts similarity index 93% rename from plugins/scaffolder/src/next/TaskPage/index.ts rename to plugins/scaffolder/src/next/OngoingTask/index.ts index 9b6e502fed..f0c7e2a6cc 100644 --- a/plugins/scaffolder/src/next/TaskPage/index.ts +++ b/plugins/scaffolder/src/next/OngoingTask/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { TaskPage } from './TaskPage'; +export { OngoingTask } from './OngoingTask'; diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 8de9ac57e4..b9c18f9d02 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -34,7 +34,7 @@ import { nextSelectedTemplateRouteRef, } from '../routes'; import { ErrorPage } from '@backstage/core-components'; -import { TaskPage } from '../TaskPage'; +import { OngoingTask } from '../OngoingTask'; /** * The Props for the Scaffolder Router @@ -97,7 +97,7 @@ export const Router = (props: PropsWithChildren) => { } /> - } /> + } /> } From c230ae79201037eea289c61045314f6c854eef65 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 30 Jan 2023 16:04:55 +0100 Subject: [PATCH 262/423] feat: added the ability to tail the logs on the LogViewer Signed-off-by: blam --- .../core-components/src/components/LogViewer/LogViewer.tsx | 4 ++++ .../src/components/LogViewer/RealLogViewer.tsx | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/packages/core-components/src/components/LogViewer/LogViewer.tsx b/packages/core-components/src/components/LogViewer/LogViewer.tsx index 20530cffaf..f1396eef36 100644 --- a/packages/core-components/src/components/LogViewer/LogViewer.tsx +++ b/packages/core-components/src/components/LogViewer/LogViewer.tsx @@ -39,6 +39,10 @@ export interface LogViewerProps { classes?: { root?: string; }; + /** + * Whether the LogViewer should automatically scroll to the bottom of the log. + */ + tail?: boolean; } /** diff --git a/packages/core-components/src/components/LogViewer/RealLogViewer.tsx b/packages/core-components/src/components/LogViewer/RealLogViewer.tsx index 59e0bea44b..d211399c69 100644 --- a/packages/core-components/src/components/LogViewer/RealLogViewer.tsx +++ b/packages/core-components/src/components/LogViewer/RealLogViewer.tsx @@ -32,6 +32,7 @@ import { useLogViewerSelection } from './useLogViewerSelection'; export interface RealLogViewerProps { text: string; classes?: { root?: string }; + tail?: boolean; } export function RealLogViewer(props: RealLogViewerProps) { @@ -52,6 +53,12 @@ export function RealLogViewer(props: RealLogViewerProps) { } }, [search.resultLine]); + useEffect(() => { + if (props.tail && listRef.current) { + listRef.current.scrollToItem(lines.length - 1, 'center'); + } + }, [lines.length, props.tail]); + useEffect(() => { if (location.hash) { // #line-6 -> 6 From ce32a61d388c29008deeaf20cd5494eb3d6d42d0 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 30 Jan 2023 22:03:36 +0100 Subject: [PATCH 263/423] chore: changeset and fixing tserrors Signed-off-by: blam --- .changeset/nasty-students-double.md | 5 +++++ .../scaffolder/src/next/OngoingTask/TaskBorder.tsx | 12 +++++------- .../src/next/OngoingTask/TaskLogStream.tsx | 4 ++++ 3 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 .changeset/nasty-students-double.md diff --git a/.changeset/nasty-students-double.md b/.changeset/nasty-students-double.md new file mode 100644 index 0000000000..d552fdf91e --- /dev/null +++ b/.changeset/nasty-students-double.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Added the ability to tail the `LogViewer` logs diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx index 1bf09bf207..ada4db1240 100644 --- a/plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx @@ -39,13 +39,11 @@ export const TaskBorder = ({ return ; } - if (isError) { - return ( - - ); - } - return ( - + ); }; diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx index 0060a9c9be..d587f47f17 100644 --- a/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx @@ -30,8 +30,12 @@ export const TaskLogStream = (opts: { logs: { [k: string]: string[] } }) => { return (
    l.join('\n')) + .filter(Boolean) + .join('\n')} />
    From c4b6770b67265d48c3e94860fd64347dda669c90 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 31 Jan 2023 12:53:53 +0100 Subject: [PATCH 264/423] chore: refactor and tidy up the UI slightly Signed-off-by: blam --- .../src/next/OngoingTask/OngoingTask.tsx | 98 ++++++++++++++++--- .../src/next/OngoingTask/TaskLogStream.tsx | 4 +- .../next/OngoingTask/TaskSteps/StepIcon.tsx | 8 +- 3 files changed, 89 insertions(+), 21 deletions(-) diff --git a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx index feed582745..68e05f29e2 100644 --- a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx @@ -13,18 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useMemo } from 'react'; +import React, { useEffect, useMemo, useState, useCallback } from 'react'; import { Page, Header, Content } from '@backstage/core-components'; import { useTaskEventStream } from '../../components/hooks/useEventStream'; -import { useParams } from 'react-router-dom'; -import { Box, Paper } from '@material-ui/core'; +import { useNavigate, useParams } from 'react-router-dom'; +import { Box, Button, Paper } from '@material-ui/core'; import { TaskSteps } from './TaskSteps'; import { TaskBorder } from './TaskBorder'; import { TaskLogStream } from './TaskLogStream'; +import { nextSelectedTemplateRouteRef } from '../routes'; +import { useRouteRef } from '@backstage/core-plugin-api'; +import qs from 'qs'; export const OngoingTask = () => { + // todo(blam): check that task Id actually exists, and that it's valid. otherwise redirect to something more useful. const { taskId } = useParams(); - // check that task Id actually exists, and that it's valid. otherwise redirect to something more useful. + const templateRouteRef = useRouteRef(nextSelectedTemplateRouteRef); + const navigate = useNavigate(); const taskStream = useTaskEventStream(taskId!); const steps = useMemo( () => @@ -35,7 +40,15 @@ export const OngoingTask = () => { [taskStream], ); - const activeStep = React.useMemo(() => { + const [logsVisible, setLogsVisible] = useState(false); + + useEffect(() => { + if (taskStream.error) { + setLogsVisible(true); + } + }, [taskStream.error]); + + const activeStep = useMemo(() => { for (let i = steps.length - 1; i >= 0; i--) { if (steps[i].status !== 'open') { return i; @@ -45,6 +58,30 @@ export const OngoingTask = () => { return 0; }, [steps]); + const startOver = useCallback(() => { + const { namespace, name } = + taskStream.task?.spec.templateInfo?.entity?.metadata ?? {}; + + const formData = taskStream.task?.spec.parameters ?? {}; + + if (!namespace || !name) { + return; + } + + navigate({ + pathname: templateRouteRef({ + namespace, + templateName: name, + }), + search: `?${qs.stringify({ formData: JSON.stringify(formData) })}`, + }); + }, [ + navigate, + taskStream.task?.spec.parameters, + taskStream.task?.spec.templateInfo?.entity?.metadata, + templateRouteRef, + ]); + const templateName = taskStream.task?.spec.templateInfo?.entity?.metadata.name; @@ -60,16 +97,49 @@ export const OngoingTask = () => { subtitle={`Task ${taskId}`} /> - - - - - + + + + + + + + + + + + + + + + + + + {logsVisible ? ( + + + + + + - + ) : null} ); diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx index d587f47f17..65c0022e1d 100644 --- a/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx @@ -20,7 +20,7 @@ import { makeStyles } from '@material-ui/core/styles'; const useStyles = makeStyles({ root: { width: '100%', - height: '200px', + height: '100%', position: 'relative', }, }); @@ -32,10 +32,8 @@ export const TaskLogStream = (opts: { logs: { [k: string]: string[] } }) => { l.join('\n')) .filter(Boolean) - .join('\n')} /> diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepIcon.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepIcon.tsx index 39ef37c771..cecf682596 100644 --- a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepIcon.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepIcon.tsx @@ -18,10 +18,10 @@ import React from 'react'; import { BackstageTheme } from '@backstage/theme'; import { CircularProgress, makeStyles, StepIconProps } from '@material-ui/core'; import RemoveCircleOutline from '@material-ui/icons/RemoveCircleOutline'; -import FiberManualRecordIcon from '@material-ui/icons/FiberManualRecord'; +import PanoramaFishEyeIcon from '@material-ui/icons/PanoramaFishEye'; import classNames from 'classnames'; import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline'; -import DeleteOutline from '@material-ui/icons/DeleteOutline'; +import ErrorOutline from '@material-ui/icons/ErrorOutline'; const useStepIconStyles = makeStyles((theme: BackstageTheme) => ({ root: { @@ -48,14 +48,14 @@ export const StepIcon = (props: StepIconProps & { skipped: boolean }) => { } if (error) { - return ; + return ; } if (skipped) { return ; } - return ; + return ; }; return ( From 25d25778d0534d1a5acbc01ec73d844b402e9c90 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 31 Jan 2023 13:39:56 +0100 Subject: [PATCH 265/423] chore: added default outputs to the template when there's links Signed-off-by: blam Signed-off-by: blam --- .../src/next/OngoingTask/OngoingTask.tsx | 4 +- .../OngoingTask/Outputs/DefaultOutputs.tsx | 35 ++++++++++ .../next/OngoingTask/Outputs/LinkOutputs.tsx | 70 +++++++++++++++++++ .../src/next/OngoingTask/Outputs/index.ts | 16 +++++ 4 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 plugins/scaffolder/src/next/OngoingTask/Outputs/DefaultOutputs.tsx create mode 100644 plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx create mode 100644 plugins/scaffolder/src/next/OngoingTask/Outputs/index.ts diff --git a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx index 68e05f29e2..15669469fe 100644 --- a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx @@ -24,6 +24,7 @@ import { TaskLogStream } from './TaskLogStream'; import { nextSelectedTemplateRouteRef } from '../routes'; import { useRouteRef } from '@backstage/core-plugin-api'; import qs from 'qs'; +import { DefaultOutputs } from './Outputs'; export const OngoingTask = () => { // todo(blam): check that task Id actually exists, and that it's valid. otherwise redirect to something more useful. @@ -108,7 +109,7 @@ export const OngoingTask = () => { - + { - {logsVisible ? ( diff --git a/plugins/scaffolder/src/next/OngoingTask/Outputs/DefaultOutputs.tsx b/plugins/scaffolder/src/next/OngoingTask/Outputs/DefaultOutputs.tsx new file mode 100644 index 0000000000..39bf89e4c5 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/Outputs/DefaultOutputs.tsx @@ -0,0 +1,35 @@ +/* + * Copyright 2023 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 { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; +import { Box, Paper } from '@material-ui/core'; +import { LinkOutputs } from './LinkOutputs'; + +export const DefaultOutputs = (props: { output?: ScaffolderTaskOutput }) => { + if (!props.output?.links) { + return null; + } + + return ( + + + + + + + + ); +}; diff --git a/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx b/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx new file mode 100644 index 0000000000..5d0f9c76fd --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx @@ -0,0 +1,70 @@ +/* + * Copyright 2023 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 { IconComponent, useApp, useRouteRef } from '@backstage/core-plugin-api'; +import { entityRouteRef } from '@backstage/plugin-catalog-react'; +import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; +import { Box, Button, makeStyles, Link } from '@material-ui/core'; +import React from 'react'; +import WebIcon from '@material-ui/icons/Web'; +import { parseEntityRef } from '@backstage/catalog-model'; + +const useStyles = makeStyles({ + root: { + '&:hover': { + textDecoration: 'none', + }, + }, +}); + +export const LinkOutputs = (props: { output: ScaffolderTaskOutput }) => { + const { links = [] } = props.output; + const classes = useStyles(); + const app = useApp(); + const entityRoute = useRouteRef(entityRouteRef); + + const iconResolver = (key?: string): IconComponent => + app.getSystemIcon(key!) ?? WebIcon; + + return ( + <> + {links + .filter(({ url, entityRef }) => url || entityRef) + .map(({ url, entityRef, title, icon }) => { + if (entityRef) { + const entityName = parseEntityRef(entityRef); + const target = entityRoute(entityName); + return { title, icon, url: target }; + } + return { title, icon, url: url! }; + }) + .map(({ url, title, icon }, i) => { + const Icon = iconResolver(icon); + return ( + } + > + {title} + + ); + })} + + ); +}; diff --git a/plugins/scaffolder/src/next/OngoingTask/Outputs/index.ts b/plugins/scaffolder/src/next/OngoingTask/Outputs/index.ts new file mode 100644 index 0000000000..647f1eebb2 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/Outputs/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 { DefaultOutputs } from './DefaultOutputs'; From 468cbbf55f3a6ed12f1f3503a4d21faeb8bbf619 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 31 Jan 2023 13:46:07 +0100 Subject: [PATCH 266/423] chore: reset some files Signed-off-by: blam --- app-config.yaml | 6 --- packages/backend/src/plugins/scaffolder.ts | 28 +------------- packages/backend/test-template.yaml | 37 ------------------- .../default-app/app-config.local.yaml | 4 -- 4 files changed, 1 insertion(+), 74 deletions(-) delete mode 100644 packages/backend/test-template.yaml diff --git a/app-config.yaml b/app-config.yaml index 2eed4762ce..dd72051189 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -255,12 +255,6 @@ catalog: # Backstage example entities - type: file target: ../catalog-model/examples/all.yaml - - - type: file - target: ./test-template.yaml - rules: - - allow: [Template] - # Backstage example groups and users - type: file target: ../catalog-model/examples/acme-corp.yaml diff --git a/packages/backend/src/plugins/scaffolder.ts b/packages/backend/src/plugins/scaffolder.ts index b6275e9883..d079b64c28 100644 --- a/packages/backend/src/plugins/scaffolder.ts +++ b/packages/backend/src/plugins/scaffolder.ts @@ -15,12 +15,7 @@ */ import { CatalogClient } from '@backstage/catalog-client'; -import { ScmIntegrations } from '@backstage/integration'; -import { - createRouter, - createTemplateAction, - createBuiltinActions, -} from '@backstage/plugin-scaffolder-backend'; +import { createRouter } from '@backstage/plugin-scaffolder-backend'; import { Router } from 'express'; import type { PluginEnvironment } from '../types'; @@ -31,26 +26,6 @@ export default async function createPlugin( discoveryApi: env.discovery, }); - const defaultActions = createBuiltinActions({ - catalogClient, - reader: env.reader, - config: env.config, - integrations: ScmIntegrations.fromConfig(env.config), - }); - - const delayAction = createTemplateAction({ - id: 'mock:delay', - async handler(ctx) { - const interval = setInterval( - () => ctx.logger.info('Writing something', new Date().toISOString()), - 1000, - ); - - await new Promise(resolve => setTimeout(resolve, 5000)); - clearTimeout(interval); - }, - }); - return await createRouter({ logger: env.logger, config: env.config, @@ -59,6 +34,5 @@ export default async function createPlugin( reader: env.reader, identity: env.identity, scheduler: env.scheduler, - actions: [...defaultActions, delayAction], }); } diff --git a/packages/backend/test-template.yaml b/packages/backend/test-template.yaml deleted file mode 100644 index 13a002e0b9..0000000000 --- a/packages/backend/test-template.yaml +++ /dev/null @@ -1,37 +0,0 @@ -apiVersion: scaffolder.backstage.io/v1beta3 -# https://backstage.io/docs/features/software-catalog/descriptor-format#kind-template -kind: Template -metadata: - name: example-delay-tempalte - title: Delay template - description: An example template for the scaffolder that creates a simple Node.js service -spec: - type: service - - parameters: [] - - steps: - - id: delay1 - name: Delay 1 - action: mock:delay - - - id: delay2 - name: Delay 2 - action: mock:delay - - - id: delay3 - name: Delay 3 - action: mock:delay - - - id: delay4 - name: Delay 4 - action: mock:delay - - - id: delay5 - if: true - name: Delay 5 - action: mock:delay - - - id: delay6 - name: Delay 6 - action: mock:delay diff --git a/packages/create-app/templates/default-app/app-config.local.yaml b/packages/create-app/templates/default-app/app-config.local.yaml index 6b4dcd0327..976293b546 100644 --- a/packages/create-app/templates/default-app/app-config.local.yaml +++ b/packages/create-app/templates/default-app/app-config.local.yaml @@ -1,5 +1 @@ # Backstage override configuration for your local development environment -catalog: - locations: - - type: file - target: ./test-template.yaml From 2d66fca317d0b2014127853b85b850b9a2f7d718 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 31 Jan 2023 13:50:28 +0100 Subject: [PATCH 267/423] chore: changelog Signed-off-by: blam --- packages/core-components/api-report.md | 1 + plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index 721c208406..f720e0305d 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -693,6 +693,7 @@ export interface LogViewerProps { classes?: { root?: string; }; + tail?: boolean; text: string; } diff --git a/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx b/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx index 5d0f9c76fd..596e91d5ab 100644 --- a/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx @@ -16,7 +16,7 @@ import { IconComponent, useApp, useRouteRef } from '@backstage/core-plugin-api'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; -import { Box, Button, makeStyles, Link } from '@material-ui/core'; +import { Button, makeStyles, Link } from '@material-ui/core'; import React from 'react'; import WebIcon from '@material-ui/icons/Web'; import { parseEntityRef } from '@backstage/catalog-model'; From b46f385effdf4928df5968e95bbc2077e7f6d3a0 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 31 Jan 2023 13:51:26 +0100 Subject: [PATCH 268/423] chore: add changeset Signed-off-by: blam --- .changeset/eleven-shoes-crash.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/eleven-shoes-crash.md diff --git a/.changeset/eleven-shoes-crash.md b/.changeset/eleven-shoes-crash.md new file mode 100644 index 0000000000..8013f311d5 --- /dev/null +++ b/.changeset/eleven-shoes-crash.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder-react': patch +'@backstage/plugin-scaffolder': patch +--- + +scaffolder/next: Implementing a simple `OngoingTask` page From ce0866d2e94c243ddc4bd0ba8f1e311d55a6d042 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 31 Jan 2023 16:26:15 +0100 Subject: [PATCH 269/423] chore: writing some tests for the new components Signed-off-by: blam --- .../src/next/OngoingTask/TaskBorder.test.tsx | 40 ++++++++++ .../src/next/OngoingTask/TaskBorder.tsx | 9 +-- .../next/OngoingTask/TaskLogStream.test.tsx | 50 ++++++++++++ .../src/next/OngoingTask/TaskLogStream.tsx | 4 +- .../OngoingTask/TaskSteps/StepTime.test.tsx | 79 +++++++++++++++++++ .../next/OngoingTask/TaskSteps/StepTime.tsx | 5 +- 6 files changed, 176 insertions(+), 11 deletions(-) create mode 100644 plugins/scaffolder/src/next/OngoingTask/TaskBorder.test.tsx create mode 100644 plugins/scaffolder/src/next/OngoingTask/TaskLogStream.test.tsx create mode 100644 plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.test.tsx diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskBorder.test.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskBorder.test.tsx new file mode 100644 index 0000000000..f3a59ad344 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskBorder.test.tsx @@ -0,0 +1,40 @@ +/* + * Copyright 2023 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 { TaskBorder } from './TaskBorder'; +import { render } from '@testing-library/react'; + +describe('TaskBorder', () => { + it('should render a pending linear progress if the task is not complete', () => { + const { getByRole } = render( + , + ); + + const progressBar = getByRole('progressbar'); + + expect(progressBar).toBeInTheDocument(); + expect(progressBar).toHaveClass('MuiLinearProgress-indeterminate'); + }); + + it('should render a determinate progress bar if the task is complete', () => { + const { getByRole } = render(); + + const progressBar = getByRole('progressbar'); + + expect(progressBar).toBeInTheDocument(); + expect(progressBar).toHaveClass('MuiLinearProgress-determinate'); + }); +}); diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx index ada4db1240..fdfab17367 100644 --- a/plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx @@ -26,23 +26,20 @@ const useStyles = makeStyles((theme: BackstageTheme) => ({ }, })); -export const TaskBorder = ({ - isComplete, - isError, -}: { +export const TaskBorder = (props: { isComplete: boolean; isError: boolean; }) => { const styles = useStyles(); - if (!isComplete) { + if (!props.isComplete) { return ; } return ( ); diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.test.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.test.tsx new file mode 100644 index 0000000000..e8f9e67e96 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.test.tsx @@ -0,0 +1,50 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { renderInTestApp } from '@backstage/test-utils'; +import React, { ReactNode } from 'react'; +import { TaskLogStream } from './TaskLogStream'; + +// The inside needs mocking to render in jsdom +jest.mock('react-virtualized-auto-sizer', () => ({ + __esModule: true, + default: (props: { + children: (size: { width: number; height: number }) => ReactNode; + }) => <>{props.children({ width: 400, height: 200 })}, +})); + +describe('TaskLogStream', () => { + it('should render a log stream with the correct log lines', async () => { + const logs = { step: ['line 1', 'line 2'], step2: ['line 3'] }; + + const { findByText } = await renderInTestApp(); + + const logLines = Object.values(logs).flat(); + + for (const line of logLines) { + await expect(findByText(line)).resolves.toBeInTheDocument(); + } + }); + + it('should filter out empty log lines', async () => { + const logs = { step: ['line 1', 'line 2'], step2: [] }; + + const { findAllByRole } = await renderInTestApp( + , + ); + + await expect(findAllByRole('row')).resolves.toHaveLength(2); + }); +}); diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx index 65c0022e1d..2cfcdf1da6 100644 --- a/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx @@ -25,13 +25,13 @@ const useStyles = makeStyles({ }, }); -export const TaskLogStream = (opts: { logs: { [k: string]: string[] } }) => { +export const TaskLogStream = (props: { logs: { [k: string]: string[] } }) => { const styles = useStyles(); return (
    l.join('\n')) .filter(Boolean) .join('\n')} diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.test.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.test.tsx new file mode 100644 index 0000000000..185d2fa7fb --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.test.tsx @@ -0,0 +1,79 @@ +/* + * Copyright 2023 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 { StepTime } from './StepTime'; +import { render, act } from '@testing-library/react'; + +describe('StepTime', () => { + it('should return empty when there is no start time', () => { + const step = { + id: 'test', + startedAt: undefined, + endedAt: undefined, + name: 'test', + }; + + const { container } = render(); + + expect(container.querySelector('span')?.textContent).toBe(''); + }); + + it('should format the time between the start and end date properly', async () => { + const step = { + id: 'test', + startedAt: '2021-01-01T00:00:00Z', + endedAt: '2021-01-01T00:00:01Z', + name: 'test', + }; + + const { findByText } = render(); + + await expect(findByText('1 second')).resolves.toBeInTheDocument(); + }); + + describe('updates', () => { + beforeEach(() => { + jest.useFakeTimers({ now: new Date('2021-01-01T00:00:00Z') }); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + it('should update the time every second', async () => { + const step = { + id: 'test', + startedAt: '2021-01-01T00:00:00Z', + endedAt: undefined, + name: 'test', + }; + + const { findByText } = render(); + + await expect(findByText('0 seconds')).resolves.toBeInTheDocument(); + + act(() => jest.advanceTimersByTime(1000)); + + await expect(findByText('1 second')).resolves.toBeInTheDocument(); + + act(() => jest.advanceTimersByTime(1000 * 60)); + + await expect( + findByText('1 minute, 1 second'), + ).resolves.toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx index 746007a7d3..2ec89f385a 100644 --- a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx @@ -19,9 +19,7 @@ import { DateTime, Interval } from 'luxon'; import humanizeDuration from 'humanize-duration'; import { Typography } from '@material-ui/core'; -export const StepTime = ({ - step, -}: { +export const StepTime = (props: { step: { id: string; name: string; @@ -30,6 +28,7 @@ export const StepTime = ({ }; }) => { const [time, setTime] = useState(''); + const { step } = props; const calculate = useCallback(() => { if (!step.startedAt) { From f08364291e9ff6ce0fadbe98a527fd75444b0ad9 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 31 Jan 2023 16:34:00 +0100 Subject: [PATCH 270/423] chore: more test Signed-off-by: blam Signed-off-by: blam --- .../OngoingTask/TaskSteps/TaskSteps.test.tsx | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.test.tsx diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.test.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.test.tsx new file mode 100644 index 0000000000..afd1f58190 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.test.tsx @@ -0,0 +1,64 @@ +/* + * Copyright 2023 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 { TaskSteps } from './TaskSteps'; +import { ScaffolderTaskStatus } from '@backstage/plugin-scaffolder-react'; +import { renderInTestApp } from '@backstage/test-utils'; + +describe('TaskSteps', () => { + it('should render each of the steps', async () => { + const steps = [ + { + id: '1', + name: 'Step 1', + status: 'processing' as ScaffolderTaskStatus, + startedAt: Date.now().toLocaleString(), + action: 'create', + }, + { + id: '2', + name: 'Step 2', + status: 'failed' as ScaffolderTaskStatus, + + startedAt: Date.now().toLocaleString(), + endedAt: Date.now().toLocaleString(), + action: 'create', + }, + { + id: '3', + name: 'Step 3', + status: 'completed' as ScaffolderTaskStatus, + startedAt: Date.now().toLocaleString(), + endedAt: Date.now().toLocaleString(), + action: 'create', + }, + { + id: '4', + name: 'Step 4', + status: 'skipped' as ScaffolderTaskStatus, + startedAt: Date.now().toLocaleString(), + endedAt: Date.now().toLocaleString(), + action: 'create', + }, + ]; + + const { getByText } = await renderInTestApp(); + + for (const step of steps) { + expect(getByText(step.name)).toBeInTheDocument(); + } + }); +}); From ba679976efb0257479386a75fa795d7b5df87ea9 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 3 Feb 2023 15:15:30 +0100 Subject: [PATCH 271/423] chore: use the backstage link component instead and wrap a div instead Signed-off-by: blam --- .../src/next/OngoingTask/Outputs/LinkOutputs.tsx | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx b/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx index 596e91d5ab..d7c5ad0b67 100644 --- a/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx @@ -16,10 +16,11 @@ import { IconComponent, useApp, useRouteRef } from '@backstage/core-plugin-api'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; -import { Button, makeStyles, Link } from '@material-ui/core'; +import { Button, makeStyles } from '@material-ui/core'; import React from 'react'; import WebIcon from '@material-ui/icons/Web'; import { parseEntityRef } from '@backstage/catalog-model'; +import { Link } from '@backstage/core-components'; const useStyles = makeStyles({ root: { @@ -53,15 +54,10 @@ export const LinkOutputs = (props: { output: ScaffolderTaskOutput }) => { .map(({ url, title, icon }, i) => { const Icon = iconResolver(icon); return ( - } - > - {title} + + ); })} From cb25785e251a941c21556f9c8163da809c4bece7 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 3 Feb 2023 16:00:08 +0100 Subject: [PATCH 272/423] chore: move the buttons to the contextmenu instead Signed-off-by: blam --- .../src/next/OngoingTask/ContextMenu.tsx | 87 +++++++++++++++++++ .../src/next/OngoingTask/OngoingTask.tsx | 35 +++----- 2 files changed, 98 insertions(+), 24 deletions(-) create mode 100644 plugins/scaffolder/src/next/OngoingTask/ContextMenu.tsx diff --git a/plugins/scaffolder/src/next/OngoingTask/ContextMenu.tsx b/plugins/scaffolder/src/next/OngoingTask/ContextMenu.tsx new file mode 100644 index 0000000000..d4c771a9f8 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/ContextMenu.tsx @@ -0,0 +1,87 @@ +/* + * Copyright 2023 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 { BackstageTheme } from '@backstage/theme'; +import { + IconButton, + ListItemIcon, + ListItemText, + makeStyles, + MenuItem, + MenuList, + Popover, +} from '@material-ui/core'; +import Retry from '@material-ui/icons/Repeat'; +import Toc from '@material-ui/icons/Toc'; +import MoreVert from '@material-ui/icons/MoreVert'; +import React, { useState } from 'react'; + +type ContextMenuProps = { + logsVisible?: boolean; + onToggleLogs?: (state: boolean) => void; + onStartOver?: () => void; +}; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + button: { + color: theme.palette.common.white, + }, +})); + +export const ContextMenu = (props: ContextMenuProps) => { + const { logsVisible, onToggleLogs, onStartOver } = props; + const classes = useStyles(); + const [anchorEl, setAnchorEl] = useState(); + + return ( + <> + ) => { + setAnchorEl(event.currentTarget); + }} + data-testid="menu-button" + color="inherit" + className={classes.button} + > + + + setAnchorEl(undefined)} + anchorEl={anchorEl} + anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} + transformOrigin={{ vertical: 'top', horizontal: 'right' }} + > + + onToggleLogs?.(!logsVisible)}> + + + + + + + + + + + + + + + ); +}; diff --git a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx index 15669469fe..a146780683 100644 --- a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx @@ -25,6 +25,7 @@ import { nextSelectedTemplateRouteRef } from '../routes'; import { useRouteRef } from '@backstage/core-plugin-api'; import qs from 'qs'; import { DefaultOutputs } from './Outputs'; +import { ContextMenu } from './ContextMenu'; export const OngoingTask = () => { // todo(blam): check that task Id actually exists, and that it's valid. otherwise redirect to something more useful. @@ -41,11 +42,11 @@ export const OngoingTask = () => { [taskStream], ); - const [logsVisible, setLogsVisible] = useState(false); + const [logsVisible, setLogVisibleState] = useState(false); useEffect(() => { if (taskStream.error) { - setLogsVisible(true); + setLogVisibleState(true); } }, [taskStream.error]); @@ -96,7 +97,13 @@ export const OngoingTask = () => {
    } subtitle={`Task ${taskId}`} - /> + > + +
    @@ -110,27 +117,7 @@ export const OngoingTask = () => { - - - - - - - - + {logsVisible ? ( From 7dcd44286df2b62d03b2ca42a7a96dda112148e1 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 6 Feb 2023 21:34:47 +0100 Subject: [PATCH 273/423] chore: removing the tail functionality for now Signed-off-by: blam Signed-off-by: blam --- packages/core-components/api-report.md | 1 - .../core-components/src/components/LogViewer/LogViewer.tsx | 4 ---- .../src/components/LogViewer/RealLogViewer.tsx | 7 ------- 3 files changed, 12 deletions(-) diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index f720e0305d..721c208406 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -693,7 +693,6 @@ export interface LogViewerProps { classes?: { root?: string; }; - tail?: boolean; text: string; } diff --git a/packages/core-components/src/components/LogViewer/LogViewer.tsx b/packages/core-components/src/components/LogViewer/LogViewer.tsx index f1396eef36..20530cffaf 100644 --- a/packages/core-components/src/components/LogViewer/LogViewer.tsx +++ b/packages/core-components/src/components/LogViewer/LogViewer.tsx @@ -39,10 +39,6 @@ export interface LogViewerProps { classes?: { root?: string; }; - /** - * Whether the LogViewer should automatically scroll to the bottom of the log. - */ - tail?: boolean; } /** diff --git a/packages/core-components/src/components/LogViewer/RealLogViewer.tsx b/packages/core-components/src/components/LogViewer/RealLogViewer.tsx index d211399c69..59e0bea44b 100644 --- a/packages/core-components/src/components/LogViewer/RealLogViewer.tsx +++ b/packages/core-components/src/components/LogViewer/RealLogViewer.tsx @@ -32,7 +32,6 @@ import { useLogViewerSelection } from './useLogViewerSelection'; export interface RealLogViewerProps { text: string; classes?: { root?: string }; - tail?: boolean; } export function RealLogViewer(props: RealLogViewerProps) { @@ -53,12 +52,6 @@ export function RealLogViewer(props: RealLogViewerProps) { } }, [search.resultLine]); - useEffect(() => { - if (props.tail && listRef.current) { - listRef.current.scrollToItem(lines.length - 1, 'center'); - } - }, [lines.length, props.tail]); - useEffect(() => { if (location.hash) { // #line-6 -> 6 From ec83fd4616568f32ff1eecb2e9337fb303fd140f Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 6 Feb 2023 21:35:36 +0100 Subject: [PATCH 274/423] chore: removing changeset Signed-off-by: blam --- .changeset/nasty-students-double.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changeset/nasty-students-double.md diff --git a/.changeset/nasty-students-double.md b/.changeset/nasty-students-double.md deleted file mode 100644 index d552fdf91e..0000000000 --- a/.changeset/nasty-students-double.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Added the ability to tail the `LogViewer` logs From 3887621d5d00aca9aa9319b484428c4f80a7d225 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 6 Feb 2023 21:35:48 +0100 Subject: [PATCH 275/423] chore: added the error panel Signed-off-by: blam --- .../src/next/OngoingTask/OngoingTask.tsx | 24 ++++++++++++++++--- .../src/next/OngoingTask/TaskLogStream.tsx | 1 - .../next/OngoingTask/TaskSteps/TaskSteps.tsx | 5 ++-- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx index a146780683..e166a96dd7 100644 --- a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx @@ -14,10 +14,10 @@ * limitations under the License. */ import React, { useEffect, useMemo, useState, useCallback } from 'react'; -import { Page, Header, Content } from '@backstage/core-components'; +import { Page, Header, Content, ErrorPanel } from '@backstage/core-components'; import { useTaskEventStream } from '../../components/hooks/useEventStream'; import { useNavigate, useParams } from 'react-router-dom'; -import { Box, Button, Paper } from '@material-ui/core'; +import { Box, makeStyles, Paper } from '@material-ui/core'; import { TaskSteps } from './TaskSteps'; import { TaskBorder } from './TaskBorder'; import { TaskLogStream } from './TaskLogStream'; @@ -27,12 +27,20 @@ import qs from 'qs'; import { DefaultOutputs } from './Outputs'; import { ContextMenu } from './ContextMenu'; +const useStyles = makeStyles({ + contentWrapper: { + display: 'flex', + flexDirection: 'column', + }, +}); + export const OngoingTask = () => { // todo(blam): check that task Id actually exists, and that it's valid. otherwise redirect to something more useful. const { taskId } = useParams(); const templateRouteRef = useRouteRef(nextSelectedTemplateRouteRef); const navigate = useNavigate(); const taskStream = useTaskEventStream(taskId!); + const classes = useStyles(); const steps = useMemo( () => taskStream.task?.spec.steps.map(step => ({ @@ -104,7 +112,16 @@ export const OngoingTask = () => { logsVisible={logsVisible} />
    - + + {taskStream.error ? ( + + + + ) : null} + { + {logsVisible ? ( diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx index 2cfcdf1da6..00e8452b42 100644 --- a/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx @@ -30,7 +30,6 @@ export const TaskLogStream = (props: { logs: { [k: string]: string[] } }) => { return (
    l.join('\n')) .filter(Boolean) diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.tsx index 40f9f9c189..7cf5ed71bf 100644 --- a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.tsx @@ -20,6 +20,7 @@ import { StepButton as MuiStepButton, StepLabel as MuiStepLabel, StepIconProps, + Box, } from '@material-ui/core'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; import { Step } from '../../../components/hooks/useEventStream'; @@ -29,7 +30,6 @@ import { StepTime } from './StepTime'; interface StepperProps { steps: (TaskStep & Step)[]; activeStep?: number; - setActiveStep?: (step: number) => void; } export const TaskSteps = (props: StepperProps) => { @@ -58,8 +58,7 @@ export const TaskSteps = (props: StepperProps) => { StepIconProps={stepIconProps} StepIconComponent={StepIcon} > - {step.name} -
    + {step.name} From 33b6ed5a5a6c5ca92aa81d69a6c303fd1d3da321 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 6 Feb 2023 21:52:15 +0100 Subject: [PATCH 276/423] chore: moving the outputs around and fixing some navigation] Signed-off-by: blam --- .../DefaultTemplateOutputs.tsx} | 11 ++++++-- .../TemplateOutputs}/LinkOutputs.tsx | 2 +- .../next/components/TemplateOutputs}/index.ts | 2 +- .../src/next/components/index.ts | 1 + .../src/next/OngoingTask/OngoingTask.tsx | 15 ++++++++--- plugins/scaffolder/src/next/Router/Router.tsx | 26 +++++++++++++++++-- .../TemplateListPage/TemplateListPage.tsx | 10 ++++++- 7 files changed, 57 insertions(+), 10 deletions(-) rename plugins/{scaffolder/src/next/OngoingTask/Outputs/DefaultOutputs.tsx => scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx} (81%) rename plugins/{scaffolder/src/next/OngoingTask/Outputs => scaffolder-react/src/next/components/TemplateOutputs}/LinkOutputs.tsx (96%) rename plugins/{scaffolder/src/next/OngoingTask/Outputs => scaffolder-react/src/next/components/TemplateOutputs}/index.ts (90%) diff --git a/plugins/scaffolder/src/next/OngoingTask/Outputs/DefaultOutputs.tsx b/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx similarity index 81% rename from plugins/scaffolder/src/next/OngoingTask/Outputs/DefaultOutputs.tsx rename to plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx index 39bf89e4c5..5fbd3a5142 100644 --- a/plugins/scaffolder/src/next/OngoingTask/Outputs/DefaultOutputs.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx @@ -14,11 +14,18 @@ * limitations under the License. */ import React from 'react'; -import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; import { Box, Paper } from '@material-ui/core'; import { LinkOutputs } from './LinkOutputs'; +import { ScaffolderTaskOutput } from '../../../api'; -export const DefaultOutputs = (props: { output?: ScaffolderTaskOutput }) => { +/** + * The DefaultOutputs renderer for the scaffolder task output + * + * @alpha + */ +export const DefaultTemplateOutputs = (props: { + output?: ScaffolderTaskOutput; +}) => { if (!props.output?.links) { return null; } diff --git a/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx b/plugins/scaffolder-react/src/next/components/TemplateOutputs/LinkOutputs.tsx similarity index 96% rename from plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx rename to plugins/scaffolder-react/src/next/components/TemplateOutputs/LinkOutputs.tsx index d7c5ad0b67..d172aa9cb3 100644 --- a/plugins/scaffolder/src/next/OngoingTask/Outputs/LinkOutputs.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/LinkOutputs.tsx @@ -15,12 +15,12 @@ */ import { IconComponent, useApp, useRouteRef } from '@backstage/core-plugin-api'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; -import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; import { Button, makeStyles } from '@material-ui/core'; import React from 'react'; import WebIcon from '@material-ui/icons/Web'; import { parseEntityRef } from '@backstage/catalog-model'; import { Link } from '@backstage/core-components'; +import { ScaffolderTaskOutput } from '../../../api'; const useStyles = makeStyles({ root: { diff --git a/plugins/scaffolder/src/next/OngoingTask/Outputs/index.ts b/plugins/scaffolder-react/src/next/components/TemplateOutputs/index.ts similarity index 90% rename from plugins/scaffolder/src/next/OngoingTask/Outputs/index.ts rename to plugins/scaffolder-react/src/next/components/TemplateOutputs/index.ts index 647f1eebb2..1c998eb1b9 100644 --- a/plugins/scaffolder/src/next/OngoingTask/Outputs/index.ts +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { DefaultOutputs } from './DefaultOutputs'; +export { DefaultTemplateOutputs } from './DefaultTemplateOutputs'; diff --git a/plugins/scaffolder-react/src/next/components/index.ts b/plugins/scaffolder-react/src/next/components/index.ts index babe3b4dcb..05e5a1105a 100644 --- a/plugins/scaffolder-react/src/next/components/index.ts +++ b/plugins/scaffolder-react/src/next/components/index.ts @@ -18,3 +18,4 @@ export * from './TemplateCard'; export * from './ReviewState'; export * from './TemplateGroup'; export * from './Workflow'; +export * from './TemplateOutputs'; diff --git a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx index e166a96dd7..a68df01ed5 100644 --- a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx @@ -24,8 +24,11 @@ import { TaskLogStream } from './TaskLogStream'; import { nextSelectedTemplateRouteRef } from '../routes'; import { useRouteRef } from '@backstage/core-plugin-api'; import qs from 'qs'; -import { DefaultOutputs } from './Outputs'; import { ContextMenu } from './ContextMenu'; +import { + DefaultTemplateOutputs, + ScaffolderTaskOutput, +} from '@backstage/plugin-scaffolder-react'; const useStyles = makeStyles({ contentWrapper: { @@ -34,7 +37,11 @@ const useStyles = makeStyles({ }, }); -export const OngoingTask = () => { +export const OngoingTask = (props: { + TemplateOutputsComponent?: React.ComponentType<{ + output?: ScaffolderTaskOutput; + }>; +}) => { // todo(blam): check that task Id actually exists, and that it's valid. otherwise redirect to something more useful. const { taskId } = useParams(); const templateRouteRef = useRouteRef(nextSelectedTemplateRouteRef); @@ -92,6 +99,8 @@ export const OngoingTask = () => { templateRouteRef, ]); + const Outputs = props.TemplateOutputsComponent ?? DefaultTemplateOutputs; + const templateName = taskStream.task?.spec.templateInfo?.entity?.metadata.name; @@ -134,7 +143,7 @@ export const OngoingTask = () => { - + {logsVisible ? ( diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index b9c18f9d02..6ac8bbff65 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -19,6 +19,7 @@ import { TemplateListPage } from '../TemplateListPage'; import { TemplateWizardPage } from '../TemplateWizardPage'; import { NextFieldExtensionOptions, + ScaffolderTaskOutput, SecretsContextProvider, useCustomFieldExtensions, useCustomLayouts, @@ -47,9 +48,21 @@ export type NextRouterProps = { template: TemplateEntityV1beta3; }>; TaskPageComponent?: React.ComponentType<{}>; + TemplateOutputsComponent?: React.ComponentType<{ + output?: ScaffolderTaskOutput; + }>; }; groups?: TemplateGroupFilter[]; + // todo(blam): rename this to formProps FormProps?: FormProps; + contextMenu?: { + /** Whether to show a link to the template editor */ + editor?: boolean; + /** Whether to show a link to the actions documentation */ + actions?: boolean; + /** Whether to show a link to the tasks page */ + tasks?: boolean; + }; }; /** @@ -58,10 +71,13 @@ export type NextRouterProps = { * @alpha */ export const Router = (props: PropsWithChildren) => { - const { components: { TemplateCardComponent } = {} } = props; + const { + components: { TemplateCardComponent, TemplateOutputsComponent } = {}, + } = props; const outlet = useOutlet() || props.children; const customFieldExtensions = useCustomFieldExtensions(outlet); + const fieldExtensions = [ ...customFieldExtensions, ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter( @@ -81,6 +97,7 @@ export const Router = (props: PropsWithChildren) => { element={ } @@ -97,7 +114,12 @@ export const Router = (props: PropsWithChildren) => { } /> - } /> + + } + /> } diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx index 4eae84b866..3097bd98be 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx @@ -37,12 +37,18 @@ import { RegisterExistingButton } from './RegisterExistingButton'; import { useRouteRef } from '@backstage/core-plugin-api'; import { TemplateGroupFilter, TemplateGroups } from './TemplateGroups'; import { registerComponentRouteRef } from '../../routes'; +import { ScaffolderPageContextMenu } from '../../components/ScaffolderPage/ScaffolderPageContextMenu'; export type TemplateListPageProps = { TemplateCardComponent?: React.ComponentType<{ template: TemplateEntityV1beta3; }>; groups?: TemplateGroupFilter[]; + contextMenu?: { + editor?: boolean; + actions?: boolean; + tasks?: boolean; + }; }; const defaultGroup: TemplateGroupFilter = { @@ -61,7 +67,9 @@ export const TemplateListPage = (props: TemplateListPageProps) => { pageTitleOverride="Create a new component" title="Create a new component" subtitle="Create new software components using standard templates in your organization" - /> + > + +

    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 literal 0 HcmV?d00001 diff --git a/plugins/adr/src/api/types.ts b/plugins/adr/src/api/types.ts index e4632e171a..0af35cc6df 100644 --- a/plugins/adr/src/api/types.ts +++ b/plugins/adr/src/api/types.ts @@ -30,6 +30,15 @@ export type AdrFileInfo = { /** The name of the ADR file. */ name: string; + + /** The title of the ADR. */ + title?: string; + + /** The status of the ADR. */ + status?: string; + + /** The date of the ADR. */ + date?: string; }; /** diff --git a/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx b/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx index d1db286943..eb5b4aed21 100644 --- a/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx +++ b/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx @@ -35,6 +35,7 @@ import { } from '@backstage/plugin-adr-common'; import { useEntity } from '@backstage/plugin-catalog-react'; import { + Chip, Grid, List, ListItem, @@ -67,7 +68,9 @@ export const EntityAdrContent = (props: { const classes = useStyles(); const { entity } = useEntity(); const rootLink = useRouteRef(rootRouteRef); - const [adrList, setAdrList] = useState([]); + const [adrList, setAdrList] = useState< + { name: string; title?: string; status?: string; date?: string }[] + >([]); const [searchParams, setSearchParams] = useSearchParams(); const scmIntegrations = useApi(scmIntegrationsApiRef); const adrApi = useApi(adrApiRef); @@ -79,10 +82,10 @@ export const EntityAdrContent = (props: { }, [entity, scmIntegrations]); const selectedAdr = - adrList.find(adr => adr === searchParams.get('record')) ?? ''; + adrList.find(adr => adr.name === searchParams.get('record'))?.name ?? ''; useEffect(() => { if (adrList.length && !selectedAdr) { - searchParams.set('record', adrList[0]); + searchParams.set('record', adrList[0].name); setSearchParams(searchParams, { replace: true }); } }); @@ -100,11 +103,22 @@ export const EntityAdrContent = (props: { ? filePathFilterFn(item.name) : madrFilePathFilter(item.name)), ) - .map(({ name }: { name: string }) => name); + .map(({ name, title, status, date }) => ({ name, title, status, date })); setAdrList(adrs); }, [filePathFilterFn, value]); + const getChipColor = (status: string) => { + switch (status) { + case 'accepted': + return 'primary'; + case 'rejected' || 'deprecated': + return 'secondary'; + default: + return 'default'; + } + }; + return ( @@ -133,13 +147,24 @@ export const EntityAdrContent = (props: { key={idx} button component={Link} - to={`${rootLink()}?record=${adr}`} - selected={selectedAdr === adr} + to={`${rootLink()}?record=${adr.name}`} + selected={selectedAdr === adr.name} > + {adr.status && ( + + )} ))} From 4660b639475ff6d7806d7f5e69b0e3917d8d70a0 Mon Sep 17 00:00:00 2001 From: David Weber Date: Wed, 1 Feb 2023 19:44:09 +0100 Subject: [PATCH 213/423] feat: add TechDocs addon LightBox Signed-off-by: David Weber --- .changeset/silver-badgers-heal.md | 35 +++++++++ docs/features/techdocs/addons.md | 1 + packages/app/src/App.tsx | 2 + .../app/src/components/catalog/EntityPage.tsx | 2 + .../api-report.md | 3 + .../package.json | 1 + .../src/LigthBox/LightBox.test.tsx | 50 +++++++++++++ .../src/LigthBox/LightBox.tsx | 71 +++++++++++++++++++ .../src/LigthBox/index.ts | 16 +++++ .../src/LigthBox/lightbox.css | 7 ++ .../src/index.ts | 1 + .../src/plugin.ts | 47 ++++++++++++ .../TechDocsReaderPage/TechDocsReaderPage.tsx | 1 + yarn.lock | 8 +++ 14 files changed, 245 insertions(+) create mode 100644 .changeset/silver-badgers-heal.md create mode 100644 plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.test.tsx create mode 100644 plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.tsx create mode 100644 plugins/techdocs-module-addons-contrib/src/LigthBox/index.ts create mode 100644 plugins/techdocs-module-addons-contrib/src/LigthBox/lightbox.css diff --git a/.changeset/silver-badgers-heal.md b/.changeset/silver-badgers-heal.md new file mode 100644 index 0000000000..b1f239c3dc --- /dev/null +++ b/.changeset/silver-badgers-heal.md @@ -0,0 +1,35 @@ +--- +'@backstage/plugin-techdocs-module-addons-contrib': patch +'@backstage/plugin-techdocs': patch +--- + +Create a TechDocs `` addon that allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. + +Here's an example on how to use it in a Backstage app: + +```diff +import { + DefaultTechDocsHome, + TechDocsIndexPage, + TechDocsReaderPage, +} from '@backstage/plugin-techdocs'; +import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha'; ++import { LightBox } from '@backstage/plugin-techdocs-module-addons-contrib'; + +const AppRoutes = () => { + + // other plugin routes + }> + + + } + > + ++ + + + ; +}; +``` diff --git a/docs/features/techdocs/addons.md b/docs/features/techdocs/addons.md index fe1058b2ca..60999f599c 100644 --- a/docs/features/techdocs/addons.md +++ b/docs/features/techdocs/addons.md @@ -125,6 +125,7 @@ discover available Addons, we've compiled a list of them here: | [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.expandablenavigation) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. | | [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.reportissue) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. | | [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.textsize) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. | +| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.lightbox) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. The image size of the light-box image is the same as the image size on the document page. | Got an Addon to contribute? Feel free to add a row above! diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 8984a69259..f789328104 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -78,6 +78,7 @@ import { ExpandableNavigation, ReportIssue, TextSize, + LightBox, } from '@backstage/plugin-techdocs-module-addons-contrib'; import { SettingsLayout, @@ -203,6 +204,7 @@ const routes = ( + + ); diff --git a/plugins/techdocs-module-addons-contrib/api-report.md b/plugins/techdocs-module-addons-contrib/api-report.md index 68fad9121d..c242bb02f2 100644 --- a/plugins/techdocs-module-addons-contrib/api-report.md +++ b/plugins/techdocs-module-addons-contrib/api-report.md @@ -10,6 +10,9 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; // @public export const ExpandableNavigation: () => JSX.Element | null; +// @public +export const LightBox: () => JSX.Element | null; + // @public export const ReportIssue: (props: ReportIssueProps) => JSX.Element | null; diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 1b92e15c16..cd72b1a548 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -44,6 +44,7 @@ "@material-ui/lab": "4.0.0-alpha.57", "@react-hookz/web": "^20.0.0", "git-url-parse": "^13.0.0", + "photoswipe": "^5.3.5", "react-use": "^17.2.4" }, "peerDependencies": { diff --git a/plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.test.tsx b/plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.test.tsx new file mode 100644 index 0000000000..b63aed8777 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.test.tsx @@ -0,0 +1,50 @@ +/* + * 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 { TechDocsAddonTester } from '@backstage/plugin-techdocs-addons-test-utils'; + +import React from 'react'; + +import { LightBox } from '../plugin'; + +describe('LightBox', () => { + it('renders without exploding', async () => { + const { getByText } = await TechDocsAddonTester.buildAddonsInTechDocs([ + , + ]) + .withDom(TEST_CONTENT) + .renderWithEffects(); + + expect(getByText('TEST_CONTENT')).toBeInTheDocument(); + }); + + it('Add onclick event to images', async () => { + const { getByTestId } = await TechDocsAddonTester.buildAddonsInTechDocs([ + , + ]) + .withDom( + dog, + ) + .renderWithEffects(); + + expect(getByTestId('fixture').onclick).not.toBeUndefined(); + expect(getByTestId('fixture').onclick).toEqual(expect.any(Function)); + }); +}); diff --git a/plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.tsx b/plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.tsx new file mode 100644 index 0000000000..b74c2f9659 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.tsx @@ -0,0 +1,71 @@ +/* + * 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 { useEffect } from 'react'; +import { useShadowRootElements } from '@backstage/plugin-techdocs-react'; +// @ts-ignore +import PhotoSwipeLightbox, { DataSource } from 'photoswipe/lightbox'; +import PhotoSwipe from 'photoswipe'; +import 'photoswipe/style.css'; +import './lightbox.css'; + +export const LightBoxAddon = () => { + const images = useShadowRootElements(['img']); + + useEffect(() => { + let dataSourceImages: DataSource | null = null; + + let lightbox = new PhotoSwipeLightbox({ + pswpModule: PhotoSwipe, + wheelToZoom: true, + arrowPrevSVG: + '', + arrowNextSVG: + '', + closeSVG: + '', + zoomSVG: + '', + }); + + images.forEach((image, index) => { + image.onclick = () => { + if (dataSourceImages === null) { + dataSourceImages = images.map(dataSourceImage => { + return { + element: dataSourceImage, + src: dataSourceImage.src, + msrc: dataSourceImage.src, + alt: dataSourceImage.alt, + width: dataSourceImage.clientWidth, + height: dataSourceImage.clientHeight, + }; + }); + } + lightbox.loadAndOpen(index, dataSourceImages); + return false; + }; + }); + lightbox.init(); + + return () => { + lightbox.destroy(); + lightbox = null; + }; + }, [images]); + + return null; +}; diff --git a/plugins/techdocs-module-addons-contrib/src/LigthBox/index.ts b/plugins/techdocs-module-addons-contrib/src/LigthBox/index.ts new file mode 100644 index 0000000000..144359abb7 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/LigthBox/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 * from './LightBox'; diff --git a/plugins/techdocs-module-addons-contrib/src/LigthBox/lightbox.css b/plugins/techdocs-module-addons-contrib/src/LigthBox/lightbox.css new file mode 100644 index 0000000000..63170792f1 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/LigthBox/lightbox.css @@ -0,0 +1,7 @@ +.pswp { + --pswp-bg: #f8f8f8; +} +.pswp__counter { + color: rgba(0, 0, 0, 0.87); + text-shadow: none; +} diff --git a/plugins/techdocs-module-addons-contrib/src/index.ts b/plugins/techdocs-module-addons-contrib/src/index.ts index 528afe5c0d..bad7701486 100644 --- a/plugins/techdocs-module-addons-contrib/src/index.ts +++ b/plugins/techdocs-module-addons-contrib/src/index.ts @@ -25,6 +25,7 @@ export { ExpandableNavigation, ReportIssue, TextSize, + LightBox, } from './plugin'; export type { ReportIssueProps, diff --git a/plugins/techdocs-module-addons-contrib/src/plugin.ts b/plugins/techdocs-module-addons-contrib/src/plugin.ts index 6136f176d0..c4023a72af 100644 --- a/plugins/techdocs-module-addons-contrib/src/plugin.ts +++ b/plugins/techdocs-module-addons-contrib/src/plugin.ts @@ -22,6 +22,7 @@ import { import { ExpandableNavigationAddon } from './ExpandableNavigation'; import { ReportIssueAddon, ReportIssueProps } from './ReportIssue'; import { TextSizeAddon } from './TextSize'; +import { LightBoxAddon } from './LigthBox'; /** * The TechDocs addons contrib plugin @@ -203,3 +204,49 @@ export const TextSize = techdocsModuleAddonsContribPlugin.provide( component: TextSizeAddon, }), ); + +/** + * This TechDocs addon allows users to open images in a lightbox on documentation pages, they can navigate between images if there are several on one page. + * + * @remarks + * The image size of the lightbox image is the same as the image size on the document page. + * + * @example + * Here's a simple example: + * ``` + * import { + * DefaultTechDocsHome, + * TechDocsIndexPage, + * TechDocsReaderPage, + * } from '@backstage/plugin-techdocs'; + * import { TechDocsAddons } from '@backstage/plugin-techdocs-react'; + * import { LightBox } from '@backstage/plugin-techdocs-module-addons-contrib'; + * + * + * const AppRoutes = () => { + * + * // other plugin routes + * }> + * + * + * } + * > + * + * + * + * + * ; + * }; + * ``` + * + * @public + */ +export const LightBox = techdocsModuleAddonsContribPlugin.provide( + createTechDocsAddonExtension({ + name: 'LightBox', + location: TechDocsAddonLocations.Content, + component: LightBoxAddon, + }), +); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx index ffe95e0b7e..ea7e4ed77b 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx @@ -102,6 +102,7 @@ CONFIGURATION 4: and provided content in + diff --git a/yarn.lock b/yarn.lock index f042b70bf5..4a15b8cf09 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8225,6 +8225,7 @@ __metadata: cross-fetch: ^3.1.5 git-url-parse: ^13.0.0 msw: ^0.49.0 + photoswipe: ^5.3.5 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -31430,6 +31431,13 @@ __metadata: languageName: node linkType: hard +"photoswipe@npm:^5.3.5": + version: 5.3.5 + resolution: "photoswipe@npm:5.3.5" + checksum: bd3eafebffc114210b8e5403746b48a9bfe436cca05a65f8d5efd6eacea785a51f0f124d7326c8f651d754d76124c9768a920383843c4a619da582a86e535b27 + languageName: node + linkType: hard + "picocolors@npm:^1.0.0": version: 1.0.0 resolution: "picocolors@npm:1.0.0" From 86ee5f2ed84e01eb80f71670ddd3f0dca94d76e6 Mon Sep 17 00:00:00 2001 From: albertojuanL Date: Mon, 6 Feb 2023 19:38:58 +0100 Subject: [PATCH 214/423] Use title when exits or humanitizeEntityRef for the default catalog entities sorting Signed-off-by: albertojuanL --- .../components/CatalogTable/CatalogTable.tsx | 30 +++++-------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index e6f9d1458e..8cee912219 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -16,7 +16,6 @@ import { ANNOTATION_EDIT_URL, ANNOTATION_VIEW_URL, - DEFAULT_NAMESPACE, Entity, RELATION_OWNED_BY, RELATION_PART_OF, @@ -64,29 +63,16 @@ const YellowStar = withStyles({ }, })(Star); -const stringifySortingEntityRef = (ref: Entity): string => { - const kind = ref.kind; - const namespace = ref.metadata.namespace ?? DEFAULT_NAMESPACE; - const name = ref.metadata.title || ref.metadata.name; - - return `${kind.toLocaleLowerCase('en-US')}:${namespace.toLocaleLowerCase( - 'en-US', - )}/${name.toLocaleLowerCase('en-US')}`; -}; - const refCompare = (a: Entity, b: Entity) => { - // in case field filtering is used, these fields might not be part of the response - if ( - a.metadata?.name === undefined || - a.kind === undefined || - b.metadata?.name === undefined || - b.kind === undefined - ) { - return 0; - } + const toRef = (entity: Entity) => + entity.metadata.title?.toLocaleLowerCase('en-US') || + humanizeEntityRef(entity, { + defaultKind: 'Component', + }); + + const aRef = toRef(a); + const bRef = toRef(b); - const aRef = stringifySortingEntityRef(a); - const bRef = stringifySortingEntityRef(b); if (aRef < bRef) { return -1; } From 1cea9544d15fd6061339713db8f1b43c8124fd7e Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Mon, 6 Feb 2023 19:44:31 +0100 Subject: [PATCH 215/423] Update silly-buckets-joke.md Signed-off-by: Ben Lambert --- .changeset/silly-buckets-joke.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/silly-buckets-joke.md b/.changeset/silly-buckets-joke.md index bd77f2ed05..113272c965 100644 --- a/.changeset/silly-buckets-joke.md +++ b/.changeset/silly-buckets-joke.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog-backend-module-msgraph': patch --- -Fixed bug in readProviderConfig as it wasn't reading the user.select field expected from the app-config.yaml configuration +Fixed a bug reading the `user.select` field expected from the `app-config.yaml` configuration From 67ebd7f8a576638d34d37e184efc0abd6a2cfb34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C5=A0neberger?= Date: Mon, 6 Feb 2023 19:45:14 +0100 Subject: [PATCH 216/423] Fix URL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Šneberger --- plugins/tech-radar/src/sample.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tech-radar/src/sample.ts b/plugins/tech-radar/src/sample.ts index 1a6f372f64..395b4f2ff5 100644 --- a/plugins/tech-radar/src/sample.ts +++ b/plugins/tech-radar/src/sample.ts @@ -180,7 +180,7 @@ entries.push({ ], links: [ { - url: 'https://reactjs.org/', + url: 'https://github.com', title: 'Learn more', }, ], From 9d4a9598f418f7e1108cd4f6618e63ec89f2f8a0 Mon Sep 17 00:00:00 2001 From: albertojuanL Date: Mon, 6 Feb 2023 19:46:51 +0100 Subject: [PATCH 217/423] To sort correctly humanitizeEntityRef needs to be in lowercase Signed-off-by: albertojuanL --- plugins/catalog/src/components/CatalogTable/CatalogTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index 8cee912219..f8617ba4b2 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -68,7 +68,7 @@ const refCompare = (a: Entity, b: Entity) => { entity.metadata.title?.toLocaleLowerCase('en-US') || humanizeEntityRef(entity, { defaultKind: 'Component', - }); + }).toLocaleLowerCase('en-US'); const aRef = toRef(a); const bRef = toRef(b); From 95433b19875cf3070349bbaf8829ae1e160623c4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 6 Feb 2023 19:55:21 +0100 Subject: [PATCH 218/423] Apply suggestions from code review Co-authored-by: Ben Lambert Signed-off-by: Patrik Oldsberg --- .changeset/little-jars-lay.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.changeset/little-jars-lay.md b/.changeset/little-jars-lay.md index 161dc099e9..f8851f7adc 100644 --- a/.changeset/little-jars-lay.md +++ b/.changeset/little-jars-lay.md @@ -1,10 +1,6 @@ --- -'@internal/plugin-todo-list-backend': patch '@backstage/plugin-user-settings-backend': patch -'@backstage/backend-test-utils': patch '@backstage/plugin-scaffolder-backend': patch -'@backstage/backend-defaults': patch -'@backstage/backend-app-api': patch '@backstage/plugin-periskop-backend': patch '@backstage/backend-common': patch '@backstage/plugin-catalog-backend': patch From f99f81b25be391e3e1a9d18dfaef92b7e523c81a Mon Sep 17 00:00:00 2001 From: albertojuanL Date: Mon, 6 Feb 2023 20:01:37 +0100 Subject: [PATCH 219/423] Change to use the same way of sorting as the custom sorting Signed-off-by: albertojuanL --- .../src/components/CatalogTable/CatalogTable.tsx | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index f8617ba4b2..18080bb7b0 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -65,21 +65,12 @@ const YellowStar = withStyles({ const refCompare = (a: Entity, b: Entity) => { const toRef = (entity: Entity) => - entity.metadata.title?.toLocaleLowerCase('en-US') || + entity.metadata.title || humanizeEntityRef(entity, { defaultKind: 'Component', - }).toLocaleLowerCase('en-US'); + }); - const aRef = toRef(a); - const bRef = toRef(b); - - if (aRef < bRef) { - return -1; - } - if (aRef > bRef) { - return 1; - } - return 0; + return toRef(a).localeCompare(toRef(b)); }; /** @public */ From c1a19d2647b391e5565e442bf3f6dc89cf0a8164 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 6 Feb 2023 21:05:07 +0100 Subject: [PATCH 220/423] chore: fix api-reports Signed-off-by: blam --- packages/backend-plugin-api/api-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index baa2b1b7dc..a8174c042c 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -508,7 +508,7 @@ export interface ServiceRefConfig { // @public export interface SharedBackendEnvironment { // (undocumented) - $$type: 'SharedBackendEnvironment'; + $$type: '@backstage/SharedBackendEnvironment'; } // @public From 65ec06e9e7b76080a48b5e19d78688eb0edf0cdb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 20:31:49 +0000 Subject: [PATCH 221/423] chore(deps): update dependency esbuild to v0.17.6 Signed-off-by: Renovate Bot --- yarn.lock | 182 +++++++++++++++++++++++++++--------------------------- 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/yarn.lock b/yarn.lock index c9caa42b95..de12cf4659 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9231,9 +9231,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/android-arm64@npm:0.17.5" +"@esbuild/android-arm64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/android-arm64@npm:0.17.6" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -9245,65 +9245,65 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/android-arm@npm:0.17.5" +"@esbuild/android-arm@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/android-arm@npm:0.17.6" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/android-x64@npm:0.17.5" +"@esbuild/android-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/android-x64@npm:0.17.6" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/darwin-arm64@npm:0.17.5" +"@esbuild/darwin-arm64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/darwin-arm64@npm:0.17.6" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/darwin-x64@npm:0.17.5" +"@esbuild/darwin-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/darwin-x64@npm:0.17.6" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/freebsd-arm64@npm:0.17.5" +"@esbuild/freebsd-arm64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/freebsd-arm64@npm:0.17.6" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/freebsd-x64@npm:0.17.5" +"@esbuild/freebsd-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/freebsd-x64@npm:0.17.6" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-arm64@npm:0.17.5" +"@esbuild/linux-arm64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-arm64@npm:0.17.6" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-arm@npm:0.17.5" +"@esbuild/linux-arm@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-arm@npm:0.17.6" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-ia32@npm:0.17.5" +"@esbuild/linux-ia32@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-ia32@npm:0.17.6" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -9315,86 +9315,86 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-loong64@npm:0.17.5" +"@esbuild/linux-loong64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-loong64@npm:0.17.6" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-mips64el@npm:0.17.5" +"@esbuild/linux-mips64el@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-mips64el@npm:0.17.6" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-ppc64@npm:0.17.5" +"@esbuild/linux-ppc64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-ppc64@npm:0.17.6" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-riscv64@npm:0.17.5" +"@esbuild/linux-riscv64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-riscv64@npm:0.17.6" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-s390x@npm:0.17.5" +"@esbuild/linux-s390x@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-s390x@npm:0.17.6" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-x64@npm:0.17.5" +"@esbuild/linux-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-x64@npm:0.17.6" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/netbsd-x64@npm:0.17.5" +"@esbuild/netbsd-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/netbsd-x64@npm:0.17.6" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/openbsd-x64@npm:0.17.5" +"@esbuild/openbsd-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/openbsd-x64@npm:0.17.6" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/sunos-x64@npm:0.17.5" +"@esbuild/sunos-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/sunos-x64@npm:0.17.6" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/win32-arm64@npm:0.17.5" +"@esbuild/win32-arm64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/win32-arm64@npm:0.17.6" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/win32-ia32@npm:0.17.5" +"@esbuild/win32-ia32@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/win32-ia32@npm:0.17.6" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/win32-x64@npm:0.17.5" +"@esbuild/win32-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/win32-x64@npm:0.17.6" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -21470,31 +21470,31 @@ __metadata: linkType: hard "esbuild@npm:^0.17.0": - version: 0.17.5 - resolution: "esbuild@npm:0.17.5" + version: 0.17.6 + resolution: "esbuild@npm:0.17.6" dependencies: - "@esbuild/android-arm": 0.17.5 - "@esbuild/android-arm64": 0.17.5 - "@esbuild/android-x64": 0.17.5 - "@esbuild/darwin-arm64": 0.17.5 - "@esbuild/darwin-x64": 0.17.5 - "@esbuild/freebsd-arm64": 0.17.5 - "@esbuild/freebsd-x64": 0.17.5 - "@esbuild/linux-arm": 0.17.5 - "@esbuild/linux-arm64": 0.17.5 - "@esbuild/linux-ia32": 0.17.5 - "@esbuild/linux-loong64": 0.17.5 - "@esbuild/linux-mips64el": 0.17.5 - "@esbuild/linux-ppc64": 0.17.5 - "@esbuild/linux-riscv64": 0.17.5 - "@esbuild/linux-s390x": 0.17.5 - "@esbuild/linux-x64": 0.17.5 - "@esbuild/netbsd-x64": 0.17.5 - "@esbuild/openbsd-x64": 0.17.5 - "@esbuild/sunos-x64": 0.17.5 - "@esbuild/win32-arm64": 0.17.5 - "@esbuild/win32-ia32": 0.17.5 - "@esbuild/win32-x64": 0.17.5 + "@esbuild/android-arm": 0.17.6 + "@esbuild/android-arm64": 0.17.6 + "@esbuild/android-x64": 0.17.6 + "@esbuild/darwin-arm64": 0.17.6 + "@esbuild/darwin-x64": 0.17.6 + "@esbuild/freebsd-arm64": 0.17.6 + "@esbuild/freebsd-x64": 0.17.6 + "@esbuild/linux-arm": 0.17.6 + "@esbuild/linux-arm64": 0.17.6 + "@esbuild/linux-ia32": 0.17.6 + "@esbuild/linux-loong64": 0.17.6 + "@esbuild/linux-mips64el": 0.17.6 + "@esbuild/linux-ppc64": 0.17.6 + "@esbuild/linux-riscv64": 0.17.6 + "@esbuild/linux-s390x": 0.17.6 + "@esbuild/linux-x64": 0.17.6 + "@esbuild/netbsd-x64": 0.17.6 + "@esbuild/openbsd-x64": 0.17.6 + "@esbuild/sunos-x64": 0.17.6 + "@esbuild/win32-arm64": 0.17.6 + "@esbuild/win32-ia32": 0.17.6 + "@esbuild/win32-x64": 0.17.6 dependenciesMeta: "@esbuild/android-arm": optional: true @@ -21542,7 +21542,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 31829b46a0cad65f58d90d39b66fd32a2de820539dd8530199975e417aa0ecd63cfc340e402f4f4e9235906a1a05969ddac1d4ad1ba611a3f11c0f62516b9390 + checksum: 13c4c3bcaa7ff291810d2c8294a1eb997b4672c60a9285b32d8eafcbc552e4468e06efe9d1a15067f5cbd41adcb12ddb4362618845e2e916e437f281c9aa80ab languageName: node linkType: hard From 546bdf30b38adbe972d39c9239d6b80333977be0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 20:33:02 +0000 Subject: [PATCH 222/423] fix(deps): update dependency @graphql-tools/schema to v9.0.16 Signed-off-by: Renovate Bot --- yarn.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/yarn.lock b/yarn.lock index c9caa42b95..a3e3cdfcbe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10125,15 +10125,15 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/merge@npm:8.3.17, @graphql-tools/merge@npm:^8.2.6": - version: 8.3.17 - resolution: "@graphql-tools/merge@npm:8.3.17" +"@graphql-tools/merge@npm:8.3.18, @graphql-tools/merge@npm:^8.2.6": + version: 8.3.18 + resolution: "@graphql-tools/merge@npm:8.3.18" dependencies: - "@graphql-tools/utils": 9.2.0 + "@graphql-tools/utils": 9.2.1 tslib: ^2.4.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 943e1ad64575ab9ae6726d434cf7b08e80099442f9d25c1ac9f11fdac7bd0e8e73109f0e2469b47650ad0a0731ac850ede844b5ff8a7eab352027a42c1e78c79 + checksum: 0834fcf13dec5ee92e39f2e1b27a098654e2db20bf6ef6f43d7efce56b7d750caa59dd16aacb211b8f5a198d29c19d36471401762f5a34e0bc22657285dcae92 languageName: node linkType: hard @@ -10261,16 +10261,16 @@ __metadata: linkType: hard "@graphql-tools/schema@npm:^9.0.0": - version: 9.0.15 - resolution: "@graphql-tools/schema@npm:9.0.15" + version: 9.0.16 + resolution: "@graphql-tools/schema@npm:9.0.16" dependencies: - "@graphql-tools/merge": 8.3.17 - "@graphql-tools/utils": 9.2.0 + "@graphql-tools/merge": 8.3.18 + "@graphql-tools/utils": 9.2.1 tslib: ^2.4.0 value-or-promise: 1.0.12 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 4361cb1a355e8811fd9b762bd137a2f8fd287b05f03cb574bc3d5e6855aeceef462e72bacfa89dd9028138e9fe3cafc4d69c95d7f9a9b6ab7f037ca3e36f52a9 + checksum: ecbd27b4a36424c8d4b2206b1f2d2ec2cff3c66f52ec452b17977642017ca7f00df4df44f2d0426174ceea9596474d0656bc0227f4c1149f2288abb6d186cd68 languageName: node linkType: hard @@ -10363,15 +10363,15 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/utils@npm:9.2.0, @graphql-tools/utils@npm:^9.0.0, @graphql-tools/utils@npm:^9.1.1": - version: 9.2.0 - resolution: "@graphql-tools/utils@npm:9.2.0" +"@graphql-tools/utils@npm:9.2.1, @graphql-tools/utils@npm:^9.0.0, @graphql-tools/utils@npm:^9.1.1": + version: 9.2.1 + resolution: "@graphql-tools/utils@npm:9.2.1" dependencies: "@graphql-typed-document-node/core": ^3.1.1 tslib: ^2.4.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 9754f8c6d52490df395626cef224542f37ca040ced6688c8ad80b1e0498006186529a50ac21979465123debba093db33dbfe8f1f7a9101f969dec0f31dc9a45b + checksum: 94ed12df5f49e5c338322ffd931236a687a3d5c443bf499f9baab5d4fcd9792234111142be8aa506a01ca2e82732996c4e1d8f6159ff9cc7fdc5c97f63e55226 languageName: node linkType: hard From f3af36dc31eb36890eb6e8cfb9ae4faa622d1e0b Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Mon, 6 Feb 2023 11:31:42 +0000 Subject: [PATCH 223/423] add failing test to createAsyncValidators Signed-off-by: Paul Cowan --- .../Stepper/createAsyncValidators.test.ts | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index 6ad14e3cc4..ff7060222d 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -154,4 +154,83 @@ describe('createAsyncValidators', () => { }), }); }); + + it('should run validation on complex nested schemas', async () => { + const schema: JsonObject = { + title: 'Select component', + properties: { + actionType: { + title: 'action type', + type: 'string', + description: 'Select the action type', + enum: ['newThing', 'existingThing'], + enumNames: ['New thing', 'Existing thing'], + default: 'newThing', + }, + }, + required: ['actionType'], + dependencies: { + actionType: { + oneOf: [ + { + properties: { + actionType: { + enum: ['newThing'], + }, + general: { + title: 'General', + type: 'object', + properties: { + name: { + title: 'Name', + type: 'string', + 'ui:field': 'NameField', + }, + }, + }, + }, + }, + { + properties: { + actionType: { + enum: ['existingThing'], + }, + thingId: { + title: 'Thing id', + type: 'string', + description: 'Enter thing id', + }, + }, + }, + ], + }, + }, + }; + + const NameField: NextCustomFieldValidator = ( + value, + { addError }, + ) => { + if (!value) { + addError('something is broken here!'); + } + }; + + const validators = { + NameField: NameField as NextCustomFieldValidator, + }; + + const validate = createAsyncValidators(schema, validators, { + apiHolder: { get: jest.fn() }, + }); + + await validate({ + actionType: 'newThing', + general: { + name: undefined, + }, + }); + + expect(validators.NameField).toHaveBeenCalled(); + }); }); From 5555e1731349e55060b87d688f7ba6fa23077e88 Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Mon, 6 Feb 2023 14:34:09 +0000 Subject: [PATCH 224/423] refactor createAsyncValidators to be recursive Signed-off-by: Paul Cowan --- .changeset/shy-buses-mix.md | 5 +++ .../scaffolder/customScaffolderExtensions.tsx | 4 +-- .../src/next/components/Stepper/Stepper.tsx | 7 ++-- .../Stepper/createAsyncValidators.test.ts | 16 ++++++--- .../Stepper/createAsyncValidators.ts | 35 +++++++++++++----- .../src/next/components/Stepper/guards.ts | 36 +++++++++++++++++++ 6 files changed, 82 insertions(+), 21 deletions(-) create mode 100644 .changeset/shy-buses-mix.md create mode 100644 plugins/scaffolder-react/src/next/components/Stepper/guards.ts diff --git a/.changeset/shy-buses-mix.md b/.changeset/shy-buses-mix.md new file mode 100644 index 0000000000..868da1cc93 --- /dev/null +++ b/.changeset/shy-buses-mix.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': minor +--- + +refactor createAsyncValidators to be recursive diff --git a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx index c521bcf86c..fc37ff9e96 100644 --- a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx @@ -68,7 +68,7 @@ export const LowerCaseValuePickerFieldExtension = scaffolderPlugin.provide( const MockDelayComponent = ( props: NextFieldExtensionComponentProps<{ test?: string }>, ) => { - const { onChange, formData, rawErrors } = props; + const { onChange, formData, rawErrors = [] } = props; return ( onChange({ test: value })} margin="normal" - error={rawErrors?.length > 0 && !formData} + error={rawErrors.length > 0 && !formData} /> ); }; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index c97d31c487..bd298fcbae 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -35,6 +35,7 @@ import { useFormDataFromQuery } from '../../hooks'; import { FormProps } from '../../types'; import { LayoutOptions } from '../../../layouts'; import { useTransformSchemaToProps } from '../../hooks/useTransformSchemaToProps'; +import { isInvalid } from './guards'; const useStyles = makeStyles(theme => ({ backButton: { @@ -136,11 +137,7 @@ export const Stepper = (stepperProps: StepperProps) => { const returnedValidation = await validation(formData); - const hasErrors = Object.values(returnedValidation).some( - i => i.__errors?.length, - ); - - if (hasErrors) { + if (isInvalid(returnedValidation)) { setErrors(returnedValidation); } else { setErrors(undefined); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index ff7060222d..15fa944b0f 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -224,13 +224,19 @@ describe('createAsyncValidators', () => { apiHolder: { get: jest.fn() }, }); - await validate({ - actionType: 'newThing', + await expect( + validate({ + actionType: 'newThing', + general: { + name: undefined, + }, + }), + ).resolves.toEqual({ general: { - name: undefined, + name: expect.objectContaining({ + __errors: ['something is broken here!'], + }), }, }); - - expect(validators.NameField).toHaveBeenCalled(); }); }); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index 79466ee602..299a2451ce 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -15,12 +15,21 @@ */ import { FieldValidation } from '@rjsf/utils'; -import { JsonObject } from '@backstage/types'; +import type { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; import { Draft07 as JSONSchema } from 'json-schema-library'; import { createFieldValidation } from '../../lib'; import { NextCustomFieldValidator } from '../../extensions'; +function isObject(value: JsonValue | undefined): value is JsonObject { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +type FormValidation = Record< + string, + FieldValidation | Record +>; + export const createAsyncValidators = ( rootSchema: JsonObject, validators: Record>, @@ -28,14 +37,17 @@ export const createAsyncValidators = ( apiHolder: ApiHolder; }, ) => { - async function validate(formData: JsonObject, pathPrefix: string = '#') { + async function validate( + formData: JsonObject, + pathPrefix: string = '#', + current: JsonObject = formData, + ): Promise> { const parsedSchema = new JSONSchema(rootSchema); - const formValidation: Record = {}; - for (const [key, value] of Object.entries(formData)) { - const definitionInSchema = parsedSchema.getSchema( - `${pathPrefix}/${key}`, - formData, - ); + const formValidation: FormValidation = {}; + + for (const [key, value] of Object.entries(current)) { + const path = `${pathPrefix}/${key}`; + const definitionInSchema = parsedSchema.getSchema(path, formData); if (definitionInSchema && 'ui:field' in definitionInSchema) { const validator = validators[definitionInSchema['ui:field']]; @@ -48,10 +60,15 @@ export const createAsyncValidators = ( } formValidation[key] = fieldValidation; } + } else if (isObject(value)) { + formValidation[key] = (await validate(formData, path, value)) as Record< + string, + FieldValidation + >; } } - return formValidation; + return formValidation as Record; } return async (formData: JsonObject) => { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/guards.ts b/plugins/scaffolder-react/src/next/components/Stepper/guards.ts new file mode 100644 index 0000000000..8dfedabd77 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/Stepper/guards.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2023 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 type { FieldValidation } from '@rjsf/utils'; + +function isFieldValidation(error: any): error is FieldValidation { + return !!error && '__errors' in error; +} + +export function isInvalid(errors?: Record): boolean { + if (!errors) { + return false; + } + + for (const error of Object.values(errors)) { + if (isFieldValidation(error)) { + return (error.__errors ?? []).length > 0; + } + + return isInvalid(error); + } + + return false; +} From ba437049cc004ec0c6f29ba79c7e99be2cdf41d4 Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Mon, 6 Feb 2023 14:42:25 +0000 Subject: [PATCH 225/423] rename isInvalid to hasErrors Signed-off-by: Paul Cowan --- .../scaffolder-react/src/next/components/Stepper/Stepper.tsx | 4 ++-- .../scaffolder-react/src/next/components/Stepper/guards.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index bd298fcbae..e6e3295aaf 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -35,7 +35,7 @@ import { useFormDataFromQuery } from '../../hooks'; import { FormProps } from '../../types'; import { LayoutOptions } from '../../../layouts'; import { useTransformSchemaToProps } from '../../hooks/useTransformSchemaToProps'; -import { isInvalid } from './guards'; +import { hasErrors } from './guards'; const useStyles = makeStyles(theme => ({ backButton: { @@ -137,7 +137,7 @@ export const Stepper = (stepperProps: StepperProps) => { const returnedValidation = await validation(formData); - if (isInvalid(returnedValidation)) { + if (hasErrors(returnedValidation)) { setErrors(returnedValidation); } else { setErrors(undefined); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/guards.ts b/plugins/scaffolder-react/src/next/components/Stepper/guards.ts index 8dfedabd77..c7afeb5664 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/guards.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/guards.ts @@ -19,7 +19,7 @@ function isFieldValidation(error: any): error is FieldValidation { return !!error && '__errors' in error; } -export function isInvalid(errors?: Record): boolean { +export function hasErrors(errors?: Record): boolean { if (!errors) { return false; } @@ -29,7 +29,7 @@ export function isInvalid(errors?: Record): boolean { return (error.__errors ?? []).length > 0; } - return isInvalid(error); + return hasErrors(error); } return false; From 65cffff8d0e4861e2e78fa09e803fb74bfeefb7f Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Mon, 6 Feb 2023 14:56:39 +0000 Subject: [PATCH 226/423] refactor types Signed-off-by: Paul Cowan --- .../src/next/components/Stepper/Stepper.tsx | 9 +++++---- .../src/next/components/Stepper/createAsyncValidators.ts | 9 ++++++--- .../src/next/components/Stepper/guards.ts | 3 ++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index e6e3295aaf..eb30329cc6 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -27,7 +27,10 @@ import { ErrorSchema, FieldValidation } from '@rjsf/utils'; import React, { useCallback, useMemo, useState, type ReactNode } from 'react'; import { NextFieldExtensionOptions } from '../../extensions'; import { TemplateParameterSchema } from '../../../types'; -import { createAsyncValidators } from './createAsyncValidators'; +import { + createAsyncValidators, + type FormValidation, +} from './createAsyncValidators'; import { ReviewState, type ReviewStateProps } from '../ReviewState'; import { useTemplateSchema } from '../../hooks/useTemplateSchema'; import validator from '@rjsf/validator-ajv8'; @@ -93,9 +96,7 @@ export const Stepper = (stepperProps: StepperProps) => { const [activeStep, setActiveStep] = useState(0); const [formState, setFormState] = useFormDataFromQuery(props.initialState); - const [errors, setErrors] = useState< - undefined | Record - >(); + const [errors, setErrors] = useState(); const styles = useStyles(); const extensions = useMemo(() => { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index 299a2451ce..92774084b2 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -25,7 +25,10 @@ function isObject(value: JsonValue | undefined): value is JsonObject { return typeof value === 'object' && value !== null && !Array.isArray(value); } -type FormValidation = Record< +/** + * @internal + */ +export type FormValidation = Record< string, FieldValidation | Record >; @@ -41,7 +44,7 @@ export const createAsyncValidators = ( formData: JsonObject, pathPrefix: string = '#', current: JsonObject = formData, - ): Promise> { + ): Promise { const parsedSchema = new JSONSchema(rootSchema); const formValidation: FormValidation = {}; @@ -68,7 +71,7 @@ export const createAsyncValidators = ( } } - return formValidation as Record; + return formValidation; } return async (formData: JsonObject) => { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/guards.ts b/plugins/scaffolder-react/src/next/components/Stepper/guards.ts index c7afeb5664..647dc89af7 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/guards.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/guards.ts @@ -14,12 +14,13 @@ * limitations under the License. */ import type { FieldValidation } from '@rjsf/utils'; +import { FormValidation } from './createAsyncValidators'; function isFieldValidation(error: any): error is FieldValidation { return !!error && '__errors' in error; } -export function hasErrors(errors?: Record): boolean { +export function hasErrors(errors?: FormValidation): boolean { if (!errors) { return false; } From 18fd02197927f627c61ee715f53fae3cc127225b Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Mon, 6 Feb 2023 14:57:25 +0000 Subject: [PATCH 227/423] refactor types Signed-off-by: Paul Cowan --- .../scaffolder-react/src/next/components/Stepper/Stepper.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index eb30329cc6..a1ad289a1a 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -23,7 +23,7 @@ import { makeStyles, } from '@material-ui/core'; import { type IChangeEvent, withTheme } from '@rjsf/core-v5'; -import { ErrorSchema, FieldValidation } from '@rjsf/utils'; +import { ErrorSchema } from '@rjsf/utils'; import React, { useCallback, useMemo, useState, type ReactNode } from 'react'; import { NextFieldExtensionOptions } from '../../extensions'; import { TemplateParameterSchema } from '../../../types'; From 1b3a9bc042e39b45d8fb11361e4c5434c87c60a4 Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Mon, 6 Feb 2023 15:54:32 +0000 Subject: [PATCH 228/423] fix changeset Signed-off-by: Paul Cowan --- .changeset/shy-buses-mix.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/shy-buses-mix.md b/.changeset/shy-buses-mix.md index 868da1cc93..c92b119664 100644 --- a/.changeset/shy-buses-mix.md +++ b/.changeset/shy-buses-mix.md @@ -2,4 +2,4 @@ '@backstage/plugin-scaffolder-react': minor --- -refactor createAsyncValidators to be recursive +refactor `createAsyncValidators` to be recursive From 79dac4ac1e9ba684ee4a61388bc950b9f4820ab9 Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Mon, 6 Feb 2023 16:44:37 +0000 Subject: [PATCH 229/423] rename guards to utils Signed-off-by: Paul Cowan --- .changeset/shy-buses-mix.md | 2 +- .../scaffolder/customScaffolderExtensions.tsx | 4 ++-- .../src/next/components/Stepper/Stepper.tsx | 2 +- .../next/components/Stepper/createAsyncValidators.ts | 12 ++++-------- .../next/components/Stepper/{guards.ts => utils.ts} | 0 5 files changed, 8 insertions(+), 12 deletions(-) rename plugins/scaffolder-react/src/next/components/Stepper/{guards.ts => utils.ts} (100%) diff --git a/.changeset/shy-buses-mix.md b/.changeset/shy-buses-mix.md index c92b119664..b7db90d03c 100644 --- a/.changeset/shy-buses-mix.md +++ b/.changeset/shy-buses-mix.md @@ -2,4 +2,4 @@ '@backstage/plugin-scaffolder-react': minor --- -refactor `createAsyncValidators` to be recursive +refactor `createAsyncValidators` to be recursive to ensure validators are called in nested schemas. diff --git a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx index fc37ff9e96..c521bcf86c 100644 --- a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx @@ -68,7 +68,7 @@ export const LowerCaseValuePickerFieldExtension = scaffolderPlugin.provide( const MockDelayComponent = ( props: NextFieldExtensionComponentProps<{ test?: string }>, ) => { - const { onChange, formData, rawErrors = [] } = props; + const { onChange, formData, rawErrors } = props; return ( onChange({ test: value })} margin="normal" - error={rawErrors.length > 0 && !formData} + error={rawErrors?.length > 0 && !formData} /> ); }; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index a1ad289a1a..9242ef0086 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -38,7 +38,7 @@ import { useFormDataFromQuery } from '../../hooks'; import { FormProps } from '../../types'; import { LayoutOptions } from '../../../layouts'; import { useTransformSchemaToProps } from '../../hooks/useTransformSchemaToProps'; -import { hasErrors } from './guards'; +import { hasErrors } from './utils'; const useStyles = makeStyles(theme => ({ backButton: { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index 92774084b2..eec1f368c6 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -28,10 +28,9 @@ function isObject(value: JsonValue | undefined): value is JsonObject { /** * @internal */ -export type FormValidation = Record< - string, - FieldValidation | Record ->; +export type FormValidation = { + [name: string]: FieldValidation | FormValidation; +}; export const createAsyncValidators = ( rootSchema: JsonObject, @@ -64,10 +63,7 @@ export const createAsyncValidators = ( formValidation[key] = fieldValidation; } } else if (isObject(value)) { - formValidation[key] = (await validate(formData, path, value)) as Record< - string, - FieldValidation - >; + formValidation[key] = await validate(formData, path, value); } } diff --git a/plugins/scaffolder-react/src/next/components/Stepper/guards.ts b/plugins/scaffolder-react/src/next/components/Stepper/utils.ts similarity index 100% rename from plugins/scaffolder-react/src/next/components/Stepper/guards.ts rename to plugins/scaffolder-react/src/next/components/Stepper/utils.ts From ba1f98a0385a08709d3e8b5e159a3fb06b04bc98 Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Mon, 6 Feb 2023 20:37:22 +0000 Subject: [PATCH 230/423] move isObject into utils Signed-off-by: Paul Cowan --- .../src/next/components/Stepper/createAsyncValidators.ts | 7 ++----- .../scaffolder-react/src/next/components/Stepper/utils.ts | 5 +++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index eec1f368c6..86b7619b34 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -15,15 +15,12 @@ */ import { FieldValidation } from '@rjsf/utils'; -import type { JsonObject, JsonValue } from '@backstage/types'; +import type { JsonObject } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; import { Draft07 as JSONSchema } from 'json-schema-library'; import { createFieldValidation } from '../../lib'; import { NextCustomFieldValidator } from '../../extensions'; - -function isObject(value: JsonValue | undefined): value is JsonObject { - return typeof value === 'object' && value !== null && !Array.isArray(value); -} +import { isObject } from './utils'; /** * @internal diff --git a/plugins/scaffolder-react/src/next/components/Stepper/utils.ts b/plugins/scaffolder-react/src/next/components/Stepper/utils.ts index 647dc89af7..e4da5882e5 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/utils.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/utils.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import type { JsonObject, JsonValue } from '@backstage/types'; import type { FieldValidation } from '@rjsf/utils'; import { FormValidation } from './createAsyncValidators'; @@ -35,3 +36,7 @@ export function hasErrors(errors?: FormValidation): boolean { return false; } + +export function isObject(value: JsonValue | undefined): value is JsonObject { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} From 7c0b64e8b9c84a51a2b9b3e7c66e64adb8bb8c0d Mon Sep 17 00:00:00 2001 From: bogdannechyporenko Date: Mon, 6 Feb 2023 23:27:00 +0100 Subject: [PATCH 231/423] Updated createValidator.test.ts Signed-off-by: bogdannechyporenko --- .../src/components/TemplatePage/createValidator.test.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts index d9b9d1c0c3..777de0cc36 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts @@ -37,9 +37,6 @@ describe('createValidator', () => { _context: { apiHolder: ApiHolder }, ) => { const input = values as string[]; - if (input.length === 0) { - fieldValidation.addError('A tag name can not be empty'); - } for (const item of input) { if (!/^[a-z0-9-]+$/.test(item)) { fieldValidation.addError( From ccbf91051b7133e17a6a583f07199e6c30958014 Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Tue, 7 Feb 2023 07:35:52 +0000 Subject: [PATCH 232/423] bump @rjsf v5 dependencies to 5.1.0 Signed-off-by: Paul Cowan --- .changeset/new-pumpkins-sleep.md | 6 +++ .../scaffolder/customScaffolderExtensions.tsx | 2 +- plugins/scaffolder-react/package.json | 8 ++-- plugins/scaffolder/package.json | 2 +- yarn.lock | 46 +++++++++---------- 5 files changed, 35 insertions(+), 29 deletions(-) create mode 100644 .changeset/new-pumpkins-sleep.md diff --git a/.changeset/new-pumpkins-sleep.md b/.changeset/new-pumpkins-sleep.md new file mode 100644 index 0000000000..cc5b89806d --- /dev/null +++ b/.changeset/new-pumpkins-sleep.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-scaffolder-react': patch +--- + +bump `@rjsf` `v5` dependencies to 5.1.0 diff --git a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx index c521bcf86c..8a2e7fba53 100644 --- a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx @@ -68,7 +68,7 @@ export const LowerCaseValuePickerFieldExtension = scaffolderPlugin.provide( const MockDelayComponent = ( props: NextFieldExtensionComponentProps<{ test?: string }>, ) => { - const { onChange, formData, rawErrors } = props; + const { onChange, formData, rawErrors = [] } = props; return ( =17 - checksum: befd0b39aab7462f23ed926ca17314a049f338e81cdda8233e35c45febb34e3d1ff550ca8db7e64570342be281e3556a4cb045b52af86a0a551041d5ee22472b + checksum: ff38046bb25de86b57e404c5d1ccea84b0485e916caf33a3cb25b030a38ed930a9b89a411671a7c29b047da38e0c682e20b43b13e61d77df770299385ba3c67a languageName: node linkType: hard @@ -12654,16 +12654,16 @@ __metadata: languageName: node linkType: hard -"@rjsf/material-ui-v5@npm:@rjsf/material-ui@5.0.1": - version: 5.0.1 - resolution: "@rjsf/material-ui@npm:5.0.1" +"@rjsf/material-ui-v5@npm:@rjsf/material-ui@5.1.0": + version: 5.1.0 + resolution: "@rjsf/material-ui@npm:5.1.0" peerDependencies: "@material-ui/core": ^4.12.3 "@material-ui/icons": ^4.11.2 "@rjsf/core": ^5.0.0 "@rjsf/utils": ^5.0.0 react: ^16.14.0 || >=17 - checksum: 041f21caef8fd8e594c3b517eea15344c97017d03de5e608b1aead3e94cca474dc874930b64f59b506c1e578889664718d07e1e580fcffc78611dad3d33099fc + checksum: f8e2c486f33a60703cae5bb42ae82bc431b3d743c239868ca71907e7b4127a39d1688200820c0c8acdf3ecd3f5eaddef4ba47264695feead28e9b439d9be7ce8 languageName: node linkType: hard @@ -12679,9 +12679,9 @@ __metadata: languageName: node linkType: hard -"@rjsf/utils@npm:5.0.1": - version: 5.0.1 - resolution: "@rjsf/utils@npm:5.0.1" +"@rjsf/utils@npm:5.1.0": + version: 5.1.0 + resolution: "@rjsf/utils@npm:5.1.0" dependencies: json-schema-merge-allof: ^0.8.1 jsonpointer: ^5.0.1 @@ -12690,21 +12690,21 @@ __metadata: react-is: ^18.2.0 peerDependencies: react: ^16.14.0 || >=17 - checksum: 7bf76106eced48cfdf3072a26306ff00d0792774dfe501b061db110e9dd2e17bead77bc9b335c85adf27926ab860c39ee4f676007f8f07e74a438f3a31004692 + checksum: 76d7caf144f98b1547067bfdc2b1baecf452c63bd9d6f2cae6c162a99154bb4d2f5033f6abc0e26ab767dca9ea743f1f5a9d796696e90dd5ed1fdca5ee3c5280 languageName: node linkType: hard -"@rjsf/validator-ajv8@npm:5.0.1": - version: 5.0.1 - resolution: "@rjsf/validator-ajv8@npm:5.0.1" +"@rjsf/validator-ajv8@npm:5.1.0": + version: 5.1.0 + resolution: "@rjsf/validator-ajv8@npm:5.1.0" dependencies: - ajv: ^8.11.0 + ajv: ^8.12.0 ajv-formats: ^2.1.1 lodash: ^4.17.15 lodash-es: ^4.17.15 peerDependencies: "@rjsf/utils": ^5.0.0 - checksum: 7d36dac876fd3536dda26af5726e847af02a9880fac9feb2683809e8c1f3743e4f5ff8399e961a79f5383e28fdb5a1e9695d89ebf7dffaa22dd76948be830c54 + checksum: 3430a0aea8235deedd306b535ea3a62a9bcdd4dcf0bf1d022fe036041dceb5ca7c147b17ae50a0d25bb7c953729e987d96c68f5220f8fde4b56a89cf3f106a49 languageName: node linkType: hard @@ -16313,7 +16313,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^8.0.0, ajv@npm:^8.10.0, ajv@npm:^8.11.0, ajv@npm:^8.8.0": +"ajv@npm:^8.0.0, ajv@npm:^8.10.0, ajv@npm:^8.12.0, ajv@npm:^8.8.0": version: 8.12.0 resolution: "ajv@npm:8.12.0" dependencies: From d19c77cc4140f774989a81a4ba78f78323e9db16 Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Tue, 7 Feb 2023 08:55:10 +0100 Subject: [PATCH 233/423] fixed API report errors and regenerated the reports Signed-off-by: Katharina Sick --- packages/core-app-api/api-report.md | 20 +++++++++++++++++++ packages/core-plugin-api/api-report.md | 5 +++++ plugins/auth-backend/api-report.md | 9 +-------- .../src/providers/bitbucketServer/provider.ts | 18 +++++++++++------ 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index 133ac22e5b..37f7a98de0 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -22,6 +22,7 @@ import { BackstageIdentityApi } from '@backstage/core-plugin-api'; import { BackstageIdentityResponse } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { bitbucketAuthApiRef } from '@backstage/core-plugin-api'; +import { bitbucketServerAuthApiRef } from '@backstage/core-plugin-api'; import { ComponentType } from 'react'; import { Config } from '@backstage/config'; import { ConfigReader } from '@backstage/config'; @@ -280,6 +281,25 @@ export class BitbucketAuth { static create(options: OAuthApiCreateOptions): typeof bitbucketAuthApiRef.T; } +// @public +export class BitbucketServerAuth { + // (undocumented) + static create( + options: OAuthApiCreateOptions, + ): typeof bitbucketServerAuthApiRef.T; +} + +// @public +export type BitbucketServerSession = { + providerInfo: { + accessToken: string; + scopes: Set; + expiresAt?: Date; + }; + profile: ProfileInfo; + backstageIdentity: BackstageIdentityResponse; +}; + // @public export type BitbucketSession = { providerInfo: { diff --git a/packages/core-plugin-api/api-report.md b/packages/core-plugin-api/api-report.md index dc7aa9eb5f..91f05921bf 100644 --- a/packages/core-plugin-api/api-report.md +++ b/packages/core-plugin-api/api-report.md @@ -241,6 +241,11 @@ export const bitbucketAuthApiRef: ApiRef< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi >; +// @public +export const bitbucketServerAuthApiRef: ApiRef< + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi +>; + // @public export type BootErrorPageProps = { step: 'load-config' | 'load-chunk'; diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index e25ed18dfe..8df6079b9f 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -16,7 +16,6 @@ import { GetEntitiesRequest } from '@backstage/catalog-client'; import { IncomingHttpHeaders } from 'http'; import { JsonValue } from '@backstage/types'; import { Logger } from 'winston'; -import passport from 'passport'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Profile } from 'passport'; @@ -133,11 +132,9 @@ export type BitbucketPassportProfile = Profile & { }; }; -// Warning: (ae-missing-release-tag) "BitbucketServerOAuthResult" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type BitbucketServerOAuthResult = { - fullProfile: PassportProfile; + fullProfile: Profile; params: { scope: string; access_token?: string; @@ -763,8 +760,4 @@ export type WebMessageResponse = type: 'authorization_response'; error: Error; }; - -// Warnings were encountered during analysis: -// -// src/providers/bitbucketServer/provider.d.ts:6:5 - (ae-forgotten-export) The symbol "PassportProfile" needs to be exported by the entry point index.d.ts ``` diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts index 397f63733f..305f07c9d5 100644 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts @@ -40,13 +40,14 @@ import { } from '../types'; import express from 'express'; import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { PassportProfile } from '../../lib/passport/types'; +import { Profile as PassportProfile } from 'passport'; import { commonByEmailResolver } from '../resolvers'; type PrivateInfo = { refreshToken: string; }; +/** @public */ export type BitbucketServerOAuthResult = { fullProfile: PassportProfile; params: { @@ -216,7 +217,7 @@ export class BitbucketServerAuthProvider implements OAuthHandlers { const user = await userResponse.json(); - return { + const passportProfile = { provider: 'bitbucketServer', id: user.id.toString(), displayName: user.displayName, @@ -226,10 +227,15 @@ export class BitbucketServerAuthProvider implements OAuthHandlers { value: user.emailAddress, }, ], - avatarUrl: user.avatarUrl - ? `https://${this.host}${user.avatarUrl}` - : undefined, - }; + } as PassportProfile; + + if (user.avatarUrl) { + passportProfile.photos = [ + { value: `https://${this.host}${user.avatarUrl}` }, + ]; + } + + return passportProfile; } } From 71a5ec0f06a849a4ba120dc4f9b771960118ab24 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 6 Feb 2023 16:36:29 +0100 Subject: [PATCH 234/423] backend-plugin-api: inlined LogMeta type Signed-off-by: Patrik Oldsberg --- .changeset/selfish-frogs-punch.md | 5 ++++ .changeset/wild-donkeys-rescue.md | 6 ++++ packages/backend-app-api/api-report.md | 13 ++++----- .../src/logging/WinstonLogger.ts | 13 ++++----- packages/backend-plugin-api/api-report.md | 15 ++++------ .../src/services/definitions/LoggerService.ts | 15 ++++------ .../src/services/definitions/index.ts | 2 +- .../next/services/MockRootLoggerService.ts | 29 +++++++++++++------ 8 files changed, 54 insertions(+), 44 deletions(-) create mode 100644 .changeset/selfish-frogs-punch.md create mode 100644 .changeset/wild-donkeys-rescue.md diff --git a/.changeset/selfish-frogs-punch.md b/.changeset/selfish-frogs-punch.md new file mode 100644 index 0000000000..9dedd3544d --- /dev/null +++ b/.changeset/selfish-frogs-punch.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +**BREAKING**: Inlined `LogMeta` type. diff --git a/.changeset/wild-donkeys-rescue.md b/.changeset/wild-donkeys-rescue.md new file mode 100644 index 0000000000..43dc3743bb --- /dev/null +++ b/.changeset/wild-donkeys-rescue.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-test-utils': patch +'@backstage/backend-app-api': patch +--- + +Updated usages of `LogMeta`. diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index 7ad4b590ab..67da4cb018 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -21,7 +21,6 @@ import { IdentityService } from '@backstage/backend-plugin-api'; import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoadConfigOptionsRemote } from '@backstage/config-loader'; import { LoggerService } from '@backstage/backend-plugin-api'; -import { LogMeta } from '@backstage/backend-plugin-api'; import { PermissionsService } from '@backstage/backend-plugin-api'; import { PluginCacheManager } from '@backstage/backend-common'; import { PluginDatabaseManager } from '@backstage/backend-common'; @@ -263,21 +262,21 @@ export class WinstonLogger implements RootLoggerService { // (undocumented) addRedactions(redactions: Iterable): void; // (undocumented) - child(meta: LogMeta): LoggerService; + child(meta: Record): LoggerService; static colorFormat(): Format; static create(options: WinstonLoggerOptions): WinstonLogger; // (undocumented) - debug(message: string, meta?: LogMeta): void; + debug(message: string, meta?: Record): void; // (undocumented) - error(message: string, meta?: LogMeta): void; + error(message: string, meta?: Record): void; // (undocumented) - info(message: string, meta?: LogMeta): void; + info(message: string, meta?: Record): void; static redacter(): { format: Format; add: (redactions: Iterable) => void; }; // (undocumented) - warn(message: string, meta?: LogMeta): void; + warn(message: string, meta?: Record): void; } // @public (undocumented) @@ -287,7 +286,7 @@ export interface WinstonLoggerOptions { // (undocumented) level: string; // (undocumented) - meta?: LogMeta; + meta?: Record; // (undocumented) transports: transport[]; } diff --git a/packages/backend-app-api/src/logging/WinstonLogger.ts b/packages/backend-app-api/src/logging/WinstonLogger.ts index d32b816523..8d48015580 100644 --- a/packages/backend-app-api/src/logging/WinstonLogger.ts +++ b/packages/backend-app-api/src/logging/WinstonLogger.ts @@ -16,7 +16,6 @@ import { LoggerService, - LogMeta, RootLoggerService, } from '@backstage/backend-plugin-api'; import { Format, TransformableInfo } from 'logform'; @@ -33,7 +32,7 @@ import { escapeRegExp } from '../lib/escapeRegExp'; * @public */ export interface WinstonLoggerOptions { - meta?: LogMeta; + meta?: Record; level: string; format: Format; transports: Transport[]; @@ -150,23 +149,23 @@ export class WinstonLogger implements RootLoggerService { this.#addRedactions = addRedactions; } - error(message: string, meta?: LogMeta): void { + error(message: string, meta?: Record): void { this.#winston.error(message, meta); } - warn(message: string, meta?: LogMeta): void { + warn(message: string, meta?: Record): void { this.#winston.warn(message, meta); } - info(message: string, meta?: LogMeta): void { + info(message: string, meta?: Record): void { this.#winston.info(message, meta); } - debug(message: string, meta?: LogMeta): void { + debug(message: string, meta?: Record): void { this.#winston.debug(message, meta); } - child(meta: LogMeta): LoggerService { + child(meta: Record): LoggerService { return new WinstonLogger(this.#winston.child(meta)); } diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index 8293ac193f..e0b8fdfa04 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -311,22 +311,17 @@ export interface LifecycleServiceShutdownOptions { // @public export interface LoggerService { // (undocumented) - child(meta: LogMeta): LoggerService; + child(meta: Record): LoggerService; // (undocumented) - debug(message: string, meta?: Error | LogMeta): void; + debug(message: string, meta?: Error | Record): void; // (undocumented) - error(message: string, meta?: Error | LogMeta): void; + error(message: string, meta?: Error | Record): void; // (undocumented) - info(message: string, meta?: Error | LogMeta): void; + info(message: string, meta?: Error | Record): void; // (undocumented) - warn(message: string, meta?: Error | LogMeta): void; + warn(message: string, meta?: Error | Record): void; } -// @public (undocumented) -export type LogMeta = { - [name: string]: unknown; -}; - // @public (undocumented) export interface PermissionsService extends PermissionEvaluator {} diff --git a/packages/backend-plugin-api/src/services/definitions/LoggerService.ts b/packages/backend-plugin-api/src/services/definitions/LoggerService.ts index 269dfa0166..ce59b47007 100644 --- a/packages/backend-plugin-api/src/services/definitions/LoggerService.ts +++ b/packages/backend-plugin-api/src/services/definitions/LoggerService.ts @@ -14,21 +14,16 @@ * limitations under the License. */ -/** - * @public - */ -export type LogMeta = { [name: string]: unknown }; - /** * A service that provides a logging facility. * * @public */ export interface LoggerService { - error(message: string, meta?: Error | LogMeta): void; - warn(message: string, meta?: Error | LogMeta): void; - info(message: string, meta?: Error | LogMeta): void; - debug(message: string, meta?: Error | LogMeta): void; + error(message: string, meta?: Error | Record): void; + warn(message: string, meta?: Error | Record): void; + info(message: string, meta?: Error | Record): void; + debug(message: string, meta?: Error | Record): void; - child(meta: LogMeta): LoggerService; + child(meta: Record): LoggerService; } diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index 720b4d634d..35c2f0251c 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -30,7 +30,7 @@ export type { LifecycleServiceShutdownHook, LifecycleServiceShutdownOptions, } from './LifecycleService'; -export type { LoggerService, LogMeta } from './LoggerService'; +export type { LoggerService } from './LoggerService'; export type { PermissionsService } from './PermissionsService'; export type { PluginMetadataService } from './PluginMetadataService'; export type { RootHttpRouterService } from './RootHttpRouterService'; diff --git a/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts b/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts index 780d330bfb..5965792932 100644 --- a/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts +++ b/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts @@ -16,38 +16,49 @@ import { LoggerService, - LogMeta, RootLoggerService, } from '@backstage/backend-plugin-api'; import type { mockServices } from './mockServices'; export class MockRootLoggerService implements RootLoggerService { #levels: Exclude; - #meta: LogMeta; + #meta: Record; - error(message: string, meta?: LogMeta | Error | undefined): void { + error( + message: string, + meta?: Record | Error | undefined, + ): void { this.#log('error', message, meta); } - warn(message: string, meta?: LogMeta | Error | undefined): void { + warn( + message: string, + meta?: Record | Error | undefined, + ): void { this.#log('warn', message, meta); } - info(message: string, meta?: LogMeta | Error | undefined): void { + info( + message: string, + meta?: Record | Error | undefined, + ): void { this.#log('info', message, meta); } - debug(message: string, meta?: LogMeta | Error | undefined): void { + debug( + message: string, + meta?: Record | Error | undefined, + ): void { this.#log('debug', message, meta); } - child(meta: LogMeta): LoggerService { + child(meta: Record): LoggerService { return new MockRootLoggerService(this.#levels, { ...this.#meta, ...meta }); } constructor( levels: mockServices.rootLogger.Options['levels'], - meta: LogMeta, + meta: Record, ) { if (typeof levels === 'boolean') { this.#levels = { @@ -65,7 +76,7 @@ export class MockRootLoggerService implements RootLoggerService { #log( level: 'error' | 'warn' | 'info' | 'debug', message: string, - meta?: LogMeta | Error | undefined, + meta?: Record | Error | undefined, ) { if (this.#levels[level]) { const labels = Object.entries(this.#meta) From e42d1595cb6b6aaae04f490ae518f5302ef6ce18 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 7 Feb 2023 10:12:22 +0100 Subject: [PATCH 235/423] backend-common: work around missing logform dependency Signed-off-by: Patrik Oldsberg --- packages/backend-common/package.json | 1 + yarn.lock | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 9f1069f322..9ec68e5531 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -53,6 +53,7 @@ "@types/dockerode": "^3.3.0", "@types/express": "^4.17.6", "@types/luxon": "^3.0.0", + "@types/triple-beam": "^1.3.2", "@types/webpack-env": "^1.15.2", "archiver": "^5.0.2", "aws-sdk": "^2.840.0", diff --git a/yarn.lock b/yarn.lock index 6e252cb1c2..adcc15e13b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3457,6 +3457,7 @@ __metadata: "@types/stoppable": ^1.1.0 "@types/supertest": ^2.0.8 "@types/tar": ^6.1.1 + "@types/triple-beam": ^1.3.2 "@types/webpack-env": ^1.15.2 "@types/yauzl": ^2.10.0 archiver: ^5.0.2 @@ -15443,6 +15444,13 @@ __metadata: languageName: node linkType: hard +"@types/triple-beam@npm:^1.3.2": + version: 1.3.2 + resolution: "@types/triple-beam@npm:1.3.2" + checksum: dd7b4a563fb710abc992e5d59eac481bed9e303fada2e276e37b00be31c392e03300ee468e57761e616512872e77935f92472877d0704a19688d15a726cee17b + languageName: node + linkType: hard + "@types/trusted-types@npm:*": version: 2.0.2 resolution: "@types/trusted-types@npm:2.0.2" From 9c9456fd33adbcc74ed65a70f5b1c45464ea4b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 7 Feb 2023 10:35:38 +0100 Subject: [PATCH 236/423] Removed the unused TypesToServiceRef type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/dull-fishes-suffer.md | 5 +++++ packages/backend-plugin-api/api-report.md | 5 ----- packages/backend-plugin-api/src/services/system/index.ts | 1 - packages/backend-plugin-api/src/services/system/types.ts | 3 --- 4 files changed, 5 insertions(+), 9 deletions(-) create mode 100644 .changeset/dull-fishes-suffer.md diff --git a/.changeset/dull-fishes-suffer.md b/.changeset/dull-fishes-suffer.md new file mode 100644 index 0000000000..54baae404e --- /dev/null +++ b/.changeset/dull-fishes-suffer.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': patch +--- + +Removed the unused `TypesToServiceRef` type diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index a7700d81ac..0a23abf0f1 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -525,11 +525,6 @@ export interface TokenManagerService { }>; } -// @public (undocumented) -export type TypesToServiceRef = { - [key in keyof T]: ServiceRef; -}; - // @public export interface UrlReaderService { readTree(url: string, options?: ReadTreeOptions): Promise; diff --git a/packages/backend-plugin-api/src/services/system/index.ts b/packages/backend-plugin-api/src/services/system/index.ts index 74be9f8b11..2b91758cbc 100644 --- a/packages/backend-plugin-api/src/services/system/index.ts +++ b/packages/backend-plugin-api/src/services/system/index.ts @@ -17,7 +17,6 @@ export type { ServiceRef, ServiceRefConfig, - TypesToServiceRef, ServiceFactory, PluginServiceFactoryConfig, RootServiceFactoryConfig, diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index 2615c5e3a3..b414c72bc5 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -47,9 +47,6 @@ export type ServiceRef< $$ref: 'service'; }; -/** @public */ -export type TypesToServiceRef = { [key in keyof T]: ServiceRef }; - /** @public */ export type ServiceFactory = | { From b729f9f31f2feeb8f319f4b58906064ad7bbecf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 7 Feb 2023 10:49:45 +0100 Subject: [PATCH 237/423] Moved the options of the config service out to the factory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/silent-peas-fly.md | 5 +++++ packages/backend-app-api/api-report.md | 4 +++- .../implementations/config/configFactory.ts | 21 ++++++++++--------- 3 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 .changeset/silent-peas-fly.md diff --git a/.changeset/silent-peas-fly.md b/.changeset/silent-peas-fly.md new file mode 100644 index 0000000000..68dd6dfe47 --- /dev/null +++ b/.changeset/silent-peas-fly.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Moved the options of the config service out to the factory itself, where it belongs diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index 7ad4b590ab..e7bdc40da5 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -53,7 +53,9 @@ export interface Backend { export const cacheFactory: () => ServiceFactory; // @public (undocumented) -export const configFactory: () => ServiceFactory; +export const configFactory: ( + options?: ConfigFactoryOptions | undefined, +) => ServiceFactory; // @public (undocumented) export interface ConfigFactoryOptions { diff --git a/packages/backend-app-api/src/services/implementations/config/configFactory.ts b/packages/backend-app-api/src/services/implementations/config/configFactory.ts index 0ec15c29fe..833730fdbd 100644 --- a/packages/backend-app-api/src/services/implementations/config/configFactory.ts +++ b/packages/backend-app-api/src/services/implementations/config/configFactory.ts @@ -35,13 +35,14 @@ export interface ConfigFactoryOptions { } /** @public */ -export const configFactory = createServiceFactory({ - service: coreServices.config, - deps: {}, - async factory({}, options?: ConfigFactoryOptions) { - const { argv = process.argv, remote } = options ?? {}; - - const { config } = await loadBackendConfig({ argv, remote }); - return config; - }, -}); +export const configFactory = createServiceFactory( + (options?: ConfigFactoryOptions) => ({ + service: coreServices.config, + deps: {}, + async factory({}) { + const { argv = process.argv, remote } = options ?? {}; + const { config } = await loadBackendConfig({ argv, remote }); + return config; + }, + }), +); From 5f98a682bb18c4b5607ff84ea7c2be0ae56f9ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 7 Feb 2023 11:15:21 +0100 Subject: [PATCH 238/423] root htt router too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/silent-peas-fly.md | 2 +- packages/backend-app-api/api-report.md | 4 +- .../rootHttpRouter/rootHttpRouterFactory.ts | 69 +++++++++---------- 3 files changed, 37 insertions(+), 38 deletions(-) diff --git a/.changeset/silent-peas-fly.md b/.changeset/silent-peas-fly.md index 68dd6dfe47..8148cb5d12 100644 --- a/.changeset/silent-peas-fly.md +++ b/.changeset/silent-peas-fly.md @@ -2,4 +2,4 @@ '@backstage/backend-app-api': patch --- -Moved the options of the config service out to the factory itself, where it belongs +Moved the options of the `config` and `rootHttpRouter` services out to the factories themselves, where they belong diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index e7bdc40da5..8dc85d1728 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -232,7 +232,9 @@ export interface RootHttpRouterConfigureOptions { } // @public (undocumented) -export const rootHttpRouterFactory: () => ServiceFactory; +export const rootHttpRouterFactory: ( + options?: RootHttpRouterFactoryOptions | undefined, +) => ServiceFactory; // @public (undocumented) export type RootHttpRouterFactoryOptions = { diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts index f46f92741b..816c615817 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts @@ -69,45 +69,42 @@ function defaultConfigure({ } /** @public */ -export const rootHttpRouterFactory = createServiceFactory({ - service: coreServices.rootHttpRouter, - deps: { - config: coreServices.config, - rootLogger: coreServices.rootLogger, - lifecycle: coreServices.rootLifecycle, - }, - async factory( - { config, rootLogger, lifecycle }, - { - indexPath, - configure = defaultConfigure, - }: RootHttpRouterFactoryOptions = {}, - ) { - const logger = rootLogger.child({ service: 'rootHttpRouter' }); - const app = express(); +export const rootHttpRouterFactory = createServiceFactory( + (options?: RootHttpRouterFactoryOptions) => ({ + service: coreServices.rootHttpRouter, + deps: { + config: coreServices.config, + rootLogger: coreServices.rootLogger, + lifecycle: coreServices.rootLifecycle, + }, + async factory({ config, rootLogger, lifecycle }) { + const { indexPath, configure = defaultConfigure } = options ?? {}; + const logger = rootLogger.child({ service: 'rootHttpRouter' }); + const app = express(); - const router = DefaultRootHttpRouter.create({ indexPath }); - const middleware = MiddlewareFactory.create({ config, logger }); + const router = DefaultRootHttpRouter.create({ indexPath }); + const middleware = MiddlewareFactory.create({ config, logger }); - configure({ - app, - routes: router.handler(), - middleware, - config, - logger, - lifecycle, - }); + configure({ + app, + routes: router.handler(), + middleware, + config, + logger, + lifecycle, + }); - const server = await createHttpServer( - app, - readHttpServerOptions(config.getOptionalConfig('backend')), - { logger }, - ); + const server = await createHttpServer( + app, + readHttpServerOptions(config.getOptionalConfig('backend')), + { logger }, + ); - lifecycle.addShutdownHook(() => server.stop()); + lifecycle.addShutdownHook(() => server.stop()); - await server.start(); + await server.start(); - return router; - }, -}); + return router; + }, + }), +); From 7e7557a2be313064e79f5d3ab7fc68b26a3a57b8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 6 Feb 2023 16:58:42 +0100 Subject: [PATCH 239/423] backend-test-utils: switch levels to level for mock logger Signed-off-by: Patrik Oldsberg --- .changeset/hip-tables-prove.md | 5 + packages/backend-test-utils/api-report.md | 9 +- .../services/MockRootLoggerService.test.ts | 131 ++++++++++++++++++ .../next/services/MockRootLoggerService.ts | 41 +++--- .../src/next/services/mockServices.ts | 6 +- 5 files changed, 163 insertions(+), 29 deletions(-) create mode 100644 .changeset/hip-tables-prove.md create mode 100644 packages/backend-test-utils/src/next/services/MockRootLoggerService.test.ts diff --git a/.changeset/hip-tables-prove.md b/.changeset/hip-tables-prove.md new file mode 100644 index 0000000000..bc2c4e83d6 --- /dev/null +++ b/.changeset/hip-tables-prove.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Updated the `mockServices.rootLogger` options to accept a single level option instead. diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index 672c574cb2..d99cf51866 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -91,14 +91,7 @@ export namespace mockServices { export namespace rootLogger { // (undocumented) export type Options = { - levels: - | boolean - | { - error: boolean; - warn: boolean; - info: boolean; - debug: boolean; - }; + level?: 'none' | 'error' | 'warn' | 'info' | 'debug'; }; const // (undocumented) factory: (options?: Options | undefined) => ServiceFactory; diff --git a/packages/backend-test-utils/src/next/services/MockRootLoggerService.test.ts b/packages/backend-test-utils/src/next/services/MockRootLoggerService.test.ts new file mode 100644 index 0000000000..a3cbb5c384 --- /dev/null +++ b/packages/backend-test-utils/src/next/services/MockRootLoggerService.test.ts @@ -0,0 +1,131 @@ +/* + * Copyright 2023 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 { MockRootLoggerService } from './MockRootLoggerService'; + +describe('MockRootLoggerService', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + it('should be silent by default', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(console, 'info').mockImplementation(() => {}); + jest.spyOn(console, 'debug').mockImplementation(() => {}); + + const logger = MockRootLoggerService.create(); + logger.error('error'); + logger.warn('warn'); + logger.info('info'); + logger.debug('debug'); + + expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + expect(console.info).not.toHaveBeenCalled(); + expect(console.debug).not.toHaveBeenCalled(); + }); + + it('shuld be able to set none level', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(console, 'info').mockImplementation(() => {}); + jest.spyOn(console, 'debug').mockImplementation(() => {}); + + const logger = MockRootLoggerService.create({ level: 'none' }); + logger.error('error'); + logger.warn('warn'); + logger.info('info'); + logger.debug('debug'); + + expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + expect(console.info).not.toHaveBeenCalled(); + expect(console.debug).not.toHaveBeenCalled(); + }); + + it('shuld be able to set error level', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(console, 'info').mockImplementation(() => {}); + jest.spyOn(console, 'debug').mockImplementation(() => {}); + + const logger = MockRootLoggerService.create({ level: 'error' }); + logger.error('error'); + logger.warn('warn'); + logger.info('info'); + logger.debug('debug'); + + expect(console.error).toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + expect(console.info).not.toHaveBeenCalled(); + expect(console.debug).not.toHaveBeenCalled(); + }); + + it('shuld be able to set warn level', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(console, 'info').mockImplementation(() => {}); + jest.spyOn(console, 'debug').mockImplementation(() => {}); + + const logger = MockRootLoggerService.create({ level: 'warn' }); + logger.error('error'); + logger.warn('warn'); + logger.info('info'); + logger.debug('debug'); + + expect(console.error).toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalled(); + expect(console.info).not.toHaveBeenCalled(); + expect(console.debug).not.toHaveBeenCalled(); + }); + + it('shuld be able to set info level', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(console, 'info').mockImplementation(() => {}); + jest.spyOn(console, 'debug').mockImplementation(() => {}); + + const logger = MockRootLoggerService.create({ level: 'info' }); + logger.error('error'); + logger.warn('warn'); + logger.info('info'); + logger.debug('debug'); + + expect(console.error).toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalled(); + expect(console.info).toHaveBeenCalled(); + expect(console.debug).not.toHaveBeenCalled(); + }); + + it('shuld be able to set debug level', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(console, 'info').mockImplementation(() => {}); + jest.spyOn(console, 'debug').mockImplementation(() => {}); + + const logger = MockRootLoggerService.create({ level: 'debug' }); + logger.error('error'); + logger.warn('warn'); + logger.info('info'); + logger.debug('debug'); + + expect(console.error).toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalled(); + expect(console.info).toHaveBeenCalled(); + expect(console.debug).toHaveBeenCalled(); + }); +}); diff --git a/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts b/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts index 5965792932..fabba82a0f 100644 --- a/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts +++ b/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts @@ -20,10 +20,28 @@ import { } from '@backstage/backend-plugin-api'; import type { mockServices } from './mockServices'; +const levels = { + none: 0, + error: 1, + warn: 2, + info: 3, + debug: 4, +}; + export class MockRootLoggerService implements RootLoggerService { - #levels: Exclude; + #level: number; #meta: Record; + static create( + options?: mockServices.rootLogger.Options, + ): MockRootLoggerService { + const level = options?.level ?? 'none'; + if (!(level in levels)) { + throw new Error(`Invalid log level '${level}'`); + } + return new MockRootLoggerService(levels[level], {}); + } + error( message: string, meta?: Record | Error | undefined, @@ -53,23 +71,11 @@ export class MockRootLoggerService implements RootLoggerService { } child(meta: Record): LoggerService { - return new MockRootLoggerService(this.#levels, { ...this.#meta, ...meta }); + return new MockRootLoggerService(this.#level, { ...this.#meta, ...meta }); } - constructor( - levels: mockServices.rootLogger.Options['levels'], - meta: Record, - ) { - if (typeof levels === 'boolean') { - this.#levels = { - error: levels, - debug: levels, - info: levels, - warn: levels, - }; - } else { - this.#levels = levels; - } + private constructor(level: number, meta: Record) { + this.#level = level; this.#meta = meta; } @@ -78,7 +84,8 @@ export class MockRootLoggerService implements RootLoggerService { message: string, meta?: Record | Error | undefined, ) { - if (this.#levels[level]) { + const levelValue = levels[level] ?? 0; + if (levelValue <= this.#level) { const labels = Object.entries(this.#meta) .map(([key, value]) => `${key}=${value}`) .join(','); diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index 5f771f13c5..2a56bd78b8 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -67,13 +67,11 @@ export namespace mockServices { } export function rootLogger(options?: rootLogger.Options): LoggerService { - return new MockRootLoggerService(options?.levels ?? false, {}); + return MockRootLoggerService.create(options); } export namespace rootLogger { export type Options = { - levels: - | boolean - | { error: boolean; warn: boolean; info: boolean; debug: boolean }; + level?: 'none' | 'error' | 'warn' | 'info' | 'debug'; }; export const factory = simpleFactory(coreServices.rootLogger, rootLogger); From c769924e856cdf815b3193222611f2e578caa39e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 7 Feb 2023 11:43:08 +0100 Subject: [PATCH 240/423] backend-plugin-api: update old LogMeta to use JsonObject instead Signed-off-by: Patrik Oldsberg --- .changeset/selfish-frogs-punch.md | 2 +- packages/backend-app-api/api-report.md | 13 +++++---- .../src/logging/WinstonLogger.ts | 13 +++++---- .../src/logging/loggerToWinstonLogger.ts | 3 +- packages/backend-plugin-api/api-report.md | 11 +++---- .../src/services/definitions/LoggerService.ts | 12 ++++---- .../next/services/MockRootLoggerService.ts | 29 ++++++------------- 7 files changed, 39 insertions(+), 44 deletions(-) diff --git a/.changeset/selfish-frogs-punch.md b/.changeset/selfish-frogs-punch.md index 9dedd3544d..6484576af8 100644 --- a/.changeset/selfish-frogs-punch.md +++ b/.changeset/selfish-frogs-punch.md @@ -2,4 +2,4 @@ '@backstage/backend-plugin-api': minor --- -**BREAKING**: Inlined `LogMeta` type. +**BREAKING**: Switched out `LogMeta` type for `JsonObject`. diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index 67da4cb018..b7670747e4 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -18,6 +18,7 @@ import { HelmetOptions } from 'helmet'; import * as http from 'http'; import { HttpRouterService } from '@backstage/backend-plugin-api'; import { IdentityService } from '@backstage/backend-plugin-api'; +import { JsonObject } from '@backstage/types'; import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoadConfigOptionsRemote } from '@backstage/config-loader'; import { LoggerService } from '@backstage/backend-plugin-api'; @@ -262,21 +263,21 @@ export class WinstonLogger implements RootLoggerService { // (undocumented) addRedactions(redactions: Iterable): void; // (undocumented) - child(meta: Record): LoggerService; + child(meta: JsonObject): LoggerService; static colorFormat(): Format; static create(options: WinstonLoggerOptions): WinstonLogger; // (undocumented) - debug(message: string, meta?: Record): void; + debug(message: string, meta?: JsonObject): void; // (undocumented) - error(message: string, meta?: Record): void; + error(message: string, meta?: JsonObject): void; // (undocumented) - info(message: string, meta?: Record): void; + info(message: string, meta?: JsonObject): void; static redacter(): { format: Format; add: (redactions: Iterable) => void; }; // (undocumented) - warn(message: string, meta?: Record): void; + warn(message: string, meta?: JsonObject): void; } // @public (undocumented) @@ -286,7 +287,7 @@ export interface WinstonLoggerOptions { // (undocumented) level: string; // (undocumented) - meta?: Record; + meta?: JsonObject; // (undocumented) transports: transport[]; } diff --git a/packages/backend-app-api/src/logging/WinstonLogger.ts b/packages/backend-app-api/src/logging/WinstonLogger.ts index 8d48015580..06a189508b 100644 --- a/packages/backend-app-api/src/logging/WinstonLogger.ts +++ b/packages/backend-app-api/src/logging/WinstonLogger.ts @@ -18,6 +18,7 @@ import { LoggerService, RootLoggerService, } from '@backstage/backend-plugin-api'; +import { JsonObject } from '@backstage/types'; import { Format, TransformableInfo } from 'logform'; import { Logger, @@ -32,7 +33,7 @@ import { escapeRegExp } from '../lib/escapeRegExp'; * @public */ export interface WinstonLoggerOptions { - meta?: Record; + meta?: JsonObject; level: string; format: Format; transports: Transport[]; @@ -149,23 +150,23 @@ export class WinstonLogger implements RootLoggerService { this.#addRedactions = addRedactions; } - error(message: string, meta?: Record): void { + error(message: string, meta?: JsonObject): void { this.#winston.error(message, meta); } - warn(message: string, meta?: Record): void { + warn(message: string, meta?: JsonObject): void { this.#winston.warn(message, meta); } - info(message: string, meta?: Record): void { + info(message: string, meta?: JsonObject): void { this.#winston.info(message, meta); } - debug(message: string, meta?: Record): void { + debug(message: string, meta?: JsonObject): void { this.#winston.debug(message, meta); } - child(meta: Record): LoggerService { + child(meta: JsonObject): LoggerService { return new WinstonLogger(this.#winston.child(meta)); } diff --git a/packages/backend-common/src/logging/loggerToWinstonLogger.ts b/packages/backend-common/src/logging/loggerToWinstonLogger.ts index f15bd5be81..4ba88358d2 100644 --- a/packages/backend-common/src/logging/loggerToWinstonLogger.ts +++ b/packages/backend-common/src/logging/loggerToWinstonLogger.ts @@ -15,6 +15,7 @@ */ import { LoggerService } from '@backstage/backend-plugin-api'; +import { JsonObject } from '@backstage/types'; import { Logger as WinstonLogger, createLogger } from 'winston'; import Transport, { TransportStreamOptions } from 'winston-transport'; @@ -31,7 +32,7 @@ class BackstageLoggerTransport extends Transport { callback(); return; } - const { level, message, ...meta } = info as { [name: string]: unknown }; + const { level, message, ...meta } = info as JsonObject; switch (level) { case 'error': this.backstageLogger.error(String(message), meta); diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index e0b8fdfa04..3ad972020d 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -8,6 +8,7 @@ import { Config } from '@backstage/config'; import { Handler } from 'express'; import { IdentityApi } from '@backstage/plugin-auth-node'; +import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; import { Knex } from 'knex'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; @@ -311,15 +312,15 @@ export interface LifecycleServiceShutdownOptions { // @public export interface LoggerService { // (undocumented) - child(meta: Record): LoggerService; + child(meta: JsonObject): LoggerService; // (undocumented) - debug(message: string, meta?: Error | Record): void; + debug(message: string, meta?: Error | JsonObject): void; // (undocumented) - error(message: string, meta?: Error | Record): void; + error(message: string, meta?: Error | JsonObject): void; // (undocumented) - info(message: string, meta?: Error | Record): void; + info(message: string, meta?: Error | JsonObject): void; // (undocumented) - warn(message: string, meta?: Error | Record): void; + warn(message: string, meta?: Error | JsonObject): void; } // @public (undocumented) diff --git a/packages/backend-plugin-api/src/services/definitions/LoggerService.ts b/packages/backend-plugin-api/src/services/definitions/LoggerService.ts index ce59b47007..2e4edc60be 100644 --- a/packages/backend-plugin-api/src/services/definitions/LoggerService.ts +++ b/packages/backend-plugin-api/src/services/definitions/LoggerService.ts @@ -14,16 +14,18 @@ * limitations under the License. */ +import { JsonObject } from '@backstage/types'; + /** * A service that provides a logging facility. * * @public */ export interface LoggerService { - error(message: string, meta?: Error | Record): void; - warn(message: string, meta?: Error | Record): void; - info(message: string, meta?: Error | Record): void; - debug(message: string, meta?: Error | Record): void; + error(message: string, meta?: Error | JsonObject): void; + warn(message: string, meta?: Error | JsonObject): void; + info(message: string, meta?: Error | JsonObject): void; + debug(message: string, meta?: Error | JsonObject): void; - child(meta: Record): LoggerService; + child(meta: JsonObject): LoggerService; } diff --git a/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts b/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts index fabba82a0f..8b973eeeab 100644 --- a/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts +++ b/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts @@ -18,6 +18,7 @@ import { LoggerService, RootLoggerService, } from '@backstage/backend-plugin-api'; +import { JsonObject } from '@backstage/types'; import type { mockServices } from './mockServices'; const levels = { @@ -30,7 +31,7 @@ const levels = { export class MockRootLoggerService implements RootLoggerService { #level: number; - #meta: Record; + #meta: JsonObject; static create( options?: mockServices.rootLogger.Options, @@ -42,39 +43,27 @@ export class MockRootLoggerService implements RootLoggerService { return new MockRootLoggerService(levels[level], {}); } - error( - message: string, - meta?: Record | Error | undefined, - ): void { + error(message: string, meta?: JsonObject | Error | undefined): void { this.#log('error', message, meta); } - warn( - message: string, - meta?: Record | Error | undefined, - ): void { + warn(message: string, meta?: JsonObject | Error | undefined): void { this.#log('warn', message, meta); } - info( - message: string, - meta?: Record | Error | undefined, - ): void { + info(message: string, meta?: JsonObject | Error | undefined): void { this.#log('info', message, meta); } - debug( - message: string, - meta?: Record | Error | undefined, - ): void { + debug(message: string, meta?: JsonObject | Error | undefined): void { this.#log('debug', message, meta); } - child(meta: Record): LoggerService { + child(meta: JsonObject): LoggerService { return new MockRootLoggerService(this.#level, { ...this.#meta, ...meta }); } - private constructor(level: number, meta: Record) { + private constructor(level: number, meta: JsonObject) { this.#level = level; this.#meta = meta; } @@ -82,7 +71,7 @@ export class MockRootLoggerService implements RootLoggerService { #log( level: 'error' | 'warn' | 'info' | 'debug', message: string, - meta?: Record | Error | undefined, + meta?: JsonObject | Error | undefined, ) { const levelValue = levels[level] ?? 0; if (levelValue <= this.#level) { From 9a3063377af82a363aa311dcd7a9636ff8dfcaab Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 7 Feb 2023 11:34:06 +0100 Subject: [PATCH 241/423] backend-plugin-api: simplify feature factory implementations Signed-off-by: Patrik Oldsberg --- .../src/wiring/factories.ts | 43 ++++++------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/packages/backend-plugin-api/src/wiring/factories.ts b/packages/backend-plugin-api/src/wiring/factories.ts index 26a65c292a..be55474904 100644 --- a/packages/backend-plugin-api/src/wiring/factories.ts +++ b/packages/backend-plugin-api/src/wiring/factories.ts @@ -17,7 +17,6 @@ import { BackendModuleRegistrationPoints, BackendPluginRegistrationPoints, - BackendRegistrationPoints, BackendFeature, ExtensionPoint, } from './types'; @@ -86,19 +85,14 @@ export interface BackendPluginConfig { export function createBackendPlugin( config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig), ): (...params: TOptions) => BackendFeature { - if (typeof config === 'function') { - return (...options: TOptions) => { - const c = config(...options); - return { - ...c, - id: c.pluginId, - }; + const configCallback = typeof config === 'function' ? config : () => config; + return (...options: TOptions) => { + const c = configCallback(...options); + return { + ...c, + id: c.pluginId, }; - } - return () => ({ - ...config, - id: config.pluginId, - }); + }; } /** @@ -132,21 +126,12 @@ export interface BackendModuleConfig { export function createBackendModule( config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig), ): (...params: TOptions) => BackendFeature { - if (typeof config === 'function') { - return (...options: TOptions) => { - const c = config(...options); - return { - id: `${c.pluginId}.${c.moduleId}`, - register: c.register, - }; + const configCallback = typeof config === 'function' ? config : () => config; + return (...options: TOptions) => { + const c = configCallback(...options); + return { + id: `${c.pluginId}.${c.moduleId}`, + register: c.register, }; - } - return () => ({ - id: `${config.pluginId}.${config.moduleId}`, - register(register: BackendRegistrationPoints) { - return config.register({ - registerInit: register.registerInit.bind(register), - }); - }, - }); + }; } From 783c54d497771958c422bb6d85f9a7b4ec0fe45a Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 12:07:20 +0100 Subject: [PATCH 242/423] chore: ignore this dependency in the typechecking Signed-off-by: blam --- packages/repo-tools/src/commands/type-deps/type-deps.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/repo-tools/src/commands/type-deps/type-deps.ts b/packages/repo-tools/src/commands/type-deps/type-deps.ts index 4f8e5e5529..852cec34d2 100644 --- a/packages/repo-tools/src/commands/type-deps/type-deps.ts +++ b/packages/repo-tools/src/commands/type-deps/type-deps.ts @@ -196,6 +196,14 @@ function findTypeDepErrors(typeDeps: string[], pkg: Package) { } for (const dep of deps) { + // Remove this once the logform issue has been fixed. + // https://github.com/winstonjs/logform/issues/242 + if ( + pkg.packageJson.name === '@backstage/backend-common' && + dep === '@types/triple-beam' + ) { + continue; + } errors.push( mkErr('WrongDepError', `Should be dev dep ${dep}`, { dep, From 70ae2c363496ce54033adb1af80936ed6f62ae01 Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Tue, 7 Feb 2023 11:32:34 +0000 Subject: [PATCH 243/423] fix stepper hasErrors to not bottom out at first error Signed-off-by: Paul Cowan --- .changeset/chilled-rice-own.md | 5 ++ .../Stepper/createAsyncValidators.test.ts | 33 ++++++++++ .../src/next/components/Stepper/utils.test.ts | 61 +++++++++++++++++++ .../src/next/components/Stepper/utils.ts | 6 +- 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 .changeset/chilled-rice-own.md create mode 100644 plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts diff --git a/.changeset/chilled-rice-own.md b/.changeset/chilled-rice-own.md new file mode 100644 index 0000000000..58810734cf --- /dev/null +++ b/.changeset/chilled-rice-own.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +fix `stepper` `hasErrors` to not bottom out at first error diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index 15fa944b0f..fe8b41a9f3 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -181,6 +181,18 @@ describe('createAsyncValidators', () => { title: 'General', type: 'object', properties: { + address: { + type: 'object', + 'ui:field': 'AddressField', + properties: { + street: { + type: 'string', + }, + postcode: { + type: 'string', + }, + }, + }, name: { title: 'Name', type: 'string', @@ -207,6 +219,19 @@ describe('createAsyncValidators', () => { }, }; + const AddressField: NextCustomFieldValidator<{ + street?: string; + postcode?: string; + }> = (value, { addError }) => { + if (!value.postcode) { + addError('postcode is missing!'); + } + + if (!value.street) { + addError('street is missing here!'); + } + }; + const NameField: NextCustomFieldValidator = ( value, { addError }, @@ -217,6 +242,7 @@ describe('createAsyncValidators', () => { }; const validators = { + AddressField: AddressField as NextCustomFieldValidator, NameField: NameField as NextCustomFieldValidator, }; @@ -228,11 +254,18 @@ describe('createAsyncValidators', () => { validate({ actionType: 'newThing', general: { + address: { + street: 'street', + postcode: 'postcode', + }, name: undefined, }, }), ).resolves.toEqual({ general: { + address: expect.objectContaining({ + __errors: [], + }), name: expect.objectContaining({ __errors: ['something is broken here!'], }), diff --git a/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts new file mode 100644 index 0000000000..f6a1b012ac --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts @@ -0,0 +1,61 @@ +/* + * Copyright 2023 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 { hasErrors } from './utils'; + +describe('hasErrors', () => { + it('should return false for empty _errors', () => { + expect( + hasErrors({ + name: { + __errors: [], + addError: jest.fn(), + }, + }), + ).toBe(false); + }); + + it('should return true for a single error', () => { + expect( + hasErrors({ + name: { + __errors: ['an error'], + addError: jest.fn(), + }, + }), + ).toBe(true); + }); + + it('should return true for more than one error', () => { + expect( + hasErrors({ + name: { + __errors: [], + addError: jest.fn(), + }, + general: { + address: { + __errors: [], + addError: jest.fn(), + }, + name: { + __errors: ['something is broken here!'], + addError: jest.fn(), + }, + }, + }), + ).toBe(true); + }); +}); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/utils.ts b/plugins/scaffolder-react/src/next/components/Stepper/utils.ts index e4da5882e5..7d3efa9d94 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/utils.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/utils.ts @@ -28,7 +28,11 @@ export function hasErrors(errors?: FormValidation): boolean { for (const error of Object.values(errors)) { if (isFieldValidation(error)) { - return (error.__errors ?? []).length > 0; + if ((error.__errors ?? []).length > 0) { + return true; + } + + continue; } return hasErrors(error); From 9603cc9e816d7c1d3f6402df424fd3a97a645378 Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Tue, 7 Feb 2023 12:37:55 +0100 Subject: [PATCH 244/423] Delete chilled-rice-own.md Signed-off-by: Ben Lambert --- .changeset/chilled-rice-own.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changeset/chilled-rice-own.md diff --git a/.changeset/chilled-rice-own.md b/.changeset/chilled-rice-own.md deleted file mode 100644 index 58810734cf..0000000000 --- a/.changeset/chilled-rice-own.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': patch ---- - -fix `stepper` `hasErrors` to not bottom out at first error From 610d65e143b6bd86bc0fe6cb1d250b6636bde3e4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 7 Feb 2023 13:11:24 +0100 Subject: [PATCH 245/423] backend-plugin-api: make BackendFeature opaque Signed-off-by: Patrik Oldsberg --- .changeset/nervous-phones-shout.md | 6 ++ .changeset/yellow-roses-tell.md | 5 + .../src/wiring/BackendInitializer.ts | 81 +++++++------- packages/backend-app-api/src/wiring/types.ts | 6 +- packages/backend-plugin-api/api-report.md | 24 +---- .../src/wiring/factories.test.ts | 59 ++++++++-- .../src/wiring/factories.ts | 101 ++++++++++++++++-- .../backend-plugin-api/src/wiring/index.ts | 1 - .../backend-plugin-api/src/wiring/types.ts | 55 ++++++---- .../src/next/wiring/TestBackend.ts | 21 ++-- 10 files changed, 250 insertions(+), 109 deletions(-) create mode 100644 .changeset/nervous-phones-shout.md create mode 100644 .changeset/yellow-roses-tell.md diff --git a/.changeset/nervous-phones-shout.md b/.changeset/nervous-phones-shout.md new file mode 100644 index 0000000000..a4e46b3be9 --- /dev/null +++ b/.changeset/nervous-phones-shout.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-test-utils': patch +'@backstage/backend-app-api': patch +--- + +Updates to match new `BackendFeature` type. diff --git a/.changeset/yellow-roses-tell.md b/.changeset/yellow-roses-tell.md new file mode 100644 index 0000000000..ad645df294 --- /dev/null +++ b/.changeset/yellow-roses-tell.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +Switched `BackendFeature` to be an opaque type. diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index 4bdee8b085..6c551f082f 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -26,10 +26,13 @@ import { EnumerableServiceHolder, ServiceOrExtensionPoint, } from './types'; +// Direct internal import to avoid duplication +// eslint-disable-next-line @backstage/no-forbidden-package-imports +import { InternalBackendFeature } from '@backstage/backend-plugin-api/src/wiring/types'; export class BackendInitializer { #startPromise?: Promise; - #features = new Map(); + #features = new Array(); #registerInits = new Array(); #extensionPoints = new Map, unknown>(); #serviceHolder: EnumerableServiceHolder; @@ -74,11 +77,22 @@ export class BackendInitializer { return Object.fromEntries(result); } - add(feature: BackendFeature, options?: TOptions) { + add(feature: BackendFeature) { if (this.#startPromise) { throw new Error('feature can not be added after the backend has started'); } - this.#features.set(feature, options); + if (feature.$$type !== '@backstage/BackendFeature') { + throw new Error( + `Failed to add feature, invalid type '${feature.$$type}'`, + ); + } + const internalFeature = feature as InternalBackendFeature; + if (internalFeature.version !== 'v1') { + throw new Error( + `Failed to add feature, invalid version '${internalFeature.version}'`, + ); + } + this.#features.push(internalFeature); } async start(): Promise { @@ -117,50 +131,39 @@ export class BackendInitializer { } // Initialize all features - for (const [feature] of this.#features) { - const provides = new Set>(); + for (const feature of this.#features) { + for (const r of feature.getRegistrations()) { + const provides = new Set>(); - let registerInit: BackendRegisterInit | undefined = undefined; + if (r.type === 'plugin') { + for (const [extRef, extImpl] of r.extensionPoints) { + if (this.#extensionPoints.has(extRef)) { + throw new Error( + `ExtensionPoint with ID '${extRef.id}' is already registered`, + ); + } + this.#extensionPoints.set(extRef, extImpl); + provides.add(extRef); + } + } - feature.register({ - registerExtensionPoint: (extensionPointRef, impl) => { - if (registerInit) { - throw new Error('registerExtensionPoint called after registerInit'); - } - if (this.#extensionPoints.has(extensionPointRef)) { - throw new Error(`API ${extensionPointRef.id} already registered`); - } - this.#extensionPoints.set(extensionPointRef, impl); - provides.add(extensionPointRef); - }, - registerInit: registerOptions => { - if (registerInit) { - throw new Error('registerInit must only be called once'); - } - registerInit = { - id: feature.id, - provides, - consumes: new Set(Object.values(registerOptions.deps)), - deps: registerOptions.deps, - init: registerOptions.init as BackendRegisterInit['init'], - }; - }, - }); - - if (!registerInit) { - throw new Error( - `registerInit was not called by register in ${feature.id}`, - ); + this.#registerInits.push({ + id: r.type === 'plugin' ? r.pluginId : `${r.pluginId}.${r.moduleId}`, + provides, + consumes: new Set(Object.values(r.init.deps)), + init: r.init, + }); } - - this.#registerInits.push(registerInit); } const orderedRegisterResults = this.#resolveInitOrder(this.#registerInits); for (const registerInit of orderedRegisterResults) { - const deps = await this.#getInitDeps(registerInit.deps, registerInit.id); - await registerInit.init(deps); + const deps = await this.#getInitDeps( + registerInit.init.deps, + registerInit.id, + ); + await registerInit.init.func(deps); } } diff --git a/packages/backend-app-api/src/wiring/types.ts b/packages/backend-app-api/src/wiring/types.ts index d3c4fc48c7..2a91bf46b9 100644 --- a/packages/backend-app-api/src/wiring/types.ts +++ b/packages/backend-app-api/src/wiring/types.ts @@ -34,8 +34,10 @@ export interface BackendRegisterInit { id: string; consumes: Set; provides: Set; - deps: { [name: string]: ServiceOrExtensionPoint }; - init: (deps: { [name: string]: unknown }) => Promise; + init: { + deps: { [name: string]: ServiceOrExtensionPoint }; + func: (deps: { [name: string]: unknown }) => Promise; + }; } /** diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index 4b8e0298ec..6dbafd0242 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -17,9 +17,7 @@ import { Readable } from 'stream'; // @public (undocumented) export interface BackendFeature { // (undocumented) - id: string; - // (undocumented) - register(reg: BackendRegistrationPoints): void; + $$type: '@backstage/BackendFeature'; } // @public @@ -72,26 +70,6 @@ export interface BackendPluginRegistrationPoints { }): void; } -// @public -export interface BackendRegistrationPoints { - // (undocumented) - registerExtensionPoint( - ref: ExtensionPoint, - impl: TExtensionPoint, - ): void; - // (undocumented) - registerInit< - Deps extends { - [name in string]: unknown; - }, - >(options: { - deps: { - [name in keyof Deps]: ServiceRef | ExtensionPoint; - }; - init(deps: Deps): Promise; - }): void; -} - // @public export interface CacheClient { delete(key: string): Promise; diff --git a/packages/backend-plugin-api/src/wiring/factories.test.ts b/packages/backend-plugin-api/src/wiring/factories.test.ts index 8e1b30ea53..ae199d84e4 100644 --- a/packages/backend-plugin-api/src/wiring/factories.test.ts +++ b/packages/backend-plugin-api/src/wiring/factories.test.ts @@ -19,6 +19,7 @@ import { createBackendPlugin, createExtensionPoint, } from './factories'; +import { InternalBackendFeature } from './types'; describe('createExtensionPoint', () => { it('should create an ExtensionPoint', () => { @@ -34,11 +35,30 @@ describe('createBackendPlugin', () => { it('should create a BackendPlugin', () => { const plugin = createBackendPlugin((_options: { a: string }) => ({ pluginId: 'x', - register() {}, + register(r) { + r.registerInit({ deps: {}, async init() {} }); + }, })); expect(plugin).toBeDefined(); expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin({ a: 'a' }).id).toBe('x'); + expect(plugin({ a: 'a' })).toEqual({ + $$type: '@backstage/BackendFeature', + version: 'v1', + getRegistrations: expect.any(Function), + }); + expect( + (plugin({ a: 'a' }) as InternalBackendFeature).getRegistrations(), + ).toEqual([ + { + type: 'plugin', + pluginId: 'x', + extensionPoints: [], + init: { + deps: expect.any(Object), + func: expect.any(Function), + }, + }, + ]); // @ts-expect-error expect(plugin()).toBeDefined(); // @ts-expect-error @@ -79,7 +99,11 @@ describe('createBackendPlugin', () => { })); expect(plugin).toBeDefined(); expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin({ a: 'a' }).id).toBe('x'); + expect(plugin({ a: 'a' })).toEqual({ + $$type: '@backstage/BackendFeature', + version: 'v1', + getRegistrations: expect.any(Function), + }); // @ts-expect-error expect(plugin()).toBeDefined(); // @ts-expect-error @@ -107,11 +131,30 @@ describe('createBackendModule', () => { const mod = createBackendModule((_options: { a: string }) => ({ pluginId: 'x', moduleId: 'y', - register() {}, + register(r) { + r.registerInit({ deps: {}, async init() {} }); + }, })); expect(mod).toBeDefined(); expect(mod({ a: 'a' })).toBeDefined(); - expect(mod({ a: 'a' }).id).toBe('x.y'); + expect(mod({ a: 'a' })).toEqual({ + $$type: '@backstage/BackendFeature', + version: 'v1', + getRegistrations: expect.any(Function), + }); + expect( + (mod({ a: 'a' }) as InternalBackendFeature).getRegistrations(), + ).toEqual([ + { + type: 'module', + pluginId: 'x', + moduleId: 'y', + init: { + deps: expect.any(Object), + func: expect.any(Function), + }, + }, + ]); // @ts-expect-error expect(mod()).toBeDefined(); // @ts-expect-error @@ -155,7 +198,11 @@ describe('createBackendModule', () => { })); expect(mod).toBeDefined(); expect(mod({ a: 'a' })).toBeDefined(); - expect(mod({ a: 'a' }).id).toBe('x.y'); + expect(mod({ a: 'a' })).toEqual({ + $$type: '@backstage/BackendFeature', + version: 'v1', + getRegistrations: expect.any(Function), + }); // @ts-expect-error expect(mod()).toBeDefined(); // @ts-expect-error diff --git a/packages/backend-plugin-api/src/wiring/factories.ts b/packages/backend-plugin-api/src/wiring/factories.ts index be55474904..928c933af0 100644 --- a/packages/backend-plugin-api/src/wiring/factories.ts +++ b/packages/backend-plugin-api/src/wiring/factories.ts @@ -19,6 +19,9 @@ import { BackendPluginRegistrationPoints, BackendFeature, ExtensionPoint, + InternalBackendFeature, + InternalBackendModuleRegistration, + InternalBackendPluginRegistration, } from './types'; /** @@ -86,11 +89,59 @@ export function createBackendPlugin( config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig), ): (...params: TOptions) => BackendFeature { const configCallback = typeof config === 'function' ? config : () => config; - return (...options: TOptions) => { + return (...options: TOptions): InternalBackendFeature => { const c = configCallback(...options); + + let registrations: InternalBackendPluginRegistration[]; + return { - ...c, - id: c.pluginId, + $$type: '@backstage/BackendFeature', + version: 'v1', + getRegistrations() { + if (registrations) { + return registrations; + } + const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] = + []; + let init: InternalBackendPluginRegistration['init'] | undefined = + undefined; + + c.register({ + registerExtensionPoint(ext, impl) { + if (init) { + throw new Error( + 'registerExtensionPoint called after registerInit', + ); + } + extensionPoints.push([ext, impl]); + }, + registerInit(regInit) { + if (init) { + throw new Error('registerInit must only be called once'); + } + init = { + deps: regInit.deps, + func: regInit.init, + }; + }, + }); + + if (!init) { + throw new Error( + `registerInit was not called by register in ${c.pluginId}`, + ); + } + + registrations = [ + { + type: 'plugin', + pluginId: c.pluginId, + extensionPoints, + init, + }, + ]; + return registrations; + }, }; }; } @@ -127,11 +178,49 @@ export function createBackendModule( config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig), ): (...params: TOptions) => BackendFeature { const configCallback = typeof config === 'function' ? config : () => config; - return (...options: TOptions) => { + return (...options: TOptions): InternalBackendFeature => { const c = configCallback(...options); + + let registrations: InternalBackendModuleRegistration[]; + return { - id: `${c.pluginId}.${c.moduleId}`, - register: c.register, + $$type: '@backstage/BackendFeature', + version: 'v1', + getRegistrations() { + if (registrations) { + return registrations; + } + let init: InternalBackendModuleRegistration['init'] | undefined = + undefined; + + c.register({ + registerInit(regInit) { + if (init) { + throw new Error('registerInit must only be called once'); + } + init = { + deps: regInit.deps, + func: regInit.init, + }; + }, + }); + + if (!init) { + throw new Error( + `registerInit was not called by register in ${c.moduleId} module for ${c.pluginId}`, + ); + } + + registrations = [ + { + type: 'module', + pluginId: c.pluginId, + moduleId: c.moduleId, + init, + }, + ]; + return registrations; + }, }; }; } diff --git a/packages/backend-plugin-api/src/wiring/index.ts b/packages/backend-plugin-api/src/wiring/index.ts index e0c25eeb4e..242301ea4d 100644 --- a/packages/backend-plugin-api/src/wiring/index.ts +++ b/packages/backend-plugin-api/src/wiring/index.ts @@ -32,7 +32,6 @@ export { export type { BackendModuleRegistrationPoints, BackendPluginRegistrationPoints, - BackendRegistrationPoints, BackendFeature, ExtensionPoint, } from './types'; diff --git a/packages/backend-plugin-api/src/wiring/types.ts b/packages/backend-plugin-api/src/wiring/types.ts index ab8ce07284..c81ee3ceb7 100644 --- a/packages/backend-plugin-api/src/wiring/types.ts +++ b/packages/backend-plugin-api/src/wiring/types.ts @@ -35,26 +35,6 @@ export type ExtensionPoint = { $$type: '@backstage/ExtensionPoint'; }; -/** - * The callbacks passed to the `register` method of a backend feature; this is - * essentially a superset of {@link BackendPluginRegistrationPoints} and - * {@link BackendModuleRegistrationPoints}. - * - * @public - */ -export interface BackendRegistrationPoints { - registerExtensionPoint( - ref: ExtensionPoint, - impl: TExtensionPoint, - ): void; - registerInit(options: { - deps: { - [name in keyof Deps]: ServiceRef | ExtensionPoint; - }; - init(deps: Deps): Promise; - }): void; -} - /** * The callbacks passed to the `register` method of a backend plugin. * @@ -89,7 +69,36 @@ export interface BackendModuleRegistrationPoints { /** @public */ export interface BackendFeature { - // TODO(Rugvip): Try to get rid of the ID at this level, allowing for a feature to register multiple features as a bundle - id: string; - register(reg: BackendRegistrationPoints): void; + // NOTE: This type is opaque in order to simplify future API evolution. + $$type: '@backstage/BackendFeature'; +} + +/** @internal */ +export interface InternalBackendFeature extends BackendFeature { + version: 'v1'; + getRegistrations(): Array< + InternalBackendPluginRegistration | InternalBackendModuleRegistration + >; +} + +/** @internal */ +export interface InternalBackendPluginRegistration { + pluginId: string; + type: 'plugin'; + extensionPoints: Array, unknown]>; + init: { + deps: Record>; + func(deps: Record): Promise; + }; +} + +/** @internal */ +export interface InternalBackendModuleRegistration { + pluginId: string; + moduleId: string; + type: 'module'; + init: { + deps: Record | ExtensionPoint>; + func(deps: Record): Promise; + }; } diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.ts index 27a8c5bceb..bbda9854d4 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.ts @@ -30,6 +30,7 @@ import { BackendFeature, ExtensionPoint, coreServices, + createBackendPlugin, } from '@backstage/backend-plugin-api'; import { mockServices } from '../services'; import { ConfigReader } from '@backstage/config'; @@ -193,16 +194,18 @@ export async function startTestBackend< backendInstancesToCleanUp.push(backend); - backend.add({ - id: `---test-extension-point-registrar`, - register(reg) { - for (const [ref, impl] of extensionPoints) { - reg.registerExtensionPoint(ref, impl); - } + backend.add( + createBackendPlugin({ + pluginId: `---test-extension-point-registrar`, + register(reg) { + for (const [ref, impl] of extensionPoints) { + reg.registerExtensionPoint(ref, impl); + } - reg.registerInit({ deps: {}, async init() {} }); - }, - }); + reg.registerInit({ deps: {}, async init() {} }); + }, + })(), + ); for (const feature of features) { backend.add(feature); From d766419067b559bc1075932c11ae6fb397510f5f Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Tue, 7 Feb 2023 07:35:24 -0500 Subject: [PATCH 246/423] Revert "add changeset documenting github-actions plugin fix" This reverts commit b623d1c8980a623cf04bd9ee44131536049bbd7a. Signed-off-by: Mike Ball --- .changeset/neat-elephants-breathe.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changeset/neat-elephants-breathe.md diff --git a/.changeset/neat-elephants-breathe.md b/.changeset/neat-elephants-breathe.md deleted file mode 100644 index d1f88556e1..0000000000 --- a/.changeset/neat-elephants-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-github-actions': patch ---- - -`yarn start` now starts a functional dev environment using a mock GitHub API to properly render the `` component. From 35d736be0e5d09ff884145bb22f6f05f5bc2c106 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 13:15:52 +0100 Subject: [PATCH 247/423] chore: renaming to ServiceFactory Signed-off-by: blam --- .../cache/{cacheFactory.ts => cacheServiceFactory.ts} | 2 +- .../src/services/implementations/cache/index.ts | 2 +- .../config/{configFactory.ts => configServiceFactory.ts} | 2 +- .../src/services/implementations/config/index.ts | 4 ++-- .../{databaseFactory.ts => databaseServiceFactory.ts} | 2 +- .../src/services/implementations/database/index.ts | 2 +- .../{discoveryFactory.ts => discoveryServiceFactory.ts} | 2 +- .../src/services/implementations/discovery/index.ts | 2 +- ...uterFactory.test.ts => httpRouterServiceFactory.test.ts} | 6 +++--- .../{httpRouterFactory.ts => httpRouterServiceFactory.ts} | 2 +- .../src/services/implementations/httpRouter/index.ts | 4 ++-- .../{identityFactory.ts => identityServiceFactory.ts} | 2 +- .../src/services/implementations/identity/index.ts | 4 ++-- .../src/services/implementations/lifecycle/index.ts | 2 +- .../{lifecycleFactory.ts => lifecycleServiceFactory.ts} | 2 +- .../src/services/implementations/logger/index.ts | 2 +- .../logger/{loggerFactory.ts => loggerServiceFactory.ts} | 2 +- .../src/services/implementations/permissions/index.ts | 2 +- .../{permissionsFactory.ts => permissionsServiceFactory.ts} | 2 +- .../src/services/implementations/rootHttpRouter/index.ts | 4 ++-- ...HttpRouterFactory.ts => rootHttpRouterServiceFactory.ts} | 2 +- .../src/services/implementations/rootLifecycle/index.ts | 2 +- ...eFactory.test.ts => rootLifecycleServiceFactory.test.ts} | 2 +- ...otLifecycleFactory.ts => rootLifecycleServiceFactory.ts} | 2 +- .../src/services/implementations/rootLogger/index.ts | 2 +- .../{rootLoggerFactory.ts => rootLoggerServiceFactory.ts} | 2 +- .../src/services/implementations/scheduler/index.ts | 2 +- ...dulerFactory.test.ts => schedulerServiceFactory.test.ts} | 4 ++-- .../{schedulerFactory.ts => schedulerServiceFactory.ts} | 2 +- .../src/services/implementations/tokenManager/index.ts | 2 +- ...erFactory.test.ts => tokenManagerServiceFactory.test.ts} | 4 ++-- ...tokenManagerFactory.ts => tokenManagerServiceFactory.ts} | 2 +- .../src/services/implementations/urlReader/index.ts | 2 +- .../{urlReaderFactory.ts => urlReaderServiceFactory.ts} | 2 +- packages/backend-app-api/src/wiring/BackendInitializer.ts | 2 +- 35 files changed, 43 insertions(+), 43 deletions(-) rename packages/backend-app-api/src/services/implementations/cache/{cacheFactory.ts => cacheServiceFactory.ts} (94%) rename packages/backend-app-api/src/services/implementations/config/{configFactory.ts => configServiceFactory.ts} (95%) rename packages/backend-app-api/src/services/implementations/database/{databaseFactory.ts => databaseServiceFactory.ts} (96%) rename packages/backend-app-api/src/services/implementations/discovery/{discoveryFactory.ts => discoveryServiceFactory.ts} (93%) rename packages/backend-app-api/src/services/implementations/httpRouter/{httpRouterFactory.test.ts => httpRouterServiceFactory.test.ts} (93%) rename packages/backend-app-api/src/services/implementations/httpRouter/{httpRouterFactory.ts => httpRouterServiceFactory.ts} (95%) rename packages/backend-app-api/src/services/implementations/identity/{identityFactory.ts => identityServiceFactory.ts} (95%) rename packages/backend-app-api/src/services/implementations/lifecycle/{lifecycleFactory.ts => lifecycleServiceFactory.ts} (95%) rename packages/backend-app-api/src/services/implementations/logger/{loggerFactory.ts => loggerServiceFactory.ts} (94%) rename packages/backend-app-api/src/services/implementations/permissions/{permissionsFactory.ts => permissionsServiceFactory.ts} (94%) rename packages/backend-app-api/src/services/implementations/rootHttpRouter/{rootHttpRouterFactory.ts => rootHttpRouterServiceFactory.ts} (97%) rename packages/backend-app-api/src/services/implementations/rootLifecycle/{rootLifecycleFactory.test.ts => rootLifecycleServiceFactory.test.ts} (95%) rename packages/backend-app-api/src/services/implementations/rootLifecycle/{rootLifecycleFactory.ts => rootLifecycleServiceFactory.ts} (96%) rename packages/backend-app-api/src/services/implementations/rootLogger/{rootLoggerFactory.ts => rootLoggerServiceFactory.ts} (96%) rename packages/backend-app-api/src/services/implementations/scheduler/{schedulerFactory.test.ts => schedulerServiceFactory.test.ts} (94%) rename packages/backend-app-api/src/services/implementations/scheduler/{schedulerFactory.ts => schedulerServiceFactory.ts} (95%) rename packages/backend-app-api/src/services/implementations/tokenManager/{tokenManagerFactory.test.ts => tokenManagerServiceFactory.test.ts} (91%) rename packages/backend-app-api/src/services/implementations/tokenManager/{tokenManagerFactory.ts => tokenManagerServiceFactory.ts} (94%) rename packages/backend-app-api/src/services/implementations/urlReader/{urlReaderFactory.ts => urlReaderServiceFactory.ts} (94%) diff --git a/packages/backend-app-api/src/services/implementations/cache/cacheFactory.ts b/packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts similarity index 94% rename from packages/backend-app-api/src/services/implementations/cache/cacheFactory.ts rename to packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts index 426a890c00..3ccd2a2fac 100644 --- a/packages/backend-app-api/src/services/implementations/cache/cacheFactory.ts +++ b/packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts @@ -21,7 +21,7 @@ import { } from '@backstage/backend-plugin-api'; /** @public */ -export const cacheFactory = createServiceFactory({ +export const cacheServiceFactory = createServiceFactory({ service: coreServices.cache, deps: { config: coreServices.config, diff --git a/packages/backend-app-api/src/services/implementations/cache/index.ts b/packages/backend-app-api/src/services/implementations/cache/index.ts index 3d1bcd75a7..f96ee77182 100644 --- a/packages/backend-app-api/src/services/implementations/cache/index.ts +++ b/packages/backend-app-api/src/services/implementations/cache/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { cacheFactory } from './cacheFactory'; +export { cacheServiceFactory } from './cacheServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/config/configFactory.ts b/packages/backend-app-api/src/services/implementations/config/configServiceFactory.ts similarity index 95% rename from packages/backend-app-api/src/services/implementations/config/configFactory.ts rename to packages/backend-app-api/src/services/implementations/config/configServiceFactory.ts index 833730fdbd..459c0d9f0c 100644 --- a/packages/backend-app-api/src/services/implementations/config/configFactory.ts +++ b/packages/backend-app-api/src/services/implementations/config/configServiceFactory.ts @@ -35,7 +35,7 @@ export interface ConfigFactoryOptions { } /** @public */ -export const configFactory = createServiceFactory( +export const configServiceFactory = createServiceFactory( (options?: ConfigFactoryOptions) => ({ service: coreServices.config, deps: {}, diff --git a/packages/backend-app-api/src/services/implementations/config/index.ts b/packages/backend-app-api/src/services/implementations/config/index.ts index b23c47ce0a..690f1e2d36 100644 --- a/packages/backend-app-api/src/services/implementations/config/index.ts +++ b/packages/backend-app-api/src/services/implementations/config/index.ts @@ -14,5 +14,5 @@ * limitations under the License. */ -export { configFactory } from './configFactory'; -export type { ConfigFactoryOptions } from './configFactory'; +export { configServiceFactory } from './configServiceFactory'; +export type { ConfigFactoryOptions } from './configServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/database/databaseFactory.ts b/packages/backend-app-api/src/services/implementations/database/databaseServiceFactory.ts similarity index 96% rename from packages/backend-app-api/src/services/implementations/database/databaseFactory.ts rename to packages/backend-app-api/src/services/implementations/database/databaseServiceFactory.ts index 4d95f863db..05e2f1deb9 100644 --- a/packages/backend-app-api/src/services/implementations/database/databaseFactory.ts +++ b/packages/backend-app-api/src/services/implementations/database/databaseServiceFactory.ts @@ -22,7 +22,7 @@ import { import { ConfigReader } from '@backstage/config'; /** @public */ -export const databaseFactory = createServiceFactory({ +export const databaseServiceFactory = createServiceFactory({ service: coreServices.database, deps: { config: coreServices.config, diff --git a/packages/backend-app-api/src/services/implementations/database/index.ts b/packages/backend-app-api/src/services/implementations/database/index.ts index 0045630e15..d676c8013e 100644 --- a/packages/backend-app-api/src/services/implementations/database/index.ts +++ b/packages/backend-app-api/src/services/implementations/database/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { databaseFactory } from './databaseFactory'; +export { databaseServiceFactory } from './databaseServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/discovery/discoveryFactory.ts b/packages/backend-app-api/src/services/implementations/discovery/discoveryServiceFactory.ts similarity index 93% rename from packages/backend-app-api/src/services/implementations/discovery/discoveryFactory.ts rename to packages/backend-app-api/src/services/implementations/discovery/discoveryServiceFactory.ts index 51ea3c881d..6c0da8521d 100644 --- a/packages/backend-app-api/src/services/implementations/discovery/discoveryFactory.ts +++ b/packages/backend-app-api/src/services/implementations/discovery/discoveryServiceFactory.ts @@ -21,7 +21,7 @@ import { } from '@backstage/backend-plugin-api'; /** @public */ -export const discoveryFactory = createServiceFactory({ +export const discoveryServiceFactory = createServiceFactory({ service: coreServices.discovery, deps: { config: coreServices.config, diff --git a/packages/backend-app-api/src/services/implementations/discovery/index.ts b/packages/backend-app-api/src/services/implementations/discovery/index.ts index 182b9f6cd2..7b3b9816b1 100644 --- a/packages/backend-app-api/src/services/implementations/discovery/index.ts +++ b/packages/backend-app-api/src/services/implementations/discovery/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { discoveryFactory } from './discoveryFactory'; +export { discoveryServiceFactory } from './discoveryServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.test.ts b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.test.ts similarity index 93% rename from packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.test.ts rename to packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.test.ts index 150bd628f5..2e124c98b6 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.test.ts @@ -18,12 +18,12 @@ import { HttpRouterService, ServiceFactory, } from '@backstage/backend-plugin-api'; -import { httpRouterFactory } from './httpRouterFactory'; +import { httpRouterServiceFactory } from './httpRouterServiceFactory'; describe('httpRouterFactory', () => { it('should register plugin paths', async () => { const rootHttpRouter = { use: jest.fn() }; - const factory = httpRouterFactory() as Exclude< + const factory = httpRouterServiceFactory() as Exclude< ServiceFactory, { scope: 'root' } >; @@ -55,7 +55,7 @@ describe('httpRouterFactory', () => { it('should use custom path generator', async () => { const rootHttpRouter = { use: jest.fn() }; - const factory = httpRouterFactory({ + const factory = httpRouterServiceFactory({ getPath: id => `/some/${id}/path`, }) as Exclude, { scope: 'root' }>; diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.ts b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.ts similarity index 95% rename from packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.ts rename to packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.ts index 218910345d..bbd54b7ade 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.ts @@ -31,7 +31,7 @@ export interface HttpRouterFactoryOptions { } /** @public */ -export const httpRouterFactory = createServiceFactory( +export const httpRouterServiceFactory = createServiceFactory( (options?: HttpRouterFactoryOptions) => ({ service: coreServices.httpRouter, deps: { diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/index.ts b/packages/backend-app-api/src/services/implementations/httpRouter/index.ts index f2db660414..9dfb01c5be 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/index.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouter/index.ts @@ -14,5 +14,5 @@ * limitations under the License. */ -export { httpRouterFactory } from './httpRouterFactory'; -export type { HttpRouterFactoryOptions } from './httpRouterFactory'; +export { httpRouterServiceFactory } from './httpRouterServiceFactory'; +export type { HttpRouterFactoryOptions } from './httpRouterServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/identity/identityFactory.ts b/packages/backend-app-api/src/services/implementations/identity/identityServiceFactory.ts similarity index 95% rename from packages/backend-app-api/src/services/implementations/identity/identityFactory.ts rename to packages/backend-app-api/src/services/implementations/identity/identityServiceFactory.ts index 0031979390..58da1c37d5 100644 --- a/packages/backend-app-api/src/services/implementations/identity/identityFactory.ts +++ b/packages/backend-app-api/src/services/implementations/identity/identityServiceFactory.ts @@ -34,7 +34,7 @@ export type IdentityFactoryOptions = { }; /** @public */ -export const identityFactory = createServiceFactory( +export const identityServiceFactory = createServiceFactory( (options?: IdentityFactoryOptions) => ({ service: coreServices.identity, deps: { diff --git a/packages/backend-app-api/src/services/implementations/identity/index.ts b/packages/backend-app-api/src/services/implementations/identity/index.ts index 9382232620..bf2f4436dd 100644 --- a/packages/backend-app-api/src/services/implementations/identity/index.ts +++ b/packages/backend-app-api/src/services/implementations/identity/index.ts @@ -14,5 +14,5 @@ * limitations under the License. */ -export { identityFactory } from './identityFactory'; -export type { IdentityFactoryOptions } from './identityFactory'; +export { identityServiceFactory } from './identityServiceFactory'; +export type { IdentityFactoryOptions } from './identityServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/lifecycle/index.ts b/packages/backend-app-api/src/services/implementations/lifecycle/index.ts index cfca37a162..8dac4c26b4 100644 --- a/packages/backend-app-api/src/services/implementations/lifecycle/index.ts +++ b/packages/backend-app-api/src/services/implementations/lifecycle/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { lifecycleFactory } from './lifecycleFactory'; +export { lifecycleServiceFactory } from './lifecycleServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts b/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleServiceFactory.ts similarity index 95% rename from packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts rename to packages/backend-app-api/src/services/implementations/lifecycle/lifecycleServiceFactory.ts index 27c1a139fd..79658c0d42 100644 --- a/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts +++ b/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleServiceFactory.ts @@ -24,7 +24,7 @@ import { * Allows plugins to register shutdown hooks that are run when the process is about to exit. * @public */ -export const lifecycleFactory = createServiceFactory({ +export const lifecycleServiceFactory = createServiceFactory({ service: coreServices.lifecycle, deps: { logger: coreServices.logger, diff --git a/packages/backend-app-api/src/services/implementations/logger/index.ts b/packages/backend-app-api/src/services/implementations/logger/index.ts index acef1b178f..ca52bf5193 100644 --- a/packages/backend-app-api/src/services/implementations/logger/index.ts +++ b/packages/backend-app-api/src/services/implementations/logger/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { loggerFactory } from './loggerFactory'; +export { loggerServiceFactory } from './loggerServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/logger/loggerFactory.ts b/packages/backend-app-api/src/services/implementations/logger/loggerServiceFactory.ts similarity index 94% rename from packages/backend-app-api/src/services/implementations/logger/loggerFactory.ts rename to packages/backend-app-api/src/services/implementations/logger/loggerServiceFactory.ts index 60c91d0ee6..d9158529ca 100644 --- a/packages/backend-app-api/src/services/implementations/logger/loggerFactory.ts +++ b/packages/backend-app-api/src/services/implementations/logger/loggerServiceFactory.ts @@ -20,7 +20,7 @@ import { } from '@backstage/backend-plugin-api'; /** @public */ -export const loggerFactory = createServiceFactory({ +export const loggerServiceFactory = createServiceFactory({ service: coreServices.logger, deps: { rootLogger: coreServices.rootLogger, diff --git a/packages/backend-app-api/src/services/implementations/permissions/index.ts b/packages/backend-app-api/src/services/implementations/permissions/index.ts index 29a6aa237a..781dda31a0 100644 --- a/packages/backend-app-api/src/services/implementations/permissions/index.ts +++ b/packages/backend-app-api/src/services/implementations/permissions/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { permissionsFactory } from './permissionsFactory'; +export { permissionsServiceFactory } from './permissionsServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/permissions/permissionsFactory.ts b/packages/backend-app-api/src/services/implementations/permissions/permissionsServiceFactory.ts similarity index 94% rename from packages/backend-app-api/src/services/implementations/permissions/permissionsFactory.ts rename to packages/backend-app-api/src/services/implementations/permissions/permissionsServiceFactory.ts index 4eb05e3e4c..38cba73eda 100644 --- a/packages/backend-app-api/src/services/implementations/permissions/permissionsFactory.ts +++ b/packages/backend-app-api/src/services/implementations/permissions/permissionsServiceFactory.ts @@ -21,7 +21,7 @@ import { import { ServerPermissionClient } from '@backstage/plugin-permission-node'; /** @public */ -export const permissionsFactory = createServiceFactory({ +export const permissionsServiceFactory = createServiceFactory({ service: coreServices.permissions, deps: { config: coreServices.config, diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/index.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/index.ts index e24662df05..93b997239d 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/index.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/index.ts @@ -15,10 +15,10 @@ */ export { - rootHttpRouterFactory, + rootHttpRouterServiceFactory, type RootHttpRouterFactoryOptions, type RootHttpRouterConfigureOptions, -} from './rootHttpRouterFactory'; +} from './rootHttpRouterServiceFactory'; export { DefaultRootHttpRouter, type DefaultRootHttpRouterOptions, diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts similarity index 97% rename from packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts rename to packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts index 816c615817..a14beb428d 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts @@ -69,7 +69,7 @@ function defaultConfigure({ } /** @public */ -export const rootHttpRouterFactory = createServiceFactory( +export const rootHttpRouterServiceFactory = createServiceFactory( (options?: RootHttpRouterFactoryOptions) => ({ service: coreServices.rootHttpRouter, deps: { diff --git a/packages/backend-app-api/src/services/implementations/rootLifecycle/index.ts b/packages/backend-app-api/src/services/implementations/rootLifecycle/index.ts index 8adefbfe84..86589cd23e 100644 --- a/packages/backend-app-api/src/services/implementations/rootLifecycle/index.ts +++ b/packages/backend-app-api/src/services/implementations/rootLifecycle/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { rootLifecycleFactory } from './rootLifecycleFactory'; +export { rootLifecycleServiceFactory } from './rootLifecycleServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.test.ts b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleServiceFactory.test.ts similarity index 95% rename from packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.test.ts rename to packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleServiceFactory.test.ts index 3a93cacc8d..8d2b2af3d5 100644 --- a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleServiceFactory.test.ts @@ -15,7 +15,7 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import { BackendLifecycleImpl } from './rootLifecycleFactory'; +import { BackendLifecycleImpl } from './rootLifecycleServiceFactory'; describe('lifecycleService', () => { it('should execute registered shutdown hook', async () => { diff --git a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleServiceFactory.ts similarity index 96% rename from packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts rename to packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleServiceFactory.ts index 2b6f7eeafe..f379c2ec52 100644 --- a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleServiceFactory.ts @@ -65,7 +65,7 @@ export class BackendLifecycleImpl implements RootLifecycleService { * * @public */ -export const rootLifecycleFactory = createServiceFactory({ +export const rootLifecycleServiceFactory = createServiceFactory({ service: coreServices.rootLifecycle, deps: { logger: coreServices.rootLogger, diff --git a/packages/backend-app-api/src/services/implementations/rootLogger/index.ts b/packages/backend-app-api/src/services/implementations/rootLogger/index.ts index ce5816e6fa..366cd53163 100644 --- a/packages/backend-app-api/src/services/implementations/rootLogger/index.ts +++ b/packages/backend-app-api/src/services/implementations/rootLogger/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { rootLoggerFactory } from './rootLoggerFactory'; +export { rootLoggerServiceFactory } from './rootLoggerServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerFactory.ts b/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts similarity index 96% rename from packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerFactory.ts rename to packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts index 1c2214b98c..11bbd58050 100644 --- a/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts @@ -23,7 +23,7 @@ import { transports, format } from 'winston'; import { createConfigSecretEnumerator } from '../../../config'; /** @public */ -export const rootLoggerFactory = createServiceFactory({ +export const rootLoggerServiceFactory = createServiceFactory({ service: coreServices.rootLogger, deps: { config: coreServices.config, diff --git a/packages/backend-app-api/src/services/implementations/scheduler/index.ts b/packages/backend-app-api/src/services/implementations/scheduler/index.ts index 8b84906b5b..8b67006a4d 100644 --- a/packages/backend-app-api/src/services/implementations/scheduler/index.ts +++ b/packages/backend-app-api/src/services/implementations/scheduler/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { schedulerFactory } from './schedulerFactory'; +export { schedulerServiceFactory } from './schedulerServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.test.ts b/packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.test.ts similarity index 94% rename from packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.test.ts rename to packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.test.ts index 15ec364ac5..7af9de44da 100644 --- a/packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.test.ts @@ -19,13 +19,13 @@ import { createBackendPlugin, } from '@backstage/backend-plugin-api'; import { startTestBackend } from '@backstage/backend-test-utils'; -import { schedulerFactory } from './schedulerFactory'; +import { schedulerServiceFactory } from './schedulerServiceFactory'; describe('schedulerFactory', () => { it('creates sidecar database features', async () => { expect.assertions(3); - const subject = schedulerFactory(); + const subject = schedulerServiceFactory(); const plugin = createBackendPlugin({ pluginId: 'example', diff --git a/packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.ts b/packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.ts similarity index 95% rename from packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.ts rename to packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.ts index 458c5acfd6..4dfe567ccc 100644 --- a/packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.ts +++ b/packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.ts @@ -22,7 +22,7 @@ import { import { TaskScheduler } from '@backstage/backend-tasks'; /** @public */ -export const schedulerFactory = createServiceFactory({ +export const schedulerServiceFactory = createServiceFactory({ service: coreServices.scheduler, deps: { plugin: coreServices.pluginMetadata, diff --git a/packages/backend-app-api/src/services/implementations/tokenManager/index.ts b/packages/backend-app-api/src/services/implementations/tokenManager/index.ts index c0685079c4..3ae3d45d2f 100644 --- a/packages/backend-app-api/src/services/implementations/tokenManager/index.ts +++ b/packages/backend-app-api/src/services/implementations/tokenManager/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { tokenManagerFactory } from './tokenManagerFactory'; +export { tokenManagerServiceFactory } from './tokenManagerServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerFactory.test.ts b/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.test.ts similarity index 91% rename from packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerFactory.test.ts rename to packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.test.ts index abc62fff69..6c33829967 100644 --- a/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.test.ts @@ -20,13 +20,13 @@ import { TokenManagerService, } from '@backstage/backend-plugin-api'; import { ConfigReader } from '@backstage/config'; -import { tokenManagerFactory } from './tokenManagerFactory'; +import { tokenManagerServiceFactory } from './tokenManagerServiceFactory'; describe('tokenManagerFactory', () => { it('should create managers that can share tokens in development', async () => { (process.env as { NODE_ENV?: string }).NODE_ENV = 'development'; - const factory = tokenManagerFactory() as Exclude< + const factory = tokenManagerServiceFactory() as Exclude< ServiceFactory, { scope: 'root' } >; diff --git a/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerFactory.ts b/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.ts similarity index 94% rename from packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerFactory.ts rename to packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.ts index ae0b402eec..b3726176b6 100644 --- a/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerFactory.ts +++ b/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.ts @@ -21,7 +21,7 @@ import { import { ServerTokenManager } from '@backstage/backend-common'; /** @public */ -export const tokenManagerFactory = createServiceFactory({ +export const tokenManagerServiceFactory = createServiceFactory({ service: coreServices.tokenManager, deps: { config: coreServices.config, diff --git a/packages/backend-app-api/src/services/implementations/urlReader/index.ts b/packages/backend-app-api/src/services/implementations/urlReader/index.ts index 5da0ef4049..6a4b9f65be 100644 --- a/packages/backend-app-api/src/services/implementations/urlReader/index.ts +++ b/packages/backend-app-api/src/services/implementations/urlReader/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { urlReaderFactory } from './urlReaderFactory'; +export { urlReaderServiceFactory } from './urlReaderServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/urlReader/urlReaderFactory.ts b/packages/backend-app-api/src/services/implementations/urlReader/urlReaderServiceFactory.ts similarity index 94% rename from packages/backend-app-api/src/services/implementations/urlReader/urlReaderFactory.ts rename to packages/backend-app-api/src/services/implementations/urlReader/urlReaderServiceFactory.ts index 1b52ce9604..83e594aa0b 100644 --- a/packages/backend-app-api/src/services/implementations/urlReader/urlReaderFactory.ts +++ b/packages/backend-app-api/src/services/implementations/urlReader/urlReaderServiceFactory.ts @@ -21,7 +21,7 @@ import { } from '@backstage/backend-plugin-api'; /** @public */ -export const urlReaderFactory = createServiceFactory({ +export const urlReaderServiceFactory = createServiceFactory({ service: coreServices.urlReader, deps: { config: coreServices.config, diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index 4bdee8b085..40e2275e2a 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -20,7 +20,7 @@ import { coreServices, ServiceRef, } from '@backstage/backend-plugin-api'; -import { BackendLifecycleImpl } from '../services/implementations/rootLifecycle/rootLifecycleFactory'; +import { BackendLifecycleImpl } from '../services/implementations/rootLifecycle/rootLifecycleServiceFactory'; import { BackendRegisterInit, EnumerableServiceHolder, From 5077fdb2424613545a5ed33059a7823ddcfacffd Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 13:21:34 +0100 Subject: [PATCH 248/423] chore: fixing usages Signed-off-by: blam --- .../backend-defaults/src/CreateBackend.ts | 60 +++++++++---------- .../src/next/services/mockServices.ts | 36 +++++------ .../src/run.ts | 40 ++++++------- 3 files changed, 68 insertions(+), 68 deletions(-) diff --git a/packages/backend-defaults/src/CreateBackend.ts b/packages/backend-defaults/src/CreateBackend.ts index 5cbed2c3df..480f365216 100644 --- a/packages/backend-defaults/src/CreateBackend.ts +++ b/packages/backend-defaults/src/CreateBackend.ts @@ -16,22 +16,22 @@ import { Backend, - cacheFactory, - configFactory, + cacheServiceFactory, + configServiceFactory, createSpecializedBackend, - databaseFactory, - discoveryFactory, - httpRouterFactory, - rootHttpRouterFactory, - lifecycleFactory, - rootLifecycleFactory, - loggerFactory, - permissionsFactory, - rootLoggerFactory, - schedulerFactory, - tokenManagerFactory, - urlReaderFactory, - identityFactory, + databaseServiceFactory, + discoveryServiceFactory, + httpRouterServiceFactory, + rootHttpRouterServiceFactory, + lifecycleServiceFactory, + rootLifecycleServiceFactory, + loggerServiceFactory, + permissionsServiceFactory, + rootLoggerServiceFactory, + schedulerServiceFactory, + tokenManagerServiceFactory, + urlReaderServiceFactory, + identityServiceFactory, } from '@backstage/backend-app-api'; import { ServiceFactory, @@ -44,21 +44,21 @@ import { import type { InternalSharedBackendEnvironment } from '@backstage/backend-plugin-api/src/wiring/createSharedEnvironment'; export const defaultServiceFactories = [ - cacheFactory(), - configFactory(), - databaseFactory(), - discoveryFactory(), - httpRouterFactory(), - identityFactory(), - lifecycleFactory(), - loggerFactory(), - permissionsFactory(), - rootHttpRouterFactory(), - rootLifecycleFactory(), - rootLoggerFactory(), - schedulerFactory(), - tokenManagerFactory(), - urlReaderFactory(), + cacheServiceFactory(), + configServiceFactory(), + databaseServiceFactory(), + discoveryServiceFactory(), + httpRouterServiceFactory(), + identityServiceFactory(), + lifecycleServiceFactory(), + loggerServiceFactory(), + permissionsServiceFactory(), + rootHttpRouterServiceFactory(), + rootLifecycleServiceFactory(), + rootLoggerServiceFactory(), + schedulerServiceFactory(), + tokenManagerServiceFactory(), + urlReaderServiceFactory(), ]; /** diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index 5f771f13c5..d65cdb2877 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -25,15 +25,15 @@ import { TokenManagerService, } from '@backstage/backend-plugin-api'; import { - cacheFactory, - databaseFactory, - httpRouterFactory, - lifecycleFactory, - loggerFactory, - permissionsFactory, - rootLifecycleFactory, - schedulerFactory, - urlReaderFactory, + cacheServiceFactory, + databaseServiceFactory, + httpRouterServiceFactory, + lifecycleServiceFactory, + loggerServiceFactory, + permissionsServiceFactory, + rootLifecycleServiceFactory, + schedulerServiceFactory, + urlReaderServiceFactory, } from '@backstage/backend-app-api'; import { ConfigReader } from '@backstage/config'; import { JsonObject } from '@backstage/types'; @@ -109,30 +109,30 @@ export namespace mockServices { // some may need a bit more refactoring for it to be simpler to // re-implement functioning mock versions here. export namespace cache { - export const factory = cacheFactory; + export const factory = cacheServiceFactory; } export namespace database { - export const factory = databaseFactory; + export const factory = databaseServiceFactory; } export namespace httpRouter { - export const factory = httpRouterFactory; + export const factory = httpRouterServiceFactory; } export namespace lifecycle { - export const factory = lifecycleFactory; + export const factory = lifecycleServiceFactory; } export namespace logger { - export const factory = loggerFactory; + export const factory = loggerServiceFactory; } export namespace permissions { - export const factory = permissionsFactory; + export const factory = permissionsServiceFactory; } export namespace rootLifecycle { - export const factory = rootLifecycleFactory; + export const factory = rootLifecycleServiceFactory; } export namespace scheduler { - export const factory = schedulerFactory; + export const factory = schedulerServiceFactory; } export namespace urlReader { - export const factory = urlReaderFactory; + export const factory = urlReaderServiceFactory; } } diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts index 2a58227862..d41b9be115 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts @@ -16,16 +16,16 @@ // eslint-disable-next-line @backstage/no-undeclared-imports import { - databaseFactory, - discoveryFactory, - httpRouterFactory, - lifecycleFactory, - loggerFactory, - permissionsFactory, - rootLoggerFactory, - schedulerFactory, - tokenManagerFactory, - urlReaderFactory, + databaseServiceFactory, + discoveryServiceFactory, + httpRouterServiceFactory, + lifecycleServiceFactory, + loggerServiceFactory, + permissionsServiceFactory, + rootLoggerServiceFactory, + schedulerServiceFactory, + tokenManagerServiceFactory, + urlReaderServiceFactory, } from '@backstage/backend-app-api'; import { coreServices } from '@backstage/backend-plugin-api'; import { startTestBackend } from '@backstage/backend-test-utils'; @@ -63,16 +63,16 @@ async function main() { await startTestBackend({ services: [ [coreServices.config, new ConfigReader(config)], - databaseFactory(), - discoveryFactory(), - httpRouterFactory(), - lifecycleFactory(), - loggerFactory(), - permissionsFactory(), - rootLoggerFactory(), - schedulerFactory(), - tokenManagerFactory(), - urlReaderFactory(), + databaseServiceFactory(), + discoveryServiceFactory(), + httpRouterServiceFactory(), + lifecycleServiceFactory(), + loggerServiceFactory(), + permissionsServiceFactory(), + rootLoggerServiceFactory(), + schedulerServiceFactory(), + tokenManagerServiceFactory(), + urlReaderServiceFactory(), ], extensionPoints: [], features: [ From 6f1f2e94510c38cdb1b74d61928e78b781bb5b9b Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 13:28:02 +0100 Subject: [PATCH 249/423] chore: updating docs Signed-off-by: blam --- docs/backend-system/architecture/03-services.md | 16 ++++++++-------- .../architecture/07-naming-patterns.md | 14 +++++++------- .../backend-system/building-backends/01-index.md | 8 ++++---- docs/backend-system/core-services/01-index.md | 16 ++++++++-------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/docs/backend-system/architecture/03-services.md b/docs/backend-system/architecture/03-services.md index d202c21740..875cb3aaea 100644 --- a/docs/backend-system/architecture/03-services.md +++ b/docs/backend-system/architecture/03-services.md @@ -61,7 +61,7 @@ class DefaultFooService implements FooService { } } -export const fooFactory = createServiceFactory({ +export const fooServiceFactory = createServiceFactory({ service: fooServiceRef, deps: { bar: barServiceRef }, factory({ bar }) { @@ -75,7 +75,7 @@ To create a service factory we need to provide a reference to the `service` for If you need the creation of the service instance to be asynchronous, you can make the `factory` function async. For example: ```ts -export const fooFactory = createServiceFactory({ +export const fooServiceFactory = createServiceFactory({ service: fooServiceRef, deps: {}, async factory() { @@ -94,18 +94,18 @@ To install a service factory in a backend instance, we pass it in through the `s ```ts const backend = createBackend({ - services: [fooFactory()], + services: [fooServiceFactory()], }); ``` -Note that we call `fooFactory` to create the service factory instance. This is because `createServiceFactory` always returns a factory function that creates the actual service factory. This is done to always allow for options to be added to the service factory in the future, without breaking existing code. To add options to your service factory, you wrap the object passed to `createServiceFactory` in a callback that accepts the desired options. For example: +Note that we call `fooServiceFactory` to create the service factory instance. This is because `createServiceFactory` always returns a factory function that creates the actual service factory. This is done to always allow for options to be added to the service factory in the future, without breaking existing code. To add options to your service factory, you wrap the object passed to `createServiceFactory` in a callback that accepts the desired options. For example: ```ts export interface FooFactoryOptions { mode: 'eager' | 'lazy'; } -export const fooFactory = createServiceFactory( +export const fooServiceFactory = createServiceFactory( (options?: FooFactoryOptions) => ({ service: fooServiceRef, deps: { bar: barServiceRef }, @@ -120,7 +120,7 @@ This lets us use the options to customize the factory implementation in any way ```ts const backend = createBackend({ - services: [fooFactory({ mode: 'eager' })], + services: [fooServiceFactory({ mode: 'eager' })], }); ``` @@ -164,7 +164,7 @@ Plugin scoped services have access to a plugin metadata service, which is a spec The plugin metadata service is the base for all plugin specific customizations for services. For example, the default implementation of the plugin scoped logger service uses the plugin metadata service to attach the plugin ID as a field in all log messages: ```ts -export const loggerFactory = createServiceFactory({ +export const loggerServiceFactory = createServiceFactory({ service: coreServices.logger, deps: { rootLogger: coreServices.rootLogger, @@ -183,7 +183,7 @@ Some services may benefit from having a context that is shared across all instan The root context is defined as part of the service factory by passing the `createRootContext` option: ```ts -export const fooFactory = createServiceFactory({ +export const fooServiceFactory = createServiceFactory({ service: fooServiceRef, deps: { rootLogger: coreServices.rootLogger, bar: barServiceRef }, createRootContext({ rootLogger }) { diff --git a/docs/backend-system/architecture/07-naming-patterns.md b/docs/backend-system/architecture/07-naming-patterns.md index b4b4c6c70f..b62e049f08 100644 --- a/docs/backend-system/architecture/07-naming-patterns.md +++ b/docs/backend-system/architecture/07-naming-patterns.md @@ -66,12 +66,12 @@ export const catalogProcessingExtensionPoint = createExtensionPointService` | `LoggerService`, `DatabaseService` | -| Reference | `ServiceRef` | `loggerServiceRef`, `databaseServiceRef` | -| ID | `.` | `'core.rootHttpRouter'`, `'catalog.catalogClient'` | -| Factory | `Factory` | `loggerFactory`, `databaseFactory` | +| Description | Pattern | Examples | +| ----------- | ---------------------- | -------------------------------------------------- | +| Interface | `Service` | `LoggerService`, `DatabaseService` | +| Reference | `ServiceRef` | `loggerServiceRef`, `databaseServiceRef` | +| ID | `.` | `'core.rootHttpRouter'`, `'catalog.catalogClient'` | +| Factory | `ServiceFactory` | `loggerServiceFactory`, `databaseServiceFactory` | Example: @@ -85,7 +85,7 @@ export const catalogClientServiceRef = createServiceRef({ ... }) -export const catalogClientFactory = createServiceFactory({ +export const catalogClientServiceFactory = createServiceFactory({ service: catalogClientServiceRef, ... }) diff --git a/docs/backend-system/building-backends/01-index.md b/docs/backend-system/building-backends/01-index.md index de01c6d39c..bda2aa7eaa 100644 --- a/docs/backend-system/building-backends/01-index.md +++ b/docs/backend-system/building-backends/01-index.md @@ -61,11 +61,11 @@ All of these services can be replaced with your own implementations if you need For example, let's say we want to customize the core configuration service to enable remote configuration loading. That would look something like this: ```ts -import { configFactory } from '@backstage/backend-app-api'; +import { configServiceFactory } from '@backstage/backend-app-api'; const backend = createBackend({ services: [ - configFactory({ + configServiceFactory({ remote: { reloadIntervalSeconds: 60 }, }), ], @@ -160,11 +160,11 @@ A shared environment is defined using `createSharedEnvironment`. In this example ```ts // packages/backend-env/src/index.ts import { createSharedEnvironment } from '@backstage/backend-plugin-api'; -import { customDiscoveryFactory } from './customDiscoveryFactory'; +import { customDiscoveryServiceFactory } from './customDiscoveryServiceFactory'; export const env = createSharedEnvironment({ services: [ - customDiscoveryFactory(), // custom DiscoveryService implementation + customDiscoveryServiceFactory(), // custom DiscoveryService implementation ], }); ``` diff --git a/docs/backend-system/core-services/01-index.md b/docs/backend-system/core-services/01-index.md index 5128a95cb3..b6682c2708 100644 --- a/docs/backend-system/core-services/01-index.md +++ b/docs/backend-system/core-services/01-index.md @@ -59,11 +59,11 @@ There's additional configuration that you can optionally pass to setup the `http You can configure these additional options by adding an override for the core service when calling `createBackend` like follows: ```ts -import { httpRouterFactory } from '@backstage/backend-app-api'; +import { httpRouterServiceFactory } from '@backstage/backend-app-api'; const backend = createBackend({ services: [ - httpRouterFactory({ + httpRouterServiceFactory({ getPath: (pluginId: string) => `/plugins/${pluginId}`, }), ], @@ -116,11 +116,11 @@ There's additional options that you can pass to configure the root HTTP Router s You can configure the root HTTP Router service by passing the options to the `createBackend` function. ```ts -import { rootHttpRouterFactory } from '@backstage/backend-app-api'; +import { rootHttpRouterServiceFactory } from '@backstage/backend-app-api'; const backend = createBackend({ services: [ - rootHttpRouterFactory({ + rootHttpRouterServiceFactory({ configure: ({ app, middleware, routes, config, logger, lifecycle }) => { // the built in middleware is provided through an option in the configure function app.use(middleware.helmet()); @@ -183,11 +183,11 @@ There's additional configuration that you can optionally pass to setup the `conf You can configure these additional options by adding an override for the core service when calling `createBackend` like follows: ```ts -import { configFactory } from '@backstage/backend-app-api'; +import { configServiceFactory } from '@backstage/backend-app-api'; const backend = createBackend({ services: [ - configFactory({ + configServiceFactory({ argv: [ '--config', '/backstage/app-config.development.yaml', @@ -438,11 +438,11 @@ There's additional configuration that you can optionally pass to setup the `iden You can configure these additional options by adding an override for the core service when calling `createBackend` like follows: ```ts -import { identityFactory } from '@backstage/backend-app-api'; +import { identityServiceFactory } from '@backstage/backend-app-api'; const backend = createBackend({ services: [ - identityFactory({ + identityServiceFactory({ issuer: 'backstage', algorithms: ['ES256', 'RS256'], }), From 4ae71b7f2e0874a0cbcd464df8113cbd537f3835 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 13:32:54 +0100 Subject: [PATCH 250/423] chore: api-reports and breaking changeset Signed-off-by: blam --- .changeset/short-apes-relate.md | 5 +++ packages/backend-app-api/api-report.md | 62 +++++++++++++------------- 2 files changed, 36 insertions(+), 31 deletions(-) create mode 100644 .changeset/short-apes-relate.md diff --git a/.changeset/short-apes-relate.md b/.changeset/short-apes-relate.md new file mode 100644 index 0000000000..d93c046a4d --- /dev/null +++ b/.changeset/short-apes-relate.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': minor +--- + +**BREAKING** Renaming `*Factory` exports to `*ServiceFactory` instead. For example `configFactory` now is exported as `configServiceFactory`. diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index 8dc85d1728..52b86eb3d5 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -50,12 +50,7 @@ export interface Backend { } // @public (undocumented) -export const cacheFactory: () => ServiceFactory; - -// @public (undocumented) -export const configFactory: ( - options?: ConfigFactoryOptions | undefined, -) => ServiceFactory; +export const cacheServiceFactory: () => ServiceFactory; // @public (undocumented) export interface ConfigFactoryOptions { @@ -63,6 +58,11 @@ export interface ConfigFactoryOptions { remote?: LoadConfigOptionsRemote; } +// @public (undocumented) +export const configServiceFactory: ( + options?: ConfigFactoryOptions | undefined, +) => ServiceFactory; + // @public (undocumented) export function createConfigSecretEnumerator(options: { logger: LoggerService; @@ -90,7 +90,7 @@ export interface CreateSpecializedBackendOptions { } // @public (undocumented) -export const databaseFactory: () => ServiceFactory; +export const databaseServiceFactory: () => ServiceFactory; // @public export class DefaultRootHttpRouter implements RootHttpRouterService { @@ -108,7 +108,7 @@ export interface DefaultRootHttpRouterOptions { } // @public (undocumented) -export const discoveryFactory: () => ServiceFactory; +export const discoveryServiceFactory: () => ServiceFactory; // @public export interface ExtendedHttpServer extends http.Server { @@ -120,16 +120,16 @@ export interface ExtendedHttpServer extends http.Server { stop(): Promise; } -// @public (undocumented) -export const httpRouterFactory: ( - options?: HttpRouterFactoryOptions | undefined, -) => ServiceFactory; - // @public (undocumented) export interface HttpRouterFactoryOptions { getPath?(pluginId: string): string; } +// @public (undocumented) +export const httpRouterServiceFactory: ( + options?: HttpRouterFactoryOptions | undefined, +) => ServiceFactory; + // @public export type HttpServerCertificateOptions = | { @@ -153,19 +153,19 @@ export type HttpServerOptions = { }; }; -// @public (undocumented) -export const identityFactory: ( - options?: IdentityFactoryOptions | undefined, -) => ServiceFactory; - // @public export type IdentityFactoryOptions = { issuer?: string; algorithms?: string[]; }; +// @public (undocumented) +export const identityServiceFactory: ( + options?: IdentityFactoryOptions | undefined, +) => ServiceFactory; + // @public -export const lifecycleFactory: () => ServiceFactory; +export const lifecycleServiceFactory: () => ServiceFactory; // @public export function loadBackendConfig(options: { @@ -176,7 +176,7 @@ export function loadBackendConfig(options: { }>; // @public (undocumented) -export const loggerFactory: () => ServiceFactory; +export const loggerServiceFactory: () => ServiceFactory; // @public export class MiddlewareFactory { @@ -204,7 +204,7 @@ export interface MiddlewareFactoryOptions { } // @public (undocumented) -export const permissionsFactory: () => ServiceFactory; +export const permissionsServiceFactory: () => ServiceFactory; // @public export function readCorsOptions(config?: Config): CorsOptions; @@ -231,25 +231,25 @@ export interface RootHttpRouterConfigureOptions { routes: RequestHandler; } -// @public (undocumented) -export const rootHttpRouterFactory: ( - options?: RootHttpRouterFactoryOptions | undefined, -) => ServiceFactory; - // @public (undocumented) export type RootHttpRouterFactoryOptions = { indexPath?: string | false; configure?(options: RootHttpRouterConfigureOptions): void; }; +// @public (undocumented) +export const rootHttpRouterServiceFactory: ( + options?: RootHttpRouterFactoryOptions | undefined, +) => ServiceFactory; + // @public -export const rootLifecycleFactory: () => ServiceFactory; +export const rootLifecycleServiceFactory: () => ServiceFactory; // @public (undocumented) -export const rootLoggerFactory: () => ServiceFactory; +export const rootLoggerServiceFactory: () => ServiceFactory; // @public (undocumented) -export const schedulerFactory: () => ServiceFactory; +export const schedulerServiceFactory: () => ServiceFactory; // @public (undocumented) export type ServiceOrExtensionPoint = @@ -257,10 +257,10 @@ export type ServiceOrExtensionPoint = | ServiceRef; // @public (undocumented) -export const tokenManagerFactory: () => ServiceFactory; +export const tokenManagerServiceFactory: () => ServiceFactory; // @public (undocumented) -export const urlReaderFactory: () => ServiceFactory; +export const urlReaderServiceFactory: () => ServiceFactory; // @public export class WinstonLogger implements RootLoggerService { From da208444d0c3080dec643e9052f7b32e44f8e72a Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 13:37:28 +0100 Subject: [PATCH 251/423] chore: removing extraneous imports as they already ship with the TestBackend now Signed-off-by: blam --- .../src/run.ts | 28 +------------------ 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts index d41b9be115..e9cc7dbb2a 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts @@ -13,20 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -// eslint-disable-next-line @backstage/no-undeclared-imports -import { - databaseServiceFactory, - discoveryServiceFactory, - httpRouterServiceFactory, - lifecycleServiceFactory, - loggerServiceFactory, - permissionsServiceFactory, - rootLoggerServiceFactory, - schedulerServiceFactory, - tokenManagerServiceFactory, - urlReaderServiceFactory, -} from '@backstage/backend-app-api'; import { coreServices } from '@backstage/backend-plugin-api'; import { startTestBackend } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; @@ -61,19 +47,7 @@ async function main() { }; await startTestBackend({ - services: [ - [coreServices.config, new ConfigReader(config)], - databaseServiceFactory(), - discoveryServiceFactory(), - httpRouterServiceFactory(), - lifecycleServiceFactory(), - loggerServiceFactory(), - permissionsServiceFactory(), - rootLoggerServiceFactory(), - schedulerServiceFactory(), - tokenManagerServiceFactory(), - urlReaderServiceFactory(), - ], + services: [[coreServices.config, new ConfigReader(config)]], extensionPoints: [], features: [ catalogPlugin(), From 407dc01fc9b4a576d37366b10636bd51d9f451ae Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 13:38:17 +0100 Subject: [PATCH 252/423] chore: changeset Signed-off-by: blam --- .changeset/friendly-chefs-rule.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/friendly-chefs-rule.md diff --git a/.changeset/friendly-chefs-rule.md b/.changeset/friendly-chefs-rule.md new file mode 100644 index 0000000000..872a36b5ae --- /dev/null +++ b/.changeset/friendly-chefs-rule.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +--- + +Removing extra imports for `run` script as `TestBackend` auto loads the default factories From e412d33025e0ab25b948fa946a8d3b8fe8d9bf95 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 13:40:10 +0100 Subject: [PATCH 253/423] chore: last changeset Signed-off-by: blam --- .changeset/quick-mice-change.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/quick-mice-change.md diff --git a/.changeset/quick-mice-change.md b/.changeset/quick-mice-change.md new file mode 100644 index 0000000000..aeee24a021 --- /dev/null +++ b/.changeset/quick-mice-change.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-test-utils': patch +'@backstage/backend-defaults': patch +--- + +Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` From b286e3d286e32c221f7d16e4f0021ecef5a6be31 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 13:53:54 +0100 Subject: [PATCH 254/423] rename: `plain` -> `pem` Signed-off-by: blam --- packages/backend-app-api/api-report.md | 2 +- packages/backend-app-api/src/http/config.test.ts | 2 +- packages/backend-app-api/src/http/config.ts | 2 +- packages/backend-app-api/src/http/types.ts | 2 +- packages/backend-common/src/service/lib/ServiceBuilderImpl.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index 8dc85d1728..1c05f14ddb 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -133,7 +133,7 @@ export interface HttpRouterFactoryOptions { // @public export type HttpServerCertificateOptions = | { - type: 'plain'; + type: 'pem'; key: string; cert: string; } diff --git a/packages/backend-app-api/src/http/config.test.ts b/packages/backend-app-api/src/http/config.test.ts index f54ba927ca..577bae08f3 100644 --- a/packages/backend-app-api/src/http/config.test.ts +++ b/packages/backend-app-api/src/http/config.test.ts @@ -53,7 +53,7 @@ describe('readHttpServerOptions', () => { { listen: { host: '', port: 7007 }, https: { - certificate: { type: 'plain', cert: 'my-cert', key: 'my-key' }, + certificate: { type: 'pem', cert: 'my-cert', key: 'my-key' }, }, }, ], diff --git a/packages/backend-app-api/src/http/config.ts b/packages/backend-app-api/src/http/config.ts index e3b41c63de..ec29a8a044 100644 --- a/packages/backend-app-api/src/http/config.ts +++ b/packages/backend-app-api/src/http/config.ts @@ -93,7 +93,7 @@ function readHttpsOptions(config?: Config): HttpServerOptions['https'] { return { certificate: { - type: 'plain', + type: 'pem', cert: cc.getString('certificate.cert'), key: cc.getString('certificate.key'), }, diff --git a/packages/backend-app-api/src/http/types.ts b/packages/backend-app-api/src/http/types.ts index ff96f69bff..2298ef11ff 100644 --- a/packages/backend-app-api/src/http/types.ts +++ b/packages/backend-app-api/src/http/types.ts @@ -51,7 +51,7 @@ export type HttpServerOptions = { */ export type HttpServerCertificateOptions = | { - type: 'plain'; + type: 'pem'; key: string; cert: string; } diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts index f74dcd9b64..f577017b77 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts @@ -102,7 +102,7 @@ export class ServiceBuilderImpl implements ServiceBuilder { this.serverOptions.https = { certificate: { ...settings.certificate, - type: 'plain', + type: 'pem', }, }; } From d31d8e00b3d64c520b52e35b408ac9af4e269c7f Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 13:57:08 +0100 Subject: [PATCH 255/423] chore: added changesets Signed-off-by: blam --- .changeset/hot-wasps-cover.md | 5 +++++ .changeset/soft-actors-worry.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/hot-wasps-cover.md create mode 100644 .changeset/soft-actors-worry.md diff --git a/.changeset/hot-wasps-cover.md b/.changeset/hot-wasps-cover.md new file mode 100644 index 0000000000..e142980b56 --- /dev/null +++ b/.changeset/hot-wasps-cover.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Updated to work with the new `type: 'pem'` with `createHttpServer` from `@backstage/backend-app-api` diff --git a/.changeset/soft-actors-worry.md b/.changeset/soft-actors-worry.md new file mode 100644 index 0000000000..5186499292 --- /dev/null +++ b/.changeset/soft-actors-worry.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': minor +--- + +**BREAKING** `HttpServerCertificateOptions` when specified with a `key` and `cert` should also have the `type: 'pem'` instead of `type: 'plain'` From ab2c12fa1dad1fcf647cd8c4028f84b38e023c0f Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 16 Jan 2023 17:02:15 +0100 Subject: [PATCH 256/423] chore: moved across the work from previous branch Signed-off-by: blam --- .../src/components/hooks/useEventStream.ts | 2 +- plugins/scaffolder/src/next/Router/Router.tsx | 14 ++++- .../scaffolder/src/next/TaskPage/TaskPage.tsx | 63 +++++++++++++++++++ .../src/next/TaskPage/TaskSteps/TaskSteps.tsx | 63 +++++++++++++++++++ .../src/next/TaskPage/TaskSteps/index.ts | 16 +++++ plugins/scaffolder/src/next/TaskPage/index.ts | 16 +++++ .../TemplateWizardPage/TemplateWizardPage.tsx | 17 +++-- 7 files changed, 183 insertions(+), 8 deletions(-) create mode 100644 plugins/scaffolder/src/next/TaskPage/TaskPage.tsx create mode 100644 plugins/scaffolder/src/next/TaskPage/TaskSteps/TaskSteps.tsx create mode 100644 plugins/scaffolder/src/next/TaskPage/TaskSteps/index.ts create mode 100644 plugins/scaffolder/src/next/TaskPage/index.ts diff --git a/plugins/scaffolder/src/components/hooks/useEventStream.ts b/plugins/scaffolder/src/components/hooks/useEventStream.ts index 0b36c85ad8..be0ff922a4 100644 --- a/plugins/scaffolder/src/components/hooks/useEventStream.ts +++ b/plugins/scaffolder/src/components/hooks/useEventStream.ts @@ -25,7 +25,7 @@ import { import { useApi } from '@backstage/core-plugin-api'; import { Subscription } from '@backstage/types'; -type Step = { +export type Step = { id: string; status: ScaffolderTaskStatus; endedAt?: string; diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 8dd47b478e..f5e186eb67 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -28,7 +28,14 @@ import { import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups'; import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default'; -import { nextSelectedTemplateRouteRef } from '../routes'; + +import { FormProps } from '../types'; +import { + nextScaffolderTaskRouteRef, + nextSelectedTemplateRouteRef, +} from '../routes'; +import { ErrorPage } from '@backstage/core-components'; +import { TaskPage } from '../TaskPage'; /** * The Props for the Scaffolder Router @@ -91,6 +98,11 @@ export const Router = (props: PropsWithChildren) => { } /> + } /> + } + /> ); }; diff --git a/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx new file mode 100644 index 0000000000..f259231e4d --- /dev/null +++ b/plugins/scaffolder/src/next/TaskPage/TaskPage.tsx @@ -0,0 +1,63 @@ +/* + * Copyright 2023 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, { useMemo } from 'react'; +import { Page, Header, Content } from '@backstage/core-components'; +import { useTaskEventStream } from '../../components/hooks/useEventStream'; +import { useParams } from 'react-router-dom'; +import { Box, LinearProgress, Paper } from '@material-ui/core'; +import { TaskSteps } from './TaskSteps'; + +export const TaskPage = () => { + const { taskId } = useParams(); + // check that task Id actually exists, and that it's valid. otherwise redirect to something more useful. + const taskStream = useTaskEventStream(taskId!); + const steps = useMemo( + () => + taskStream.task?.spec.steps.map(step => ({ + ...step, + ...taskStream?.steps?.[step.id], + })) ?? [], + [taskStream], + ); + + const activeStep = React.useMemo(() => { + for (let i = steps.length - 1; i >= 0; i--) { + if (steps[i].status !== 'open') { + return i; + } + } + + return 0; + }, [steps]); + + return ( + +

    Date: Mon, 6 Feb 2023 21:54:20 +0100 Subject: [PATCH 277/423] chore: fixing api-reports Signed-off-by: blam --- plugins/badges-backend/api-report.md | 2 +- plugins/bitbucket-cloud-common/api-report.md | 14 +++++++------- plugins/scaffolder-react/api-report.md | 5 +++++ plugins/scaffolder/api-report.md | 8 ++++++++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/plugins/badges-backend/api-report.md b/plugins/badges-backend/api-report.md index 8ca4b561a2..0ecf41ee85 100644 --- a/plugins/badges-backend/api-report.md +++ b/plugins/badges-backend/api-report.md @@ -79,7 +79,7 @@ export type BadgeSpec = { }; // @public (undocumented) -export type BadgeStyle = (typeof BADGE_STYLES)[number]; +export type BadgeStyle = typeof BADGE_STYLES[number]; // @public (undocumented) export const createDefaultBadgeFactories: () => BadgeFactories; diff --git a/plugins/bitbucket-cloud-common/api-report.md b/plugins/bitbucket-cloud-common/api-report.md index 95e6f36836..5182579a4b 100644 --- a/plugins/bitbucket-cloud-common/api-report.md +++ b/plugins/bitbucket-cloud-common/api-report.md @@ -132,7 +132,7 @@ export namespace Models { readonly Plaintext: 'plaintext'; }; export type BaseCommitSummaryMarkupEnum = - (typeof BaseCommitSummaryMarkupEnum)[keyof typeof BaseCommitSummaryMarkupEnum]; + typeof BaseCommitSummaryMarkupEnum[keyof typeof BaseCommitSummaryMarkupEnum]; export interface Branch { default_merge_strategy?: string; // (undocumented) @@ -150,7 +150,7 @@ export namespace Models { readonly FastForward: 'fast_forward'; }; export type BranchMergeStrategiesEnum = - (typeof BranchMergeStrategiesEnum)[keyof typeof BranchMergeStrategiesEnum]; + typeof BranchMergeStrategiesEnum[keyof typeof BranchMergeStrategiesEnum]; export interface Commit extends BaseCommit { // (undocumented) participants?: Array; @@ -179,7 +179,7 @@ export namespace Models { }; // (undocumented) export type CommitFileAttributesEnum = - (typeof CommitFileAttributesEnum)[keyof typeof CommitFileAttributesEnum]; + typeof CommitFileAttributesEnum[keyof typeof CommitFileAttributesEnum]; export interface Link { // (undocumented) href?: string; @@ -221,7 +221,7 @@ export namespace Models { }; // (undocumented) export type ParticipantRoleEnum = - (typeof ParticipantRoleEnum)[keyof typeof ParticipantRoleEnum]; + typeof ParticipantRoleEnum[keyof typeof ParticipantRoleEnum]; const // (undocumented) ParticipantStateEnum: { readonly Approved: 'approved'; @@ -230,7 +230,7 @@ export namespace Models { }; // (undocumented) export type ParticipantStateEnum = - (typeof ParticipantStateEnum)[keyof typeof ParticipantStateEnum]; + typeof ParticipantStateEnum[keyof typeof ParticipantStateEnum]; export interface Project extends ModelObject { // (undocumented) created_on?: string; @@ -306,7 +306,7 @@ export namespace Models { readonly NoForks: 'no_forks'; }; export type RepositoryForkPolicyEnum = - (typeof RepositoryForkPolicyEnum)[keyof typeof RepositoryForkPolicyEnum]; + typeof RepositoryForkPolicyEnum[keyof typeof RepositoryForkPolicyEnum]; const // (undocumented) RepositoryScmEnum: { readonly Git: 'git'; @@ -336,7 +336,7 @@ export namespace Models { } // (undocumented) export type RepositoryScmEnum = - (typeof RepositoryScmEnum)[keyof typeof RepositoryScmEnum]; + typeof RepositoryScmEnum[keyof typeof RepositoryScmEnum]; // (undocumented) export interface SearchCodeSearchResult { // (undocumented) diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index deead4366c..72a0b92eef 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -85,6 +85,11 @@ export type CustomFieldValidator = ( }, ) => void | Promise; +// @alpha +export const DefaultTemplateOutputs: (props: { + output?: ScaffolderTaskOutput; +}) => JSX.Element | null; + // @alpha (undocumented) export const EmbeddableWorkflow: (props: WorkflowProps) => JSX.Element; diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index 1fb72b0fac..43b885b81a 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -197,9 +197,17 @@ export type NextRouterProps = { template: TemplateEntityV1beta3; }>; TaskPageComponent?: React_2.ComponentType<{}>; + TemplateOutputsComponent?: React_2.ComponentType<{ + output?: ScaffolderTaskOutput_2; + }>; }; groups?: TemplateGroupFilter[]; FormProps?: FormProps_2; + contextMenu?: { + editor?: boolean; + actions?: boolean; + tasks?: boolean; + }; }; // @alpha From 01b6f56c8072ee155008943ae652d9dc0d3a2a36 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 10:49:48 +0100 Subject: [PATCH 278/423] chore: fixing api-reports Signed-off-by: blam --- plugins/scaffolder/src/components/Router.tsx | 5 +- plugins/scaffolder/src/next/Router/Router.tsx | 9 ++ .../src/next/TemplateListPage/ContextMenu.tsx | 123 ++++++++++++++++++ .../TemplateListPage/TemplateListPage.tsx | 4 +- plugins/scaffolder/src/next/routes.ts | 21 +++ 5 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 plugins/scaffolder/src/next/TemplateListPage/ContextMenu.tsx diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index ccc2bd283b..06c28682c5 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -149,12 +149,13 @@ export const Router = (props: RouterProps) => { } /> + + } /> + } /> } /> - } /> - } /> ) => { } /> + } /> + } + /> } diff --git a/plugins/scaffolder/src/next/TemplateListPage/ContextMenu.tsx b/plugins/scaffolder/src/next/TemplateListPage/ContextMenu.tsx new file mode 100644 index 0000000000..3bca46af2a --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateListPage/ContextMenu.tsx @@ -0,0 +1,123 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { useRouteRef } from '@backstage/core-plugin-api'; +import IconButton from '@material-ui/core/IconButton'; +import ListItemIcon from '@material-ui/core/ListItemIcon'; +import ListItemText from '@material-ui/core/ListItemText'; +import MenuItem from '@material-ui/core/MenuItem'; +import MenuList from '@material-ui/core/MenuList'; +import Popover from '@material-ui/core/Popover'; +import { makeStyles } from '@material-ui/core/styles'; +import Description from '@material-ui/icons/Description'; +import Edit from '@material-ui/icons/Edit'; +import List from '@material-ui/icons/List'; +import MoreVert from '@material-ui/icons/MoreVert'; +import React, { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { + nextActionsRouteRef, + nextEditRouteRef, + nextScaffolderListTaskRouteRef, +} from '../routes'; + +const useStyles = makeStyles({ + button: { + color: 'white', + }, +}); + +export type ScaffolderPageContextMenuProps = { + editor?: boolean; + actions?: boolean; + tasks?: boolean; +}; + +export function ContextMenu(props: ScaffolderPageContextMenuProps) { + const classes = useStyles(); + const [anchorEl, setAnchorEl] = useState(); + const editLink = useRouteRef(nextEditRouteRef); + const actionsLink = useRouteRef(nextActionsRouteRef); + const tasksLink = useRouteRef(nextScaffolderListTaskRouteRef); + + const navigate = useNavigate(); + + const showEditor = props.editor !== false; + const showActions = props.actions !== false; + const showTasks = props.tasks !== false; + + if (!showEditor && !showActions) { + return null; + } + + const onOpen = (event: React.SyntheticEvent) => { + setAnchorEl(event.currentTarget); + }; + + const onClose = () => { + setAnchorEl(undefined); + }; + + return ( + <> + + + + + + {showEditor && ( + navigate(editLink())}> + + + + + + )} + {showActions && ( + navigate(actionsLink())}> + + + + + + )} + {showTasks && ( + navigate(tasksLink())}> + + + + + + )} + + + + ); +} diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx index 3097bd98be..b701ceb3c4 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx @@ -37,7 +37,7 @@ import { RegisterExistingButton } from './RegisterExistingButton'; import { useRouteRef } from '@backstage/core-plugin-api'; import { TemplateGroupFilter, TemplateGroups } from './TemplateGroups'; import { registerComponentRouteRef } from '../../routes'; -import { ScaffolderPageContextMenu } from '../../components/ScaffolderPage/ScaffolderPageContextMenu'; +import { ContextMenu } from './ContextMenu'; export type TemplateListPageProps = { TemplateCardComponent?: React.ComponentType<{ @@ -68,7 +68,7 @@ export const TemplateListPage = (props: TemplateListPageProps) => { title="Create a new component" subtitle="Create new software components using standard templates in your organization" > - +
    diff --git a/plugins/scaffolder/src/next/routes.ts b/plugins/scaffolder/src/next/routes.ts index 620122ee60..12fad4210a 100644 --- a/plugins/scaffolder/src/next/routes.ts +++ b/plugins/scaffolder/src/next/routes.ts @@ -34,3 +34,24 @@ export const nextScaffolderTaskRouteRef = createSubRouteRef({ parent: nextRouteRef, path: '/tasks/:taskId', }); + +/** @alpha */ +export const nextScaffolderListTaskRouteRef = createSubRouteRef({ + id: 'scaffolder/next/list-tasks', + parent: nextRouteRef, + path: '/tasks', +}); + +/** @alpha */ +export const nextActionsRouteRef = createSubRouteRef({ + id: 'scaffolder/next/actions', + parent: nextRouteRef, + path: '/actions', +}); + +/** @alpha */ +export const nextEditRouteRef = createSubRouteRef({ + id: 'scaffolder/next/edit', + parent: nextRouteRef, + path: '/edit', +}); From 419aaafd18a9ba2ae26eef93cba1248df1192b5e Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 11:20:59 +0100 Subject: [PATCH 279/423] chore: fixing the prettier of the api-reports Signed-off-by: blam --- plugins/badges-backend/api-report.md | 2 +- plugins/bitbucket-cloud-common/api-report.md | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/badges-backend/api-report.md b/plugins/badges-backend/api-report.md index 0ecf41ee85..8ca4b561a2 100644 --- a/plugins/badges-backend/api-report.md +++ b/plugins/badges-backend/api-report.md @@ -79,7 +79,7 @@ export type BadgeSpec = { }; // @public (undocumented) -export type BadgeStyle = typeof BADGE_STYLES[number]; +export type BadgeStyle = (typeof BADGE_STYLES)[number]; // @public (undocumented) export const createDefaultBadgeFactories: () => BadgeFactories; diff --git a/plugins/bitbucket-cloud-common/api-report.md b/plugins/bitbucket-cloud-common/api-report.md index 5182579a4b..95e6f36836 100644 --- a/plugins/bitbucket-cloud-common/api-report.md +++ b/plugins/bitbucket-cloud-common/api-report.md @@ -132,7 +132,7 @@ export namespace Models { readonly Plaintext: 'plaintext'; }; export type BaseCommitSummaryMarkupEnum = - typeof BaseCommitSummaryMarkupEnum[keyof typeof BaseCommitSummaryMarkupEnum]; + (typeof BaseCommitSummaryMarkupEnum)[keyof typeof BaseCommitSummaryMarkupEnum]; export interface Branch { default_merge_strategy?: string; // (undocumented) @@ -150,7 +150,7 @@ export namespace Models { readonly FastForward: 'fast_forward'; }; export type BranchMergeStrategiesEnum = - typeof BranchMergeStrategiesEnum[keyof typeof BranchMergeStrategiesEnum]; + (typeof BranchMergeStrategiesEnum)[keyof typeof BranchMergeStrategiesEnum]; export interface Commit extends BaseCommit { // (undocumented) participants?: Array; @@ -179,7 +179,7 @@ export namespace Models { }; // (undocumented) export type CommitFileAttributesEnum = - typeof CommitFileAttributesEnum[keyof typeof CommitFileAttributesEnum]; + (typeof CommitFileAttributesEnum)[keyof typeof CommitFileAttributesEnum]; export interface Link { // (undocumented) href?: string; @@ -221,7 +221,7 @@ export namespace Models { }; // (undocumented) export type ParticipantRoleEnum = - typeof ParticipantRoleEnum[keyof typeof ParticipantRoleEnum]; + (typeof ParticipantRoleEnum)[keyof typeof ParticipantRoleEnum]; const // (undocumented) ParticipantStateEnum: { readonly Approved: 'approved'; @@ -230,7 +230,7 @@ export namespace Models { }; // (undocumented) export type ParticipantStateEnum = - typeof ParticipantStateEnum[keyof typeof ParticipantStateEnum]; + (typeof ParticipantStateEnum)[keyof typeof ParticipantStateEnum]; export interface Project extends ModelObject { // (undocumented) created_on?: string; @@ -306,7 +306,7 @@ export namespace Models { readonly NoForks: 'no_forks'; }; export type RepositoryForkPolicyEnum = - typeof RepositoryForkPolicyEnum[keyof typeof RepositoryForkPolicyEnum]; + (typeof RepositoryForkPolicyEnum)[keyof typeof RepositoryForkPolicyEnum]; const // (undocumented) RepositoryScmEnum: { readonly Git: 'git'; @@ -336,7 +336,7 @@ export namespace Models { } // (undocumented) export type RepositoryScmEnum = - typeof RepositoryScmEnum[keyof typeof RepositoryScmEnum]; + (typeof RepositoryScmEnum)[keyof typeof RepositoryScmEnum]; // (undocumented) export interface SearchCodeSearchResult { // (undocumented) From 0f0f48cb821ef397e5e61ef9d6b264c4310439e7 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 12:40:05 +0100 Subject: [PATCH 280/423] chore: reset router Signed-off-by: blam --- plugins/scaffolder/src/components/Router.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index 06c28682c5..ccc2bd283b 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -149,13 +149,12 @@ export const Router = (props: RouterProps) => { } /> - - } /> - } /> } /> + } /> + } /> Date: Tue, 7 Feb 2023 12:50:38 +0100 Subject: [PATCH 281/423] chore: prefer useMountEffect over use memo Signed-off-by: blam --- .../src/next/OngoingTask/TaskSteps/StepTime.tsx | 5 +++-- plugins/scaffolder/src/next/Router/Router.tsx | 10 ++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx index 2ec89f385a..653fe6e942 100644 --- a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useCallback, useMemo, useState } from 'react'; +import React, { useCallback, useState } from 'react'; import useInterval from 'react-use/lib/useInterval'; import { DateTime, Interval } from 'luxon'; import humanizeDuration from 'humanize-duration'; import { Typography } from '@material-ui/core'; +import { useMountEffect } from '@react-hookz/web'; export const StepTime = (props: { step: { @@ -48,7 +49,7 @@ export const StepTime = (props: { setTime(humanizeDuration(formatted, { round: true })); }, [step.endedAt, step.startedAt]); - useMemo(() => calculate(), [calculate]); + useMountEffect(() => calculate()); useInterval(() => !step.endedAt && calculate(), 1000); diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 0ca9e452cd..049579e16c 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -76,7 +76,11 @@ export type NextRouterProps = { */ export const Router = (props: PropsWithChildren) => { const { - components: { TemplateCardComponent, TemplateOutputsComponent } = {}, + components: { + TemplateCardComponent, + TemplateOutputsComponent, + TaskPageComponent = OngoingTask, + } = {}, } = props; const outlet = useOutlet() || props.children; const customFieldExtensions = @@ -121,7 +125,9 @@ export const Router = (props: PropsWithChildren) => { + } /> } /> From 01a075ec1df4d493b94df660ecc5660fd0837898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 7 Feb 2023 14:15:53 +0100 Subject: [PATCH 282/423] rename RootHttpRouterConfigureOptions, remove ServiceOrExtensionPoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/afraid-planets-crash.md | 5 +++++ packages/backend-app-api/api-report.md | 11 ++--------- .../services/implementations/rootHttpRouter/index.ts | 2 +- .../rootHttpRouter/rootHttpRouterServiceFactory.ts | 11 ++++------- packages/backend-app-api/src/wiring/index.ts | 6 +----- 5 files changed, 13 insertions(+), 22 deletions(-) create mode 100644 .changeset/afraid-planets-crash.md diff --git a/.changeset/afraid-planets-crash.md b/.changeset/afraid-planets-crash.md new file mode 100644 index 0000000000..b31a492f3d --- /dev/null +++ b/.changeset/afraid-planets-crash.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': minor +--- + +**BREAKING**: Renamed `RootHttpRouterConfigureOptions` to `RootHttpRouterConfigureContext`, and removed the unused type `ServiceOrExtensionPoint`. diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index 02b5685ead..e4c3e34751 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -11,7 +11,6 @@ import { ConfigService } from '@backstage/backend-plugin-api'; import { CorsOptions } from 'cors'; import { ErrorRequestHandler } from 'express'; import { Express as Express_2 } from 'express'; -import { ExtensionPoint } from '@backstage/backend-plugin-api'; import { Format } from 'logform'; import { Handler } from 'express'; import { HelmetOptions } from 'helmet'; @@ -34,7 +33,6 @@ import { RootLoggerService } from '@backstage/backend-plugin-api'; import { SchedulerService } from '@backstage/backend-plugin-api'; import { ServiceFactory } from '@backstage/backend-plugin-api'; import { ServiceFactoryOrFunction } from '@backstage/backend-plugin-api'; -import { ServiceRef } from '@backstage/backend-plugin-api'; import { TokenManagerService } from '@backstage/backend-plugin-api'; import { transport } from 'winston'; import { UrlReader } from '@backstage/backend-common'; @@ -216,7 +214,7 @@ export function readHelmetOptions(config?: Config): HelmetOptions; export function readHttpServerOptions(config?: Config): HttpServerOptions; // @public (undocumented) -export interface RootHttpRouterConfigureOptions { +export interface RootHttpRouterConfigureContext { // (undocumented) app: Express_2; // (undocumented) @@ -234,7 +232,7 @@ export interface RootHttpRouterConfigureOptions { // @public (undocumented) export type RootHttpRouterFactoryOptions = { indexPath?: string | false; - configure?(options: RootHttpRouterConfigureOptions): void; + configure?(context: RootHttpRouterConfigureContext): void; }; // @public (undocumented) @@ -251,11 +249,6 @@ export const rootLoggerServiceFactory: () => ServiceFactory; // @public (undocumented) export const schedulerServiceFactory: () => ServiceFactory; -// @public (undocumented) -export type ServiceOrExtensionPoint = - | ExtensionPoint - | ServiceRef; - // @public (undocumented) export const tokenManagerServiceFactory: () => ServiceFactory; diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/index.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/index.ts index 93b997239d..8437399fec 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/index.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/index.ts @@ -17,7 +17,7 @@ export { rootHttpRouterServiceFactory, type RootHttpRouterFactoryOptions, - type RootHttpRouterConfigureOptions, + type RootHttpRouterConfigureContext, } from './rootHttpRouterServiceFactory'; export { DefaultRootHttpRouter, diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts index a14beb428d..5eaf8aa152 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts @@ -32,7 +32,7 @@ import { DefaultRootHttpRouter } from './DefaultRootHttpRouter'; /** * @public */ -export interface RootHttpRouterConfigureOptions { +export interface RootHttpRouterConfigureContext { app: Express; middleware: MiddlewareFactory; routes: RequestHandler; @@ -51,14 +51,11 @@ export type RootHttpRouterFactoryOptions = { */ indexPath?: string | false; - configure?(options: RootHttpRouterConfigureOptions): void; + configure?(context: RootHttpRouterConfigureContext): void; }; -function defaultConfigure({ - app, - routes, - middleware, -}: RootHttpRouterConfigureOptions) { +function defaultConfigure(context: RootHttpRouterConfigureContext) { + const { app, routes, middleware } = context; app.use(middleware.helmet()); app.use(middleware.cors()); app.use(middleware.compression()); diff --git a/packages/backend-app-api/src/wiring/index.ts b/packages/backend-app-api/src/wiring/index.ts index 6e0fb272ae..00e4a9d4b4 100644 --- a/packages/backend-app-api/src/wiring/index.ts +++ b/packages/backend-app-api/src/wiring/index.ts @@ -14,9 +14,5 @@ * limitations under the License. */ -export type { - Backend, - CreateSpecializedBackendOptions, - ServiceOrExtensionPoint, -} from './types'; +export type { Backend, CreateSpecializedBackendOptions } from './types'; export { createSpecializedBackend } from './createSpecializedBackend'; From b2a73c984a9c2271d0f3eb68f2301f98744beb91 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 7 Feb 2023 15:03:45 +0000 Subject: [PATCH 283/423] Version Packages (next) --- .changeset/pre.json | 69 +- docs/releases/v1.11.0-next.2-changelog.md | 2289 +++++++++++++++++ package.json | 2 +- packages/app-defaults/CHANGELOG.md | 11 + packages/app-defaults/package.json | 2 +- packages/app/CHANGELOG.md | 64 + packages/app/package.json | 2 +- packages/backend-app-api/CHANGELOG.md | 28 + packages/backend-app-api/package.json | 2 +- packages/backend-common/CHANGELOG.md | 19 + packages/backend-common/package.json | 2 +- packages/backend-defaults/CHANGELOG.md | 9 + packages/backend-defaults/package.json | 2 +- packages/backend-dev-utils/CHANGELOG.md | 7 + packages/backend-dev-utils/package.json | 2 +- packages/backend-next/CHANGELOG.md | 10 + packages/backend-next/package.json | 2 +- packages/backend-plugin-api/CHANGELOG.md | 20 + packages/backend-plugin-api/package.json | 2 +- packages/backend-tasks/CHANGELOG.md | 10 + packages/backend-tasks/package.json | 2 +- packages/backend-test-utils/CHANGELOG.md | 20 + packages/backend-test-utils/package.json | 2 +- packages/backend/CHANGELOG.md | 49 + packages/backend/package.json | 2 +- packages/catalog-client/CHANGELOG.md | 8 + packages/catalog-client/package.json | 2 +- packages/catalog-model/CHANGELOG.md | 13 + packages/catalog-model/package.json | 2 +- packages/cli/CHANGELOG.md | 15 + packages/cli/package.json | 2 +- packages/codemods/CHANGELOG.md | 8 + packages/codemods/package.json | 2 +- packages/core-components/CHANGELOG.md | 12 + packages/core-components/package.json | 2 +- packages/create-app/CHANGELOG.md | 8 + packages/create-app/package.json | 2 +- packages/dev-utils/CHANGELOG.md | 15 + packages/dev-utils/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 7 + packages/eslint-plugin/package.json | 2 +- packages/integration-react/CHANGELOG.md | 11 + packages/integration-react/package.json | 2 +- packages/repo-tools/CHANGELOG.md | 9 + packages/repo-tools/package.json | 2 +- .../techdocs-cli-embedded-app/CHANGELOG.md | 19 + .../techdocs-cli-embedded-app/package.json | 2 +- packages/techdocs-cli/CHANGELOG.md | 11 + packages/techdocs-cli/package.json | 2 +- plugins/adr-backend/CHANGELOG.md | 14 + plugins/adr-backend/package.json | 2 +- plugins/adr-common/CHANGELOG.md | 9 + plugins/adr-common/package.json | 2 +- plugins/adr/CHANGELOG.md | 20 + plugins/adr/package.json | 2 +- plugins/airbrake-backend/CHANGELOG.md | 8 + plugins/airbrake-backend/package.json | 2 +- plugins/airbrake/CHANGELOG.md | 13 + plugins/airbrake/package.json | 2 +- plugins/allure/CHANGELOG.md | 11 + plugins/allure/package.json | 2 +- plugins/analytics-module-ga/CHANGELOG.md | 10 + plugins/analytics-module-ga/package.json | 2 +- plugins/apache-airflow/CHANGELOG.md | 8 + plugins/apache-airflow/package.json | 2 +- plugins/api-docs/CHANGELOG.md | 17 + plugins/api-docs/package.json | 2 +- plugins/apollo-explorer/CHANGELOG.md | 9 + plugins/apollo-explorer/package.json | 2 +- plugins/app-backend/CHANGELOG.md | 12 + plugins/app-backend/package.json | 2 +- plugins/auth-backend/CHANGELOG.md | 13 + plugins/auth-backend/package.json | 2 +- plugins/auth-node/CHANGELOG.md | 9 + plugins/auth-node/package.json | 2 +- plugins/azure-devops-backend/CHANGELOG.md | 9 + plugins/azure-devops-backend/package.json | 2 +- plugins/azure-devops/CHANGELOG.md | 13 + plugins/azure-devops/package.json | 2 +- plugins/azure-sites-backend/CHANGELOG.md | 9 + plugins/azure-sites-backend/package.json | 2 +- plugins/azure-sites/CHANGELOG.md | 14 + plugins/azure-sites/package.json | 2 +- plugins/badges-backend/CHANGELOG.md | 11 + plugins/badges-backend/package.json | 2 +- plugins/badges/CHANGELOG.md | 12 + plugins/badges/package.json | 2 +- plugins/bazaar-backend/CHANGELOG.md | 14 + plugins/bazaar-backend/package.json | 2 +- plugins/bazaar/CHANGELOG.md | 15 + plugins/bazaar/package.json | 2 +- plugins/bitrise/CHANGELOG.md | 11 + plugins/bitrise/package.json | 2 +- .../catalog-backend-module-aws/CHANGELOG.md | 16 + .../catalog-backend-module-aws/package.json | 2 +- .../catalog-backend-module-azure/CHANGELOG.md | 16 + .../catalog-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 18 + .../package.json | 2 +- .../CHANGELOG.md | 15 + .../package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 15 + .../package.json | 2 +- .../CHANGELOG.md | 19 + .../package.json | 2 +- .../CHANGELOG.md | 17 + .../package.json | 2 +- .../CHANGELOG.md | 19 + .../package.json | 2 +- .../catalog-backend-module-ldap/CHANGELOG.md | 12 + .../catalog-backend-module-ldap/package.json | 2 +- .../CHANGELOG.md | 22 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- plugins/catalog-backend/CHANGELOG.md | 22 + plugins/catalog-backend/package.json | 2 +- plugins/catalog-common/CHANGELOG.md | 9 + plugins/catalog-common/package.json | 2 +- plugins/catalog-customized/CHANGELOG.md | 8 + plugins/catalog-customized/package.json | 2 +- plugins/catalog-graph/CHANGELOG.md | 12 + plugins/catalog-graph/package.json | 2 +- plugins/catalog-graphql/CHANGELOG.md | 9 + plugins/catalog-graphql/package.json | 2 +- plugins/catalog-import/CHANGELOG.md | 16 + plugins/catalog-import/package.json | 2 +- plugins/catalog-node/CHANGELOG.md | 12 + plugins/catalog-node/package.json | 2 +- plugins/catalog-react/CHANGELOG.md | 18 + plugins/catalog-react/package.json | 2 +- plugins/catalog/CHANGELOG.md | 22 + plugins/catalog/package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/cicd-statistics/CHANGELOG.md | 9 + plugins/cicd-statistics/package.json | 2 +- plugins/circleci/CHANGELOG.md | 12 + plugins/circleci/package.json | 2 +- plugins/cloudbuild/CHANGELOG.md | 11 + plugins/cloudbuild/package.json | 2 +- plugins/code-climate/CHANGELOG.md | 11 + plugins/code-climate/package.json | 2 +- plugins/code-coverage-backend/CHANGELOG.md | 12 + plugins/code-coverage-backend/package.json | 2 +- plugins/code-coverage/CHANGELOG.md | 13 + plugins/code-coverage/package.json | 2 +- plugins/codescene/CHANGELOG.md | 11 + plugins/codescene/package.json | 2 +- plugins/config-schema/CHANGELOG.md | 12 + plugins/config-schema/package.json | 2 +- plugins/cost-insights/CHANGELOG.md | 13 + plugins/cost-insights/package.json | 2 +- plugins/dynatrace/CHANGELOG.md | 11 + plugins/dynatrace/package.json | 2 +- plugins/entity-validation/CHANGELOG.md | 19 + plugins/entity-validation/package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../events-backend-module-azure/CHANGELOG.md | 8 + .../events-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../events-backend-module-gerrit/CHANGELOG.md | 8 + .../events-backend-module-gerrit/package.json | 2 +- .../events-backend-module-github/CHANGELOG.md | 9 + .../events-backend-module-github/package.json | 2 +- .../events-backend-module-gitlab/CHANGELOG.md | 9 + .../events-backend-module-gitlab/package.json | 2 +- .../events-backend-test-utils/CHANGELOG.md | 7 + .../events-backend-test-utils/package.json | 2 +- plugins/events-backend/CHANGELOG.md | 11 + plugins/events-backend/package.json | 2 +- plugins/events-node/CHANGELOG.md | 8 + plugins/events-node/package.json | 2 +- .../example-todo-list-backend/CHANGELOG.md | 11 + .../example-todo-list-backend/package.json | 2 +- plugins/example-todo-list/CHANGELOG.md | 9 + plugins/example-todo-list/package.json | 2 +- plugins/explore-backend/CHANGELOG.md | 10 + plugins/explore-backend/package.json | 2 +- plugins/explore/CHANGELOG.md | 20 + plugins/explore/package.json | 2 +- plugins/firehydrant/CHANGELOG.md | 10 + plugins/firehydrant/package.json | 2 +- plugins/fossa/CHANGELOG.md | 12 + plugins/fossa/package.json | 2 +- plugins/gcalendar/CHANGELOG.md | 10 + plugins/gcalendar/package.json | 2 +- plugins/gcp-projects/CHANGELOG.md | 9 + plugins/gcp-projects/package.json | 2 +- plugins/git-release-manager/CHANGELOG.md | 10 + plugins/git-release-manager/package.json | 2 +- plugins/github-actions/CHANGELOG.md | 12 + plugins/github-actions/package.json | 2 +- plugins/github-deployments/CHANGELOG.md | 14 + plugins/github-deployments/package.json | 2 +- plugins/github-issues/CHANGELOG.md | 13 + plugins/github-issues/package.json | 2 +- .../github-pull-requests-board/CHANGELOG.md | 12 + .../github-pull-requests-board/package.json | 2 +- plugins/gitops-profiles/CHANGELOG.md | 9 + plugins/gitops-profiles/package.json | 2 +- plugins/gocd/CHANGELOG.md | 12 + plugins/gocd/package.json | 2 +- plugins/graphiql/CHANGELOG.md | 9 + plugins/graphiql/package.json | 2 +- plugins/graphql-backend/CHANGELOG.md | 9 + plugins/graphql-backend/package.json | 2 +- plugins/graphql-voyager/CHANGELOG.md | 16 + plugins/graphql-voyager/package.json | 2 +- plugins/home/CHANGELOG.md | 12 + plugins/home/package.json | 2 +- plugins/ilert/CHANGELOG.md | 12 + plugins/ilert/package.json | 2 +- plugins/jenkins-backend/CHANGELOG.md | 14 + plugins/jenkins-backend/package.json | 2 +- plugins/jenkins-common/CHANGELOG.md | 8 + plugins/jenkins-common/package.json | 2 +- plugins/jenkins/CHANGELOG.md | 13 + plugins/jenkins/package.json | 2 +- plugins/kafka-backend/CHANGELOG.md | 13 + plugins/kafka-backend/package.json | 2 +- plugins/kafka/CHANGELOG.md | 12 + plugins/kafka/package.json | 2 +- plugins/kubernetes-backend/CHANGELOG.md | 15 + plugins/kubernetes-backend/package.json | 2 +- plugins/kubernetes-common/CHANGELOG.md | 7 + plugins/kubernetes-common/package.json | 2 +- plugins/kubernetes/CHANGELOG.md | 13 + plugins/kubernetes/package.json | 2 +- plugins/lighthouse-backend/CHANGELOG.md | 18 + plugins/lighthouse-backend/package.json | 2 +- plugins/lighthouse-common/CHANGELOG.md | 12 + plugins/lighthouse-common/package.json | 2 +- plugins/lighthouse/CHANGELOG.md | 36 + plugins/lighthouse/package.json | 2 +- plugins/newrelic-dashboard/CHANGELOG.md | 11 + plugins/newrelic-dashboard/package.json | 2 +- plugins/newrelic/CHANGELOG.md | 9 + plugins/newrelic/package.json | 2 +- plugins/org-react/CHANGELOG.md | 12 + plugins/org-react/package.json | 2 +- plugins/org/CHANGELOG.md | 11 + plugins/org/package.json | 2 +- plugins/pagerduty/CHANGELOG.md | 12 + plugins/pagerduty/package.json | 2 +- plugins/periskop-backend/CHANGELOG.md | 11 + plugins/periskop-backend/package.json | 2 +- plugins/periskop/CHANGELOG.md | 12 + plugins/periskop/package.json | 2 +- plugins/permission-backend/CHANGELOG.md | 12 + plugins/permission-backend/package.json | 2 +- plugins/permission-node/CHANGELOG.md | 11 + plugins/permission-node/package.json | 2 +- plugins/playlist-backend/CHANGELOG.md | 16 + plugins/playlist-backend/package.json | 2 +- plugins/playlist/CHANGELOG.md | 17 + plugins/playlist/package.json | 2 +- plugins/proxy-backend/CHANGELOG.md | 11 + plugins/proxy-backend/package.json | 2 +- plugins/rollbar-backend/CHANGELOG.md | 8 + plugins/rollbar-backend/package.json | 2 +- plugins/rollbar/CHANGELOG.md | 11 + plugins/rollbar/package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/scaffolder-backend/CHANGELOG.md | 21 + plugins/scaffolder-backend/package.json | 2 +- plugins/scaffolder-common/CHANGELOG.md | 8 + plugins/scaffolder-common/package.json | 2 +- plugins/scaffolder-node/CHANGELOG.md | 10 + plugins/scaffolder-node/package.json | 2 +- plugins/scaffolder-react/CHANGELOG.md | 22 + plugins/scaffolder-react/package.json | 2 +- plugins/scaffolder/CHANGELOG.md | 23 + plugins/scaffolder/package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/search-backend-module-pg/CHANGELOG.md | 10 + plugins/search-backend-module-pg/package.json | 2 +- plugins/search-backend-node/CHANGELOG.md | 12 + plugins/search-backend-node/package.json | 2 +- plugins/search-backend/CHANGELOG.md | 16 + plugins/search-backend/package.json | 2 +- plugins/search-react/CHANGELOG.md | 16 + plugins/search-react/package.json | 2 +- plugins/search/CHANGELOG.md | 18 + plugins/search/package.json | 2 +- plugins/sentry/CHANGELOG.md | 15 + plugins/sentry/package.json | 2 +- plugins/shortcuts/CHANGELOG.md | 10 + plugins/shortcuts/package.json | 2 +- plugins/sonarqube-backend/CHANGELOG.md | 9 + plugins/sonarqube-backend/package.json | 2 +- plugins/sonarqube-react/CHANGELOG.md | 8 + plugins/sonarqube-react/package.json | 2 +- plugins/sonarqube/CHANGELOG.md | 12 + plugins/sonarqube/package.json | 2 +- plugins/splunk-on-call/CHANGELOG.md | 11 + plugins/splunk-on-call/package.json | 2 +- plugins/stack-overflow-backend/CHANGELOG.md | 9 + plugins/stack-overflow-backend/package.json | 2 +- plugins/stack-overflow/CHANGELOG.md | 13 + plugins/stack-overflow/package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- plugins/tech-insights-backend/CHANGELOG.md | 15 + plugins/tech-insights-backend/package.json | 2 +- plugins/tech-insights-node/CHANGELOG.md | 11 + plugins/tech-insights-node/package.json | 2 +- plugins/tech-insights/CHANGELOG.md | 14 + plugins/tech-insights/package.json | 2 +- plugins/tech-radar/CHANGELOG.md | 25 + plugins/tech-radar/package.json | 2 +- .../techdocs-addons-test-utils/CHANGELOG.md | 16 + .../techdocs-addons-test-utils/package.json | 2 +- plugins/techdocs-backend/CHANGELOG.md | 16 + plugins/techdocs-backend/package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- plugins/techdocs-node/CHANGELOG.md | 13 + plugins/techdocs-node/package.json | 2 +- plugins/techdocs-react/CHANGELOG.md | 11 + plugins/techdocs-react/package.json | 2 +- plugins/techdocs/CHANGELOG.md | 22 + plugins/techdocs/package.json | 2 +- plugins/todo-backend/CHANGELOG.md | 12 + plugins/todo-backend/package.json | 2 +- plugins/todo/CHANGELOG.md | 12 + plugins/todo/package.json | 2 +- plugins/user-settings-backend/CHANGELOG.md | 14 + plugins/user-settings-backend/package.json | 2 +- plugins/user-settings/CHANGELOG.md | 13 + plugins/user-settings/package.json | 2 +- plugins/vault-backend/CHANGELOG.md | 11 + plugins/vault-backend/package.json | 2 +- plugins/vault/CHANGELOG.md | 13 + plugins/vault/package.json | 2 +- plugins/xcmetrics/CHANGELOG.md | 10 + plugins/xcmetrics/package.json | 2 +- 349 files changed, 4825 insertions(+), 175 deletions(-) create mode 100644 docs/releases/v1.11.0-next.2-changelog.md create mode 100644 packages/backend-dev-utils/CHANGELOG.md create mode 100644 packages/eslint-plugin/CHANGELOG.md create mode 100644 plugins/entity-validation/CHANGELOG.md create mode 100644 plugins/graphql-voyager/CHANGELOG.md diff --git a/.changeset/pre.json b/.changeset/pre.json index 8d412f53b5..9b28c37a30 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -195,82 +195,149 @@ "@backstage/plugin-vault": "0.1.8", "@backstage/plugin-vault-backend": "0.2.6", "@backstage/plugin-xcmetrics": "0.2.34", - "@backstage/plugin-scaffolder-node": "0.0.0" + "@backstage/plugin-scaffolder-node": "0.0.0", + "@backstage/backend-dev-utils": "0.0.0", + "@backstage/eslint-plugin": "0.0.0", + "@backstage/plugin-entity-validation": "0.0.0", + "@backstage/plugin-graphql-voyager": "0.0.0", + "@backstage/plugin-lighthouse-backend": "0.0.0", + "@backstage/plugin-lighthouse-common": "0.0.0" }, "changesets": [ "afraid-foxes-provide", + "afraid-planets-crash", "brave-cougars-burn", + "breezy-ears-rule", "bright-eagles-love", + "bright-plums-cough", + "bright-teachers-compete", "brown-islands-own", "calm-avocados-exercise", "chatty-owls-care", + "chilled-sheep-collect", "clean-queens-judge", "cold-cycles-switch", + "cool-spoons-bathe", "create-app-1674561612", "cuddly-boxes-agree", "cyan-deers-walk", "dry-donkeys-cheer", + "dull-fishes-suffer", "dull-gorillas-sing", "eight-falcons-explode", "eight-hotels-sparkle", + "eight-vans-drum", + "eleven-shoes-crash", + "few-moons-accept", "flat-cups-itch", "four-candles-add", "four-rivers-enjoy", + "four-tables-fix", + "friendly-chefs-rule", "friendly-scissors-shop", "gold-bulldogs-talk", "gold-lemons-eat", "gold-masks-sleep", + "great-goats-talk", + "green-adults-retire", + "green-guests-flow", "grumpy-bottles-stare", + "grumpy-fireants-drop", "happy-cows-moo", + "hip-chairs-double", + "hip-onions-tan", "hip-pugs-teach", + "hip-tables-prove", "hot-lions-cover", + "hot-wasps-cover", "hungry-news-fix", + "itchy-chairs-punch", "itchy-goats-melt", "khaki-toes-care", "late-rice-crash", "lazy-badgers-rule", "lazy-badgers-try", "lemon-tables-train", + "little-jars-lay", + "long-chefs-burn", "lovely-ladybugs-taste", "many-nails-joke", + "many-pans-unite", + "mean-squids-kneel", "modern-cats-worry", "nasty-beans-accept", + "neat-schools-raise", "neat-zebras-run", "nervous-apricots-whisper", "nervous-mangos-rhyme", + "nervous-phones-shout", + "new-pumpkins-sleep", "nine-glasses-invent", "nine-guests-compete", + "nine-ravens-kiss", "ninety-hats-serve", "old-knives-wonder", + "old-ways-know", "perfect-cheetahs-serve", "pink-falcons-serve", "poor-moons-confess", "popular-dancers-join", "pretty-ladybugs-taste", + "proud-glasses-live", "purple-feet-smile", "quick-ladybugs-reply", + "quick-mice-change", + "rare-berries-give", "rare-melons-battle", + "red-kiwis-compare", "renovate-0b349f9", "renovate-0c3644c", + "renovate-53e8b07", "rich-snakes-rest", "rotten-mayflies-love", + "selfish-frogs-punch", + "serious-pigs-watch", "sharp-lobsters-build", "shiny-years-tap", + "short-apes-relate", + "shy-buses-mix", "shy-steaks-invite", + "silent-peas-fly", + "silly-buckets-joke", + "silly-socks-lie", "silly-turkeys-hang", + "silver-wolves-breathe", + "slow-carrots-sniff", + "slow-moles-sin", "smart-dingos-raise", + "soft-actors-worry", "soft-boxes-buy", "soft-snails-notice", "spotty-coats-clean", "stale-dots-smile", + "stale-experts-punch", "stupid-ladybugs-brake", "swift-fishes-smash", + "tall-falcons-teach", + "tall-tables-hide", "tall-years-relate", + "tasty-jobs-help", "thick-clocks-pump", + "thick-tables-travel", + "thin-donkeys-attack", + "thin-scissors-press", + "tough-jeans-camp", "twenty-islands-wonder", "twenty-parents-relate", "two-melons-lie", + "violet-tips-rhyme", + "weak-radios-sing", + "wicked-beers-walk", + "wild-donkeys-rescue", "witty-moose-itch", + "yellow-roses-tell", + "young-beans-float", + "young-points-drop", "young-singers-learn" ] } diff --git a/docs/releases/v1.11.0-next.2-changelog.md b/docs/releases/v1.11.0-next.2-changelog.md new file mode 100644 index 0000000000..65f6622921 --- /dev/null +++ b/docs/releases/v1.11.0-next.2-changelog.md @@ -0,0 +1,2289 @@ +# Release v1.11.0-next.2 + +## @backstage/backend-app-api@0.4.0-next.2 + +### Minor Changes + +- 01a075ec1d: **BREAKING**: Renamed `RootHttpRouterConfigureOptions` to `RootHttpRouterConfigureContext`, and removed the unused type `ServiceOrExtensionPoint`. +- 4ae71b7f2e: **BREAKING** Renaming `*Factory` exports to `*ServiceFactory` instead. For example `configFactory` now is exported as `configServiceFactory`. +- d31d8e00b3: **BREAKING** `HttpServerCertificateOptions` when specified with a `key` and `cert` should also have the `type: 'pem'` instead of `type: 'plain'` + +### Patch Changes + +- e716946103: Updated usage of the lifecycle service. +- f60cca9da1: Updated database factory to pass service deps required for restoring database state during development. +- 610d65e143: Updates to match new `BackendFeature` type. +- ab22515647: The shutdown signal handlers are now installed as part of the backend instance rather than the lifecycle service, and explicitly cause the process to exit. +- b729f9f31f: Moved the options of the `config` and `rootHttpRouter` services out to the factories themselves, where they belong +- 71a5ec0f06: Updated usages of `LogMeta`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/backend-dev-utils@0.1.0-next.0 + +### Minor Changes + +- 9d9cdea117: Introduced a new package for backend development utilities. Similar to how `@backstage/dev-utils` is used in the frontend. + +## @backstage/backend-plugin-api@0.4.0-next.2 + +### Minor Changes + +- e716946103: **BREAKING**: Split out the hook for both lifecycle services so that the first parameter of `addShutdownHook` is the hook function, and the second is the options. +- 0ff03319be: **BREAKING**: The plugin ID option passed to `createBackendPlugin` is now `pluginId`, rather than just `id`. This is to make it match `createBackendModule` more closely. +- 71a5ec0f06: **BREAKING**: Switched out `LogMeta` type for `JsonObject`. +- 610d65e143: Switched `BackendFeature` to be an opaque type. + +### Patch Changes + +- 9c9456fd33: Removed the unused `TypesToServiceRef` type +- 181c03edb5: Aligned opaque type markers to all use a `$type` property with namespacing. +- Updated dependencies + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/catalog-model@1.2.0-next.1 + +### Minor Changes + +- d51668882d: Adds the tRPC API type to the catalog. + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/eslint-plugin@0.1.0-next.0 + +### Minor Changes + +- 179d301518: Added a new ESLint plugin with common rules for Backstage projects. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for more details. + +## @backstage/plugin-adr@0.4.0-next.2 + +### Minor Changes + +- ec34b535c0: The `AdrSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- ec34b535c0: Support displaying an icon on `AdrSearchResultListItem` +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-adr-common@0.2.6-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-api-docs@0.9.0-next.2 + +### Minor Changes + +- 9ed53218a5: Adds a new tRPC API definition widget which users can utilize to integrate their tRPC API definitions into Backstage. + +### Patch Changes + +- 6856ab98f4: Updated dependency `@asyncapi/react-component` to `1.0.0-next.47`. +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.0-next.2 + +### Minor Changes + +- fb568e2683: Improve performance when loading users via group membership. + Users data is now loaded from a paged query, rather than having to make an extra call per user to load each user's profiles. + + Note, there are still additional per user calls made to load user avatars + +### Patch Changes + +- 28f9883440: Fixed a bug reading the `user.select` field expected from the `app-config.yaml` configuration +- c5b119ad9c: Increased default page size to 999 (from 100) to reduce the number of calls made to the Microsoft Graph API. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-entity-validation@0.1.0-next.0 + +### Minor Changes + +- d34b3267f9: First implementation for the entity validation UI. For more information refer to its `README.md`. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-graphql-voyager@0.1.0-next.0 + +### Minor Changes + +- d1fb4b7bf1: Add the new GraphQL Voyager tool as a plugin for backstage, expose necessary API and components needed for it. + + For more information on how to use this plugin and configure it, please navigate to the [README](https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager/README.md) of the plugin. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-lighthouse@0.4.0-next.2 + +### Minor Changes + +- eef62546ce: Require @backstage/plugin-lighthouse-common package where API implementation moved to. + + **BREAKING**: the following types have been moved to @backstage/plugin-lighthouse-common: + + - `Audit` + - `AuditBase` + - `AuditCompleted` + - `AuditFailed` + - `AuditRunning` + - `FetchError` + - `LASListRequest` + - `LASListResponse` + - `LighthouseApi` + - `LighthouseCategoryAbbr` + - `LighthouseCategoryId` + - `LighthouseConfigSettings` + - `LighthouseRestApi` + - `TriggerAuditPayload` + - `Website` + - `WebsiteListResponse` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-lighthouse-common@0.1.0-next.0 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-lighthouse-backend@0.1.0-next.0 + +### Minor Changes + +- eef62546ce: Introduce Lighthouse Backend Plugin to run scheduled Lighthouse Audits + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-lighthouse-common@0.1.0-next.0 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-lighthouse-common@0.1.0-next.0 + +### Minor Changes + +- eef62546ce: Introduce @backstage/plugin-lighthouse-common with the API implementation + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + +## @backstage/plugin-scaffolder-react@1.1.0-next.2 + +### Minor Changes + +- 5555e17313: refactor `createAsyncValidators` to be recursive to ensure validators are called in nested schemas. + +### Patch Changes + +- b46f385eff: scaffolder/next: Implementing a simple `OngoingTask` page +- ccbf91051b: bump `@rjsf` `v5` dependencies to 5.1.0 +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + +## @backstage/plugin-sentry@0.5.0-next.2 + +### Minor Changes + +- 6a8d6b9a0c: Add option to filter issues based on the time it was triggered + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/app-defaults@1.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-permission-react@0.4.9 + +## @backstage/backend-common@0.18.2-next.2 + +### Patch Changes + +- e716946103: Updated usage of the lifecycle service. +- d31d8e00b3: Updated to work with the new `type: 'pem'` with `createHttpServer` from `@backstage/backend-app-api` +- 0ff03319be: Updated usage of `createBackendPlugin`. +- f60cca9da1: The `DatabaseManager.forPlugin` method now accepts additional service dependencies. There is no need to update existing code to pass these dependencies. +- Updated dependencies + - @backstage/backend-app-api@0.4.0-next.2 + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-dev-utils@0.1.0-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/backend-defaults@0.1.7-next.2 + +### Patch Changes + +- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` +- Updated dependencies + - @backstage/backend-app-api@0.4.0-next.2 + - @backstage/backend-plugin-api@0.4.0-next.2 + +## @backstage/backend-tasks@0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/backend-test-utils@0.1.34-next.2 + +### Patch Changes + +- baf6e4c96a: Removed unnecessary `@backstage/cli` dependency. +- 1835311713: Added explicit return type signature for `mockServices.config()`. +- e716946103: Updated usage of the lifecycle service. +- 7e7557a2be: Updated the `mockServices.rootLogger` options to accept a single level option instead. +- 610d65e143: Updates to match new `BackendFeature` type. +- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` +- f1adb2e36b: Removed the `ref` from all `mockServices`. +- 71a5ec0f06: Updated usages of `LogMeta`. +- Updated dependencies + - @backstage/backend-app-api@0.4.0-next.2 + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/catalog-client@1.3.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/errors@1.1.4 + +## @backstage/cli@0.22.2-next.1 + +### Patch Changes + +- dd8a9afe66: Replaced several monorepo lint rules with new rules from `@backstage/eslint-plugin`. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for a full list of rules. +- 90616df9a8: Added an experimental mode for the `package start` command for backend packages. Enabled by setting `EXPERIMENTAL_BACKEND_START`. +- Updated dependencies + - @backstage/eslint-plugin@0.1.0-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/release-manifests@0.0.8 + - @backstage/types@1.0.2 + +## @backstage/codemods@0.1.43-next.0 + +### Patch Changes + +- 02f1316e57: Moved `commander` to being a regular dependency. +- Updated dependencies + - @backstage/cli-common@0.1.11 + +## @backstage/core-components@0.12.4-next.1 + +### Patch Changes + +- 66e2aab4c4: Navigation items in mobile sidebar now have aria label. +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/version-bridge@1.0.3 + +## @backstage/create-app@0.4.37-next.2 + +### Patch Changes + +- 02f1316e57: Updated `packages/app/cypress/.eslintrc.json` to remove the unnecessary `import/no-extraneous-dependencies` rule. +- Updated dependencies + - @backstage/cli-common@0.1.11 + +## @backstage/dev-utils@1.0.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/app-defaults@1.1.1-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/integration-react@1.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + +## @backstage/repo-tools@0.1.2-next.0 + +### Patch Changes + +- ff63acf30a: Packages without a declared `backstage.role` are now ignored. +- Updated dependencies + - @backstage/cli-common@0.1.11 + - @backstage/errors@1.1.4 + +## @techdocs/cli@1.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/plugin-techdocs-node@1.4.6-next.2 + +## @backstage/plugin-adr-backend@0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-common@0.2.6-next.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-adr-common@0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/integration@1.4.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-airbrake@0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/dev-utils@1.0.12-next.2 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-airbrake-backend@0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-allure@0.1.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-analytics-module-ga@0.1.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-apache-airflow@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + +## @backstage/plugin-apollo-explorer@0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-app-backend@0.3.42-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/types@1.0.2 + +## @backstage/plugin-auth-backend@0.17.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-auth-node@0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-azure-devops@0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-devops-common@0.3.0 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-azure-devops-backend@0.3.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-sites@0.1.4-next.2 + +### Patch Changes + +- 98a00a09d5: Fixed `AzureSites` plugin start and stop issue #15904 + Fixed `AzureSites` UI load issue #15907 +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-sites-common@0.1.0 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-azure-sites-backend@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-badges@0.2.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-badges-backend@0.1.36-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-bazaar@0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.1 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-bazaar-backend@0.2.5-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-bitrise@0.1.42-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-catalog@1.8.0-next.2 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-backend@1.7.2-next.2 + +### Patch Changes + +- e716946103: Updated usage of the lifecycle service. +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-backend-module-aws@0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-azure@0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + - @backstage/plugin-catalog-common@1.0.11-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-catalog-backend-module-github@0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.1.13-next.2 + +### Patch Changes + +- 49948f644f: The config now consistently uses the term 'instance' to refer to a single GitLab API host. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.2.0-next.2 + +### Patch Changes + +- 407dc01fc9: Removing extra imports for `run` script as `TestBackend` auto loads the default factories +- 77c41b6924: Updated README to include newer API options for incremental entity providers +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-common@1.0.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-graph@0.2.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-catalog-graphql@0.3.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-import@0.9.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-catalog-node@1.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + +## @backstage/plugin-catalog-react@1.3.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + +## @backstage/plugin-cicd-statistics@0.1.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/plugin-cicd-statistics@0.1.17-next.2 + +## @backstage/plugin-circleci@0.3.15-next.2 + +### Patch Changes + +- 1616e06047: Making workflow a link +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-cloudbuild@0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-code-climate@0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-code-coverage@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-code-coverage-backend@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-codescene@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-config-schema@0.1.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + +## @backstage/plugin-cost-insights@0.12.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-cost-insights-common@0.1.1 + +## @backstage/plugin-dynatrace@2.0.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-events-backend@0.2.3-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-events-backend-module-aws-sqs@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-events-backend-module-azure@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + +## @backstage/plugin-events-backend-module-gerrit@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + +## @backstage/plugin-events-backend-module-github@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-events-backend-module-gitlab@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-events-backend-test-utils@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.3-next.2 + +## @backstage/plugin-events-node@0.2.3-next.2 + +### Patch Changes + +- 19d4abf72c: Make `EventParams` typed for implementing tidier event handling. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + +## @backstage/plugin-explore@0.4.0-next.2 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-explore-react@0.0.25 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-explore-backend@0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-firehydrant@0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-fossa@0.2.47-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-gcalendar@0.3.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-gcp-projects@0.3.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-git-release-manager@0.3.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-github-actions@0.5.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-github-deployments@0.1.46-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-github-issues@0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-github-pull-requests-board@0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-gitops-profiles@0.3.33-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-gocd@0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-graphiql@0.2.47-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-graphql-backend@0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-catalog-graphql@0.3.18-next.1 + +## @backstage/plugin-home@0.4.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-ilert@0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-jenkins@0.7.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-jenkins-common@0.1.13-next.1 + +## @backstage/plugin-jenkins-backend@0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-jenkins-common@0.1.13-next.1 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-jenkins-common@0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-kafka@0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-kafka-backend@0.2.35-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-kubernetes@0.7.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-kubernetes-common@0.6.0-next.2 + +## @backstage/plugin-kubernetes-backend@0.9.3-next.2 + +### Patch Changes + +- 7ff81f7692: Kubernetes proxy endpoint now accepts content types that are not json +- Updated dependencies + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-kubernetes-common@0.6.0-next.2 + +## @backstage/plugin-kubernetes-common@0.6.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + +## @backstage/plugin-newrelic@0.3.33-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-newrelic-dashboard@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-org@0.6.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-org-react@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-pagerduty@0.5.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-periskop@0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-periskop-backend@0.1.13-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-permission-backend@0.5.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-permission-node@0.7.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-playlist@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-playlist-common@0.1.4 + +## @backstage/plugin-playlist-backend@0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-playlist-common@0.1.4 + +## @backstage/plugin-proxy-backend@0.2.36-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-rollbar@0.4.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-rollbar-backend@0.1.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-scaffolder@1.11.0-next.2 + +### Patch Changes + +- b46f385eff: scaffolder/next: Implementing a simple `OngoingTask` page +- ccbf91051b: bump `@rjsf` `v5` dependencies to 5.1.0 +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + +## @backstage/plugin-scaffolder-backend@1.11.0-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-common@1.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-node@0.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + +## @backstage/plugin-search@1.1.0-next.2 + +### Patch Changes + +- 66e2aab4c4: Updated colors for each tab used on search modal, to improve color contrast. Aria label added to tabs wrapper component. `disableRipple` property on the `Tab` component removed to improve keyboard navigation indicator. +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend@1.2.3-next.2 + +### Patch Changes + +- 1b30c9a0f7: Change the router's response to include the error message instead of its object type in case it fails during a search query because the messages have more info. +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-module-elasticsearch@1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-module-pg@0.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-node@1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-react@1.5.0-next.1 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-shortcuts@0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + +## @backstage/plugin-sonarqube@0.6.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-sonarqube-react@0.1.2-next.1 + +## @backstage/plugin-sonarqube-backend@0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-sonarqube-react@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-plugin-api@1.3.0 + +## @backstage/plugin-splunk-on-call@0.4.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-stack-overflow@0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-home@0.4.31-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-stack-overflow-backend@0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-tech-insights@0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + +## @backstage/plugin-tech-insights-backend@0.5.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/plugin-tech-insights-node@0.4.0-next.2 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.26-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/plugin-tech-insights-node@0.4.0-next.2 + +## @backstage/plugin-tech-insights-node@0.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + +## @backstage/plugin-tech-radar@0.6.1-next.1 + +### Patch Changes + +- acf6c8c10b: Deprecate `RadarEntry.url` - use `RadarEntry.links` instead + + ```diff + - url: 'https://www.javascript.com/', + key: 'javascript', + id: 'javascript', + title: 'JavaScript', + quadrant: 'languages', + links: [ + + { + + url: 'https://www.javascript.com/', + + title: 'Learn more', + + }, + ], + ``` + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-techdocs@1.5.0-next.2 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.5.0-next.2 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + +## @backstage/plugin-techdocs-backend@1.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-node@1.4.6-next.2 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + +## @backstage/plugin-techdocs-node@1.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-aws-node@0.1.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-techdocs-react@1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/version-bridge@1.0.3 + +## @backstage/plugin-todo@0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-todo-backend@0.1.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-user-settings@0.6.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-user-settings-backend@0.1.6-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-vault@0.1.9-next.2 + +### Patch Changes + +- fd7a77b9c4: Surface additional context and details to the Backstage UI when the Vault plugin encounters non-successful HTTP responses from the Vault API. +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-vault-backend@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-xcmetrics@0.2.35-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## example-app@0.2.80-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0-next.2 + - @backstage/plugin-scaffolder@1.11.0-next.2 + - @backstage/cli@0.22.2-next.1 + - @backstage/plugin-api-docs@0.9.0-next.2 + - @backstage/plugin-tech-radar@0.6.1-next.1 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-techdocs@1.5.0-next.2 + - @backstage/plugin-explore@0.4.0-next.2 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/plugin-sentry@0.5.0-next.2 + - @backstage/plugin-circleci@0.3.15-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/plugin-azure-sites@0.1.4-next.2 + - @backstage/plugin-search@1.1.0-next.2 + - @backstage/plugin-lighthouse@0.4.0-next.2 + - @backstage/app-defaults@1.1.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-airbrake@0.3.15-next.2 + - @backstage/plugin-apache-airflow@0.2.8-next.1 + - @backstage/plugin-azure-devops@0.2.6-next.2 + - @backstage/plugin-badges@0.2.39-next.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-graph@0.2.27-next.2 + - @backstage/plugin-catalog-import@0.9.5-next.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-cloudbuild@0.3.15-next.2 + - @backstage/plugin-code-coverage@0.2.8-next.2 + - @backstage/plugin-cost-insights@0.12.4-next.2 + - @backstage/plugin-dynatrace@2.0.0-next.2 + - @backstage/plugin-gcalendar@0.3.11-next.1 + - @backstage/plugin-gcp-projects@0.3.34-next.1 + - @backstage/plugin-github-actions@0.5.15-next.2 + - @backstage/plugin-gocd@0.1.21-next.2 + - @backstage/plugin-graphiql@0.2.47-next.1 + - @backstage/plugin-home@0.4.31-next.2 + - @backstage/plugin-jenkins@0.7.14-next.2 + - @backstage/plugin-kafka@0.3.15-next.2 + - @backstage/plugin-kubernetes@0.7.8-next.2 + - @backstage/plugin-newrelic@0.3.33-next.1 + - @backstage/plugin-newrelic-dashboard@0.2.8-next.2 + - @backstage/plugin-org@0.6.5-next.2 + - @backstage/plugin-pagerduty@0.5.8-next.2 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-playlist@0.1.6-next.2 + - @backstage/plugin-rollbar@0.4.15-next.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-shortcuts@0.3.7-next.1 + - @backstage/plugin-stack-overflow@0.1.11-next.2 + - @backstage/plugin-tech-insights@0.3.7-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.10-next.2 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + - @backstage/plugin-todo@0.2.17-next.2 + - @backstage/plugin-user-settings@0.6.3-next.2 + - @internal/plugin-catalog-customized@0.0.7-next.2 + +## example-backend@0.2.80-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-lighthouse-backend@0.1.0-next.0 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/plugin-search-backend@1.2.3-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-events-backend@0.2.3-next.2 + - @backstage/plugin-kafka-backend@0.2.35-next.2 + - @backstage/plugin-proxy-backend@0.2.36-next.2 + - @backstage/plugin-app-backend@0.3.42-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-kubernetes-backend@0.9.3-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-backend@0.17.5-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/plugin-playlist-backend@0.2.5-next.2 + - @backstage/plugin-rollbar-backend@0.1.39-next.2 + - @backstage/plugin-search-backend-module-pg@0.5.3-next.2 + - @backstage/plugin-tech-insights-backend@0.5.8-next.2 + - @backstage/plugin-techdocs-backend@1.5.3-next.2 + - example-app@0.2.80-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-backend@0.2.7-next.2 + - @backstage/plugin-azure-devops-backend@0.3.21-next.2 + - @backstage/plugin-azure-sites-backend@0.1.4-next.2 + - @backstage/plugin-badges-backend@0.1.36-next.2 + - @backstage/plugin-code-coverage-backend@0.2.8-next.2 + - @backstage/plugin-explore-backend@0.0.4-next.2 + - @backstage/plugin-graphql-backend@0.1.32-next.2 + - @backstage/plugin-jenkins-backend@0.1.32-next.2 + - @backstage/plugin-permission-backend@0.5.17-next.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.10-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.1.3-next.2 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.26-next.2 + - @backstage/plugin-tech-insights-node@0.4.0-next.2 + - @backstage/plugin-todo-backend@0.1.39-next.2 + +## example-backend-next@0.0.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-app-backend@0.3.42-next.2 + - @backstage/backend-defaults@0.1.7-next.2 + +## techdocs-cli-embedded-app@0.2.79-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.1 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-techdocs@1.5.0-next.2 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/app-defaults@1.1.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + +## @internal/plugin-catalog-customized@0.0.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @internal/plugin-todo-list@1.0.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @internal/plugin-todo-list-backend@1.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 diff --git a/package.json b/package.json index e08ca3adfd..286e750f29 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@types/react": "^17", "@types/react-dom": "^17" }, - "version": "1.11.0-next.1", + "version": "1.11.0-next.2", "dependencies": { "@backstage/errors": "workspace:^", "@manypkg/get-packages": "^1.1.3" diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index ecd6c448d5..e785ffe05a 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/app-defaults +## 1.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-permission-react@0.4.9 + ## 1.1.1-next.0 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 793baff253..8ffdfd60bc 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.1.1-next.0", + "version": "1.1.1-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index a541927bf4..818d21840d 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,69 @@ # example-app +## 0.2.80-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0-next.2 + - @backstage/plugin-scaffolder@1.11.0-next.2 + - @backstage/cli@0.22.2-next.1 + - @backstage/plugin-api-docs@0.9.0-next.2 + - @backstage/plugin-tech-radar@0.6.1-next.1 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-techdocs@1.5.0-next.2 + - @backstage/plugin-explore@0.4.0-next.2 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/plugin-sentry@0.5.0-next.2 + - @backstage/plugin-circleci@0.3.15-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/plugin-azure-sites@0.1.4-next.2 + - @backstage/plugin-search@1.1.0-next.2 + - @backstage/plugin-lighthouse@0.4.0-next.2 + - @backstage/app-defaults@1.1.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-airbrake@0.3.15-next.2 + - @backstage/plugin-apache-airflow@0.2.8-next.1 + - @backstage/plugin-azure-devops@0.2.6-next.2 + - @backstage/plugin-badges@0.2.39-next.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-graph@0.2.27-next.2 + - @backstage/plugin-catalog-import@0.9.5-next.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-cloudbuild@0.3.15-next.2 + - @backstage/plugin-code-coverage@0.2.8-next.2 + - @backstage/plugin-cost-insights@0.12.4-next.2 + - @backstage/plugin-dynatrace@2.0.0-next.2 + - @backstage/plugin-gcalendar@0.3.11-next.1 + - @backstage/plugin-gcp-projects@0.3.34-next.1 + - @backstage/plugin-github-actions@0.5.15-next.2 + - @backstage/plugin-gocd@0.1.21-next.2 + - @backstage/plugin-graphiql@0.2.47-next.1 + - @backstage/plugin-home@0.4.31-next.2 + - @backstage/plugin-jenkins@0.7.14-next.2 + - @backstage/plugin-kafka@0.3.15-next.2 + - @backstage/plugin-kubernetes@0.7.8-next.2 + - @backstage/plugin-newrelic@0.3.33-next.1 + - @backstage/plugin-newrelic-dashboard@0.2.8-next.2 + - @backstage/plugin-org@0.6.5-next.2 + - @backstage/plugin-pagerduty@0.5.8-next.2 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-playlist@0.1.6-next.2 + - @backstage/plugin-rollbar@0.4.15-next.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-shortcuts@0.3.7-next.1 + - @backstage/plugin-stack-overflow@0.1.11-next.2 + - @backstage/plugin-tech-insights@0.3.7-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.10-next.2 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + - @backstage/plugin-todo@0.2.17-next.2 + - @backstage/plugin-user-settings@0.6.3-next.2 + - @internal/plugin-catalog-customized@0.0.7-next.2 + ## 0.2.80-next.1 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index f6631ed05b..1b3841ceae 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.80-next.1", + "version": "0.2.80-next.2", "private": true, "backstage": { "role": "frontend" diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index 6e7dcbfde5..daae24c717 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/backend-app-api +## 0.4.0-next.2 + +### Minor Changes + +- 01a075ec1d: **BREAKING**: Renamed `RootHttpRouterConfigureOptions` to `RootHttpRouterConfigureContext`, and removed the unused type `ServiceOrExtensionPoint`. +- 4ae71b7f2e: **BREAKING** Renaming `*Factory` exports to `*ServiceFactory` instead. For example `configFactory` now is exported as `configServiceFactory`. +- d31d8e00b3: **BREAKING** `HttpServerCertificateOptions` when specified with a `key` and `cert` should also have the `type: 'pem'` instead of `type: 'plain'` + +### Patch Changes + +- e716946103: Updated usage of the lifecycle service. +- f60cca9da1: Updated database factory to pass service deps required for restoring database state during development. +- 610d65e143: Updates to match new `BackendFeature` type. +- ab22515647: The shutdown signal handlers are now installed as part of the backend instance rather than the lifecycle service, and explicitly cause the process to exit. +- b729f9f31f: Moved the options of the `config` and `rootHttpRouter` services out to the factories themselves, where they belong +- 71a5ec0f06: Updated usages of `LogMeta`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.3.2-next.1 ### Patch Changes diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index 0bd4eab227..3bbae1f7fe 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.3.2-next.1", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index f8090ae971..1a495ff771 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/backend-common +## 0.18.2-next.2 + +### Patch Changes + +- e716946103: Updated usage of the lifecycle service. +- d31d8e00b3: Updated to work with the new `type: 'pem'` with `createHttpServer` from `@backstage/backend-app-api` +- 0ff03319be: Updated usage of `createBackendPlugin`. +- f60cca9da1: The `DatabaseManager.forPlugin` method now accepts additional service dependencies. There is no need to update existing code to pass these dependencies. +- Updated dependencies + - @backstage/backend-app-api@0.4.0-next.2 + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-dev-utils@0.1.0-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.18.2-next.1 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 9ec68e5531..3152cd0b28 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.18.2-next.1", + "version": "0.18.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index 0824ee5655..89f3ee25c6 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/backend-defaults +## 0.1.7-next.2 + +### Patch Changes + +- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` +- Updated dependencies + - @backstage/backend-app-api@0.4.0-next.2 + - @backstage/backend-plugin-api@0.4.0-next.2 + ## 0.1.7-next.1 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 6b1b173205..2d92d15ab8 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.7-next.1", + "version": "0.1.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-dev-utils/CHANGELOG.md b/packages/backend-dev-utils/CHANGELOG.md new file mode 100644 index 0000000000..9acf8cf15f --- /dev/null +++ b/packages/backend-dev-utils/CHANGELOG.md @@ -0,0 +1,7 @@ +# @backstage/backend-dev-utils + +## 0.1.0-next.0 + +### Minor Changes + +- 9d9cdea117: Introduced a new package for backend development utilities. Similar to how `@backstage/dev-utils` is used in the frontend. diff --git a/packages/backend-dev-utils/package.json b/packages/backend-dev-utils/package.json index 735185e37f..6e1cf7d3b0 100644 --- a/packages/backend-dev-utils/package.json +++ b/packages/backend-dev-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-dev-utils", - "version": "0.0.0", + "version": "0.1.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-next/CHANGELOG.md b/packages/backend-next/CHANGELOG.md index 914835b1c4..9e8f7a2d83 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,15 @@ # example-backend-next +## 0.0.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-app-backend@0.3.42-next.2 + - @backstage/backend-defaults@0.1.7-next.2 + ## 0.0.8-next.1 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index fb821e19eb..8f007dc7ea 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.8-next.1", + "version": "0.0.8-next.2", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index 3ad0715538..f5aa2dd9fc 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/backend-plugin-api +## 0.4.0-next.2 + +### Minor Changes + +- e716946103: **BREAKING**: Split out the hook for both lifecycle services so that the first parameter of `addShutdownHook` is the hook function, and the second is the options. +- 0ff03319be: **BREAKING**: The plugin ID option passed to `createBackendPlugin` is now `pluginId`, rather than just `id`. This is to make it match `createBackendModule` more closely. +- 71a5ec0f06: **BREAKING**: Switched out `LogMeta` type for `JsonObject`. +- 610d65e143: Switched `BackendFeature` to be an opaque type. + +### Patch Changes + +- 9c9456fd33: Removed the unused `TypesToServiceRef` type +- 181c03edb5: Aligned opaque type markers to all use a `$type` property with namespacing. +- Updated dependencies + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + ## 0.3.2-next.1 ### Patch Changes diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 954112bc2d..7243f3485c 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.3.2-next.1", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index 04ce4e9c3b..1e32f34978 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/backend-tasks +## 0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.4.3-next.1 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 574f3dc812..ee7d7d6e67 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.4.3-next.1", + "version": "0.4.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index f532e08d81..bf7b6c6713 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/backend-test-utils +## 0.1.34-next.2 + +### Patch Changes + +- baf6e4c96a: Removed unnecessary `@backstage/cli` dependency. +- 1835311713: Added explicit return type signature for `mockServices.config()`. +- e716946103: Updated usage of the lifecycle service. +- 7e7557a2be: Updated the `mockServices.rootLogger` options to accept a single level option instead. +- 610d65e143: Updates to match new `BackendFeature` type. +- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` +- f1adb2e36b: Removed the `ref` from all `mockServices`. +- 71a5ec0f06: Updated usages of `LogMeta`. +- Updated dependencies + - @backstage/backend-app-api@0.4.0-next.2 + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.1.34-next.1 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index d1f0a86d43..08e00e1c5e 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.34-next.1", + "version": "0.1.34-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 24b00f192c..7053244da9 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,54 @@ # example-backend +## 0.2.80-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-lighthouse-backend@0.1.0-next.0 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/plugin-search-backend@1.2.3-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-events-backend@0.2.3-next.2 + - @backstage/plugin-kafka-backend@0.2.35-next.2 + - @backstage/plugin-proxy-backend@0.2.36-next.2 + - @backstage/plugin-app-backend@0.3.42-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-kubernetes-backend@0.9.3-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-backend@0.17.5-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/plugin-playlist-backend@0.2.5-next.2 + - @backstage/plugin-rollbar-backend@0.1.39-next.2 + - @backstage/plugin-search-backend-module-pg@0.5.3-next.2 + - @backstage/plugin-tech-insights-backend@0.5.8-next.2 + - @backstage/plugin-techdocs-backend@1.5.3-next.2 + - example-app@0.2.80-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-backend@0.2.7-next.2 + - @backstage/plugin-azure-devops-backend@0.3.21-next.2 + - @backstage/plugin-azure-sites-backend@0.1.4-next.2 + - @backstage/plugin-badges-backend@0.1.36-next.2 + - @backstage/plugin-code-coverage-backend@0.2.8-next.2 + - @backstage/plugin-explore-backend@0.0.4-next.2 + - @backstage/plugin-graphql-backend@0.1.32-next.2 + - @backstage/plugin-jenkins-backend@0.1.32-next.2 + - @backstage/plugin-permission-backend@0.5.17-next.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.10-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.1.3-next.2 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.26-next.2 + - @backstage/plugin-tech-insights-node@0.4.0-next.2 + - @backstage/plugin-todo-backend@0.1.39-next.2 + ## 0.2.80-next.1 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index e554036ede..3678c1f9ae 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.80-next.1", + "version": "0.2.80-next.2", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index cf61dee463..1602dfbb79 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/catalog-client +## 1.3.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/errors@1.1.4 + ## 1.3.1-next.0 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 8b7c09d2ef..ac233e293a 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.3.1-next.0", + "version": "1.3.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 5bb6033940..1f14aba820 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/catalog-model +## 1.2.0-next.1 + +### Minor Changes + +- d51668882d: Adds the tRPC API type to the catalog. + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 1.1.6-next.0 ### Patch Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 5dba193a61..117035a82e 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.6-next.0", + "version": "1.2.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index caf890a14f..09e7f44eb4 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/cli +## 0.22.2-next.1 + +### Patch Changes + +- dd8a9afe66: Replaced several monorepo lint rules with new rules from `@backstage/eslint-plugin`. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for a full list of rules. +- 90616df9a8: Added an experimental mode for the `package start` command for backend packages. Enabled by setting `EXPERIMENTAL_BACKEND_START`. +- Updated dependencies + - @backstage/eslint-plugin@0.1.0-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/release-manifests@0.0.8 + - @backstage/types@1.0.2 + ## 0.22.2-next.0 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 587c91ce5e..a3020de1da 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.22.2-next.0", + "version": "0.22.2-next.1", "publishConfig": { "access": "public" }, diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index 2481aff8b1..5dc610d5c1 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/codemods +## 0.1.43-next.0 + +### Patch Changes + +- 02f1316e57: Moved `commander` to being a regular dependency. +- Updated dependencies + - @backstage/cli-common@0.1.11 + ## 0.1.42 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 1ae4d04485..7c6af890b0 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.42", + "version": "0.1.43-next.0", "publishConfig": { "access": "public", "main": "dist/index.cjs.js" diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index efded8f3c1..30c4e92173 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/core-components +## 0.12.4-next.1 + +### Patch Changes + +- 66e2aab4c4: Navigation items in mobile sidebar now have aria label. +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/version-bridge@1.0.3 + ## 0.12.4-next.0 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index dc65108d4a..7eedac93ac 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.12.4-next.0", + "version": "0.12.4-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 4b757a47c9..198d4d92a9 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/create-app +## 0.4.37-next.2 + +### Patch Changes + +- 02f1316e57: Updated `packages/app/cypress/.eslintrc.json` to remove the unnecessary `import/no-extraneous-dependencies` rule. +- Updated dependencies + - @backstage/cli-common@0.1.11 + ## 0.4.37-next.1 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index e87dc7b0ac..cfdccc5a2b 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.37-next.1", + "version": "0.4.37-next.2", "publishConfig": { "access": "public" }, diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 0b66dd3019..6996180db5 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/dev-utils +## 1.0.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/app-defaults@1.1.1-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 1.0.12-next.1 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index b00f5e58a2..773dc3cac0 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.12-next.1", + "version": "1.0.12-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md new file mode 100644 index 0000000000..35e3c8f0ea --- /dev/null +++ b/packages/eslint-plugin/CHANGELOG.md @@ -0,0 +1,7 @@ +# @backstage/eslint-plugin + +## 0.1.0-next.0 + +### Minor Changes + +- 179d301518: Added a new ESLint plugin with common rules for Backstage projects. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for more details. diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 84fc16b98f..0aea11d370 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/eslint-plugin", "description": "Backstage ESLint plugin", - "version": "0.0.0", + "version": "0.1.0-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 5e880265f8..8813458f86 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/integration-react +## 1.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + ## 1.1.10-next.0 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index 8fdc8d4841..b287f88f87 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.10-next.0", + "version": "1.1.10-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index 5969521581..2875d54fef 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/repo-tools +## 0.1.2-next.0 + +### Patch Changes + +- ff63acf30a: Packages without a declared `backstage.role` are now ignored. +- Updated dependencies + - @backstage/cli-common@0.1.11 + - @backstage/errors@1.1.4 + ## 0.1.1 ### Patch Changes diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index dd70575433..5ea26060c4 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/repo-tools", "description": "CLI for Backstage repo tooling ", - "version": "0.1.1", + "version": "0.1.2-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index f82207ff06..55d39a6ee5 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,24 @@ # techdocs-cli-embedded-app +## 0.2.79-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.1 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-techdocs@1.5.0-next.2 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/app-defaults@1.1.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + ## 0.2.79-next.1 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 68d443db99..acee2e8cb3 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,6 +1,6 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.79-next.1", + "version": "0.2.79-next.2", "private": true, "backstage": { "role": "frontend" diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index 8e0bc02dca..54bf7d2e8c 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,16 @@ # @techdocs/cli +## 1.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/plugin-techdocs-node@1.4.6-next.2 + ## 1.3.2-next.1 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 5f2e7db65d..092bd687bc 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.3.2-next.1", + "version": "1.3.2-next.2", "publishConfig": { "access": "public" }, diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index c791947589..11f11a19b9 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-adr-backend +## 0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-common@0.2.6-next.1 + - @backstage/plugin-search-common@1.2.1 + ## 0.2.7-next.1 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index 0c74df5cf2..33679a00dc 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.7-next.1", + "version": "0.2.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr-common/CHANGELOG.md b/plugins/adr-common/CHANGELOG.md index 4ee9e2fd8e..7ed77717a1 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-adr-common +## 0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/integration@1.4.2 + - @backstage/plugin-search-common@1.2.1 + ## 0.2.6-next.0 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index a34cf5497c..7bae7294bb 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.6-next.0", + "version": "0.2.6-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index 6f9a6b4be6..cea1b59deb 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-adr +## 0.4.0-next.2 + +### Minor Changes + +- ec34b535c0: The `AdrSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- ec34b535c0: Support displaying an icon on `AdrSearchResultListItem` +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-adr-common@0.2.6-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + ## 0.3.1-next.1 ### Patch Changes diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 5f3d3ba12a..085729f86f 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.3.1-next.1", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md index 81a9eb4ae1..16ad4db685 100644 --- a/plugins/airbrake-backend/CHANGELOG.md +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-airbrake-backend +## 0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + ## 0.2.15-next.1 ### Patch Changes diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index 9d56c6defa..4d8cde9678 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.15-next.1", + "version": "0.2.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index 4132257d2e..0d7ccc3e7e 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-airbrake +## 0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/dev-utils@1.0.12-next.2 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.3.15-next.1 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index d87b734674..c16cccd171 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.15-next.1", + "version": "0.3.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index 4bc73ee469..02c249120e 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-allure +## 0.1.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.1.31-next.1 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index a36762e5ac..cdd0b6c71f 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.31-next.1", + "version": "0.1.31-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index 0114443617..61cd39fcb8 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.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.1.26-next.0 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 17ee33eea9..e98aa30b4b 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.26-next.0", + "version": "0.1.26-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index e597c164a0..1434589d01 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-apache-airflow +## 0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + ## 0.2.8-next.0 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index c589a58557..45116f3171 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.8-next.0", + "version": "0.2.8-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index b002e4c373..39796b3231 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-api-docs +## 0.9.0-next.2 + +### Minor Changes + +- 9ed53218a5: Adds a new tRPC API definition widget which users can utilize to integrate their tRPC API definitions into Backstage. + +### Patch Changes + +- 6856ab98f4: Updated dependency `@asyncapi/react-component` to `1.0.0-next.47`. +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.8.15-next.1 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index a23a123dc3..ee3e88fe11 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.15-next.1", + "version": "0.9.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apollo-explorer/CHANGELOG.md b/plugins/apollo-explorer/CHANGELOG.md index df9c9d8270..8903d504a9 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-apollo-explorer +## 0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.1.8-next.0 ### Patch Changes diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index 713ad945ad..7917f5a417 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.8-next.0", + "version": "0.1.8-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index a8a9ca7edf..617d74217b 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-app-backend +## 0.3.42-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/types@1.0.2 + ## 0.3.42-next.1 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index d434749619..ff9cd8fe5f 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.42-next.1", + "version": "0.3.42-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index a1bee43423..f76848cb94 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-auth-backend +## 0.17.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.17.5-next.1 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index a95465dbad..7a855e62a8 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.17.5-next.1", + "version": "0.17.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index d569650cd5..7f9e0f8a33 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-node +## 0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.11-next.1 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 5d0748cdee..fe7adb300d 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.11-next.1", + "version": "0.2.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index 2c7f39f8b3..7488628b80 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-azure-devops-backend +## 0.3.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-devops-common@0.3.0 + ## 0.3.21-next.1 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index c62602a8f5..2103acf8fc 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.21-next.1", + "version": "0.3.21-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index e6ab23c37c..cb4be6f908 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-azure-devops +## 0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-devops-common@0.3.0 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.2.6-next.1 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 71ff024078..bfb09aff1d 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.6-next.1", + "version": "0.2.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites-backend/CHANGELOG.md b/plugins/azure-sites-backend/CHANGELOG.md index 30e29db0ae..e3680abddb 100644 --- a/plugins/azure-sites-backend/CHANGELOG.md +++ b/plugins/azure-sites-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-azure-sites-backend +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-sites-common@0.1.0 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/azure-sites-backend/package.json b/plugins/azure-sites-backend/package.json index fbc98b0d5e..c053435161 100644 --- a/plugins/azure-sites-backend/package.json +++ b/plugins/azure-sites-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites-backend", - "version": "0.1.4-next.1", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites/CHANGELOG.md b/plugins/azure-sites/CHANGELOG.md index 32c55b424c..8c44d24ff3 100644 --- a/plugins/azure-sites/CHANGELOG.md +++ b/plugins/azure-sites/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-azure-sites +## 0.1.4-next.2 + +### Patch Changes + +- 98a00a09d5: Fixed `AzureSites` plugin start and stop issue #15904 + Fixed `AzureSites` UI load issue #15907 +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-sites-common@0.1.0 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index a2032f9292..3cfe1ea9c3 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites", - "version": "0.1.4-next.1", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index c3ed18ac63..ca5bbb859d 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-badges-backend +## 0.1.36-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.36-next.1 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 33e945bfd0..25beed0238 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.36-next.1", + "version": "0.1.36-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index c58757b38d..cefd2f8ccd 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-badges +## 0.2.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.2.39-next.1 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 8e6eb3c88d..4c8edbd09f 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.39-next.1", + "version": "0.2.39-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index 6fc165aebc..5a7107312e 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-bazaar-backend +## 0.2.5-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.5-next.1 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 0d21223078..d67bba4eb5 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.2.5-next.1", + "version": "0.2.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index a24a4164ce..d3b9cc6a71 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-bazaar +## 0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.1 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.2.4-next.1 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index d4d88176d8..7558aaf2ec 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.2.4-next.1", + "version": "0.2.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index be81c9f7af..65cef85765 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-bitrise +## 0.1.42-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.1.42-next.1 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 3f064430cc..13cc29fd06 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.42-next.1", + "version": "0.1.42-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index bea397e7b5..d0eeb5702c 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.1.15-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 083ed52fab..0c9d9af8bb 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.15-next.1", + "version": "0.1.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index c71b691a7a..05e48690d7 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.1.13-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index da7d1f5aa3..9552fe1e98 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.13-next.1", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index 4cd4b6565c..261a192dfa 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + - @backstage/plugin-catalog-common@1.0.11-next.1 + ## 0.1.9-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 1e1f94ac38..78e1e15653 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.9-next.1", + "version": "0.1.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index ef7755cf0d..b3b825bbc6 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index eba6a276ad..edd1fbf0e6 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.7-next.1", + "version": "0.1.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md index 455abd3f2b..b07c7a92bb 100644 --- a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-bitbucket +## 0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + ## 0.2.9-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index 646f9af81e..7df64bbc87 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.9-next.1", + "version": "0.2.9-next.2", "deprecated": true, "main": "src/index.ts", "types": "src/index.ts", diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index f048780bb7..9efd73aac5 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.1.10-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index f2327ed216..4e8d389c9c 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.10-next.1", + "version": "0.1.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index 430615eabd..089cd237e2 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-backend-module-github +## 0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + ## 0.2.5-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index d72d520f6a..36cd96274a 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.2.5-next.1", + "version": "0.2.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 9da2c77fdf..1f5fc26f38 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.1.13-next.2 + +### Patch Changes + +- 49948f644f: The config now consistently uses the term 'instance' to refer to a single GitLab API host. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.1.13-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 44aadec29b..6668e2f45d 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.13-next.1", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index b52760e185..1953885783 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.2.0-next.2 + +### Patch Changes + +- 407dc01fc9: Removing extra imports for `run` script as `TestBackend` auto loads the default factories +- 77c41b6924: Updated README to include newer API options for incremental entity providers +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + ## 0.2.0-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index ec50c44311..b29771c74d 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-incremental-ingestion", "description": "An entity provider for streaming large asset sources into the catalog", - "version": "0.2.0-next.1", + "version": "0.2.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index f64a4460ea..50245d20ae 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.5.9-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index aed68ebdf9..6a5e1426f7 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.9-next.1", + "version": "0.5.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index e53d159d1d..0ee67c7a3c 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.5.0-next.2 + +### Minor Changes + +- fb568e2683: Improve performance when loading users via group membership. + Users data is now loaded from a paged query, rather than having to make an extra call per user to load each user's profiles. + + Note, there are still additional per user calls made to load user avatars + +### Patch Changes + +- 28f9883440: Fixed a bug reading the `user.select` field expected from the `app-config.yaml` configuration +- c5b119ad9c: Increased default page size to 999 (from 100) to reduce the number of calls made to the Microsoft Graph API. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + ## 0.4.8-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 7be2678bc6..7ae0af0bea 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.8-next.1", + "version": "0.5.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index 5dd91ecd63..496221964e 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.1.8-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index 6ccc4971b0..8f08f4b183 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.8-next.1", + "version": "0.1.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 1ee436c075..329f641c78 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-catalog-backend +## 1.7.2-next.2 + +### Patch Changes + +- e716946103: Updated usage of the lifecycle service. +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + - @backstage/plugin-search-common@1.2.1 + ## 1.7.2-next.1 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 2bf0429932..cebd91932b 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.7.2-next.1", + "version": "1.7.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-common/CHANGELOG.md b/plugins/catalog-common/CHANGELOG.md index 7ea2f35c98..b5dc4e29e8 100644 --- a/plugins/catalog-common/CHANGELOG.md +++ b/plugins/catalog-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-common +## 1.0.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.0.11-next.0 ### Patch Changes diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index f5c91f3697..2ba16c3d2a 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-common", "description": "Common functionalities for the catalog plugin", - "version": "1.0.11-next.0", + "version": "1.0.11-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-customized/CHANGELOG.md b/plugins/catalog-customized/CHANGELOG.md index 13b1364d66..f8ff5a85b8 100644 --- a/plugins/catalog-customized/CHANGELOG.md +++ b/plugins/catalog-customized/CHANGELOG.md @@ -1,5 +1,13 @@ # @internal/plugin-catalog-customized +## 0.0.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.0.7-next.1 ### Patch Changes diff --git a/plugins/catalog-customized/package.json b/plugins/catalog-customized/package.json index e72331539d..9f1e310508 100644 --- a/plugins/catalog-customized/package.json +++ b/plugins/catalog-customized/package.json @@ -1,7 +1,7 @@ { "name": "@internal/plugin-catalog-customized", "description": "The internal Backstage Customizable plugin for browsing the Backstage catalog", - "version": "0.0.7-next.1", + "version": "0.0.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index dcdbe96b91..d45fa8f234 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-graph +## 0.2.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.2.27-next.1 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 9ff0c8e92a..aee919241c 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.27-next.1", + "version": "0.2.27-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md index 5d4581212a..ee49cb0c3e 100644 --- a/plugins/catalog-graphql/CHANGELOG.md +++ b/plugins/catalog-graphql/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-graphql +## 0.3.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.3.18-next.0 ### Patch Changes diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 2f68052900..e66e0e0db2 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.18-next.0", + "version": "0.3.18-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 3f0711c721..9c74c13c88 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-import +## 0.9.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.9.5-next.1 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 36351746e5..a128aedfd8 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.9.5-next.1", + "version": "0.9.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index b01d88ae26..8d5667e4a6 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-node +## 1.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + ## 1.3.3-next.1 ### Patch Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 7874e36072..70071dcaea 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.3.3-next.1", + "version": "1.3.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 7f657f418f..662b57550a 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-react +## 1.3.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + ## 1.3.0-next.1 ### Minor Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 705c1b544a..c3e6cdda46 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.3.0-next.1", + "version": "1.3.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 588bfd40cd..204df92577 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-catalog +## 1.8.0-next.2 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + ## 1.8.0-next.1 ### Minor Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 333d621d40..c5e2c675c9 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.8.0-next.1", + "version": "1.8.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md index 811df4adcb..6516506197 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.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/plugin-cicd-statistics@0.1.17-next.2 + ## 0.1.11-next.1 ### Patch Changes diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index 32c33e207a..2c79050e98 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.11-next.1", + "version": "0.1.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics/CHANGELOG.md b/plugins/cicd-statistics/CHANGELOG.md index a09c2b3339..5dcd054002 100644 --- a/plugins/cicd-statistics/CHANGELOG.md +++ b/plugins/cicd-statistics/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-cicd-statistics +## 0.1.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.1.17-next.1 ### Patch Changes diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index 09ff03a4c7..795d8a6c8f 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.17-next.1", + "version": "0.1.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index c3b50931e8..701b6f5a86 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-circleci +## 0.3.15-next.2 + +### Patch Changes + +- 1616e06047: Making workflow a link +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.3.15-next.1 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 6e370c5def..b72b344eeb 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.15-next.1", + "version": "0.3.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index e69f59d9bf..2b2c262778 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-cloudbuild +## 0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.3.15-next.1 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index f80944b683..c1ac873f30 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.15-next.1", + "version": "0.3.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-climate/CHANGELOG.md b/plugins/code-climate/CHANGELOG.md index 84c51e3f43..5264e35a96 100644 --- a/plugins/code-climate/CHANGELOG.md +++ b/plugins/code-climate/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-code-climate +## 0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.1.15-next.1 ### Patch Changes diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 9783ee7583..9146f3e118 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.15-next.1", + "version": "0.1.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index 4d6a69c494..a5e6acae94 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.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 1d3ae89cc3..f9bcefbd5d 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.8-next.1", + "version": "0.2.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index f787ac85aa..5064067470 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-code-coverage +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index d336d9324f..fd15272e38 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.8-next.1", + "version": "0.2.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/codescene/CHANGELOG.md b/plugins/codescene/CHANGELOG.md index a89f49dc62..d07630cadf 100644 --- a/plugins/codescene/CHANGELOG.md +++ b/plugins/codescene/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-codescene +## 0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.1.10-next.0 ### Patch Changes diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index 6f763d529c..4249e11064 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-codescene", - "version": "0.1.10-next.0", + "version": "0.1.10-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index a8b4640584..21f079f591 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-config-schema +## 0.1.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + ## 0.1.38-next.0 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index f7bb416f22..95221632e6 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.38-next.0", + "version": "0.1.38-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 7c69958dde..05d55f3bfe 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-cost-insights +## 0.12.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-cost-insights-common@0.1.1 + ## 0.12.4-next.1 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 6e2bb01ef9..02a86793b0 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.12.4-next.1", + "version": "0.12.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/dynatrace/CHANGELOG.md b/plugins/dynatrace/CHANGELOG.md index 60be881c47..e403cf500c 100644 --- a/plugins/dynatrace/CHANGELOG.md +++ b/plugins/dynatrace/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-dynatrace +## 2.0.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 2.0.0-next.1 ### Patch Changes diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index c7656c52de..4cf4a84c33 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-dynatrace", - "version": "2.0.0-next.1", + "version": "2.0.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-validation/CHANGELOG.md b/plugins/entity-validation/CHANGELOG.md new file mode 100644 index 0000000000..aa1e41a299 --- /dev/null +++ b/plugins/entity-validation/CHANGELOG.md @@ -0,0 +1,19 @@ +# @backstage/plugin-entity-validation + +## 0.1.0-next.0 + +### Minor Changes + +- d34b3267f9: First implementation for the entity validation UI. For more information refer to its `README.md`. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index 3ff4f0ad5c..6a00e4ad16 100644 --- a/plugins/entity-validation/package.json +++ b/plugins/entity-validation/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-validation", - "version": "0.0.0", + "version": "0.1.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-aws-sqs/CHANGELOG.md b/plugins/events-backend-module-aws-sqs/CHANGELOG.md index b3431b3510..31596ba402 100644 --- a/plugins/events-backend-module-aws-sqs/CHANGELOG.md +++ b/plugins/events-backend-module-aws-sqs/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-events-backend-module-aws-sqs +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index 1925781020..bf06d46648 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-aws-sqs", - "version": "0.1.4-next.1", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-azure/CHANGELOG.md b/plugins/events-backend-module-azure/CHANGELOG.md index 12bc4a0798..83fadeba7b 100644 --- a/plugins/events-backend-module-azure/CHANGELOG.md +++ b/plugins/events-backend-module-azure/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-azure +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 6520ed83ca..12420646ae 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-azure", - "version": "0.1.4-next.1", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md index 182d5633ed..6808429921 100644 --- a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-bitbucket-cloud +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index 6a18b548e8..04e6248a5f 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-bitbucket-cloud", - "version": "0.1.4-next.1", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gerrit/CHANGELOG.md b/plugins/events-backend-module-gerrit/CHANGELOG.md index 4d1857f4d6..e05890268c 100644 --- a/plugins/events-backend-module-gerrit/CHANGELOG.md +++ b/plugins/events-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-gerrit +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index 8765f7777d..59cded8497 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gerrit", - "version": "0.1.4-next.1", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-github/CHANGELOG.md b/plugins/events-backend-module-github/CHANGELOG.md index d15c3c82ce..88fe36262b 100644 --- a/plugins/events-backend-module-github/CHANGELOG.md +++ b/plugins/events-backend-module-github/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-events-backend-module-github +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/config@1.0.6 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index aa2f6b26fb..6d1fb5b412 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-github", - "version": "0.1.4-next.1", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gitlab/CHANGELOG.md b/plugins/events-backend-module-gitlab/CHANGELOG.md index 4e7598b084..4265fa2c71 100644 --- a/plugins/events-backend-module-gitlab/CHANGELOG.md +++ b/plugins/events-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-events-backend-module-gitlab +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/config@1.0.6 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index bfca24f6bc..ad0b497421 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gitlab", - "version": "0.1.4-next.1", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-test-utils/CHANGELOG.md b/plugins/events-backend-test-utils/CHANGELOG.md index d495725662..713df91935 100644 --- a/plugins/events-backend-test-utils/CHANGELOG.md +++ b/plugins/events-backend-test-utils/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-events-backend-test-utils +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.3-next.2 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index 8032c98031..9df1f423e1 100644 --- a/plugins/events-backend-test-utils/package.json +++ b/plugins/events-backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-backend-test-utils", "description": "The plugin-events-backend-test-utils for @backstage/plugin-events-node", - "version": "0.1.4-next.1", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend/CHANGELOG.md b/plugins/events-backend/CHANGELOG.md index 1d5927c387..1d3ae288b4 100644 --- a/plugins/events-backend/CHANGELOG.md +++ b/plugins/events-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-events-backend +## 0.2.3-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/config@1.0.6 + ## 0.2.3-next.1 ### Patch Changes diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index d120ae892b..1154fc0633 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend", - "version": "0.2.3-next.1", + "version": "0.2.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-node/CHANGELOG.md b/plugins/events-node/CHANGELOG.md index ef0d97ad18..99423d1f4a 100644 --- a/plugins/events-node/CHANGELOG.md +++ b/plugins/events-node/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-node +## 0.2.3-next.2 + +### Patch Changes + +- 19d4abf72c: Make `EventParams` typed for implementing tidier event handling. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + ## 0.2.3-next.1 ### Patch Changes diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index 2cfff749e3..e1b784c6c4 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-node", "description": "The plugin-events-node module for @backstage/plugin-events-backend", - "version": "0.2.3-next.1", + "version": "0.2.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list-backend/CHANGELOG.md b/plugins/example-todo-list-backend/CHANGELOG.md index e3379a0082..d2212665fd 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @internal/plugin-todo-list-backend +## 1.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 1.0.10-next.1 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 11973d8f2a..5cda8b5f52 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.10-next.1", + "version": "1.0.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list/CHANGELOG.md b/plugins/example-todo-list/CHANGELOG.md index 17c56cc5d1..6b0da992bc 100644 --- a/plugins/example-todo-list/CHANGELOG.md +++ b/plugins/example-todo-list/CHANGELOG.md @@ -1,5 +1,14 @@ # @internal/plugin-todo-list +## 1.0.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 1.0.10-next.0 ### Patch Changes diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index fe4ac8d1c3..7d4378b51f 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list", - "version": "1.0.10-next.0", + "version": "1.0.10-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore-backend/CHANGELOG.md b/plugins/explore-backend/CHANGELOG.md index e9a25933de..80503f396a 100644 --- a/plugins/explore-backend/CHANGELOG.md +++ b/plugins/explore-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-explore-backend +## 0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.1 + ## 0.0.4-next.1 ### Patch Changes diff --git a/plugins/explore-backend/package.json b/plugins/explore-backend/package.json index 8356240641..77b6b05374 100644 --- a/plugins/explore-backend/package.json +++ b/plugins/explore-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-explore-backend", - "version": "0.0.4-next.1", + "version": "0.0.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index dfa262e63d..58f14ca14d 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-explore +## 0.4.0-next.2 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-explore-react@0.0.25 + - @backstage/plugin-search-common@1.2.1 + ## 0.4.0-next.1 ### Minor Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 8a6b856262..888040e1cb 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.4.0-next.1", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index 73f7de642f..c4660e5479 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-firehydrant +## 0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.1.32-next.1 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 4b40c86c3c..8edcade92b 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.32-next.1", + "version": "0.1.32-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index c0987cd461..1e906085e4 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-fossa +## 0.2.47-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.2.47-next.1 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 444471315c..a93d3b3922 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.47-next.1", + "version": "0.2.47-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcalendar/CHANGELOG.md b/plugins/gcalendar/CHANGELOG.md index a1f2b5a0c7..5134ae8c3f 100644 --- a/plugins/gcalendar/CHANGELOG.md +++ b/plugins/gcalendar/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-gcalendar +## 0.3.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.3.11-next.0 ### Patch Changes diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index 48e78f175a..5c84ebe6cb 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcalendar", - "version": "0.3.11-next.0", + "version": "0.3.11-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index 0a8693a233..405a344b28 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-gcp-projects +## 0.3.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.3.34-next.0 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index a3894760cf..54bfc85dd2 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.34-next.0", + "version": "0.3.34-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index 707f7be510..3fee0c167b 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.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + ## 0.3.28-next.0 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 7ec7d5806c..171a909b74 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.28-next.0", + "version": "0.3.28-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index 160a0f8a22..5ae3bafb5d 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-github-actions +## 0.5.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.5.15-next.1 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 509255d343..5165820d62 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.15-next.1", + "version": "0.5.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 68156abda2..9c3d9c85e4 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-github-deployments +## 0.1.46-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.1.46-next.1 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index ec596194c7..17d6239b90 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.46-next.1", + "version": "0.1.46-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-issues/CHANGELOG.md b/plugins/github-issues/CHANGELOG.md index 38c0387429..35aa080016 100644 --- a/plugins/github-issues/CHANGELOG.md +++ b/plugins/github-issues/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-github-issues +## 0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.2.4-next.1 ### Patch Changes diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index 284518bad3..574968d61a 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-issues", - "version": "0.2.4-next.1", + "version": "0.2.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-pull-requests-board/CHANGELOG.md b/plugins/github-pull-requests-board/CHANGELOG.md index fa4123887b..8dd45cd956 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.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.1.9-next.1 ### Patch Changes diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index e947557825..163b7a1967 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.9-next.1", + "version": "0.1.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index fa835e2131..4ade8515ff 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-gitops-profiles +## 0.3.33-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.3.33-next.0 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 3f0f3614cd..f43e7bb14b 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.33-next.0", + "version": "0.3.33-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index adecc5b5f1..01037953b0 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-gocd +## 0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.1.21-next.1 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index f659fe4525..f89a11047d 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.21-next.1", + "version": "0.1.21-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index 1be4fe30b5..68d6fa8e25 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphiql +## 0.2.47-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.2.47-next.0 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index b5c868d86d..15d15a38ca 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.47-next.0", + "version": "0.2.47-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/graphql-backend/CHANGELOG.md b/plugins/graphql-backend/CHANGELOG.md index 4686d4b103..28efff9546 100644 --- a/plugins/graphql-backend/CHANGELOG.md +++ b/plugins/graphql-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphql-backend +## 0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-catalog-graphql@0.3.18-next.1 + ## 0.1.32-next.1 ### Patch Changes diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index d3b4fc8707..0f44248997 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.32-next.1", + "version": "0.1.32-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphql-voyager/CHANGELOG.md b/plugins/graphql-voyager/CHANGELOG.md new file mode 100644 index 0000000000..3712169ea1 --- /dev/null +++ b/plugins/graphql-voyager/CHANGELOG.md @@ -0,0 +1,16 @@ +# @backstage/plugin-graphql-voyager + +## 0.1.0-next.0 + +### Minor Changes + +- d1fb4b7bf1: Add the new GraphQL Voyager tool as a plugin for backstage, expose necessary API and components needed for it. + + For more information on how to use this plugin and configure it, please navigate to the [README](https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager/README.md) of the plugin. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index 02e8ec95ca..b20d045640 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-voyager", "description": "Backstage plugin for GraphQL Voyager", - "version": "0.0.0", + "version": "0.1.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index e9698a5cde..400ca51ae9 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-home +## 0.4.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.4.31-next.1 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index 8f6a4f755f..6923b87c83 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.31-next.1", + "version": "0.4.31-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index d0edef70c6..a12bd0a010 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-ilert +## 0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.2.4-next.1 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 459f823255..757b91f78e 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.2.4-next.1", + "version": "0.2.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins-backend/CHANGELOG.md b/plugins/jenkins-backend/CHANGELOG.md index 9cbcc43f5f..00f1cdfe1b 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-jenkins-backend +## 0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-jenkins-common@0.1.13-next.1 + - @backstage/plugin-permission-common@0.7.3 + ## 0.1.32-next.1 ### Patch Changes diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index 43614edea2..d3107cba77 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.32-next.1", + "version": "0.1.32-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins-common/CHANGELOG.md b/plugins/jenkins-common/CHANGELOG.md index 71719e20e2..75a1470ed0 100644 --- a/plugins/jenkins-common/CHANGELOG.md +++ b/plugins/jenkins-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-jenkins-common +## 0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + ## 0.1.13-next.0 ### Patch Changes diff --git a/plugins/jenkins-common/package.json b/plugins/jenkins-common/package.json index c2d15a7da6..b37d1cfb8d 100644 --- a/plugins/jenkins-common/package.json +++ b/plugins/jenkins-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins-common", - "version": "0.1.13-next.0", + "version": "0.1.13-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index 045236e8aa..291f175013 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-jenkins +## 0.7.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-jenkins-common@0.1.13-next.1 + ## 0.7.14-next.1 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index 2fc0ed67ca..d2c629136b 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.14-next.1", + "version": "0.7.14-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index a07fb79fae..262cca0397 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-kafka-backend +## 0.2.35-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.35-next.1 ### Patch Changes diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 623764c147..f0c8d10bde 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.35-next.1", + "version": "0.2.35-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index 573a28a957..74d5b82c97 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-kafka +## 0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.3.15-next.1 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 7583fd06b5..546cf976d5 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.15-next.1", + "version": "0.3.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index fe00c7f8a1..a8726b238a 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-kubernetes-backend +## 0.9.3-next.2 + +### Patch Changes + +- 7ff81f7692: Kubernetes proxy endpoint now accepts content types that are not json +- Updated dependencies + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-kubernetes-common@0.6.0-next.2 + ## 0.9.3-next.1 ### Patch Changes diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 68225c489a..5b49d18543 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.9.3-next.1", + "version": "0.9.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index 4f369bf289..cd4df4d54a 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-kubernetes-common +## 0.6.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + ## 0.6.0-next.1 ### Patch Changes diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index 21f6480aa1..4a4e2a30bf 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.6.0-next.1", + "version": "0.6.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 2c375b8d0a..e30b168693 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-kubernetes +## 0.7.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-kubernetes-common@0.6.0-next.2 + ## 0.7.8-next.1 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 6c9c56db09..e51726b296 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.8-next.1", + "version": "0.7.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse-backend/CHANGELOG.md b/plugins/lighthouse-backend/CHANGELOG.md index e69de29bb2..d64d035fa3 100644 --- a/plugins/lighthouse-backend/CHANGELOG.md +++ b/plugins/lighthouse-backend/CHANGELOG.md @@ -0,0 +1,18 @@ +# @backstage/plugin-lighthouse-backend + +## 0.1.0-next.0 + +### Minor Changes + +- eef62546ce: Introduce Lighthouse Backend Plugin to run scheduled Lighthouse Audits + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-lighthouse-common@0.1.0-next.0 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 diff --git a/plugins/lighthouse-backend/package.json b/plugins/lighthouse-backend/package.json index 560ed4e8f7..60b8570481 100644 --- a/plugins/lighthouse-backend/package.json +++ b/plugins/lighthouse-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse-backend", "description": "Backend functionalities for lighthouse", - "version": "0.0.0", + "version": "0.1.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse-common/CHANGELOG.md b/plugins/lighthouse-common/CHANGELOG.md index e69de29bb2..189507371a 100644 --- a/plugins/lighthouse-common/CHANGELOG.md +++ b/plugins/lighthouse-common/CHANGELOG.md @@ -0,0 +1,12 @@ +# @backstage/plugin-lighthouse-common + +## 0.1.0-next.0 + +### Minor Changes + +- eef62546ce: Introduce @backstage/plugin-lighthouse-common with the API implementation + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 diff --git a/plugins/lighthouse-common/package.json b/plugins/lighthouse-common/package.json index 8dcc00960d..50281e17ba 100644 --- a/plugins/lighthouse-common/package.json +++ b/plugins/lighthouse-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse-common", "description": "Common functionalities for lighthouse, to be shared between lighthouse and lighthouse-backend plugin", - "version": "0.0.0", + "version": "0.1.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index 1c54959f18..a79e4795e2 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-lighthouse +## 0.4.0-next.2 + +### Minor Changes + +- eef62546ce: Require @backstage/plugin-lighthouse-common package where API implementation moved to. + + **BREAKING**: the following types have been moved to @backstage/plugin-lighthouse-common: + + - `Audit` + - `AuditBase` + - `AuditCompleted` + - `AuditFailed` + - `AuditRunning` + - `FetchError` + - `LASListRequest` + - `LASListResponse` + - `LighthouseApi` + - `LighthouseCategoryAbbr` + - `LighthouseCategoryId` + - `LighthouseConfigSettings` + - `LighthouseRestApi` + - `TriggerAuditPayload` + - `Website` + - `WebsiteListResponse` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-lighthouse-common@0.1.0-next.0 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.3.15-next.1 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index bee2b66a54..c52858b666 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.15-next.1", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic-dashboard/CHANGELOG.md b/plugins/newrelic-dashboard/CHANGELOG.md index 3f9352d0d2..78aadfc390 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-newrelic-dashboard +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index 09d4afcd93..5fe39fd8a3 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.8-next.1", + "version": "0.2.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index 10a7d6131b..8858555c7c 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-newrelic +## 0.3.33-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.3.33-next.0 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 60f6019ccf..e02c690eff 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.33-next.0", + "version": "0.3.33-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org-react/CHANGELOG.md b/plugins/org-react/CHANGELOG.md index 6400654730..6af5e01b9b 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-org-react +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index bf3fbe4050..6e939b1954 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org-react", - "version": "0.1.4-next.1", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index c4cd46928b..31c7843fa4 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-org +## 0.6.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.6.5-next.1 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index ef9106808b..240e473b88 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.6.5-next.1", + "version": "0.6.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index c10c36ee38..f9424baaea 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-pagerduty +## 0.5.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.5.8-next.1 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index a26ac1137f..df20b498ed 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.8-next.1", + "version": "0.5.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/periskop-backend/CHANGELOG.md b/plugins/periskop-backend/CHANGELOG.md index afeec402d4..1e6ff6f307 100644 --- a/plugins/periskop-backend/CHANGELOG.md +++ b/plugins/periskop-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-periskop-backend +## 0.1.13-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + ## 0.1.13-next.1 ### Patch Changes diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index dc29122b8e..419d430fac 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.13-next.1", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/periskop/CHANGELOG.md b/plugins/periskop/CHANGELOG.md index 5d093e566f..eeabe21052 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-periskop +## 0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.1.13-next.1 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index a35c7332b2..08d875e51f 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.13-next.1", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index 475ec1fa67..f8cb24795b 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-permission-backend +## 0.5.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + ## 0.5.17-next.1 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index ef319d2e4b..b0b54f6b6e 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.17-next.1", + "version": "0.5.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index 2c56e28584..51c27671db 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-permission-node +## 0.7.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + ## 0.7.5-next.1 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index e2de41927f..c43904fd00 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.7.5-next.1", + "version": "0.7.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist-backend/CHANGELOG.md b/plugins/playlist-backend/CHANGELOG.md index ee9c9940b1..c634e3c2e0 100644 --- a/plugins/playlist-backend/CHANGELOG.md +++ b/plugins/playlist-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-playlist-backend +## 0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-playlist-common@0.1.4 + ## 0.2.5-next.1 ### Patch Changes diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index 211ef7f3c9..5cbce033b4 100644 --- a/plugins/playlist-backend/package.json +++ b/plugins/playlist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist-backend", - "version": "0.2.5-next.1", + "version": "0.2.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist/CHANGELOG.md b/plugins/playlist/CHANGELOG.md index 8651137680..ea27ee40f3 100644 --- a/plugins/playlist/CHANGELOG.md +++ b/plugins/playlist/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-playlist +## 0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-playlist-common@0.1.4 + ## 0.1.6-next.1 ### Patch Changes diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index 9954d9b45c..624fdbcd75 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist", - "version": "0.1.6-next.1", + "version": "0.1.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index 1ccb8ba717..ad235f36e8 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-proxy-backend +## 0.2.36-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + ## 0.2.36-next.1 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 1d93d0eb4f..76440ce0a9 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.36-next.1", + "version": "0.2.36-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index 0995c42725..9e6955c033 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-rollbar-backend +## 0.1.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + ## 0.1.39-next.1 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 8aadcde236..876c797a78 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.39-next.1", + "version": "0.1.39-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 8fab9cd0c6..1fe3b3d6ba 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-rollbar +## 0.4.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.4.15-next.1 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index e33ed45d20..2d65565015 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.15-next.1", + "version": "0.4.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index 2ca4243b25..65121ebda8 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.2.17-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 6f2868d2f6..669f498c1e 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.17-next.1", + "version": "0.2.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index 8fc899ef79..51a6a9b796 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.4.10-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 21e9c1f31c..1e4d881ef0 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.10-next.1", + "version": "0.4.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md index 7ad3b35da6..9a7df7e14b 100644 --- a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-scaffolder-backend-module-sentry +## 0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.2-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index 2136a9055e..903ad54dc1 100644 --- a/plugins/scaffolder-backend-module-sentry/package.json +++ b/plugins/scaffolder-backend-module-sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-sentry", - "version": "0.1.2-next.1", + "version": "0.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index d736daf17e..5c4acbd85c 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.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.2.15-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index eb8598ac8f..7ae88b60e6 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.15-next.1", + "version": "0.2.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index b43edb7c73..d6db10f4ae 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-scaffolder-backend +## 1.11.0-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + ## 1.11.0-next.1 ### Minor Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index e50ebba1b8..ccc586f55b 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.11.0-next.1", + "version": "1.11.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-common/CHANGELOG.md b/plugins/scaffolder-common/CHANGELOG.md index 4b7444994a..e1936292f9 100644 --- a/plugins/scaffolder-common/CHANGELOG.md +++ b/plugins/scaffolder-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-scaffolder-common +## 1.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/types@1.0.2 + ## 1.2.5-next.0 ### Patch Changes diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index bf8c32d5d1..3ec3528427 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.5-next.0", + "version": "1.2.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-node/CHANGELOG.md b/plugins/scaffolder-node/CHANGELOG.md index 19e00ac8b4..cd2ef0259e 100644 --- a/plugins/scaffolder-node/CHANGELOG.md +++ b/plugins/scaffolder-node/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-node +## 0.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + ## 0.1.0-next.1 ### Patch Changes diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index dc93306107..ce82f57f5f 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-node", "description": "The plugin-scaffolder-node module for @backstage/plugin-scaffolder-backend", - "version": "0.1.0-next.1", + "version": "0.1.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-react/CHANGELOG.md b/plugins/scaffolder-react/CHANGELOG.md index 384680c672..51fa1abc63 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-scaffolder-react +## 1.1.0-next.2 + +### Minor Changes + +- 5555e17313: refactor `createAsyncValidators` to be recursive to ensure validators are called in nested schemas. + +### Patch Changes + +- b46f385eff: scaffolder/next: Implementing a simple `OngoingTask` page +- ccbf91051b: bump `@rjsf` `v5` dependencies to 5.1.0 +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + ## 1.1.0-next.1 ### Patch Changes diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 844dc97e95..e26bd973d5 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-react", "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", - "version": "1.1.0-next.1", + "version": "1.1.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 9fc78b0416..37da3b63e1 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-scaffolder +## 1.11.0-next.2 + +### Patch Changes + +- b46f385eff: scaffolder/next: Implementing a simple `OngoingTask` page +- ccbf91051b: bump `@rjsf` `v5` dependencies to 5.1.0 +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + ## 1.11.0-next.1 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index d52e8e332a..86f9100deb 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.11.0-next.1", + "version": "1.11.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index dddb776afc..71dccfef4f 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + ## 1.1.3-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 05395fbdb2..2eb85f5f2c 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.1.3-next.1", + "version": "1.1.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index 907235f958..1d17c6707c 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-search-backend-module-pg +## 0.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + ## 0.5.3-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 299c66a0bd..7883475f34 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.5.3-next.1", + "version": "0.5.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index 9a5b76131d..bf9306cb1d 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-search-backend-node +## 1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.1.3-next.1 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 9c4f3842ed..1bf73971d1 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.1.3-next.1", + "version": "1.1.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index 33fa09cb39..c31930c867 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-search-backend +## 1.2.3-next.2 + +### Patch Changes + +- 1b30c9a0f7: Change the router's response to include the error message instead of its object type in case it fails during a search query because the messages have more info. +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + ## 1.2.3-next.1 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index cc903a5b8d..31594bc8af 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.2.3-next.1", + "version": "1.2.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-react/CHANGELOG.md b/plugins/search-react/CHANGELOG.md index f5074bee18..fa58979796 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-search-react +## 1.5.0-next.1 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.5.0-next.0 ### Minor Changes diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 4e9dd292ba..d353189add 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-react", - "version": "1.5.0-next.0", + "version": "1.5.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 4e4d5de406..7853a44abb 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-search +## 1.1.0-next.2 + +### Patch Changes + +- 66e2aab4c4: Updated colors for each tab used on search modal, to improve color contrast. Aria label added to tabs wrapper component. `disableRipple` property on the `Tab` component removed to improve keyboard navigation indicator. +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + ## 1.1.0-next.1 ### Minor Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index 6acb85af9b..c2f635f762 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.1.0-next.1", + "version": "1.1.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index b19a4b29d9..922b06c8d8 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-sentry +## 0.5.0-next.2 + +### Minor Changes + +- 6a8d6b9a0c: Add option to filter issues based on the time it was triggered + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.4.8-next.1 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index f9b5dad4b8..e757ff25a4 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.8-next.1", + "version": "0.5.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index 224ad0a78d..94baec18aa 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-shortcuts +## 0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + ## 0.3.7-next.0 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 3a955b95e0..61b48b1c55 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.7-next.0", + "version": "0.3.7-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-backend/CHANGELOG.md b/plugins/sonarqube-backend/CHANGELOG.md index 4f568d7442..6fb7414acb 100644 --- a/plugins/sonarqube-backend/CHANGELOG.md +++ b/plugins/sonarqube-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-sonarqube-backend +## 0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/sonarqube-backend/package.json b/plugins/sonarqube-backend/package.json index 785911f6c0..99c0a8b486 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.7-next.1", + "version": "0.1.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-react/CHANGELOG.md b/plugins/sonarqube-react/CHANGELOG.md index 41b5d5b371..b938ce8b37 100644 --- a/plugins/sonarqube-react/CHANGELOG.md +++ b/plugins/sonarqube-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-sonarqube-react +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-plugin-api@1.3.0 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index ebf75572ec..53837a47cf 100644 --- a/plugins/sonarqube-react/package.json +++ b/plugins/sonarqube-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-react", - "version": "0.1.2-next.0", + "version": "0.1.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index a419f321e3..e51e0a65ac 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-sonarqube +## 0.6.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-sonarqube-react@0.1.2-next.1 + ## 0.6.3-next.1 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 8c5d706db2..80dd578523 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.6.3-next.1", + "version": "0.6.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index 401f927bd9..c5de65a3d3 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.4.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.4.4-next.1 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 0700dacf92..097cc1c6fd 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.4.4-next.1", + "version": "0.4.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow-backend/CHANGELOG.md b/plugins/stack-overflow-backend/CHANGELOG.md index 5a8f26be5f..aac07808c9 100644 --- a/plugins/stack-overflow-backend/CHANGELOG.md +++ b/plugins/stack-overflow-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-stack-overflow-backend +## 0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-search-common@1.2.1 + ## 0.1.11-next.1 ### Patch Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index ca8e4a2a55..e40e3e846a 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.11-next.1", + "version": "0.1.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow/CHANGELOG.md b/plugins/stack-overflow/CHANGELOG.md index 00ed8a363c..f80e350a03 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-stack-overflow +## 0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-home@0.4.31-next.2 + - @backstage/plugin-search-common@1.2.1 + ## 0.1.11-next.1 ### Patch Changes diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index d073d519c1..c9fbe7e7a3 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.11-next.1", + "version": "0.1.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index 64ceb662d2..28a8ae4e05 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.26-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/plugin-tech-insights-node@0.4.0-next.2 + ## 0.1.26-next.1 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index f7c1b6563b..d3a3260f87 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.26-next.1", + "version": "0.1.26-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index 42e4c273a0..bef4e4c472 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-tech-insights-backend +## 0.5.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/plugin-tech-insights-node@0.4.0-next.2 + ## 0.5.8-next.1 ### Patch Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index c04ce8f483..2b32f72763 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.8-next.1", + "version": "0.5.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index 867a242826..aa058fdc3b 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-tech-insights-node +## 0.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + ## 0.4.0-next.1 ### Minor Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index 79f8846f51..7f49679030 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.4.0-next.1", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index 907fc50495..37e46a4b5a 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-tech-insights +## 0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + ## 0.3.7-next.1 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index f4515d94b0..e874d2ba30 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.7-next.1", + "version": "0.3.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index f6983f4875..37aa1e8336 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-tech-radar +## 0.6.1-next.1 + +### Patch Changes + +- acf6c8c10b: Deprecate `RadarEntry.url` - use `RadarEntry.links` instead + + ```diff + - url: 'https://www.javascript.com/', + key: 'javascript', + id: 'javascript', + title: 'JavaScript', + quadrant: 'languages', + links: [ + + { + + url: 'https://www.javascript.com/', + + title: 'Learn more', + + }, + ], + ``` + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.6.1-next.0 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 78b0afd963..2aad00f224 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.6.1-next.0", + "version": "0.6.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index bba46a23c2..9afcf3aace 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.5.0-next.2 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + ## 1.0.10-next.1 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 82d5913a2e..1ad762a09d 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.10-next.1", + "version": "1.0.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 04c7a54f20..dbad0b17b1 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-techdocs-backend +## 1.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-node@1.4.6-next.2 + ## 1.5.3-next.1 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index dd16050e5d..9c8ce22bef 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.5.3-next.1", + "version": "1.5.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index aab943c78f..22630158f1 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.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + ## 1.0.10-next.1 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 1b92e15c16..154832f3fd 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.10-next.1", + "version": "1.0.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index 6547d5db59..a6d32d8d9f 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-techdocs-node +## 1.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-aws-node@0.1.1 + - @backstage/plugin-search-common@1.2.1 + ## 1.4.6-next.1 ### Patch Changes diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index d9b7b72d91..0a6ffd721b 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.6-next.1", + "version": "1.4.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index 0403406407..34617eb3f5 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-techdocs-react +## 1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/version-bridge@1.0.3 + ## 1.1.3-next.1 ### Patch Changes diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 01bf2ceec4..29587c3e1e 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.1.3-next.1", + "version": "1.1.3-next.2", "publishConfig": { "access": "public", "alphaTypes": "dist/index.alpha.d.ts", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 01ad074f1c..352114d77d 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-techdocs +## 1.5.0-next.2 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + ## 1.5.0-next.1 ### Minor Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 788b82cfa5..5e113f3e7f 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.5.0-next.1", + "version": "1.5.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index 5009bb66b1..9f44d33d18 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-todo-backend +## 0.1.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.1.39-next.1 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index b7eae2bf52..6120e76a5e 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.39-next.1", + "version": "0.1.39-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index c5ef6bddfa..49a8241e30 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-todo +## 0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.2.17-next.1 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index a6ed7e591e..d337834872 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.17-next.1", + "version": "0.2.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings-backend/CHANGELOG.md b/plugins/user-settings-backend/CHANGELOG.md index 25d3b6b935..20a7f0c6e5 100644 --- a/plugins/user-settings-backend/CHANGELOG.md +++ b/plugins/user-settings-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-user-settings-backend +## 0.1.6-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.1.6-next.1 ### Patch Changes diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index 97570989f6..b77050a5af 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.6-next.1", + "version": "0.1.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index 51de164e53..478b60b6da 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-user-settings +## 0.6.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.6.3-next.1 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index ad046124c4..319ce98fee 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.6.3-next.1", + "version": "0.6.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault-backend/CHANGELOG.md b/plugins/vault-backend/CHANGELOG.md index d81f582d2c..2c7715cd73 100644 --- a/plugins/vault-backend/CHANGELOG.md +++ b/plugins/vault-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-vault-backend +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index 58a16853e6..88545aaeb1 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.8-next.1", + "version": "0.2.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault/CHANGELOG.md b/plugins/vault/CHANGELOG.md index 7e661f0a8a..60fe5c4c8b 100644 --- a/plugins/vault/CHANGELOG.md +++ b/plugins/vault/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-vault +## 0.1.9-next.2 + +### Patch Changes + +- fd7a77b9c4: Surface additional context and details to the Backstage UI when the Vault plugin encounters non-successful HTTP responses from the Vault API. +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + ## 0.1.9-next.1 ### Patch Changes diff --git a/plugins/vault/package.json b/plugins/vault/package.json index 9d59cba50a..15bae8c3ad 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.9-next.1", + "version": "0.1.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index e73dbc7e64..af4665e980 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-xcmetrics +## 0.2.35-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.2.35-next.0 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index fc85d7b050..775e884f4b 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.35-next.0", + "version": "0.2.35-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", From 9f71a2fd20442888ccae9ed5c2da05e7ebfd686d Mon Sep 17 00:00:00 2001 From: Justin De Burgo Date: Tue, 7 Feb 2023 10:22:10 -0600 Subject: [PATCH 284/423] adding changelog Signed-off-by: Justin De Burgo --- .changeset/famous-squids-wonder.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/famous-squids-wonder.md diff --git a/.changeset/famous-squids-wonder.md b/.changeset/famous-squids-wonder.md new file mode 100644 index 0000000000..11ca76ddc1 --- /dev/null +++ b/.changeset/famous-squids-wonder.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Adding dot option to mini match used in catalog rules to allow for catalog imports with hidden folders From bb3e4c3f8d89733097f0d4fbfb44cbbdb165d842 Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Tue, 7 Feb 2023 17:30:34 +0100 Subject: [PATCH 285/423] use msw for tests & fix resolver type Signed-off-by: Katharina Sick --- plugins/auth-backend/api-report.md | 2 +- plugins/auth-backend/package.json | 2 + .../bitbucketServer/provider.test.ts | 174 ++++++++++-------- .../src/providers/bitbucketServer/provider.ts | 3 +- plugins/auth-backend/src/setupTests.ts | 3 +- yarn.lock | 4 +- 6 files changed, 105 insertions(+), 83 deletions(-) diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 8df6079b9f..032344a4f4 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -507,7 +507,7 @@ export const providers: Readonly<{ | undefined, ) => AuthProviderFactory; resolvers: Readonly<{ - emailMatchingUserEntityProfileEmail: () => SignInResolver; + emailMatchingUserEntityProfileEmail: () => SignInResolver; }>; }>; cfAccess: Readonly<{ diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index a95465dbad..91fb5bed5b 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -78,6 +78,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@testing-library/jest-dom": "^5.16.5", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", @@ -89,6 +90,7 @@ "@types/passport-saml": "^1.1.3", "@types/passport-strategy": "^0.2.35", "@types/xml2js": "^0.4.7", + "cross-fetch": "^3.1.5", "msw": "^0.49.0", "supertest": "^6.1.3" }, diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts index 127ca71a17..3934cafd36 100644 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts @@ -18,10 +18,16 @@ import * as helpers from '../../lib/passport/PassportStrategyHelper'; import { makeProfileInfo } from '../../lib/passport/PassportStrategyHelper'; import { AuthResolverContext } from '../types'; import { + bitbucketServer, BitbucketServerAuthProvider, BitbucketServerOAuthResult, } from './provider'; -import { commonByEmailResolver } from '../resolvers'; +import { setupServer } from 'msw/node'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; +import { fetch } from 'cross-fetch'; +import { rest } from 'msw'; + +global.fetch = fetch; jest.mock('../../lib/passport/PassportStrategyHelper', () => { return { @@ -51,60 +57,60 @@ const passportProfile = { photos: [{ value: 'https://bitbucket.org/user/123/avatar' }], }; -const mockFetchUserRequests = ( - failOnWhoAmI: boolean = false, - whoAmIValue: string = passportProfile.username, - failOnGetUser: boolean = false, - getUserOk: boolean = true, - avatarUrl: string = '/user/123/avatar', - setDisplayName: boolean = true, - setUserName: boolean = true, -) => { - const fetchMock = global.fetch as jest.Mock; - if (failOnWhoAmI) { - fetchMock.mockRejectedValueOnce(() => {}); - } else { - fetchMock.mockResolvedValueOnce({ - headers: { get: jest.fn(() => whoAmIValue) }, - }); - } - if (failOnGetUser) { - fetchMock.mockRejectedValueOnce(() => {}); - } else { - fetchMock.mockResolvedValueOnce({ - ok: getUserOk, - json: () => ({ - name: setUserName ? 'john.doe' : undefined, - emailAddress: 'john@doe.com', - id: 123, - displayName: setDisplayName ? 'John Doe' : undefined, - active: true, - slug: 'john.doe', - type: 'NORMAL', - links: { - self: [ - { - href: 'https://bitbucket.org/users/john.doe', - }, - ], - }, - avatarUrl: avatarUrl, - }), - }); - } -}; +const mockHost = 'bitbucket.org'; +const mockBaseUrl = `https://${mockHost}`; + +const whoAmIHandler = (options?: { fail?: boolean; value?: string }) => + rest.get( + `${mockBaseUrl}/plugins/servlet/applinks/whoami`, + (_req, res, ctx) => { + if (options?.fail) { + res.networkError('error'); + } + return res( + ctx.status(200), + ctx.set('X-Ausername', options?.value ?? passportProfile.username), + ); + }, + ); + +const getUserHandler = (options?: { + fail?: boolean; + status?: number; + avatarUrl?: string; + noDisplayName?: boolean; + noUserName?: boolean; +}) => + rest.get( + `${mockBaseUrl}/rest/api/latest/users/${passportProfile.username}`, + (_req, res, ctx) => { + if (options?.fail) { + res.networkError('error'); + } + return res( + ctx.status(options?.status ?? 200), + ctx.json({ + name: options?.noUserName ? undefined : 'john.doe', + emailAddress: 'john@doe.com', + id: 123, + displayName: options?.noDisplayName ? undefined : 'John Doe', + active: true, + slug: 'john.doe', + type: 'NORMAL', + links: { + self: [ + { + href: 'https://bitbucket.org/users/john.doe', + }, + ], + }, + avatarUrl: options?.avatarUrl ?? '/user/123/avatar', + }), + ); + }, + ); describe('BitbucketServerAuthProvider', () => { - const originalFetch = global.fetch; - - beforeEach(() => { - global.fetch = jest.fn(); - }); - - afterEach(() => { - global.fetch = originalFetch; - }); - const provider = new BitbucketServerAuthProvider({ resolverContext: { signInWithCatalogUser: jest.fn(info => { @@ -113,21 +119,26 @@ describe('BitbucketServerAuthProvider', () => { }; }), } as unknown as AuthResolverContext, - signInResolver: commonByEmailResolver, + signInResolver: + bitbucketServer.resolvers.emailMatchingUserEntityProfileEmail(), authHandler: async ({ fullProfile }) => ({ profile: makeProfileInfo(fullProfile), }), callbackUrl: 'mock', clientId: 'mock', clientSecret: 'mock', - host: 'bitbucket.org', + host: mockHost, authorizationUrl: 'mock', tokenUrl: 'mock', }); describe('when transforming to type OAuthResponse', () => { + const server = setupServer(); + setupRequestMockHandlers(server); + it('should map to a valid response', async () => { - mockFetchUserRequests(); + server.use(whoAmIHandler(), getUserHandler()); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; @@ -153,8 +164,10 @@ describe('BitbucketServerAuthProvider', () => { const { response } = await provider.handler({} as any); expect(response).toEqual(expected); }); + it('should throw if whoami fails', async () => { - mockFetchUserRequests(true); + server.use(whoAmIHandler({ fail: true }), getUserHandler()); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; mockFrameHandler.mockResolvedValueOnce({ @@ -166,8 +179,10 @@ describe('BitbucketServerAuthProvider', () => { `Failed to retrieve the username of the logged in user`, ); }); + it('should throw if whoami returns an invalid response', async () => { - mockFetchUserRequests(false, ''); + server.use(whoAmIHandler({ value: '' }), getUserHandler()); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; mockFrameHandler.mockResolvedValueOnce({ @@ -179,8 +194,9 @@ describe('BitbucketServerAuthProvider', () => { `Failed to retrieve the username of the logged in user`, ); }); + it('should throw if get user fails', async () => { - mockFetchUserRequests(false, passportProfile.username, true); + server.use(whoAmIHandler(), getUserHandler({ fail: true })); const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; mockFrameHandler.mockResolvedValueOnce({ @@ -192,8 +208,9 @@ describe('BitbucketServerAuthProvider', () => { `Failed to retrieve the user '${passportProfile.username}'`, ); }); + it('should throw if get user is not ok', async () => { - mockFetchUserRequests(false, passportProfile.username, false, false); + server.use(whoAmIHandler(), getUserHandler({ status: 500 })); const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; mockFrameHandler.mockResolvedValueOnce({ @@ -205,8 +222,9 @@ describe('BitbucketServerAuthProvider', () => { `Failed to retrieve the user '${passportProfile.username}'`, ); }); + it('should not set an avatar url if not given', async () => { - mockFetchUserRequests(false, passportProfile.username, false, true, ''); + server.use(whoAmIHandler(), getUserHandler({ avatarUrl: '' })); const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; @@ -231,15 +249,10 @@ describe('BitbucketServerAuthProvider', () => { const { response } = await provider.handler({} as any); expect(response).toEqual(expected); }); + it('should fallback to the username if no displayName is given', async () => { - mockFetchUserRequests( - false, - passportProfile.username, - false, - true, - '/user/123/avatar', - false, - ); + server.use(whoAmIHandler(), getUserHandler({ noDisplayName: true })); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; @@ -265,16 +278,13 @@ describe('BitbucketServerAuthProvider', () => { const { response } = await provider.handler({} as any); expect(response).toEqual(expected); }); + it('should fallback to the user id if no name is given', async () => { - mockFetchUserRequests( - false, - passportProfile.username, - false, - true, - '/user/123/avatar', - false, - false, + server.use( + whoAmIHandler(), + getUserHandler({ noDisplayName: true, noUserName: true }), ); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; @@ -303,8 +313,12 @@ describe('BitbucketServerAuthProvider', () => { }); describe('when authenticating', () => { + const server = setupServer(); + setupRequestMockHandlers(server); + it('should forward the refresh token', async () => { - mockFetchUserRequests(); + server.use(whoAmIHandler(), getUserHandler()); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; mockFrameHandler.mockResolvedValueOnce({ @@ -334,8 +348,10 @@ describe('BitbucketServerAuthProvider', () => { expect(response).toEqual(expected); }); + it('should forward a new refresh token on refresh', async () => { - mockFetchUserRequests(); + server.use(whoAmIHandler(), getUserHandler()); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; const mockRefreshToken = jest.spyOn( diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts index 305f07c9d5..cd082ee953 100644 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts @@ -298,6 +298,7 @@ export const bitbucketServer = createAuthProviderIntegration({ /** * Looks up the user by matching their email to the entity email. */ - emailMatchingUserEntityProfileEmail: () => commonByEmailResolver, + emailMatchingUserEntityProfileEmail: + (): SignInResolver => commonByEmailResolver, }, }); diff --git a/plugins/auth-backend/src/setupTests.ts b/plugins/auth-backend/src/setupTests.ts index d3232290a7..c1d649f2ad 100644 --- a/plugins/auth-backend/src/setupTests.ts +++ b/plugins/auth-backend/src/setupTests.ts @@ -14,4 +14,5 @@ * limitations under the License. */ -export {}; +import '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/yarn.lock b/yarn.lock index 1621cdc5b1..7bfbb5ea1f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4537,6 +4537,7 @@ __metadata: "@backstage/types": "workspace:^" "@davidzemon/passport-okta-oauth": ^0.0.5 "@google-cloud/firestore": ^6.0.0 + "@testing-library/jest-dom": ^5.16.5 "@types/body-parser": ^1.19.0 "@types/cookie-parser": ^1.4.2 "@types/express": ^4.17.6 @@ -4553,6 +4554,7 @@ __metadata: compression: ^1.7.4 cookie-parser: ^1.4.5 cors: ^2.8.5 + cross-fetch: ^3.1.5 express: ^4.17.1 express-promise-router: ^4.1.0 express-session: ^1.17.1 @@ -13578,7 +13580,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/jest-dom@npm:^5.10.1, @testing-library/jest-dom@npm:^5.16.4": +"@testing-library/jest-dom@npm:^5.10.1, @testing-library/jest-dom@npm:^5.16.4, @testing-library/jest-dom@npm:^5.16.5": version: 5.16.5 resolution: "@testing-library/jest-dom@npm:5.16.5" dependencies: From 30966a2f3e1d6f2f399d8988f4b3bba3329d7798 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 7 Feb 2023 21:28:26 +0100 Subject: [PATCH 286/423] chore: fix the triple-beam workaround Signed-off-by: blam --- packages/backend-common/package.json | 1 - packages/repo-tools/src/commands/type-deps/type-deps.ts | 8 -------- yarn.lock | 8 -------- 3 files changed, 17 deletions(-) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 3152cd0b28..9619ef25f8 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -53,7 +53,6 @@ "@types/dockerode": "^3.3.0", "@types/express": "^4.17.6", "@types/luxon": "^3.0.0", - "@types/triple-beam": "^1.3.2", "@types/webpack-env": "^1.15.2", "archiver": "^5.0.2", "aws-sdk": "^2.840.0", diff --git a/packages/repo-tools/src/commands/type-deps/type-deps.ts b/packages/repo-tools/src/commands/type-deps/type-deps.ts index 852cec34d2..4f8e5e5529 100644 --- a/packages/repo-tools/src/commands/type-deps/type-deps.ts +++ b/packages/repo-tools/src/commands/type-deps/type-deps.ts @@ -196,14 +196,6 @@ function findTypeDepErrors(typeDeps: string[], pkg: Package) { } for (const dep of deps) { - // Remove this once the logform issue has been fixed. - // https://github.com/winstonjs/logform/issues/242 - if ( - pkg.packageJson.name === '@backstage/backend-common' && - dep === '@types/triple-beam' - ) { - continue; - } errors.push( mkErr('WrongDepError', `Should be dev dep ${dep}`, { dep, diff --git a/yarn.lock b/yarn.lock index 1621cdc5b1..7261a68b88 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3457,7 +3457,6 @@ __metadata: "@types/stoppable": ^1.1.0 "@types/supertest": ^2.0.8 "@types/tar": ^6.1.1 - "@types/triple-beam": ^1.3.2 "@types/webpack-env": ^1.15.2 "@types/yauzl": ^2.10.0 archiver: ^5.0.2 @@ -15482,13 +15481,6 @@ __metadata: languageName: node linkType: hard -"@types/triple-beam@npm:^1.3.2": - version: 1.3.2 - resolution: "@types/triple-beam@npm:1.3.2" - checksum: dd7b4a563fb710abc992e5d59eac481bed9e303fada2e276e37b00be31c392e03300ee468e57761e616512872e77935f92472877d0704a19688d15a726cee17b - languageName: node - linkType: hard - "@types/trusted-types@npm:*": version: 2.0.2 resolution: "@types/trusted-types@npm:2.0.2" From 8ab66746c899379c4cc591263e205fb140988539 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Tue, 7 Feb 2023 17:16:31 -0500 Subject: [PATCH 287/423] Add yaml spec. Signed-off-by: Aramis Sennyey --- plugins/catalog-backend/openapi.yaml | 755 +++++++++++++++++++++++++++ 1 file changed, 755 insertions(+) create mode 100644 plugins/catalog-backend/openapi.yaml diff --git a/plugins/catalog-backend/openapi.yaml b/plugins/catalog-backend/openapi.yaml new file mode 100644 index 0000000000..a058831d55 --- /dev/null +++ b/plugins/catalog-backend/openapi.yaml @@ -0,0 +1,755 @@ +components: + examples: {} + headers: {} + parameters: {} + requestBodies: {} + responses: {} + schemas: + RefreshOptions: + properties: + authorizationToken: + type: string + entityRef: + type: string + description: The reference to a single entity that should be refreshed + required: + - entityRef + type: object + description: Options for requesting a refresh of entities in the catalog. + JsonObject: + properties: {} + type: object + description: A type representing all allowed JSON object values. + MapStringString: + properties: {} + type: object + additionalProperties: + type: string + description: Construct a type with a set of properties K of type T + EntityLink: + properties: + type: + type: string + description: An optional value to categorize links into specific groups + icon: + type: string + description: An optional semantic key that represents a visual icon. + title: + type: string + description: An optional descriptive title for the link. + url: + type: string + description: The url to the external site, document, etc. + required: + - url + type: object + description: A link to external information that is related to the entity. + EntityMeta: + allOf: + - $ref: '#/components/schemas/JsonObject' + - properties: + links: + items: + $ref: '#/components/schemas/EntityLink' + type: array + description: A list of external hyperlinks related to the entity. + tags: + items: + type: string + type: array + description: |- + A list of single-valued strings, to for example classify catalog entities in + various ways. + annotations: + $ref: '#/components/schemas/MapStringString' + labels: + $ref: '#/components/schemas/MapStringString' + description: + type: string + description: |- + A short (typically relatively few words, on one line) description of the + entity. + title: + type: string + description: |- + A display name of the entity, to be presented in user interfaces instead + of the `name` property above, when available. + This field is sometimes useful when the `name` is cumbersome or ends up + being perceived as overly technical. The title generally does not have + as stringent format requirements on it, so it may contain special + characters and be more explanatory. Do keep it very short though, and + avoid situations where a title can be confused with the name of another + entity, or where two entities share a title. + Note that this is only for display purposes, and may be ignored by some + parts of the code. Entity references still always make use of the `name` + property, not the title. + namespace: + type: string + description: The namespace that the entity belongs to. + name: + type: string + description: |- + The name of the entity. + Must be unique within the catalog at any given point in time, for any + given namespace + kind pair. This value is part of the technical + identifier of the entity, and as such it will appear in URLs, database + tables, entity references, and similar. It is subject to restrictions + regarding what characters are allowed. + If you want to use a different, more human readable string with fewer + restrictions on it in user interfaces, see the `title` field below. + etag: + type: string + description: |- + An opaque string that changes for each update operation to any part of + the entity, including metadata. + This field can not be set by the user at creation time, and the server + will reject an attempt to do so. The field will be populated in read + operations. The field can (optionally) be specified when performing + update or delete operations, and the server will then reject the + operation if it does not match the current stored value. + uid: + type: string + description: |- + A globally unique ID for the entity. + This field can not be set by the user at creation time, and the server + will reject an attempt to do so. The field will be populated in read + operations. The field can (optionally) be specified when performing + update or delete operations, but the server is free to reject requests + that do so in such a way that it breaks semantics. + required: + - name + type: object + description: Metadata fields common to all versions/kinds of entity. + EntityRelation: + properties: + targetRef: + type: string + description: The entity ref of the target of this relation. + type: + type: string + description: The type of the relation. + required: + - targetRef + - type + type: object + description: A relation of a specific type to another entity in the catalog. + Entity: + properties: + relations: + items: + $ref: '#/components/schemas/EntityRelation' + type: array + description: The relations that this entity has with other entities. + spec: + $ref: '#/components/schemas/JsonObject' + metadata: + $ref: '#/components/schemas/EntityMeta' + kind: + type: string + description: The high level entity type being described. + apiVersion: + type: string + description: |- + The version of specification format for this particular entity that + this is written against. + required: + - metadata + - kind + - apiVersion + type: object + description: The parts of the format that's common to all versions/kinds of entity. + EntityAncestryResponse: + properties: + items: + items: + properties: + parentEntityRefs: + items: + type: string + type: array + entity: + $ref: '#/components/schemas/Entity' + required: + - parentEntityRefs + - entity + type: object + type: array + rootEntityRef: + type: string + required: + - items + - rootEntityRef + type: object + EntitiesBatchResponse: + properties: + items: + items: + allOf: + - $ref: '#/components/schemas/Entity' + nullable: true + type: array + description: |- + The list of entities, in the same order as the refs in the request. Entries + that are null signify that no entity existed with that ref. + required: + - items + type: object + EntityFacets: + type: object + properties: + value: + type: string + count: + type: number + description: Construct a type with a set of properties K of type T + EntityFacetsResponse: + properties: {} + type: object + additionalProperties: + $ref: '#/components/schemas/EntityFacets' + required: + - facets + Location: + properties: + target: + type: string + type: + type: string + id: + type: string + required: + - target + - type + - id + type: object + description: Entity location for a specific entity. + LocationSpec: + properties: + presence: + type: string + enum: + - optional + - required + target: + type: string + type: + type: string + required: + - target + - type + type: object + description: Holds the entity location information. + AnalyzeLocationExistingEntity: + properties: + entity: + $ref: '#/components/schemas/Entity' + isRegistered: + type: boolean + location: + $ref: '#/components/schemas/LocationSpec' + required: + - entity + - isRegistered + - location + type: object + description: |- + If the folder pointed to already contained catalog info yaml files, they are + read and emitted like this so that the frontend can inform the user that it + located them and can make sure to register them as well if they weren't + already + RecursivePartial_Entity_: + properties: + apiVersion: + type: string + description: |- + The version of specification format for this particular entity that + this is written against. + kind: + type: string + description: The high level entity type being described. + metadata: + $ref: '#/components/schemas/EntityMeta' + spec: + $ref: '#/components/schemas/JsonObject' + relations: + items: + $ref: '#/components/schemas/EntityRelation' + type: array + description: The relations that this entity has with other entities. + type: object + description: Makes all keys of an entire hierarchy optional. + AnalyzeLocationEntityField: + properties: + description: + type: string + description: |- + A text to show to the user to inform about the choices made. Like, it could say + "Found a CODEOWNERS file that covers this target, so we suggest leaving this + field empty; which would currently make it owned by X" where X is taken from the + codeowners file. + value: + type: string + nullable: true + state: + type: string + enum: + - analysisSuggestedValue + - analysisSuggestedNoValue + - needsUserInput + description: The outcome of the analysis for this particular field + field: + type: string + description: |- + e.g. "spec.owner"? The frontend needs to know how to "inject" the field into the + entity again if the user wants to change it + required: + - description + - value + - state + - field + type: object + AnalyzeLocationGenerateEntity: + properties: + fields: + items: + $ref: '#/components/schemas/AnalyzeLocationEntityField' + type: array + entity: + $ref: '#/components/schemas/RecursivePartial_Entity_' + required: + - fields + - entity + type: object + description: |- + This is some form of representation of what the analyzer could deduce. + We should probably have a chat about how this can best be conveyed to + the frontend. It'll probably contain a (possibly incomplete) entity, plus + enough info for the frontend to know what form data to show to the user + for overriding/completing the info. + AnalyzeLocationResponse: + properties: + generateEntities: + items: + $ref: '#/components/schemas/AnalyzeLocationGenerateEntity' + type: array + existingEntityFiles: + items: + $ref: '#/components/schemas/AnalyzeLocationExistingEntity' + type: array + required: + - generateEntities + - existingEntityFiles + type: object + LocationInput: + properties: + type: + type: string + target: + type: string + presence: + type: string + enum: + - optional + - required + required: + - type + - target + - presence + type: object + SerializedError: + allOf: + - $ref: '#/components/schemas/JsonObject' + - properties: + code: + type: string + description: A custom code (not necessarily the same as an HTTP response code); may not be present + stack: + type: string + description: A stringified stack trace; may not be present + message: + type: string + description: The message of the exception that was thrown + name: + type: string + description: The name of the exception that was thrown + required: + - message + - name + type: object + description: The serialized form of an Error. + securitySchemes: + JWT: + type: http + scheme: bearer + bearerFormat: JWT +info: + title: '@backstage/plugin-catalog-backend' + version: 1.6.0-next.1 + description: The Backstage backend plugin that provides the Backstage catalog + license: + name: Apache-2.0 + contact: {} +openapi: 3.0.3 +paths: + /refresh: + post: + operationId: RefreshEntity + responses: + '200': + description: Refreshed + security: + - JWT: [] + parameters: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RefreshOptions' + /entities: + get: + operationId: GetEntities + responses: + '200': + description: '' + content: + application/json: + schema: + items: + $ref: '#/components/schemas/Entity' + type: array + security: + - JWT: [] + parameters: + - in: query + name: filter + required: false + schema: + type: string + - in: query + name: fields + required: false + schema: + type: string + - in: query + name: offset + required: false + schema: + type: string + - in: query + name: limit + required: false + schema: + type: string + - in: query + name: after + required: false + schema: + type: string + /entities/by-uid/{uid}: + get: + operationId: GetEntityByUid + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/Entity' + security: + - JWT: [] + parameters: + - in: path + name: uid + required: true + schema: + type: string + delete: + operationId: DeleteEntityByUid + responses: + '204': + description: Deleted successfully. + security: + - JWT: [] + parameters: + - in: path + name: uid + required: true + schema: + type: string + + /entities/by-name/{kind}/{namespace}/{name}: + get: + operationId: GetEntityByName + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/Entity' + security: + - JWT: [] + parameters: + - in: path + name: kind + required: true + schema: + type: string + - in: path + name: namespace + required: true + schema: + type: string + - in: path + name: name + required: true + schema: + type: string + /entities/by-name/{kind}/{namespace}/{name}/ancestry: + get: + operationId: GetEntityAncestryByName + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/EntityAncestryResponse' + security: + - JWT: [] + parameters: + - in: path + name: kind + required: true + schema: + type: string + - in: path + name: namespace + required: true + schema: + type: string + - in: path + name: name + required: true + schema: + type: string + /entities/by-refs: + post: + operationId: GetEntitiesByRefs + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/EntitiesBatchResponse' + security: + - JWT: [] + parameters: + - in: query + name: fields + required: false + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + items: + type: string + type: array + /entity-facets: + get: + operationId: GetEntityFacets + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/EntityFacetsResponse' + security: + - JWT: [] + parameters: + - in: query + name: facet + required: true + schema: + type: string + - in: query + name: filter + required: false + schema: + type: string + /locations: + post: + operationId: CreateLocation + responses: + '200': + description: Ok + content: + application/json: + schema: + properties: + exists: + type: boolean + entities: + items: + $ref: '#/components/schemas/Entity' + type: array + location: + $ref: '#/components/schemas/Location' + required: + - entities + - location + type: object + security: + - JWT: [] + parameters: + - in: query + name: dryRun + required: false + schema: + type: boolean + requestBody: + required: true + content: + application/json: + schema: + properties: + presence: + type: string + enum: + - required + - optional + target: + type: string + type: + type: string + required: + - presence + - target + - type + type: object + get: + operationId: GetLocations + responses: + '200': + description: Ok + content: + application/json: + schema: + items: + properties: + data: + $ref: '#/components/schemas/Location' + required: + - data + type: object + type: array + security: + - JWT: [] + parameters: [] + /locations/{id}: + get: + operationId: GetLocation + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/Location' + security: + - JWT: [] + parameters: + - in: path + name: id + required: true + schema: + type: string + delete: + operationId: DeleteLocation + responses: + '204': + description: No content + security: + - JWT: [] + parameters: + - in: path + name: id + required: true + schema: + type: string + /analyze-location: + post: + operationId: AnalyzeLocation + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/AnalyzeLocationResponse' + security: + - JWT: [] + parameters: [] + requestBody: + required: true + content: + application/json: + schema: + properties: + catalogFileName: + type: string + location: + $ref: '#/components/schemas/LocationInput' + required: + - catalogFileName + - location + type: object + /validate-entity: + post: + operationId: ValidateEntity + responses: + '200': + description: Ok + content: + application/json: + schema: + anyOf: + - properties: + errors: + $ref: '#/components/schemas/SerializedError' + required: + - errors + type: object + - properties: + errors: + items: + $ref: '#/components/schemas/SerializedError' + type: array + required: + - errors + type: object + security: + - JWT: [] + parameters: [] + requestBody: + required: true + content: + application/json: + schema: + properties: + location: + type: string + entity: + $ref: '#/components/schemas/Entity' + required: + - location + - entity + type: object +servers: + - url: / From a3c86a7ed2510df014dcab21f2bb36236370f0ca Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Thu, 19 Jan 2023 15:00:48 -0500 Subject: [PATCH 288/423] feat(entity-feedback): implement plugin Signed-off-by: Phil Kuang --- .changeset/gorgeous-llamas-mate.md | 7 + microsite/data/plugins/entity-feedback.yaml | 10 + microsite/static/img/entity-feedback-logo.png | Bin 0 -> 894 bytes packages/app/package.json | 1 + .../app/src/components/catalog/EntityPage.tsx | 56 +++- packages/backend/package.json | 1 + packages/backend/src/index.ts | 5 + .../backend/src/plugins/entityFeedback.ts | 28 ++ plugins/entity-feedback-backend/.eslintrc.js | 1 + plugins/entity-feedback-backend/README.md | 50 +++ plugins/entity-feedback-backend/api-report.md | 26 ++ .../migrations/20230109124329_init.js | 69 ++++ plugins/entity-feedback-backend/package.json | 50 +++ plugins/entity-feedback-backend/src/index.ts | 22 ++ plugins/entity-feedback-backend/src/run.ts | 33 ++ .../src/service/DatabaseHandler.test.ts | 310 ++++++++++++++++++ .../src/service/DatabaseHandler.ts | 161 +++++++++ .../src/service/router.test.ts | 290 ++++++++++++++++ .../src/service/router.ts | 215 ++++++++++++ .../src/service/standaloneServer.ts | 80 +++++ .../entity-feedback-backend/src/setupTests.ts | 17 + plugins/entity-feedback-common/.eslintrc.js | 1 + plugins/entity-feedback-common/README.md | 3 + plugins/entity-feedback-common/api-report.md | 42 +++ plugins/entity-feedback-common/package.json | 31 ++ plugins/entity-feedback-common/src/index.ts | 52 +++ .../entity-feedback-common/src/setupTests.ts | 16 + plugins/entity-feedback/.eslintrc.js | 1 + plugins/entity-feedback/README.md | 136 ++++++++ plugins/entity-feedback/api-report.md | 180 ++++++++++ .../docs/feedback-response-dialog.png | Bin 0 -> 46890 bytes .../docs/feedback-response-table.png | Bin 0 -> 32787 bytes .../docs/like-dislike-rating.png | Bin 0 -> 8754 bytes .../docs/like-dislike-table.png | Bin 0 -> 39177 bytes .../docs/starred-rating-table.png | Bin 0 -> 32379 bytes .../entity-feedback/docs/starred-rating.png | Bin 0 -> 9677 bytes plugins/entity-feedback/package.json | 63 ++++ .../src/api/EntityFeedbackApi.ts | 49 +++ .../src/api/EntityFeedbackClient.test.ts | 175 ++++++++++ .../src/api/EntityFeedbackClient.ts | 136 ++++++++ plugins/entity-feedback/src/api/index.ts | 18 + .../FeedbackRatingsTable.test.tsx | 117 +++++++ .../FeedbackRatingsTable.tsx | 123 +++++++ .../components/FeedbackRatingsTable/index.ts | 17 + .../FeedbackResponseDialog.test.tsx | 118 +++++++ .../FeedbackResponseDialog.tsx | 176 ++++++++++ .../FeedbackResponseDialog/index.ts | 17 + .../FeedbackResponseTable.test.tsx | 76 +++++ .../FeedbackResponseTable.tsx | 121 +++++++ .../components/FeedbackResponseTable/index.ts | 17 + .../LikeDislikeButtons.test.tsx | 147 +++++++++ .../LikeDislikeButtons/LikeDislikeButtons.tsx | 154 +++++++++ .../components/LikeDislikeButtons/index.ts | 17 + .../LikeDislikeRatingsTable.test.tsx | 42 +++ .../LikeDislikeRatingsTable.tsx | 46 +++ .../LikeDislikeRatingsTable/index.ts | 17 + .../StarredRatingButtons.test.tsx | 159 +++++++++ .../StarredRatingButtons.tsx | 160 +++++++++ .../components/StarredRatingButtons/index.ts | 17 + .../StarredRatingsTable.test.tsx | 44 +++ .../StarredRatingsTable.tsx | 44 +++ .../components/StarredRatingsTable/index.ts | 17 + .../entity-feedback/src/components/index.ts | 25 ++ plugins/entity-feedback/src/index.ts | 32 ++ plugins/entity-feedback/src/plugin.test.ts | 23 ++ plugins/entity-feedback/src/plugin.tsx | 212 ++++++++++++ plugins/entity-feedback/src/routes.ts | 21 ++ plugins/entity-feedback/src/setupTests.ts | 18 + yarn.lock | 72 +++- 69 files changed, 4381 insertions(+), 3 deletions(-) create mode 100644 .changeset/gorgeous-llamas-mate.md create mode 100644 microsite/data/plugins/entity-feedback.yaml create mode 100644 microsite/static/img/entity-feedback-logo.png create mode 100644 packages/backend/src/plugins/entityFeedback.ts create mode 100644 plugins/entity-feedback-backend/.eslintrc.js create mode 100644 plugins/entity-feedback-backend/README.md create mode 100644 plugins/entity-feedback-backend/api-report.md create mode 100644 plugins/entity-feedback-backend/migrations/20230109124329_init.js create mode 100644 plugins/entity-feedback-backend/package.json create mode 100644 plugins/entity-feedback-backend/src/index.ts create mode 100644 plugins/entity-feedback-backend/src/run.ts create mode 100644 plugins/entity-feedback-backend/src/service/DatabaseHandler.test.ts create mode 100644 plugins/entity-feedback-backend/src/service/DatabaseHandler.ts create mode 100644 plugins/entity-feedback-backend/src/service/router.test.ts create mode 100644 plugins/entity-feedback-backend/src/service/router.ts create mode 100644 plugins/entity-feedback-backend/src/service/standaloneServer.ts create mode 100644 plugins/entity-feedback-backend/src/setupTests.ts create mode 100644 plugins/entity-feedback-common/.eslintrc.js create mode 100644 plugins/entity-feedback-common/README.md create mode 100644 plugins/entity-feedback-common/api-report.md create mode 100644 plugins/entity-feedback-common/package.json create mode 100644 plugins/entity-feedback-common/src/index.ts create mode 100644 plugins/entity-feedback-common/src/setupTests.ts create mode 100644 plugins/entity-feedback/.eslintrc.js create mode 100644 plugins/entity-feedback/README.md create mode 100644 plugins/entity-feedback/api-report.md create mode 100644 plugins/entity-feedback/docs/feedback-response-dialog.png create mode 100644 plugins/entity-feedback/docs/feedback-response-table.png create mode 100644 plugins/entity-feedback/docs/like-dislike-rating.png create mode 100644 plugins/entity-feedback/docs/like-dislike-table.png create mode 100644 plugins/entity-feedback/docs/starred-rating-table.png create mode 100644 plugins/entity-feedback/docs/starred-rating.png create mode 100644 plugins/entity-feedback/package.json create mode 100644 plugins/entity-feedback/src/api/EntityFeedbackApi.ts create mode 100644 plugins/entity-feedback/src/api/EntityFeedbackClient.test.ts create mode 100644 plugins/entity-feedback/src/api/EntityFeedbackClient.ts create mode 100644 plugins/entity-feedback/src/api/index.ts create mode 100644 plugins/entity-feedback/src/components/FeedbackRatingsTable/FeedbackRatingsTable.test.tsx create mode 100644 plugins/entity-feedback/src/components/FeedbackRatingsTable/FeedbackRatingsTable.tsx create mode 100644 plugins/entity-feedback/src/components/FeedbackRatingsTable/index.ts create mode 100644 plugins/entity-feedback/src/components/FeedbackResponseDialog/FeedbackResponseDialog.test.tsx create mode 100644 plugins/entity-feedback/src/components/FeedbackResponseDialog/FeedbackResponseDialog.tsx create mode 100644 plugins/entity-feedback/src/components/FeedbackResponseDialog/index.ts create mode 100644 plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.test.tsx create mode 100644 plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.tsx create mode 100644 plugins/entity-feedback/src/components/FeedbackResponseTable/index.ts create mode 100644 plugins/entity-feedback/src/components/LikeDislikeButtons/LikeDislikeButtons.test.tsx create mode 100644 plugins/entity-feedback/src/components/LikeDislikeButtons/LikeDislikeButtons.tsx create mode 100644 plugins/entity-feedback/src/components/LikeDislikeButtons/index.ts create mode 100644 plugins/entity-feedback/src/components/LikeDislikeRatingsTable/LikeDislikeRatingsTable.test.tsx create mode 100644 plugins/entity-feedback/src/components/LikeDislikeRatingsTable/LikeDislikeRatingsTable.tsx create mode 100644 plugins/entity-feedback/src/components/LikeDislikeRatingsTable/index.ts create mode 100644 plugins/entity-feedback/src/components/StarredRatingButtons/StarredRatingButtons.test.tsx create mode 100644 plugins/entity-feedback/src/components/StarredRatingButtons/StarredRatingButtons.tsx create mode 100644 plugins/entity-feedback/src/components/StarredRatingButtons/index.ts create mode 100644 plugins/entity-feedback/src/components/StarredRatingsTable/StarredRatingsTable.test.tsx create mode 100644 plugins/entity-feedback/src/components/StarredRatingsTable/StarredRatingsTable.tsx create mode 100644 plugins/entity-feedback/src/components/StarredRatingsTable/index.ts create mode 100644 plugins/entity-feedback/src/components/index.ts create mode 100644 plugins/entity-feedback/src/index.ts create mode 100644 plugins/entity-feedback/src/plugin.test.ts create mode 100644 plugins/entity-feedback/src/plugin.tsx create mode 100644 plugins/entity-feedback/src/routes.ts create mode 100644 plugins/entity-feedback/src/setupTests.ts diff --git a/.changeset/gorgeous-llamas-mate.md b/.changeset/gorgeous-llamas-mate.md new file mode 100644 index 0000000000..a2553875e9 --- /dev/null +++ b/.changeset/gorgeous-llamas-mate.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-entity-feedback-backend': minor +'@backstage/plugin-entity-feedback-common': minor +'@backstage/plugin-entity-feedback': minor +--- + +Implement entity feedback plugin, check out the `README.md` for more details! diff --git a/microsite/data/plugins/entity-feedback.yaml b/microsite/data/plugins/entity-feedback.yaml new file mode 100644 index 0000000000..c40d0450ca --- /dev/null +++ b/microsite/data/plugins/entity-feedback.yaml @@ -0,0 +1,10 @@ +--- +title: Entity Feedback +author: Phil Kuang +authorUrl: https://github.com/kuangp +category: Quality +description: Give and view feedback on entities available in the Backstage catalog. +documentation: https://github.com/backstage/backstage/tree/master/plugins/entity-feedback +iconUrl: img/entity-feedback-logo.png +npmPackageName: '@backstage/plugin-entity-feedback' +addedDate: '2023-01-20' diff --git a/microsite/static/img/entity-feedback-logo.png b/microsite/static/img/entity-feedback-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e172b260a0027bb669bb105d8e1e095061ae3691 GIT binary patch literal 894 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmUKs7M+SzC{oH>NS%G|oWRD45dJguM!v-tY$DUh!@P+6=(yLU`z6LcLCBs@Y8vBJ&@uo z@Q5r1(g|SvA=~LZ0|Qfor;B4q#=WaEyt73dMciKdB^W~l)A?;2c4uuf`B3_RF>mjh zS?Ag15;kVJ$yYR-4lVw5fY~SP?5n1HhShvGVoU!qORSt_uKS10VEwwap=VzkZMeW( zC$eMWBJZ!4#0vKDFw4h$*!H%wow1?Z^)q+FuCf@HsBP=(jgQHE)>2S%m0DrRwe8Kr zCHgg*m)_qozP`h2d%Q{gS$o&%&#qK{Jl(hF9z($m!~8QXDG$25zOq_KO=>Kix+>D5 zCXTJaSnI6(0~ZgrX(6+o+I?K!kbc1N7-x}m22*K1^8twqVVTQ*ANhZVW8KyX?Ty)5 zN7WQKKbjXevETS;^xd(rNVqY^zNC}S1$2Bkh9WnO-Ts5`sYZ4bNZylJ@pwe zm#izd?`=P4#QJ7+yV<*$>%CjwNtAFsn~>(^VixoB)C;G5zfyZDlOMX5CQGv2tG@T& z$>m?vkK?Oyck?iBJ~l(Q|M&dk55AuJaaZUEyYPl(`z}{5dh53~bU~o$`ZjsRTZj6y z%{eNv6T1FYJuwy(%S}*=sK|a0w&BCI1FPje@VCp|lghAu5Z?Bw`EBBZT#)e28;|sL ze$43PKJa(ThyM)j;UAo*Gfv+NOq8l6t`Q|Ei6yC4$wjF^iowXh$XM6FP}k5h#K_1B rh)m724GgRd4E!9{8lz~)%}>cptHiCrURJapsDZ)L)z4*}Q$iB}C{%i? literal 0 HcmV?d00001 diff --git a/packages/app/package.json b/packages/app/package.json index 1b3841ceae..d6a05d58fc 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -30,6 +30,7 @@ "@backstage/plugin-code-coverage": "workspace:^", "@backstage/plugin-cost-insights": "workspace:^", "@backstage/plugin-dynatrace": "workspace:^", + "@backstage/plugin-entity-feedback": "workspace:^", "@backstage/plugin-explore": "workspace:^", "@backstage/plugin-gcalendar": "workspace:^", "@backstage/plugin-gcp-projects": "workspace:^", diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 3566800f0b..4b7722008e 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -25,7 +25,7 @@ import { RELATION_PART_OF, RELATION_PROVIDES_API, } from '@backstage/catalog-model'; -import { EmptyState } from '@backstage/core-components'; +import { EmptyState, InfoCard } from '@backstage/core-components'; import { EntityApiDefinitionCard, EntityConsumedApisCard, @@ -79,6 +79,11 @@ import { DynatraceTab, isDynatraceAvailable, } from '@backstage/plugin-dynatrace'; +import { + EntityFeedbackResponseContent, + EntityLikeDislikeRatingsCard, + LikeDislikeButtons, +} from '@backstage/plugin-entity-feedback'; import { EntityGithubActionsContent, EntityRecentGithubActionsRunsCard, @@ -374,6 +379,12 @@ const overviewContent = ( + + + + + + {cicdCard} @@ -511,6 +522,10 @@ const serviceEntityPage = ( > + + + + ); @@ -590,6 +605,10 @@ const websiteEntityPage = ( + + + + ); @@ -606,6 +625,10 @@ const defaultEntityPage = ( + + + + ); @@ -642,6 +665,11 @@ const apiPage = ( + + + + + @@ -654,6 +682,10 @@ const apiPage = ( + + + + ); @@ -671,6 +703,9 @@ const userPage = ( entityFilterKind={customEntityFilterKind} /> + + + @@ -693,6 +728,9 @@ const groupPage = ( + + + @@ -718,6 +756,11 @@ const systemPage = ( + + + + + @@ -746,6 +789,9 @@ const systemPage = ( unidirectional={false} /> + + + ); @@ -763,8 +809,16 @@ const domainPage = ( + + + + + + + + ); diff --git a/packages/backend/package.json b/packages/backend/package.json index 3678c1f9ae..34a7498927 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -42,6 +42,7 @@ "@backstage/plugin-catalog-backend": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-code-coverage-backend": "workspace:^", + "@backstage/plugin-entity-feedback-backend": "workspace:^", "@backstage/plugin-events-backend": "workspace:^", "@backstage/plugin-events-node": "workspace:^", "@backstage/plugin-explore-backend": "workspace:^", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index b68b162e52..495dc435c1 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -44,6 +44,7 @@ import azureDevOps from './plugins/azure-devops'; import catalog from './plugins/catalog'; import catalogEventBasedProviders from './plugins/catalogEventBasedProviders'; import codeCoverage from './plugins/codecoverage'; +import entityFeedback from './plugins/entityFeedback'; import events from './plugins/events'; import explore from './plugins/explore'; import kubernetes from './plugins/kubernetes'; @@ -147,6 +148,9 @@ async function main() { ); const permissionEnv = useHotMemoize(module, () => createEnv('permission')); const playlistEnv = useHotMemoize(module, () => createEnv('playlist')); + const entityFeedbackEnv = useHotMemoize(module, () => + createEnv('entityFeedback'), + ); const eventsEnv = useHotMemoize(module, () => createEnv('events')); const exploreEnv = useHotMemoize(module, () => createEnv('explore')); const lighthouseEnv = useHotMemoize(module, () => createEnv('lighthouse')); @@ -179,6 +183,7 @@ async function main() { apiRouter.use('/permission', await permission(permissionEnv)); apiRouter.use('/playlist', await playlist(playlistEnv)); apiRouter.use('/explore', await explore(exploreEnv)); + apiRouter.use('/entity-feedback', await entityFeedback(entityFeedbackEnv)); apiRouter.use('/adr', await adr(adrEnv)); apiRouter.use(notFoundHandler()); diff --git a/packages/backend/src/plugins/entityFeedback.ts b/packages/backend/src/plugins/entityFeedback.ts new file mode 100644 index 0000000000..c37c3c9a97 --- /dev/null +++ b/packages/backend/src/plugins/entityFeedback.ts @@ -0,0 +1,28 @@ +/* + * Copyright 2023 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 { createRouter } from '@backstage/plugin-entity-feedback-backend'; +import { Router } from 'express'; +import { PluginEnvironment } from '../types'; + +export default function createPlugin(env: PluginEnvironment): Promise { + return createRouter({ + database: env.database, + discovery: env.discovery, + identity: env.identity, + logger: env.logger, + }); +} diff --git a/plugins/entity-feedback-backend/.eslintrc.js b/plugins/entity-feedback-backend/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/entity-feedback-backend/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/entity-feedback-backend/README.md b/plugins/entity-feedback-backend/README.md new file mode 100644 index 0000000000..ef180dbae5 --- /dev/null +++ b/plugins/entity-feedback-backend/README.md @@ -0,0 +1,50 @@ +# Entity Feedback Backend + +Welcome to the entity-feedback backend plugin! + +## Installation + +### Install the package + +```bash +# From your Backstage root directory +yarn add --cwd packages/backend @backstage/plugin-entity-feedback-backend +``` + +### Adding the plugin to your `packages/backend` + +You'll need to add the plugin to the router in your `backend` package. You can do this by creating a file called `packages/backend/src/plugins/entityFeedback.ts` + +```tsx +import { createRouter } from '@backstage/plugin-entity-feedback-backend'; +import { Router } from 'express'; +import { PluginEnvironment } from '../types'; + +export default function createPlugin(env: PluginEnvironment): Promise { + return createRouter({ + database: env.database, + discovery: env.discovery, + identity: env.identity, + logger: env.logger, + }); +} +``` + +With the `entityFeedback.ts` router setup in place, add the router to `packages/backend/src/index.ts`: + +```diff ++import entityFeedback from './plugins/entityFeedback'; + +async function main() { + ... + const createEnv = makeCreateEnv(config); + + const catalogEnv = useHotMemoize(module, () => createEnv('catalog')); ++ const entityFeedbackEnv = useHotMemoize(module, () => createEnv('entityFeedback')); + + const apiRouter = Router(); ++ apiRouter.use('/entity-feedback', await entityFeedback(entityFeedbackEnv)); + ... + apiRouter.use(notFoundHandler()); + +``` diff --git a/plugins/entity-feedback-backend/api-report.md b/plugins/entity-feedback-backend/api-report.md new file mode 100644 index 0000000000..3909ac3056 --- /dev/null +++ b/plugins/entity-feedback-backend/api-report.md @@ -0,0 +1,26 @@ +## API Report File for "@backstage/plugin-entity-feedback-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import express from 'express'; +import { IdentityApi } from '@backstage/plugin-auth-node'; +import { Logger } from 'winston'; +import { PluginDatabaseManager } from '@backstage/backend-common'; +import { PluginEndpointDiscovery } from '@backstage/backend-common'; + +// @public (undocumented) +export function createRouter(options: RouterOptions): Promise; + +// @public (undocumented) +export interface RouterOptions { + // (undocumented) + database: PluginDatabaseManager; + // (undocumented) + discovery: PluginEndpointDiscovery; + // (undocumented) + identity: IdentityApi; + // (undocumented) + logger: Logger; +} +``` diff --git a/plugins/entity-feedback-backend/migrations/20230109124329_init.js b/plugins/entity-feedback-backend/migrations/20230109124329_init.js new file mode 100644 index 0000000000..42a48d264c --- /dev/null +++ b/plugins/entity-feedback-backend/migrations/20230109124329_init.js @@ -0,0 +1,69 @@ +/* + * Copyright 2023 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. + */ + +// @ts-check + +/** + * @param { import("knex").Knex } knex + */ +exports.up = async function up(knex) { + await knex.schema.createTable('ratings', table => { + table.comment('Ratings table'); + table + .string('entity_ref') + .notNullable() + .comment('The ref of the entity being rated'); + table + .string('user_ref') + .notNullable() + .comment('The user applying the rating'); + table.string('rating').notNullable().comment('The rating value'); + table + .timestamp('timestamp') + .defaultTo(knex.fn.now()) + .notNullable() + .comment('When the rating was recorded'); + }); + + await knex.schema.createTable('responses', table => { + table.comment('Responses table'); + table + .string('entity_ref') + .notNullable() + .comment('The ref of the applicable entity'); + table.string('user_ref').notNullable().comment('The user responding'); + table.text('response').comment('The serialized response'); + table.text('comments').comment('Additional user comments'); + table + .boolean('consent') + .defaultTo(true) + .notNullable() + .comment('Whether user (if recorded) consents to being contacted'); + table + .timestamp('timestamp') + .defaultTo(knex.fn.now()) + .notNullable() + .comment('When the response was recorded'); + }); +}; + +/** + * @param { import("knex").Knex } knex + */ +exports.down = async function down(knex) { + await knex.schema.dropTable('ratings'); + await knex.schema.dropTable('responses'); +}; diff --git a/plugins/entity-feedback-backend/package.json b/plugins/entity-feedback-backend/package.json new file mode 100644 index 0000000000..487d5f5d5e --- /dev/null +++ b/plugins/entity-feedback-backend/package.json @@ -0,0 +1,50 @@ +{ + "name": "@backstage/plugin-entity-feedback-backend", + "version": "0.1.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": "workspace:^", + "@backstage/catalog-client": "workspace:^", + "@backstage/catalog-model": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/plugin-auth-node": "workspace:^", + "@backstage/plugin-entity-feedback-common": "workspace:^", + "@types/express": "*", + "express": "^4.18.1", + "express-promise-router": "^4.1.0", + "knex": "^2.0.0", + "node-fetch": "^2.6.7", + "winston": "^3.2.1", + "yn": "^4.0.0" + }, + "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@types/supertest": "^2.0.12", + "msw": "^0.49.0", + "supertest": "^6.2.4" + }, + "files": [ + "dist", + "migrations/**/*.{js,d.ts}" + ] +} diff --git a/plugins/entity-feedback-backend/src/index.ts b/plugins/entity-feedback-backend/src/index.ts new file mode 100644 index 0000000000..b3c4139eed --- /dev/null +++ b/plugins/entity-feedback-backend/src/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2023 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. + */ + +/** + * Entity Feedback backend plugin + * + * @packageDocumentation + */ +export * from './service/router'; diff --git a/plugins/entity-feedback-backend/src/run.ts b/plugins/entity-feedback-backend/src/run.ts new file mode 100644 index 0000000000..7344f24c17 --- /dev/null +++ b/plugins/entity-feedback-backend/src/run.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2023 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/entity-feedback-backend/src/service/DatabaseHandler.test.ts b/plugins/entity-feedback-backend/src/service/DatabaseHandler.test.ts new file mode 100644 index 0000000000..c6cde95b3c --- /dev/null +++ b/plugins/entity-feedback-backend/src/service/DatabaseHandler.test.ts @@ -0,0 +1,310 @@ +/* + * Copyright 2023 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 { DatabaseHandler } from './DatabaseHandler'; + +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; + + beforeEach(async () => { + ({ knex, dbHandler } = await createDatabaseHandler(databaseId)); + }, 30000); + + afterEach(async () => { + // Clean up after each test + await knex('ratings').del(); + await knex('responses').del(); + }, 30000); + + it('getAllRatedEntities', async () => { + await knex('ratings').insert([ + { + entity_ref: 'component:default/service', + user_ref: 'user:default/foo', + rating: 'DISLIKE', + }, + { + entity_ref: 'component:default/service', + user_ref: 'user:default/foo', + rating: 'LIKE', + }, + { + entity_ref: 'component:default/library', + user_ref: 'user:default/bar', + rating: 'LIKE', + }, + { + entity_ref: 'component:default/website', + user_ref: 'user:default/foo', + rating: 'LIKE', + }, + ]); + + const entities = await dbHandler.getAllRatedEntities(); + expect(entities.length).toEqual(3); + expect(entities).toEqual( + expect.arrayContaining([ + 'component:default/service', + 'component:default/library', + 'component:default/website', + ]), + ); + }); + + it('getRatingsAggregates', async () => { + await knex('ratings').insert([ + { + entity_ref: 'component:default/service', + user_ref: 'user:default/foo', + rating: 'DISLIKE', + timestamp: '2004-10-19 10:23:54', + }, + { + entity_ref: 'component:default/service', + user_ref: 'user:default/foo', + rating: 'LIKE', + timestamp: '2004-11-19 08:23:54', + }, + { + entity_ref: 'component:default/service', + user_ref: 'user:default/bar', + rating: 'LIKE', + timestamp: '2004-11-20 08:23:54', + }, + { + entity_ref: 'component:default/website', + user_ref: 'user:default/foo', + rating: 'LIKE', + timestamp: '2004-11-20 08:23:54', + }, + { + entity_ref: 'component:default/website', + user_ref: 'user:default/test', + rating: 'DISLIKE', + timestamp: '2004-11-20 08:23:54', + }, + ]); + + let ratings = await dbHandler.getRatingsAggregates([ + 'component:default/service', + 'component:default/website', + ]); + expect(ratings.length).toEqual(3); + expect(ratings).toEqual( + expect.arrayContaining([ + { + entityRef: 'component:default/service', + rating: 'LIKE', + count: 2, + }, + { + entityRef: 'component:default/website', + rating: 'DISLIKE', + count: 1, + }, + { + entityRef: 'component:default/website', + rating: 'LIKE', + count: 1, + }, + ]), + ); + + ratings = await dbHandler.getRatingsAggregates([ + 'component:default/website', + ]); + expect(ratings.length).toEqual(2); + expect(ratings).toEqual( + expect.arrayContaining([ + { + entityRef: 'component:default/website', + rating: 'DISLIKE', + count: 1, + }, + { + entityRef: 'component:default/website', + rating: 'LIKE', + count: 1, + }, + ]), + ); + }); + + it('recordRating', async () => { + const newRating = { + userRef: 'user:default/me', + entityRef: 'component:default/service', + rating: 'LIKE', + }; + + await dbHandler.recordRating(newRating); + + const ratings = await knex('ratings').select(); + expect(ratings.length).toEqual(1); + expect(ratings[0]).toEqual( + expect.objectContaining({ + user_ref: newRating.userRef, + entity_ref: newRating.entityRef, + rating: newRating.rating, + timestamp: expect.anything(), + }), + ); + }); + + it('getRatings', async () => { + await knex('ratings').insert([ + { + entity_ref: 'component:default/service', + user_ref: 'user:default/foo', + rating: 'DISLIKE', + timestamp: '2004-10-19 10:23:54', + }, + { + entity_ref: 'component:default/service', + user_ref: 'user:default/foo', + rating: 'LIKE', + timestamp: '2004-11-19 08:23:54', + }, + { + entity_ref: 'component:default/service', + user_ref: 'user:default/bar', + rating: 'LIKE', + timestamp: '2004-11-20 08:23:54', + }, + { + entity_ref: 'component:default/website', + user_ref: 'user:default/foo', + rating: 'LIKE', + timestamp: '2004-11-20 08:23:54', + }, + ]); + + const ratings = await dbHandler.getRatings('component:default/service'); + expect(ratings.length).toEqual(2); + expect(ratings).toEqual( + expect.arrayContaining([ + { userRef: 'user:default/foo', rating: 'LIKE' }, + { userRef: 'user:default/bar', rating: 'LIKE' }, + ]), + ); + }); + + it('recordResponse', async () => { + const newResponse = { + userRef: 'user:default/me', + entityRef: 'component:default/service', + response: 'blah', + comments: 'here is some feedback', + consent: false, + }; + + await dbHandler.recordResponse(newResponse); + + const responses = await knex('responses').select(); + expect(responses.length).toEqual(1); + expect({ + ...responses[0], + consent: Boolean(responses[0].consent), + }).toEqual( + expect.objectContaining({ + user_ref: newResponse.userRef, + entity_ref: newResponse.entityRef, + response: newResponse.response, + comments: newResponse.comments, + consent: newResponse.consent, + timestamp: expect.anything(), + }), + ); + }); + + it('getResponses', async () => { + await knex('responses').insert([ + { + entity_ref: 'component:default/service', + user_ref: 'user:default/foo', + response: 'blah', + comments: 'here is some feedback', + consent: true, + timestamp: '2004-10-19 10:23:54', + }, + { + entity_ref: 'component:default/service', + user_ref: 'user:default/foo', + response: 'asdf', + comments: 'here is new feedback', + consent: false, + timestamp: '2004-11-19 08:23:54', + }, + { + entity_ref: 'component:default/service', + user_ref: 'user:default/bar', + response: 'noop', + comments: 'here is different feedback', + consent: true, + timestamp: '2004-11-20 08:23:54', + }, + { + entity_ref: 'component:default/website', + user_ref: 'user:default/foo', + response: 'cool', + comments: 'no comment', + consent: true, + timestamp: '2004-11-20 08:23:54', + }, + ]); + + const responses = await dbHandler.getResponses( + 'component:default/service', + ); + expect(responses.length).toEqual(2); + expect(responses).toEqual( + expect.arrayContaining([ + { + userRef: 'user:default/foo', + response: 'asdf', + comments: 'here is new feedback', + consent: false, + }, + { + userRef: 'user:default/bar', + response: 'noop', + comments: 'here is different feedback', + consent: true, + }, + ]), + ); + }); + }, + 60000, + ); +}); diff --git a/plugins/entity-feedback-backend/src/service/DatabaseHandler.ts b/plugins/entity-feedback-backend/src/service/DatabaseHandler.ts new file mode 100644 index 0000000000..aeeaffd694 --- /dev/null +++ b/plugins/entity-feedback-backend/src/service/DatabaseHandler.ts @@ -0,0 +1,161 @@ +/* + * Copyright 2023 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 { Rating, Response } from '@backstage/plugin-entity-feedback-common'; +import { Knex } from 'knex'; + +const migrationsDir = resolvePackagePath( + '@backstage/plugin-entity-feedback-backend', + 'migrations', +); + +type RatingsAggregatesResult = { + entityRef: string; + rating: string; + count: number; +}[]; + +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; + } + + async getAllRatedEntities(): Promise { + return (await this.database('ratings').distinct('entity_ref')).map( + ({ entity_ref }) => entity_ref, + ); + } + + async getRatingsAggregates( + entityRefs: string[], + ): Promise { + return ( + await this.database('ratings') + .whereIn('ratings.entity_ref', entityRefs) + .innerJoin( + this.database('ratings') + .as('latest_ratings') + .select('entity_ref', 'user_ref') + .max('timestamp', { as: 'timestamp' }) + .whereIn('entity_ref', entityRefs) + .groupBy('entity_ref', 'user_ref'), + function joinClause() { + this.on('ratings.entity_ref', '=', 'latest_ratings.entity_ref') + .andOn('ratings.user_ref', '=', 'latest_ratings.user_ref') + .andOn('ratings.timestamp', '=', 'latest_ratings.timestamp'); + }, + ) + .select('ratings.entity_ref', 'rating') + .count('ratings.user_ref as count') + .groupBy('ratings.entity_ref', 'rating') + ).map(({ entity_ref, rating, count }) => ({ + entityRef: entity_ref as string, + rating: rating as string, + count: Number(count), + })); + } + + async recordRating(rating: Rating) { + await this.database('ratings').insert({ + entity_ref: rating.entityRef, + rating: rating.rating, + user_ref: rating.userRef, + }); + } + + async getRatings(entityRef: string): Promise[]> { + return ( + await this.database('ratings') + .where('entity_ref', entityRef) + .innerJoin( + this.database('ratings') + .as('latest_ratings') + .select('user_ref') + .max('timestamp', { as: 'timestamp' }) + .where('entity_ref', entityRef) + .groupBy('user_ref'), + function joinClause() { + this.on('ratings.user_ref', '=', 'latest_ratings.user_ref').andOn( + 'ratings.timestamp', + '=', + 'latest_ratings.timestamp', + ); + }, + ) + .select('ratings.user_ref', 'rating') + ).map(rating => ({ userRef: rating.user_ref, rating: rating.rating })); + } + + async recordResponse(response: Response) { + await this.database('responses').insert({ + entity_ref: response.entityRef, + response: response.response, + comments: response.comments, + consent: response.consent, + user_ref: response.userRef, + }); + } + + async getResponses( + entityRef: string, + ): Promise[]> { + return ( + await this.database('responses') + .where('entity_ref', entityRef) + .innerJoin( + this.database('responses') + .as('latest_responses') + .select('user_ref') + .max('timestamp', { as: 'timestamp' }) + .where('entity_ref', entityRef) + .groupBy('user_ref'), + function joinClause() { + this.on( + 'responses.user_ref', + '=', + 'latest_responses.user_ref', + ).andOn('responses.timestamp', '=', 'latest_responses.timestamp'); + }, + ) + .select('responses.user_ref', 'response', 'comments', 'consent') + ).map(response => ({ + userRef: response.user_ref, + response: response.response, + comments: response.comments, + consent: Boolean(response.consent), + })); + } +} diff --git a/plugins/entity-feedback-backend/src/service/router.test.ts b/plugins/entity-feedback-backend/src/service/router.test.ts new file mode 100644 index 0000000000..74fae8248b --- /dev/null +++ b/plugins/entity-feedback-backend/src/service/router.test.ts @@ -0,0 +1,290 @@ +/* + * Copyright 2023 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, + PluginEndpointDiscovery, +} from '@backstage/backend-common'; +import { stringifyEntityRef } from '@backstage/catalog-model'; +import { ConfigReader } from '@backstage/config'; +import { IdentityApi } from '@backstage/plugin-auth-node'; +import express from 'express'; +import request from 'supertest'; + +import { createRouter } from './router'; + +const sampleOwnedEntities = [ + { + kind: 'component', + metadata: { + namespace: 'default', + name: 'foo', + title: 'Foo Component', + }, + }, + { + kind: 'component', + metadata: { + namespace: 'default', + name: 'bar', + title: 'Bar Component', + }, + }, +]; + +const sampleEntities = [ + ...sampleOwnedEntities, + { + kind: 'user', + metadata: { + namespace: 'default', + name: 'foo', + }, + }, + null, + { + kind: 'user', + metadata: { + namespace: 'default', + name: 'bar', + }, + }, +]; + +const mockGetEntties = jest + .fn() + .mockImplementation(async () => ({ items: sampleOwnedEntities })); + +const mockGetEnttiesByRefs = jest + .fn() + .mockImplementation(async () => ({ items: sampleEntities })); + +jest.mock('@backstage/catalog-client', () => ({ + CatalogClient: jest.fn().mockImplementation(() => ({ + getEntities: mockGetEntties, + getEntitiesByRefs: mockGetEnttiesByRefs, + })), +})); + +jest.mock('@backstage/plugin-auth-node', () => ({ + getBearerTokenFromAuthorizationHeader: () => 'token', +})); + +const mockRatings = [ + { userRef: 'user:default/foo', rating: 'LIKE' }, + { userRef: 'user:default/bar', rating: 'LIKE' }, + { userRef: 'user:default/test', rating: 'DISLIKE' }, +]; + +const mockResponses = [ + { + userRef: 'user:default/foo', + response: 'asdf', + comments: 'here is new feedback', + consent: false, + }, + { + userRef: 'user:default/bar', + response: 'noop', + comments: 'here is different feedback', + consent: true, + }, + { + userRef: 'user:default/test', + response: 'err', + comments: 'no comment', + consent: false, + }, +]; + +const mockDbHandler = { + getAllRatedEntities: jest + .fn() + .mockImplementation(async () => [ + 'component:default/foo', + 'component:default/bar', + 'component:default/test', + ]), + getRatingsAggregates: jest.fn().mockImplementation(async () => [ + { entityRef: 'component:default/foo', rating: 'LIKE', count: 3 }, + { entityRef: 'component:default/foo', rating: 'DISLIKE', count: 1 }, + { entityRef: 'component:default/bar', rating: 'LIKE', count: 5 }, + ]), + recordRating: jest.fn().mockImplementation(async () => {}), + getRatings: jest.fn().mockImplementation(async () => mockRatings), + recordResponse: jest.fn().mockImplementation(async () => {}), + getResponses: jest.fn().mockImplementation(async () => mockResponses), +}; + +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('entity-feedback'); + + const mockIdentityClient = { + getIdentity: jest.fn().mockImplementation(async () => ({ + identity: { userEntityRef: 'user:default/me' }, + })), + } 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(), + }); + + app = express().use(router); + jest.clearAllMocks(); + }); + + describe('GET /ratings', () => { + it('should get ratings for all entities correctly', async () => { + const response = await request(app).get('/ratings').send(); + + expect(mockDbHandler.getAllRatedEntities).toHaveBeenCalled(); + expect(mockDbHandler.getRatingsAggregates).toHaveBeenCalledWith( + sampleEntities + .filter(Boolean) + .map((ent: any) => stringifyEntityRef(ent)), + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual([ + { + entityRef: 'component:default/foo', + entityTitle: 'Foo Component', + ratings: { LIKE: 3, DISLIKE: 1 }, + }, + { + entityRef: 'component:default/bar', + entityTitle: 'Bar Component', + ratings: { LIKE: 5 }, + }, + ]); + }); + + it('should get ratings for all owned entities correctly', async () => { + const response = await request(app) + .get('/ratings?ownerRef=group:default/test-team') + .send(); + + expect(mockGetEntties).toHaveBeenCalledWith( + expect.objectContaining({ + filter: { 'relations.ownedBy': 'group:default/test-team' }, + }), + { token: 'token' }, + ); + expect(mockDbHandler.getAllRatedEntities).not.toHaveBeenCalled(); + expect(mockDbHandler.getRatingsAggregates).toHaveBeenCalledWith( + sampleOwnedEntities.map((ent: any) => stringifyEntityRef(ent)), + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual([ + { + entityRef: 'component:default/foo', + entityTitle: 'Foo Component', + ratings: { LIKE: 3, DISLIKE: 1 }, + }, + { + entityRef: 'component:default/bar', + entityTitle: 'Bar Component', + ratings: { LIKE: 5 }, + }, + ]); + }); + }); + + describe('POST /ratings/:entityRef', () => { + it('should record a rating correctly', async () => { + const body = { rating: 'LIKE' }; + const response = await request(app) + .post('/ratings/component%3Adefault%2Fservice') + .send(body); + expect(mockDbHandler.recordRating).toHaveBeenCalledWith({ + entityRef: 'component:default/service', + userRef: 'user:default/me', + ...body, + }); + expect(response.status).toEqual(201); + }); + }); + + describe('GET /ratings/:entityRef', () => { + it('should get ratings for an entity correctly', async () => { + const response = await request(app) + .get('/ratings/component%3Adefault%2Fservice') + .send(); + expect(mockDbHandler.getRatings).toHaveBeenCalledWith( + 'component:default/service', + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual( + mockRatings.filter(r => r.userRef !== 'user:default/test'), + ); + }); + }); + + describe('POST /responses/:entityRef', () => { + it('should record a response correctly', async () => { + const body = { response: 'blah', comments: 'feedback', consent: true }; + const response = await request(app) + .post('/responses/component%3Adefault%2Fservice') + .send(body); + expect(mockDbHandler.recordResponse).toHaveBeenCalledWith({ + entityRef: 'component:default/service', + userRef: 'user:default/me', + ...body, + }); + expect(response.status).toEqual(201); + }); + }); + + describe('GET /responses/:entityRef', () => { + it('should get responses for an entity correctly', async () => { + const response = await request(app) + .get('/responses/component%3Adefault%2Fservice') + .send(); + expect(mockDbHandler.getResponses).toHaveBeenCalledWith( + 'component:default/service', + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual( + mockResponses.filter(r => r.userRef !== 'user:default/test'), + ); + }); + }); +}); diff --git a/plugins/entity-feedback-backend/src/service/router.ts b/plugins/entity-feedback-backend/src/service/router.ts new file mode 100644 index 0000000000..e1243cedaf --- /dev/null +++ b/plugins/entity-feedback-backend/src/service/router.ts @@ -0,0 +1,215 @@ +/* + * Copyright 2023 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, + PluginEndpointDiscovery, +} from '@backstage/backend-common'; +import { CatalogClient } from '@backstage/catalog-client'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { + getBearerTokenFromAuthorizationHeader, + IdentityApi, +} from '@backstage/plugin-auth-node'; +import { EntityRatingsData } from '@backstage/plugin-entity-feedback-common'; +import express from 'express'; +import Router from 'express-promise-router'; +import { Logger } from 'winston'; + +import { DatabaseHandler } from './DatabaseHandler'; + +/** + * @public + */ +export interface RouterOptions { + database: PluginDatabaseManager; + discovery: PluginEndpointDiscovery; + identity: IdentityApi; + logger: Logger; +} + +/** + * @public + */ +export async function createRouter( + options: RouterOptions, +): Promise { + const { database, discovery, identity, logger } = options; + + logger.info('Initializing Entity Feedback backend'); + + const catalogClient = new CatalogClient({ discoveryApi: discovery }); + const db = await database.getClient(); + const dbHandler = await DatabaseHandler.create({ database: db }); + + const router = Router(); + router.use(express.json()); + + router.get('/ratings', async (req, res) => { + const token = getBearerTokenFromAuthorizationHeader( + req.header('authorization'), + ); + + const requestedEntities: { [ref: string]: Entity } = {}; + if (req.query.ownerRef) { + // Get ratings from all owned entities (also ensures only accessible entities are requested) + ( + await catalogClient.getEntities( + { + filter: { 'relations.ownedBy': req.query.ownerRef as string }, + fields: [ + 'kind', + 'metadata.name', + 'metadata.namespace', + 'metadata.title', + ], + }, + { token }, + ) + ).items.forEach(ent => { + requestedEntities[stringifyEntityRef(ent)] = ent; + }); + } else { + const allRatedEntities = await dbHandler.getAllRatedEntities(); + + // Filter entities to only expose entity refs accessible by current user + ( + await catalogClient.getEntitiesByRefs( + { + entityRefs: allRatedEntities, + fields: [ + 'kind', + 'metadata.namespace', + 'metadata.name', + 'metadata.title', + ], + }, + { token }, + ) + ).items + .filter(Boolean) + .forEach(ent => { + requestedEntities[stringifyEntityRef(ent!)] = ent!; + }); + } + + const entityRatings = await dbHandler.getRatingsAggregates( + Object.keys(requestedEntities), + ); + + // Merge rating aggregates into a condensed per entity structure + const entityRatingsMap = entityRatings.reduce<{ + [ref: string]: EntityRatingsData; + }>((ratingsMap, { entityRef, rating, count }) => { + ratingsMap[entityRef] = ratingsMap[entityRef] ?? { + entityRef, + entityTitle: requestedEntities[entityRef].metadata.title, + ratings: {}, + }; + ratingsMap[entityRef].ratings[rating] = count; + return ratingsMap; + }, {}); + + res.json(Object.values(entityRatingsMap)); + }); + + router.post('/ratings/:entityRef', async (req, res) => { + const user = await identity.getIdentity({ request: req }); + const rating = req.body.rating; + if (!user || !rating) { + res.status(400).end(); + return; + } + + await dbHandler.recordRating({ + entityRef: req.params.entityRef, + rating, + userRef: user.identity.userEntityRef, + }); + + res.status(201).end(); + }); + + router.get('/ratings/:entityRef', async (req, res) => { + const ratings = await dbHandler.getRatings(req.params.entityRef); + + const token = getBearerTokenFromAuthorizationHeader( + req.header('authorization'), + ); + + // Filter ratings via user refs to only expose entity refs accessible by current user + const accessibleEntityRefs = ( + await catalogClient.getEntitiesByRefs( + { + entityRefs: ratings.map(r => r.userRef), + fields: ['kind', 'metadata.namespace', 'metadata.name'], + }, + { token }, + ) + ).items + .filter(Boolean) + .map(ent => stringifyEntityRef(ent!)); + + res.json(ratings.filter(r => accessibleEntityRefs.includes(r.userRef))); + }); + + router.post('/responses/:entityRef', async (req, res) => { + const user = await identity.getIdentity({ request: req }); + const { response, comments, consent } = req.body; + + if (!user) { + res.status(400).end(); + return; + } + + await dbHandler.recordResponse({ + entityRef: req.params.entityRef, + response, + comments, + consent, + userRef: user.identity.userEntityRef, + }); + + res.status(201).end(); + }); + + router.get('/responses/:entityRef', async (req, res) => { + const responses = await dbHandler.getResponses(req.params.entityRef); + + const token = getBearerTokenFromAuthorizationHeader( + req.header('authorization'), + ); + + // Filter responses via user refs to only expose entity refs accessible by current user + const accessibleEntityRefs = ( + await catalogClient.getEntitiesByRefs( + { + entityRefs: responses.map(r => r.userRef), + fields: ['kind', 'metadata.namespace', 'metadata.name'], + }, + { token }, + ) + ).items + .filter(Boolean) + .map(ent => stringifyEntityRef(ent!)); + + res.json(responses.filter(r => accessibleEntityRefs.includes(r.userRef))); + }); + + router.use(errorHandler()); + return router; +} diff --git a/plugins/entity-feedback-backend/src/service/standaloneServer.ts b/plugins/entity-feedback-backend/src/service/standaloneServer.ts new file mode 100644 index 0000000000..9395c72141 --- /dev/null +++ b/plugins/entity-feedback-backend/src/service/standaloneServer.ts @@ -0,0 +1,80 @@ +/* + * Copyright 2023 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, + SingleHostDiscovery, + useHotMemoize, +} from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { DefaultIdentityClient } from '@backstage/plugin-auth-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: 'entity-feedback-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('entity-feedback'); + }); + + const identity = DefaultIdentityClient.create({ + discovery, + issuer: await discovery.getExternalBaseUrl('auth'), + }); + + logger.debug('Starting application server...'); + const router = await createRouter({ + database, + discovery, + identity, + logger, + }); + + let service = createServiceBuilder(module) + .setPort(options.port) + .addRouter('/entity-feedback', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } + + return service.start().catch(err => { + logger.error(err); + process.exit(1); + }); +} + +module.hot?.accept(); diff --git a/plugins/entity-feedback-backend/src/setupTests.ts b/plugins/entity-feedback-backend/src/setupTests.ts new file mode 100644 index 0000000000..aa70772592 --- /dev/null +++ b/plugins/entity-feedback-backend/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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/entity-feedback-common/.eslintrc.js b/plugins/entity-feedback-common/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/entity-feedback-common/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/entity-feedback-common/README.md b/plugins/entity-feedback-common/README.md new file mode 100644 index 0000000000..430d14aeab --- /dev/null +++ b/plugins/entity-feedback-common/README.md @@ -0,0 +1,3 @@ +# Entity Feedback Common + +Common types for the entity-feedback plugin. diff --git a/plugins/entity-feedback-common/api-report.md b/plugins/entity-feedback-common/api-report.md new file mode 100644 index 0000000000..35da32c1da --- /dev/null +++ b/plugins/entity-feedback-common/api-report.md @@ -0,0 +1,42 @@ +## API Report File for "@backstage/plugin-entity-feedback-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +// @public (undocumented) +export interface EntityRatingsData { + // (undocumented) + entityRef: string; + // (undocumented) + entityTitle?: string; + // (undocumented) + ratings: { + [ratingValue: string]: number; + }; +} + +// @public (undocumented) +export interface Rating { + // (undocumented) + entityRef: string; + // (undocumented) + rating: string; + // (undocumented) + userRef: string; +} + +// @public (undocumented) +interface Response_2 { + // (undocumented) + comments?: string; + // (undocumented) + consent?: boolean; + // (undocumented) + entityRef: string; + // (undocumented) + response?: string; + // (undocumented) + userRef: string; +} +export { Response_2 as Response }; +``` diff --git a/plugins/entity-feedback-common/package.json b/plugins/entity-feedback-common/package.json new file mode 100644 index 0000000000..45a5a2b131 --- /dev/null +++ b/plugins/entity-feedback-common/package.json @@ -0,0 +1,31 @@ +{ + "name": "@backstage/plugin-entity-feedback-common", + "description": "Common functionalities for the entity-feedback plugin", + "version": "0.1.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" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/entity-feedback-common/src/index.ts b/plugins/entity-feedback-common/src/index.ts new file mode 100644 index 0000000000..f19fcdd648 --- /dev/null +++ b/plugins/entity-feedback-common/src/index.ts @@ -0,0 +1,52 @@ +/* + * Copyright 2023 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 entity-feedback plugin. + * + * @packageDocumentation + */ + +/** + * @public + */ +export interface Rating { + entityRef: string; + rating: string; + userRef: string; +} + +/** + * @public + */ +export interface Response { + entityRef: string; + response?: string; + comments?: string; + consent?: boolean; + userRef: string; +} + +/** + * @public + */ +export interface EntityRatingsData { + entityRef: string; + entityTitle?: string; + ratings: { + [ratingValue: string]: number; + }; +} diff --git a/plugins/entity-feedback-common/src/setupTests.ts b/plugins/entity-feedback-common/src/setupTests.ts new file mode 100644 index 0000000000..4b9026cde5 --- /dev/null +++ b/plugins/entity-feedback-common/src/setupTests.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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/entity-feedback/.eslintrc.js b/plugins/entity-feedback/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/entity-feedback/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/entity-feedback/README.md b/plugins/entity-feedback/README.md new file mode 100644 index 0000000000..fdfa4761d6 --- /dev/null +++ b/plugins/entity-feedback/README.md @@ -0,0 +1,136 @@ +# Entity Feedback Plugin + +Welcome to the entity-feedback plugin! + +This plugin allows you give and view feedback on entities available in the Backstage catalog. + +## Features + +### Rate entities + +#### Like/Dislike rating + +![Like dislike rating example](./docs/like-dislike-rating.png) + +#### Starred rating + +![Starred rating example](./docs/starred-rating.png) + +### Request additional feedback when poorly rated + +![Response dialog example](./docs/feedback-response-dialog.png) + +### View entity feedback responses + +![Feedback responses example](./docs/feedback-response-table.png) + +### View aggregated ratings on owned entities + +#### Total likes/dislikes + +![Like dislike table example](./docs/like-dislike-table.png) + +#### Star breakdowns + +![Starred rating table example](./docs/starred-rating-table.png) + +## Setup + +The following sections will help you get the Entity Feedback plugin setup and running + +### Backend + +You need to setup the [Entity Feedback backend plugin](https://github.com/backstage/backstage/tree/master/plugins/entity-feedback-backend) before you move forward with any of these steps if you haven't already + +### Installation + +Install this plugin: + +```bash +# From your Backstage root directory +yarn --cwd packages/app add @backstage/plugin-entity-feedback +``` + +### Entity Pages + +Add rating and feedback components to your `EntityPage.tsx` to hook up UI so that users +can rate your entities and for owners to view feedback/responses. + +To allow users to apply "Like" and "Dislike" ratings add the following to each kind/type of +entity in your `EntityPage.tsx` you want to be rated (if you prefer to use star ratings, replace +`EntityLikeDislikeRatingsCard` with `EntityStarredRatingsCard` and `LikeDislikeButtons` with +`StarredRatingButtons`): + +```diff +import { + ... ++ InfoCard, + ... +} from '@backstage/core-components'; ++import { ++ EntityFeedbackResponseContent, ++ EntityLikeDislikeRatingsCard, ++ LikeDislikeButtons, ++} from '@backstage/plugin-entity-feedback'; + +// Add to each applicable kind/type of entity as desired +const overviewContent = ( + + ... ++ ++ ++ ++ ++ + ... + +); + +... + +// Add to each applicable kind/type of entity as desired +const serviceEntityPage = ( + + ... ++ ++ ++ + ... + +); + +... + +// Add ratings card component to user/group entities to view ratings of owned entities +const userPage = ( + + + + ... ++ ++ ++ + ... + + + + +); + +const groupPage = ( + + + + ... ++ ++ ++ + ... + + + + +); +``` + +Note: For a full example of this you can look at [this EntityPage](../../packages/app/src/components/catalog/EntityPage.tsx) diff --git a/plugins/entity-feedback/api-report.md b/plugins/entity-feedback/api-report.md new file mode 100644 index 0000000000..399e84e674 --- /dev/null +++ b/plugins/entity-feedback/api-report.md @@ -0,0 +1,180 @@ +## API Report File for "@backstage/plugin-entity-feedback" + +> 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 { Entity } from '@backstage/catalog-model'; +import { EntityRatingsData } from '@backstage/plugin-entity-feedback-common'; +import { FetchApi } from '@backstage/core-plugin-api'; +import { Rating } from '@backstage/plugin-entity-feedback-common'; +import { ReactNode } from 'react'; +import { Response as Response_2 } from '@backstage/plugin-entity-feedback-common'; +import { RouteRef } from '@backstage/core-plugin-api'; + +// @public (undocumented) +export interface EntityFeedbackApi { + // (undocumented) + getAllRatings(): Promise; + // (undocumented) + getOwnedRatings(ownerRef: string): Promise; + // (undocumented) + getRatings(entityRef: string): Promise[]>; + // (undocumented) + getResponses(entityRef: string): Promise[]>; + // (undocumented) + recordRating(entityRef: string, rating: string): Promise; + // (undocumented) + recordResponse( + entityRef: string, + response: Omit, + ): Promise; +} + +// @public (undocumented) +export const entityFeedbackApiRef: ApiRef; + +// @public (undocumented) +export class EntityFeedbackClient implements EntityFeedbackApi { + constructor(options: { discoveryApi: DiscoveryApi; fetchApi: FetchApi }); + // (undocumented) + getAllRatings(): Promise; + // (undocumented) + getOwnedRatings(ownerRef: string): Promise; + // (undocumented) + getRatings(entityRef: string): Promise[]>; + // (undocumented) + getResponses(entityRef: string): Promise[]>; + // (undocumented) + recordRating(entityRef: string, rating: string): Promise; + // (undocumented) + recordResponse( + entityRef: string, + response: Omit, + ): Promise; +} + +// @public (undocumented) +export const entityFeedbackPlugin: BackstagePlugin< + { + root: RouteRef; + }, + {}, + {} +>; + +// @public (undocumented) +export interface EntityFeedbackResponse { + // (undocumented) + id: string; + // (undocumented) + label: string; +} + +// @public (undocumented) +export const EntityFeedbackResponseContent: () => JSX.Element; + +// @public (undocumented) +export const EntityLikeDislikeRatingsCard: () => JSX.Element; + +// @public (undocumented) +export const EntityStarredRatingsCard: () => JSX.Element; + +// @public (undocumented) +export const FeedbackResponseDialog: ( + props: FeedbackResponseDialogProps, +) => JSX.Element; + +// @public (undocumented) +export interface FeedbackResponseDialogProps { + // (undocumented) + entity: Entity; + // (undocumented) + feedbackDialogResponses?: EntityFeedbackResponse[]; + // (undocumented) + feedbackDialogTitle?: ReactNode; + // (undocumented) + onClose: () => void; + // (undocumented) + open: boolean; +} + +// @public (undocumented) +export const FeedbackResponseTable: ( + props: FeedbackResponseTableProps, +) => JSX.Element; + +// @public (undocumented) +export interface FeedbackResponseTableProps { + // (undocumented) + entityRef: string; + // (undocumented) + title?: string; +} + +// @public (undocumented) +export const LikeDislikeButtons: ( + props: LikeDislikeButtonsProps, +) => JSX.Element; + +// @public (undocumented) +export interface LikeDislikeButtonsProps { + // (undocumented) + feedbackDialogResponses?: EntityFeedbackResponse[]; + // (undocumented) + feedbackDialogTitle?: ReactNode; + // (undocumented) + requestResponse?: boolean; +} + +// @public (undocumented) +export const LikeDislikeRatingsTable: ( + props: LikeDislikeRatingsTableProps, +) => JSX.Element; + +// @public (undocumented) +export interface LikeDislikeRatingsTableProps { + // (undocumented) + allEntities?: boolean; + // (undocumented) + ownerRef?: string; + // (undocumented) + title?: string; +} + +// @public (undocumented) +export const StarredRatingButtons: ( + props: StarredRatingButtonsProps, +) => JSX.Element; + +// @public (undocumented) +export interface StarredRatingButtonsProps { + // (undocumented) + feedbackDialogResponses?: EntityFeedbackResponse[]; + // (undocumented) + feedbackDialogTitle?: ReactNode; + // (undocumented) + requestResponse?: boolean; + // (undocumented) + requestResponseThreshold?: number; +} + +// @public (undocumented) +export const StarredRatingsTable: ( + props: StarredRatingsTableProps, +) => JSX.Element; + +// @public (undocumented) +export interface StarredRatingsTableProps { + // (undocumented) + allEntities?: boolean; + // (undocumented) + ownerRef?: string; + // (undocumented) + title?: string; +} +``` diff --git a/plugins/entity-feedback/docs/feedback-response-dialog.png b/plugins/entity-feedback/docs/feedback-response-dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..74270c805a549412e34b0e95785114f601ca60ba GIT binary patch literal 46890 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 literal 0 HcmV?d00001 diff --git a/plugins/entity-feedback/docs/feedback-response-table.png b/plugins/entity-feedback/docs/feedback-response-table.png new file mode 100644 index 0000000000000000000000000000000000000000..3795ac809d07381fd734818f51dc3afa915755f8 GIT binary patch literal 32787 zcmeFZby$^K*FH*jC?YK&-7TG>bO}f|A|c(K0s_+AOKGK%PC;0dfPjQ_gLJ3xn``fP z$9cc)_B!X!-}$^QaIw}C^BHrFF~_*?d#o@OC24F75)3#vIBZ#&N2+jesN`^P@YrZ5 z;2loUHV7OX#=NDZq>8MhB&CX@-E&K8GdMVzu*76kb+sN6|Fzkpm|HRrk#b+oB5feW z;CaI3X+A-hrF`=;ulY_R$6L((YqZ)#58YsD9KWZyRT=I`><5Y`7I5)@gvUeoZMkaKz*dh zsl0kmtkb(xImX21qG_H{iQwD;-?x%KR*fa*TuPyWhgSpMUm0c100}0D=j~Uxp=t%1w5a^`)tI|3@RM%7^ z8eLs0k%!eT+&RTF$w(bD+j$&y;I%w}ue=#22XDawC;nsM!+<>@T!J?oiH?V(U zvPFdhAE#3yOa+4`WO<0of>j+UQT*-@c_GRLx*&RHP^tL6A;dydl9#jM*~a(^fg9z# z)>wlf+8m@ffz%7g_83h>13`xik@f<5$P^)@^GNmDI4NoKsl`UA(LY}{6{ZhIP=Zv2gYVg`1VAj7> zoZ=B5gdJj+<2BT=Zb!r=g=re#@X?;5A_c!6PXRt3tBS%2!RfXW;Yg@Qbf*ci)}7)z zyl|wUik)nowrx9~#!Pj~?@btNq2Yv%v}w;z+u!GBW5d++pNbNCEflf&>3BhOF>$ZK zUAKusl$^b*>|^o*?!w@_(Eg9JCxI9rU(G*6yT6BC|5EW~^ULS$iVrD_6AI;c?l;_~ z4lDZf^^>E?y?v^E&i#_OxVVWztK$%aq7O|Fl6}O5O4u@4Nf&h~JT_;}#h_xd&M+>{2&m%1%=* z$Lvc3|QYe^(v!Ojyzj#Vf?9>w?&YThQEFCA(;+h)soEy-c(9{k3*b(Zc)K{3pd< z3ilt~DX}ai&aZ#ul)U=*^PAM8)KYE_ZcKCX^m7%=F|Kipah-QhOI-9{Jkph(GSq$B ztbf^b5`!ZNRil4epuYBc0K%p?uCJM^`_4<_6j?2@=XpMNUn*frho_Dwyr*Nci08Iv z&IR4YlZzKeo5$Hix3INPdQkFEN>DmN8bX|~lZnSjM0u!)Dqg>ontJ{1wJ1?K5tOKm z+m?r%;|bqF%5v&xnlLYIx@QU-ZwXhkX~+Z9)V$Pfo<=jAbfFZ?&&;3gblM1_2&f`5 z3GP*KRArclnLqvfy^=<|lC_HU1*=yvk;X@j7sVtc2A_E|?uj+JyH0J{jp2-KjCqw% zOsd!**o;l^Of^+Js9l-V_%>TXJ#{`=^5I3LmyMk>WpG}!R&J&%vbkx%O5Ocv8))gRHrt;gx-Or=h# za#JcxZy_DGiPo(Z8WH*OL;BPfR|L0IIuXjPjHukQ<~!(HLoAf&lk%gt@0^@P=vL)7%8l$_`Fd;HPm8i!48sje=E_@xZd7lQ;1tAF#2v&5rPDi>M(slo zGZB(e4bZ5NA0s_Q62aufO+w)t3|>PSnBh9z7tZlm^oYDq`SMOB?Xqm4?E2!6VSBmp z8{$vvO+PuN#yYc*#Uzx{rrsi;Uk|2xm>uMxP)j3;t*s{O_Dox3326v zaxcwdtOJS}BcgcZ##izWc9%sacP0}jDUu(t3uNV_Q4iE-y~t`5trZ(&x0_QvQk@+h zGxO}zVBgdpFlaGH{y=5OZVlTv&%FK?>r>uE-t(HBgZYE} z?T{%xyBpQ}#dW$HPqkYmUqCPJQMewsx$YcHKdsgEa{IC~C>HM9)C%=emP~Ybs{Now zu<_!2cD>o=QtQ&{V zHk0Kk<@4o(31(c2g|%zd>EvS>5FNCN+?;@ zHm)|J`w?H+QI$3_-wBtvdX5k;re1NInja2CeUQ-!8OY1nw9y~ESohvK7b0wD`(TLG z;C>!Amv?BhRa2Eb!PsuQXxGthmM7=FjweFNV*bVx~;&R)lSNY zL;gt4;j~TmRPv7fj$WhCt}V2=(Cf4juc2Z0a2Hot#&7S!_@v{D^m}qsazfE39;zqm zo0eb8p0|#<3AtwP>~GXxvn)>L7#QsK%{^=N+353A@--MMn=<4!60)}%vfCSrIA^~w zkTZzFxqDT5aT%qVU*>z=aTvYXQPJU3mRAOywRV5Mf6^v&=~hDhhFW>fyout6%Gr~p zrH{(R$~M`iqNmYp=Yf~1*I&0@9M(eYqM=+}T{L=(Zg203-$ztZLYe;zpDPxH=sDDtLHH0APT*7=R2Qnb|s7*g3m?mplTO z8n;x}a@JB*5Hz*3VKaVaXJW?YZetHS1y0yq5WKW8b2g@Qx3RW$5_A`#`t1lo@EZ0u zI~C<`hd93wq0&-Rp_H_9G^6BY<6z^U62+jTq!f01_FPc)k<@=q2Y-oBSvWh}3$nAj zxw)~qakJSunzM5X2neuqaItf7v4SI5ojh!vjon#oov44m$RF2vWaeb*Xld_kX=h6b zyRNZ`or|*w6&378fByS@oM!Hpf8EK}=|7JJ9*`aO2|Fhn2m7Db2B!+c-W61_bT_ls zeq?C_%meNr%Ec=n{M+&W5qgA<37eI%jo4!<>nT8IDj zN8P?8r+)>+1d1o*`nYrUt{0Zo7M?DTYh;D->k8>eY{_nFeA88z$z;avi8qp=L-kH;Llve_m5qSjooOr# z28chxzx+~hf;S1gL#Kc?=Xc|i!tY=*??cP^@gy-x82R2*tsTYlRI?^Rlp^1R`v`0o8Xh4RU4C}g^LE}8!}6fjUlN^!Wj2_w15 z6l0wvpHhas6ka29tTHRrf3pR!RKO}BC9f9SdXnUyKPJxf0N(P^oFS;4=p?*k+(;Z=vTUmmAJZ8Tr;z{)n~S5xYNfI@!A z@BPc;N^W!PO^`gOee#P*3=jsk_8@Ed<#A(ZMDEs+X;Z&&H;8x^u(dGG+%J!N0ZdaP z_1Wg%;{aHa%D~p-p?1GI4)Oq)MmJ}b_gBj+hTdqNGrEKCSI7PTav2U)JRq$;=GAX- zMhEe?#H!ZN?}rPKn6LNKDfRUFay<&4qbDiC9*)(Gso$@HR~V{02E}fKul71{^E4Xu z{@on{Ea_AT1E3Ga^|&+K7sH-rF8jkHwny^KYJKGmPMxZLLAaXfHaoq@-g?F5eLCY- zfBK@V*_D6c$_si!Y&#KAx}8&=WiFQEtcPn~o8>(l*b$OYXV;X8JP8pt$Lv zci}bnK)2bXS+agReYSU;mth1Ul4_&dE;)|K(NOvKcke^ul?00jI`>lkeKB!E+OY1q zv$!>Hbn<(j?djEo-JxGK7(YN>xmb)~cYI9g-?08R0tF$Ov7~B1@QvH<>_Px4xlDxj zFJiD!8v3Z&{C;I08>ZW=hj|3Oh;jQ%g7MnU-edz$#=XK?=flr@p;LCPB4t`tpLumB zfI-{YefJ}#501wT=h{q_ItYI{@@jlYm4fR-_;UDfamUZ z?VRYe*KYH|h_YB@-&(fcHHYig#NOP^HD6eiX>{G4kOh`n5qbXc`?8jBCxZiJ{$p=Fi#Nf;_Ybnpp)KF6-Urhr>v7HVS&bI% z^)i>eOg8itz~B7ZbDgAXTVKA@uo+UnmL+s`R3L_ZbA8&{0iKyKG@q5s#1&MN-9GM3 zKTf6=s>cm5No_tnnMPe3*ykUMU~fs$EN$mwF0C`sa-B5mFo|F#5Om!ln)NxI*;`Gw z3yGzcR^s$q0kcnjSc%(vGU#{BZIDwvro+rq)z9TX+=_ZS=jYed5)55LwC=#>!;)uj zcFt&wpOX;n&hkF!X?wu3+AjJ$%VTxuy=Iw3*l7xz;Jwd$bNJ+REo-M% zOObq09g7Eza-yQ@6dud5dtIb<_%mI>KbduLZZz-nmE?+n>ODPG1%FTN??DlH+RsyI zt;;{6EJO+Iplv~O#i=p(yhP``4}l6>geu4s*y?<(X`ACv5C2! zg_~JU0UPnP(BMia>pY9GtzStJ#~rYylBvJBzJxv&yV{c!)^PQCVR*;;>iTk5GMP<( zkqzy`-TdvEDK;|uHh9jqw6VOlZLlowDG973H2G^6C}p-&+?+wnFTTGo*zy>>+^SMO z>odH@8{{rIJ0J8TAJcRCe0DOXYlkhgRW6D3J@0tK{ex=#UOQ&NndyBZ&k5tuPTZIe z*n{4Xn7XdD3@4>o3e&+XktL6cYq0pDOZ2bzLdBL#5&LA1&_qB4YDcB;-t)usy^@{Z zTaH)GqGBiJCqyWgrton-+o~FLoZ2(VOVq%Ck~t~N?&@GL+_4q~QO<;ttMN;j@A3Qc zwJfjagewNSO@{-VXWi3pA`ftBG~EsVc~2FW#5mfX;)}{3Pir@Hn{iqA_M)uBO6~in zq9FFf^==bYBdJ@EQ`^&>8PlfKlG<4&&t7?!ibq?wx_ZGHYqiMo)YVE3koLTj-}aP~ zLx(HjV$EsRW36*%90XX5?Wx*98zqjNAxT{9BevXAl7Rc32WE{fRdc`*OFL&nkxnL( z{HMvB`eUcWny)9=OE}SNhrOa6-Kqr18G>DLfjPMd%M{gZad`>p6U~X77|Mm6#@#F- z{I!Q}N28MQ1~ES_PjON2Ijdk9#l^x|VhA1th?fcLWZg$cX8$xfyuay+_@$9J)h zs$rh#qOqe_cXIUMnIDY~qY-c%X%tVNxVoK52(^KC+pumtd0s-mJX13T*sKofBE^1^ zodj4iiu>?U*HzP1*yt7{Y8nWPk#dvh^OlsiV>mbqCq0S2=p;1!bm20qrm4J!|2>;H zbr0-;J)O4-JM!7mE+z!lGPt7*q}K=pGg9yi^WXv=nJB*Ik!8XX&4*A|Bub$RI+D8( zyH7t)w?T+j-AFah3KRJpUP3=HT4vZPzAF-FdbwR|I8T9R2|`5}Jo%~(4IC6XZ(Lsv z35^2mbVoJoho;dY1n#$%>NS{jj~CQJ%~-f!u{A(B1F)Fng(f@$s$5EHA9f`fjR-Pk!w| zsJKxc=jNHiV5=v(z8G)KujMS4(w51vt7xPC$RqjzZF*lqd@m-;zoB}oA%xWN zW_cquEifwKP}%Q7O*pzIo*p&CAn%kmKoubnc$YmE$tuQCD`Byz));Vgk!w!8z02b= zzk6k3+Gi?M7BVVvbCLMYG-zJk_d}OGNmZo|V(XqGQEv?N?_!G>pSMwQ&aK|n)Vp1V zem;T9mJsB@x8Wh%t0Q_k?X-W&Q+l?K3O}pwI!W7Nrlo@zE!$=O&&5be62j<{+Wag} zoy4$g~1;<$mwqU;S1LkLmsHJ^vrip7Y$(a?IYH+VLFp;WN_g=l;SX{9g z?Xp9A&BbE={fAT;6gZCuo?2VDI4yjk)t!%mSo|WA`N1J!_4lF(T{>)a|(=R`(YNO-TIWhXfI3lmq$~#1~oYG4m5xg@X zdbxGxo9QwZrk~dXMKzN1ZoA!-{}pG7iw3@i@%AmY2W8KCm#Th}$qiW`9LeS4G;na* zXumUO)q{F{*CM`WSCp3&eq3HOkcva0P|~>`nEORcN#X=-il1=!M*GwT72hf)Maft; z)(uf$j0T8fusmPVWITx-`zpc7%=S*LL_O9fTA%_ZKhFYF*&(&Nfv^*{2LdU3) z=2UkTL)z|f7>REkOUvITFJ>n=lfR_X(mIRISg=NS#cQMHOkfOKf`zmF2V%phk8MBR zB;~bH_Yvwle|Zb_JN~L!mEMW_b_>DN0MDI9M&3VKoFXhM6sxoMKHP2##2WlWFQ_(LsJ3SZ`$QcvZjKOr-f}R$=RpsLjWoU#k+@ zhF~f(9t$e$GW)b#?ld|z3r>dk6}~8`*0BEgQB2L3Q(15$mq2hm_=g;A7x44?{Y^#tO35lH%;?>m}Wxn!ILSewD(wCj5*h@^!~rFd0w$U0G;z>$ z?oWz$o^-h5M&~Yz2%bKcs!t8GPc^h@_ZSo=qu4Ah#@dBjG{pmI?iTj7EsbWFeCHK; zaA^@?1AR?=$7}MoJq;%dL%d(UKOubnm=cOy`PM#^Vvw2cqs(g6w9B~u(!oHc5b7!h z8IOg^))%Ns;nf|wFO5;;?yR(dZZrr!SVawBZw!HzT*V)TGdYX-|DF`J< zj(#_nbDwp@JYPhjpSK9G>1OlxzN>qqq*5LkQJ zd^#(15~9%O^Rsd$zq)Po=vl^?8FS6eD7+a+4&!Uyfp!n|3>YfJ1GFI2rntp4U;QlDR%BcWfwG{&)^8%@3L^`K8 z!{MzY`7L^6v<;u`j0j<^mUay0m$0B(u`lc4DB&3!=*=k>Q@12f~p)B&|-=fs!| z)kPCElA$=Ck5^6kpLo{C5?#1VlpB|bsP}9WwIq08s>w-uABax5WRiy?O;?6_prPWB z5v|9%?bNSz%~MIhJdph~#br!;iLPH>mc12JioA^xdTrc|F>h4HwM-+o-ii;!qWh`I z9Xbv-#?59h9&e1$^PQUL)GS2_sWsfk-b$7P>XZrDkS9kesu2xmCTfnI*jI1F@1ZAP z2;%wYF5Ri%IN(w3jTZeX+v7H6Q`?r4chpTC{ZdUyATN)_Z2UG{ZnY%Iuv6$g*H@C^ zQKWpO*3oTct=EEfH?Tb2eKpnmw*t$nsv=IfRbrx*xDGof~Jh%)d2uchfoq))@_yk=scMtFF0{R0tR$#=4L z&i7I;tVfr>^|_A6K@WXsx@`la5|IMsL2@e)8JS$2?ZYZB8SSO(5u~o83!%e)?i_jw zJfuzD$!GC;v+#&0NFgzqX-7vR%Ao+q;Mg$%OEPLaIx7T8b7LW8yCOBPwx6*lh=3c( zp1poKZf`v&y32zPeayCI@_D@nMK-9A`8DZKAq5-x>9!=%o!(J;@5c@OM4UH<&BEtS zt?jvO=W+iz|4}g##Nc>K?(*R{VST21RAcn>u*b_MaOguEa^yJ&occt^*Ps-VC@w22 zsMIAu#z1~Wf9u74ocQgHl!H98<@-rrzinI&U+0fIfo->7yoZ~RGN7GjgC(FA7SwTe zwQU)Ofq{fLp3zBA<2g|t%u|qcSmb}Qf6us=l9YF!cjU6hdzHe9WcGoO8|5M1aQyzK zJIb%kp3e*j?Fx6k$p*EuJxGDqlI~atZ{)_C_(%GE6JBr0+UD%J1m!tZt>Ou?gq)|` z2`Hf&`CIZ`FeDncGQ!xK_8!*lcab_tb`5iLO$l*rznq`fcbiF^t+_}wC_=(Ghogmy z#Fdctbx2-zfwLAx|N#NcO zl7)&YjN?YeeZj`)57XwzR;=Q;GDlU#W9O+Qpb52OW~Iw#E&`)gw8(bvg^voUCz2X0 zG#d=roLhZ=w5Qv(OfJ$Ly{5L40|ET;7Hjfs?eSsZlN`s!XL_5~gnFKH0C(}-Kbw?w zne_LY2g|_+i))yQhPJEiIlrps=Du=f0=D2VW{lAcz~Zuad%T|GbamhevEb0B=}Y)0 zkSBBomLEM6zF5y$Du2I`VyWwyljYDw9AJ7!_%KjZo< z%tIZ=lB#&zL+KV!TXxN+VckwwoNzRdCUbaHT1&ktutps%%!NhFMN`YpqBazJj6_`q zK)S6R?~f(yR4gg@qs&RR zVg@0!{pEs*0Kru1PfE?-u-5?3JCsopSdl3*-&LL#zveztd9QsdQ2t2DT9Ha761gHVe@8~!=BIUhbzrWt{c?Q)1AohLo)w9!_09g|$R zi$^jkLynL*0+h)EdwpV!MCrV+L(jELx5b=coBo2I*&fE_j8*|Qz|!7j{dOJLV3aG? zU>Vh{uUfHvz)!N!-xwh93!BYo-a$}L+_RQ*dteIE*WN-fy7l%Xv)?@5TXF0=90JuMH#q&-aD#cp2^0SNySR!By zJ;V26qhxBR1YZSmANk^VlTW{Qn=E=Hcrxgpp`t&o&M=e$EH#lb{#ljz4}<^nfQDjV z2gW3Se)x+6RSW_BvbpK0Me>u4;tzY1r~*Dm(tsE9r%wC(h{SyW8CP7kX>9q6S+|e@ z6c)C}B+G|iEU9B!K(e)zhUWc(>;ksL66Rets~Y-eoBV09(PXf?FB-^`e!=ergx~`< z?thK=kLLWp%7_6`Uy~aAZmz%Dn)v?05AZEi0%lyNO5VoRZcbLMEjtR(D`%0pE2Qx- z_JewDrLxiB&#>`_@BEi1q&=DkfDa~sXmPi{RYydt7Obee&wHj<`lp}&xm5q3@!&2d zaIKWy*Z(*ne>+q~4)`h~aq=&GA0plfoS!+LE9Vy;h>?KDv8N^1wergwR{+lnFX}J+ z)sy6bc$yUFQ2(nNtFr*#H(}yt`iVvU7?3z42qwRq5Sx0aNUeb5=ISss^?6#+b2HoV zQvLO@65SNjC;=-C6x^TdFT`1q1;-BN$#r3y5=lTXfeynKfY6Lv&Q~#!uIUuh@MryQ zesEX}LH0mB57l?un&8X;$=H6Ioa^j#= z4@_=5TX3ble(u4SIQIl!ver&>6<2hTym49^;Dmy#jWh(8f*gj&(J5zTO!g-K@o@js zm^@{`&a2HeS*Zw$tmVUU%)v0s^Xjzq2Af(s3JXU5ZrRj<+%>cVS4+tr%<+aE^q*B$DP$8=FWg?#rr z2^ZeIFYP_{@86#HV-LY1j?;Yv7u&W3@!$twIqlK<7wY2H z>x+ejPzt5@Kgrl(-U_iq&RD9jWG|u57eB<{$flMo#1rmExhG&6=zkQrHJm4(;l%mA z9B@@#5bBO>1BcGLv_VmmHaec4RmyTfZNSM+dRYLa37d_f`+59$jszAdcl*;5vbz>s z0WgXn>kACBWgK|zK~C(N$TP0zv{GVdRg|~rQ|FLw`v#QB877AxSXNT0 zf-wIpnEdTe3odYdMOO)td&uBctIug%cBbpsH}Y2i=chP(adWjMw(v!oBC>A`R7Cu! zrUoHQbGbhXmdyBeM~l?F(+{4FpX>ZIcm+Jix9D!8b}C^7C4U8<8ki&xjL&C{%L0rX zGf1N6%kl2T9;>PJFv|6_&<>bc(lyg(#=Xg0)82=l7eF=jJ1#+o`l-5wZlhSz6gLRFn?uEFU#}c`QA{|#BQyQ*!O4B!jmoz z)yclaHxGmXjx1eZu@kRZ%bN+#`y(PGo`PK3jY!nny$OBJIP_loK_5Fs5X!PCe+Qs0 zIE0T!)f}o|{%sAYj(wMf=-t*E(G2Hd**99`tItdgx7Gk%DQ#3I6%R7#g0_hY(~eLI zU!s)FSPxQkh6BF-rf2|Q=(8M=+BMzoil)dW)Vcy7r)djd=pT>)vdS2sIyf*C0Rf?6}Pysa%6proZd`^QYe9!LhB*~S-;?H$dL00n-|0=f! zK%Mq?!(MMV!5DW87$MXFtU*}2X1C?mdZ|x#eFjMS$UY5#tf#aBD0g23>I(qwj`@#4 zrY&-V@hCDr7f0xprB7YEGRoYh9i)l4pDRq){>iX`!r0!g5@1eUMpW2!GIq_!8ck)F z0Mc-LoCe@4L>Dp`RX*Pmadf_x4ZS2@Emdap+C6DQ#Qh`~@gZuL97c$F3pp%)vcKAg zLU+X{FZ;k5Jg><`1a0tkcX_{A+Oh!;}C) zL14mti}lR1YBF8FF{<3Y0K$W1SLkO!zM;uSw6?srU%CSpeu)YJ!dzVbaKgIk^WtSF zxhF&V*KrI66=?+TFL@FOhMt=GE?>|50>o*Wv(C8s=Pm%oq+9vvYWoh)r1OYkhv#Mq zp#kuRwwna25%7rkfYr@(zY4+;WIzc+OH;wo*};2FWB*JQq8b472q+ zi5fbLw_Y^?uKlov*(J;SIWW!j0=?L|?EGPxhkmMZ;{Ajo_nda-&sAx)l7Gp{Mzs7d z(_ov`?3%q@@{Sr><$mS@5W+-6_7XL(fZ2Y1OyXT;l$*e&-|)#Z3Rys=o4{jPUb`gn0Rs*UNROkiek*rDuP z5I@1Gt+$b+8?T$iw~ z$m4NdA0pa&-tjP+T*M^HI+(~W2>7liRzoY;?CWiYF|Va2vU=$T60g*|_fr)YGc2`YRErL2 z{KGJt)1+S$-43d@mb9}7%(jgB`hg<*k0Ll=<9^%FuF!6i(^j*44{h@Djsrh0Hm&9I zW23lnudNE{6tg7l#dYRr;RBgcccisxVPMy^-?iVubB|dB7a&BV90K+o_uRYp_@?{wq;RniqOs7S)L!vfb@j3N z^lH3c7TLT;vh=0R)~F&_@Cd8(*VJ4Mfh;y)gSu^wr^I^W_>s{nNWddlBdVn7Q{4MG zq0b0A$63UHLL^_y!1^O_H%)5?Td|{QlRAywwi_l-r&RnD9eB~*LWQ^O!Qr$Bu8hZ9 zliW2~%DWzP6Z+fcX0BeMd;;WQ81HyqGB)E>g|$(ZOl-u;+I3rd0*5qZ_6fmaK5>gD z!Tu5-kMRH@8!JL#kNW}T+i`ojyn(|YTv0TvY$dZ9boz{2Xi<)0Z7u6hjs6rDTiq8| ziS{B6DObjRuPRVjE8{}w?I$bI)b7PfqTw+3=?C7a>7*dmjt9|xF!}3g3a$s(A3MPQ z#)T7^9hK;#G&N)&@r6wlS9YhvLRdS6!OvJ9gIe}kUr)V*o!tCB2m=gL>s5P1O=Zh1 z5J z1*dYv;bv(gTP@4BR|l07@kmh2T!)n?vzoHL=#6T$K2t85Fqbo9(L_w1rFL(8@8hB9 ztd@Svo}rZw)`N7bye4dNAy#IEr7)&Ube+~4?5~~S@2#&@*JRJ_-$=tNsYCYLqTsCM zC0Wf+cVGOGn?YESEndkmjo*s(E_$NfP}ZA7ZIgYHJjTh++f0Zq%*F0T!jwX#%UBdg+%TR0k z`g7TzIlGEbKnRBLuvLslfyHs{R%KtvO0uD74W1rQu(!if))a^^t*0a`x!ADrX0vwa zerTIgzhM4K0I!41F=r<2KH(D1)$drAI5YB@!eXrFkNy5Dv0x`a3}_k;iq=p+J=B&h zdrZ#ADf}HG5wxfqGH0Sy3>e0Ouk~v@35*^XcLG`snmvQDc_%3MwDnT7l*Qu)9YS8L zaAz!W5aOMyJtm#1cFt1Q0EE7F1s~j{NeX9RDiSlXRXxYLwieFZpM|6itGFqXYQ-h} zce0d@SYtUg(E~@r$2sq;<)+LJE3*9Wp9W8haSEciP$9ADl2nIXZDo7Wepf9#G-C54 zvA!$M<4s+ds%YqQ{Pe`eTQO$`2oOb4cq|ph($sfaViwL7|EhT+=~WKfsQId=-MO1c zJ0hQ{SrMF^kP65DG-tO#^?Us8i{WYACNNzS>eCLeZxvJ_M0hx^NS+&9B|| z#VQ_z&0{<1A0Ufh>rSTqs8ifVLIJGXn(eY%fPlX*NR6Pg0m{Prj||=vE;I5%O+lzW z+ABB~l#us5E$o-ufK^U@?CMru!bQ`G9Q+?;wLj{(r_*){xC-mq8CQ?@#5EBZe1U=e zIpQ)Cbt@pKOu^|lQcND2d^fl-EJE_8$}NhQ4DK{<-u0?W~c+@79m0xcFgWBKa3VR z(P~QWTkUC~YfA~yHRJcjyPWr}(poeq)zg>z7WIU#jy*>y|C@S`&zk_K)ziP0@o1>{ zXT<1fq&o_^!->F-jDvi_UikwX8st{(Y&mZ{*?L_aTAtru}?# z-VWKIAPl%5fON7+UheUwxA2c(eg_;+KdEP88;W5ix>WA$XP`p$pj7#oyqAFH%aOnx ziC5b2{oM!tlUWn5YiSO$Wta+Zy1|4UrnEToi@c!+G>Atr8b44377&FeR&vnLM&46> z|NI*IWiQ~|P)nnyVgetq+*xlZMvPer?Un3hqPjdA;kR;ofFuNo4c7`l4 zvG{<=^S&k^#rFS!ho4J-zcu?qxbk_Dj#W{e@CqXf;_i9Is$HzO3GY5%_en0S4iFu2 zif@$`J!JmDQot46%8n3yH2f*z65Uflbye>44(4B+8zd5`E9xHUnnA8;(1ILsV%Q~q zNQj|L_1DEG!_y)Ck&2R4v&~+pAzX?sWYbF=cd=aX6`0jh>IN4ZWz%%>%LBBGeP;_6 zG$upNJI-4q_Z+S6oECVyEs(uav~dA(#^J9CV&K?Dwjy_5#EUR5 zbQ={e(|W3KCg~Xr2^fDE?SUbqUTJ>kZZv(CyNT-)Z^aeAqDP(dVY5V_axJujU*$En zkZR$NCKKSo5t2njSrsxay}e4j;D-Vqj)*JFfwR(0Xsd&L$ftz+9hRL9AZzlMF&hS+ z&pj-sO-HlE8=7~g3Hi7+S!M36s1ip$O_SA=&P3?0*n)3y9~b^DA`U+#ieQlik%%Wx zgcEBB;3H;<_=}gdgtkAZ2~!|E-g*Jbif9}plS)YyDB@X;G1A!#9fR~x>}>I58+Gf5 z-kkNKTX1+b*d?l_2wPTngTpy>77qD3%{f~SXByq2bMW_0V@YoCZTq}P;K&?4-R88@ zQD%Q6x@Nhp90c!aGwc*go`5uj8JfWAl6BSm8>dov+dDS^{*W*hV;6mR|F0q-KM&4@ z7*-V;&D!qB*F`U0qMiyKJj z<*}g=&zUOAzg@OdHQLAi366xjJtdB%Wy z5LaisDwUjmVExuHK_f7j@i?4GZ@_EyCDoG!Wznb?s=x*BKsxt;@|lgBUclSj129b8vY)P8LPXbHEIZjw z@p{w!)^Is2rd!>8H*(k6!|plX*l&ukM8~7yvgMJ;i((c}1!zNdm=vyB)GxKQ>!RCF z5mB&SNj9sde%j>;>t$PAA{KPEFg|HIg|#vmz0$fSS6kc-a2$@y76@~XSyz;W#LY8h z&oL$nDl_es)~}{bP$$eCk7|V(ClH4;Ywh}fQ2r~!1@cbGcd+X52#6tgGgb|vKDl8^ zDa)!+y`~To&G5TE=cK@{QpJ4~(rP|&p=sz-{fyI+QffX{FkUX-a-KZ)lDdVu!bU!9 zmk`WgoiwxcS(onw-$#v*rZT#xj)q#FulwKsl>&$%Z2J~tv6JfOyv;!6`*6gNrV-Zb zWZRp%8Jpz45z@5huCAl{MhVV8{94ZT1Lo<17c#zu9(+r}E=W`Nce9NZ z!>|r-!#Y2N93)co>0%&P=RAW|s!-$mlk+fzFxFl9=trJRN%E}sm>XG}q5SLzYQ_@& z-8`lkFev7(3es?qwF%qTBE_v}6r`)Hr1bRa=?XNZN_M8*_4{domn$_+&3`OcjuPZE z(RLC1V**R(1QY19mj$*n4V_-8Jj+%U-k;dcySM z#uhoxQ31MwbZf-Efc0JysjH`I3ciX_7yf*oP>~+oOYaQ|BiEGP+@u=iOZmQyV19s= zKo?@sL^aY2jf@yHnXpsVqV7{}9D@uL3td(&l0Q80{kNsOs}Bk=i1D76@bJiMqj#2F zcP;t`DJW@$ClC=rhjA!V;hq z7=@%DFldDb-!Bn_(h0GAFqNwL2WI#`VCsOHTjfwwU4{lAnMo-{z|!>uSa&F_sbQc) z#!kxfg00uZB!C%Fr83xs0aB*4^TTVwH^)2bMnhg;tH-q#EmKevgUA) z6d+SR4u#{>I85#pFvyG&)&M{v6-B1~k>L5yX;8>E($@ZjYtjxtM)PypK$b+z)_gQP z!5otn^;@(Mj3Rl!qzAOI70~;g#GpNlAJ8Nnu>KP-JT}n4!nuA1VENz|rS(Rer~QoIkBK))<^VvyT}_4ylU z9T2~@2fCq3($y%9WY5pV`ULi@{|q001HgZuQ-}f5djCj^&*emYh~Tzr&l?T-o;uLu zMk3{ZjxPqnW#vjHXecJ)v(=mQ9uYzekh-=^{~uTRvj(gG-m3d zMf^%^L5=BLT(bvSM#^089R68O{`Z6YXIMa*u?6%lcN3fRLAwrpa-V?5!E&4FaIWkd zQ|LR>#1+?F&tD7-zfdgz{SMtrpbram-Tu}oU1TCSYW05^Cu+qL?h6OUl?nSUfIqX1 zf0|Fo-}up=*!(}||1ZV-Gw1zZ6aF-4{C{BSf3*soi}?$P{}XVH8Zi3BZm!;FmKnSO zeW%86f(bBSZLt<}E!R_6ia>ec4NAs^AE$G;Wz8o#L;{Y_V5vnx*vt`ETGkqmB4ipQ zM*lGS5edle0Y+$GxhEbGmuW`Ol}AH+pzrwiqZK0IK7J7Oxp)a+F>@3IbpN9VX1P zeMsJ#n^p_+7?JSX8xes5r#gLgrHnqOMzEmi&e1=ApMeXVisgJo2LdLGydL9w<0iT_B#G11K}wV&ldH0UiYS-xFPfZ^~rf~BIjT>Gvn4yhUM9V zS!*V!yg@!kdpNoj4yEuD20GQ;&bJP;iASC+=A(-ezIv&weX!<&^WYsoz1vQb~K4L{w8V20#*{Qav*RQ8W8^99iKi~%~U zZ8!~^OUO7)9=Wf-3GF3#KYd;mBzN$^86wv=JS_T7o3DDMWL0bR=|AngkSrv@F*ReB z2(Yj@M37hY&A*f%&AtzHh>pau)B7=cB>VxYN=ZKi>jvC3VHX8ykNrxbW{8@y$b-EL zz!jo{+|)~t7l_hBLFWIU7>J!6Mquz37LdupxH4lkh<9e9_VENA}Wff{;Yim zwlR>!8wX+YqJd(>ZyofdP47O{)W1s(*zdZz-&F9YfM>*np{pqz#t-?Ah9o6{;yxl% zN3ZJ~DDJmu$E)6E-1Y$U*L#aY(3Bej=JEkxT6rB9#z7)0SjGYnCGyFRR#5G&AMX0y z2p#Rr2&GkCZI-p-fX1vR?tuDz2)b%JK&w6xtogtmde2Q^A<(8my+`2g)PUJPMG6d_ z22j0_{=m=y`Y?+`aSXw($f;^8Lfc&NbTpO^Ll0SZ)?mp#$bMb17W2kI*MJ@W*?f>G zdpAt2ZVS@vLDWDinE2*wX4jVx@dabI>xd#>=R7%lAB@?>5s`z7Kl+GD@e+gvPH#}( zFRY2(c$|Ur5JivxWxr4k`2A3DUG@yGoqEm~H^7O8g3e?f&;bizvRy+)IR!9)(k zm+9b(F@)(Z^9X60QKI=5Uva=71@b`e0Zw6S`9n>|V!44!iC5jtJp$A~Iox}RV ze=umynoQLx{3pPrNzQ{s`0CWOb0EZvX-qS23@APL10U0RM66i8ZwNKH%*yI3zD&vb zMlSzHOtc_{l_R9kjTS;CAE1~Po{8RsziZ(P9~2eoi_9v9VEJkgf8K=QY2b4#^fWvP zX>zQR3s_MHdK*|u!kcf?gJKKz%@E14Wj>cTa|B`Y3t*8^jC0a3N|xajQai99Bpt!! zn$N?UtCJ5+;}v;(nzORli2{>8#Z)jlv|uIcFwshi%KII}XMZ}R@|QJv_04trx{R4e zL_!S6fcRN##_~pe_5YAFa@UAAgfissfw~d8a2Qd-tXBgQQhD)*bY#cIyHIc+d_A51 z&sGn4f_&}AY8p9c1e!rH`q4XupY)qm1J-O+&Kaz~u7!ap5X$(a?=lnU*?;6m9Rb|V z;*}a${l08std~TNk@dwyY*FV0s+|lX>`FkDG{Lz`wNrPkUb(7ge|Rjobr{2uMi?3`mG{N-3d8 zcL{<@Bi$(7g5;3WAwvr)2+|#+Ac8c~Er^7GG`wqj)N`KuDCg_@;r=%8+cSHwy4Jd` zf9w^H;fRY92`_Mv5T6HxCeccqeg}k=ty;!y7_KmXN1WC34Sk!Y*D~)cWt3ZErNS?q z57L_B^&5AE;i%K;%S>-XYYas)?x#)8OHo>rEVvk_NsA^!_%zk}D_(bnK!Z8Q@+6J7 zyYU?{?@?=1y-z;A6Zru-OkZ_s_`(X#zQT+K1E!_HNgns_5F!s(be&+J7W?brQJ+5g1ip*T7}Oo ziRO_Rkl+$YZ1fVaG6sHKIN~hIZM?AIqi(A%n~I52P??Z8>;#mZ^k**;Z0mNXze2n= z{4dI`IOn`O|L^BosI(*kaf2nAvi0YHh>w!=wsDl*bTCsOAVqL?KlArsU^!puJ7H7( z1#?3%6>u)NeabueM_RV1Vj8H>`VobY?+QM3IUt0zZLxp3YWn72az2rkrB<@S{yskQ zYvthNE#PWG%cX#ryE>m>)U@>M1)@Xh#aR|XiaHL)`TWeU3C<98Z8R$;0TtpLyA8;b zk401k9}+Eup5O4}h9TxIilv!*$|JaA#7N9A!OB&%BTU}>PA=sa;=S-1RM&`o4?PdJ z28#*hmKq0vRfu+e>zzj)h&5OF)i-@cCE1uSCm@8MK!N_TY%A{hyB>kuRLpVA%P~fW zz#1b$-3vI z_QyD`%!76@C@5W_uck)15ipooU=leqJu57c8*-TmcN~T@Sxnr-H7_OD#50dic-Nlzf&wjo+35dv{aiZ$FR65q` zyApqqU|MUK0(PyEeK{M7E;Nt{hHIYU2#PBItfYk;_`SQS6r0Enk_P`!D9X?s*b zA@nSoE|GbkrZ(ccZp`bj#R(oe=SlyurulL)CT1w=j`DNULY#^FJlDojeMTWqi@!8+ zX&c2?ka>zQ1@GoXw`d{(}St8O@$VwS*Ln!GJI`Q_*GE z66}zlU4?A2roanvQ0pq44q~|myVV|)_*&;#2HlL@{tBkEJWZFXX5=s z2>t7j>!;*Cyk3w@r!PBQmuzYBt0ZYk;#+m*T8}(^vP+lBMdmTU9^?M>#@#OfH~mRq zt3HK5OKAW-Azv02;{4Onv=NB(2c5PC*ZnIq)Via#N8j}}U(B|8bn&{d&E>^iahCGc z(sOCdf9cVcFuSKM$79e6)R=Q{xC!=DMcs^y;v^fz*uV;SDypX3x-6RCJr|124mW3f z8_p&0jp2PdCk#fdZYWaAOfmmR<2}9g!YjE_b(8}YIALyn9K8dg{1f50&fVe}2#PIaM< zG&dr{_D|>dPgQ#x7*?HMkvAh~U31p{)v>6G05p20^5aGB`!UbeA z&5+diuZN?@_EwlKVV5NhZ{oJ6sL4CyjH2w32}Si6ccd$O^N8ZG=X478WlUtdVmYZ} z8tCgbakK3aD1R=bfI4wj%i%@5G1)#z09m`5YkK4$vVrASrAhWucwTZ7>y?1}f2}CL z8mLU&`FBWBgJuHhEd__aQd#z2-WTkNg(um^B)FX^Nf}(kPJQB9YD{k@%_$Ms1+m?F z=S^6zpY4bq0iH{9-%>j}I-M;}B|Nzwlrm!)OX>s@NEGlP4OoN**c(a+9%+ zS%b0$nOoE%lob2{PsQL7J%*784sH7wAi|8&mbO^*Fv9k}tb)eebn=*4%5Ca#e}SMO zxq?N5Cp@tJ=#`n!siXSdg4E+J>!_aNZ-)ERj=5#Qhfh8}%&#OlqhjhG^$0y*^9s)& zXE1lWpS%+=t;}E5EI63F?KqgB#4Ie5jZ0Iv{PyLie;>40z>WBFL3+VCej3W_ra&#` z+$I4Vu3EM`*9DdPl;?SSh((s$`$b3!2zTVSFo&JlY$H2t310&@It8Px+iI{J>bfm%IsSek11GpRBa|kOL@^6Np>lew{DXv6R)9 z1a?+m=|Jre~@McGa^`0~CPKAJFhsEgZtpl~@{U*n5Vw&TX_pNX2hKG58U zHgaIzTWsV?AHEs68mq1p?8sM=Qi*@YE1NLX%&L>0Sx{!Ifl!)?&_C|ou8fKuup9}O z7>|GE{ss|0h)dbt$N7#}wibpKUCKila>_^<(Q$tyni~dAL(PDCK^DJ03J%CM2DfHH zNWHjh8APro8l|-G@%BwX-frwxnjV_+&NQvBX7J!0U4wsy#lvScg4Lh)kJVzm-dx&9X3KrjL*KnilCzALs9#e<{!mPpnyf4?E@1@C;Edf zXBpxus8MXRwRGL+jadigXAv`7y)4Knd2_}$S)XBp2{bZXc%;$k*Ic{R}K}Px0^LR8ZttLo1ob8Pt%!PqJ2XK5B#D(M9^Lftl)yA z5v~kMpOh?xbl^l9itLnUJGvM)z4v<4r*|FS&zeMU#-=CVX>W)psnbw-&HG*uWhYRl zl`(}?B0?iX0fx+5_I@5QR4UDgE+}$a9OOk5?EZp=Is$JL$J;#jSx!iX-Z#Qhik* zu{B(ab0c|v_w}G@yY6yg150?15XZthPrB=~YR#`mM}j(jR#JVXNX@oq!fiTcZXUQi zfc@oaCm}CiVIKEsQTl~=+ko<^HxB6O`S422%ewrkuJWwn^WwDYX%}x+EGB>KOY-bx zjUj#XXfBIww3|oFQ9m+$(r zRuFDi%r--U`EIbfOLV^lv94ZdwT9(^-P4eBH&y-H!7nL4Zv+Njkb13D z0kPTQa=w58<%Qd1^6VhgcPKZ+V2{GYa!m|NnR1ez-ZQpPudG7mk9mJgm%O|Hext%VWB23Ufd@1C7CNIR1h`4RS&$5@QEY~VO%XCvNh3B3JMuzn? z_kdu6%VG8n|5-uOwEgdhgN924a0mL8R#2UCdkHZn?JwV*e>>~70}^(8BXopyO3cfw zpT$OTLU2z>l{>$h`y068`?dXNfNH()*oL@2wY>6wAkr!TX~0HU`m9|19~YYOLoI$F zDMIrz_IJx4H83&wp0&&z|^uRQe~({9!fy6K4Lq@u@x7zp=l#?Jw7faj|d0E-35?zr1T={1(en2Qvo;gJ9?_EI^Lu}ef0sZG_|vahZ7K++c|saDc%lQ z$?$sw*ws$Wha4I@^K!=s7X1Pid31q8^3R0ocfB5hQwU@qQvf)LKnjez(6g1ip?j)V z?`4paXo~ZlMG4sb0G^|7f>hfO>GNef%d-H8#=Q*O6Q+Ri6-Sja+3O;VQ`ayBvg~Kt z9s!r%66NA zf5OcF+^`Wm2;!xpd0(FDqRE)3z>UN&>)Pe@qNG33yZ>rKMidNEA#(wqz#6b{4TP%O zgUX`2#-IA1X64yP&U|A=CSNUb}NILBEoTDEdXi-a^pU+F%G8YuVWVm|E$17ku-n?L=MW_J~cjwcvL^1%gN+*9imQ z!#D*Qwu2wh;?R3l_Xc|njw_(kZLjkr5n~$QQj}?c;a(E&4O!HI$}lTs#xg+S0dM4Z zaD1#*TXV}ELyuQD-#|D->LS*dOosO5#}c$iIN|u_oq+2-l4MwSXFcogkmpB*xNwsk zVM)0f_~zZj)6pP^jqH)cHi=5`59F+Ur?9c9dv4#3N@QmI)~hZdFH$OyLYNeliMbCx z(i_w{R)lg`uT?_^6J=#(of2bNoq8`%H-Lx&UPi5xguCXRLv!o-2Q3@tdM^ViuAX$5 z$8vz^Sp;iMfD)s)55_4>7@UCi|9&Wfje{~;DVU*cQ}BCq#=()?asiZ}tfW59arAhi z_}Fv~5QyafrfrB%GXbX1wI-|8@me9aFlLURz`!0L^?rhljs5jgEzqyz!bwm!Q@I@q zT?+=`%)lQJP11X3W%w17C$ReyvZJD+dZ%tmIyhd)nObLS_=y}vJyNS+k`5?~$#p=d zySdRNHW6*&;v$$%Ikjgz2ejvJP+l{sWA)zNI>m;PURp*@tAKG42>~>lfHN_sA{kdV zYG>a{y^e6w*%?~#lA1LDaUus^xec@Fwp850ricz+Mu|8*Q;ggwr>LJolXN$96Ze^hg5vFU<1oK4AD+D}!1u`l5Z@*5%sRltV6S6|19{ZN*83$y zhwOXThFy;bit};Tj`H2j;zhfXuCR6{^5)v>E_9_U&&C;T}Fc5REPnRUtceV zWT^4jb*QU{pEDvcb_|{ZG5sL`62d2n_zg9z1Lharr&^{EjjW5lHZotJeG#Ws{q6SJ&{FX5A08dXf>U^> zlBX8T4_D)9KvM1jy>Q{m%^flWW5>j+4{h+VlDDte3LxR3gfYa@jBTrcn8W%amCSOp z)vOKT=OA6et}qzE27#ArQgbGFYeJst7I3%e1@BnuS?Yh*3oy4hew)#R*H**PkZ!$A z$V5Qr5z;v*!eoE7W&jfs+l46i^9TzkNpH99?|>Y3p~I-!Rl}}dIQQ#;c4$ejT=nMg z1!U^C`A?j`TVybJX?6o(+ocb>giYFm9vFNS@nK5)^E$9uvDp;y^V^}`*NrPKE^d3O zz5jf7PmrMAsHi64h$rWHm}&$hLd2(nBJQf*~Qwj83`DUHn+XJ|h?s zP+kn&K;fR!T5~LcoJZ;4Zdsl8(gFGTTZL0(^ioEA2G#LO%Nv~vMl6$t;U5y*cEr4k zxZRfe@{?0__Uq@5)u-wc&*yf z+@joc+;U-;AX-@O*SU_3*k?cwr5sAi-fqeL#C!%gUICwrcj2}5NKZq9xc%)T1OidF^01#qa!A`ltM+I@xL!zx zNc2dzU0{Hc-hzHMqD)D^c08qd9aIL!TnsziKVE4_4$Ds6w<_p=o0ekqhZvBNC9Ysz z<+46qYTB9f`MIFoq&VUX#Z&ph@*VKXh^&MV9w}a%i8>Kaz$h9_omi5F37sY5csGbH z^Yrv&UIN=uIb}T5Qsx|0Pr#h|TF0vOeAf9J$DNAqgq$mW6@aHUr<(Wy374t|R)Cwp z5=CICax5H9JyP5vA{{)*Evg#gxhqY1q`GO#vhM*bcY28KzfY0nPPKamF0RjNY-}V^ zhoOaY=;`Uh)$75kB}soP7gwintIHVuQK-SPfAzttV^_#|);3+|x*?il7CO;&!xp~` zoZrtq0$MwFOhWSa$pV~`1>pX$(No2W~ysqN_KC<0F1{EB$bs>P_fes@p$_fhWq9WtbR zOXv~qmdmJ|Gk@Rg{&PxvB0AM*6n{;o{Q5~hrUWiZ-TQdy|8AQ9`8%}TjF^6C4%bK< z|KDz~|GHK@67uF};>@Ijo;&SxqMgBj; zl<%$SW2SW}RM#8%%{_j7t?H)u+7RQp9_y3FHcvf6ZEdKxSN*=;i9PPqKyo&=6V8f- zRQEWSM1R5{i)To{`hIh1%ui;fZc*Yx{bXM<2m@Qis8va>NO_+O|v0 zd)4&x^pZq9-NqxXvP6_uRjV}`sj3Eqevr}lI5Lv#kIpn~G`cu-;>=n&!*@C~>P#CG zPvhlIw9eS=#mVA4F3dJFS{C3iJvkII;C0e8NM%w92qUhyb!Lk5L+7zwc>J>1LZW=> z@yv-WD2*47I`d>vb8eEGrKm?dQAsf9gxQbb`<`^?IIA$#^PJnC&J^FLlXxdslSwo_ z^C!g#Cx4&GV#>5k_mf6a_Y>mRT>j06KDITn3fnh!%$dSh Rptq08N-Euaena2y{{ed7=1>3t literal 0 HcmV?d00001 diff --git a/plugins/entity-feedback/docs/like-dislike-rating.png b/plugins/entity-feedback/docs/like-dislike-rating.png new file mode 100644 index 0000000000000000000000000000000000000000..0267218243ab67ccad8417f9c6bcb15e84ede7dd GIT binary patch literal 8754 zcmdsb1yGdl_wNErN=b)w3BoS1bS=%Ibhm)CG}20lAl)q`Qo@3?Gzbe)%K`!d0!m7E z*MI%~>O1$&-2cp-`On)_IXaf`<~}~PL!603K0Pv0RR9Xf~hL%000;eH2o0| z2mQ^KT}J}|5d3shP|$)YC@^bzy4g8Cw*>%HqtY^P^>hd5Le>|K6G>I&fgi#bfE&O> zvH(D_p*B8@xiCDF6u3ROL{LS*%4%friG`r5Dx?y-=BZM5*h@Jo3|n*F?^-kWq`vHS z94$!h$=dG*t#{sC+aiah@32E245z7%TTuc8dyU84gTZ#s&7{buNtmIyP9X%mpQW*=(e!ZR793s^DB<5)Gl_KVx{FIzG6<1MRKy!^j z77+R+N5-2YdDd0l5>--sYK7DUVgz^o zU%qB?BdL@|bF7U`6jAkYP4eKh$VZ3NZ*SU5mM^)TMiXy}E$*w-h&-mDEhx*C%Qq6f>9<>v^d3Q;ZcoTYS&jzL*1K>WZ2Y_ZMDH`eqMIPL<)hY(#xSV*}RH>st-R zsHR`!XJppzvZiczmEsQrSCAB%Tghq|4!i*9&98c-J2fCR2ta4z@9B8@fmr&s3&2{y zyof_ofJGR>{YkOb3s}`fejWxT#blLxV1(xf#S;vn;Kdl~a?%1sciDZS)C-v}pnCvR z=@LNUX@q+HB>Rlx8ru5v{%@R@KRIY{_PQSe<;30+jxiIdQVWLhGMm1|ZdT~f;-?@+ z$VF)put%(*1RePFfN4-l6k{3ACB6iH?&~Tj0}87Qmo9t(nr}t%By8i8$aBKc2xESF z;xM*f*zN>vG|1OSzvA4*&9Ipw=zn_c3!j625Os#DXaS1DtqYE|(jQU{(o=>-t8f&3 zD5ETs*Q5PNpdaa^+)(IR)S|6Wrs=?&9bxyLZ>;J!z?&jF(jwL(bRnb)%A_b-04{JV z3Pkn%cB2tgzGoBa(e2J(lSwg5_5`DZu#U+K)9bz$^+cq90>YZsh`f?q1VA6DjsPKC zyLNl0Y)n5fe7D%fBaWQtGXD9)oka`;x@QlIwIblT{tlbehMti-**t)$&#KlEnvdQlZHyBFV&wCaNT=ZUfJ11!htn zXd+qN*ryXmQ}UB#c_vcfsp5k{t7(I2gG7V5gVhg#(f8k|8>g zSW_A)%sS4h67m=OcaGGG+HBu`tG3fbVugNPF8xxy z^;l#9NPXJe@Pp~cK!Y=E-M9g}5}~0i>dc-1lK_kW&vxm6oq(cC&P(k}=i{xDd>T?B zBb))8VjMV5Pee(TzM{bHdclvho+yVTF4c`$geH>D|035Teg%4 zM@~Q{NCYm}ZWAGFlU1Cx18KD-&XLT#H}Yu2&7_Meo{BXlmx`f|zwVuVl)e7QW-YsM zEngjrBZH_yIhb`sQZ3`xD-T{OF1~( z)v_Jyaq4NY5j1#_5>xazeMlff){M`5!i=Pucvv8dEwj#7qdKR9e%d9$v`KP8dhAB! z%#}o%q)H{NUq};6vt#|$=&MFr$+VZ5H-kg7k2ha@*?Qd+bLP26#gv-RsadGm3Z4`l zZ2EFmp5I{^Z3$oe)cN{O=Pn)a1gZt~fKsdE^elgKkHE^s%)qt4W5rei>I0?kiIAk@ zh>pHl$3e~uo*hUP`7im$u`q{|*K(}D%3!~jP?ldlSruBPS&jC%e93szq=aInQhE^W z$FxD&%zdbx>X<6^Q8=3{m(-m6hNX|IguO)4$7lQSyR%2O$NSGEer7@5*SF_M7ad1U z$i2tzst;8^H+4OeLxw%NCrn)emTG@n`?mGBA1kK-=YiG|wJTmzv}AHGY&Hope6;4W z+`bZc`1s;Arl?$0f$R)lGrK=Cg3tExU;#?Oi1PuNe+-XewJw&9Z|N)5doamFk#xos zi~P`0)nPI2lIV$EYQYzRUV@VBRLPjIGwTe5DK*LC*B`EI6Q74xa>v9&)TUQU4)<21 zXLe`OW|%S*!Qy#E*=)$>Jm8u+)mB|(Vf}YdESMf>hDG8Potb* z7O=haW>Y$~tl~GtdySykfa2kf=Vu~IA{ULjhd&QXb|U6P-R^W)DnFZU=o@z`IQL&N zF!>z%`s^P5&~Gvg^c~wBm5qMY*4ZDdsgUNOZ!Fv>(Rz8Y@VnjR%IM1J)Oi;?dv_9Y z4n6DMe@*T5&dG_`kzrQv-t?d|E(zCzju*Y_s=B$h^LYWvFUPdq^`ZXS6B3> zCi|S@r|GIB&15}#e)UE9^q)rLXo%*xiZ43tW=?pNOcWjcaLJ#`*md7EYn9w{?Qbs& zJZmLuY1up4Bau=K-oLau?HN<4V68oUFF%obr|Q$=^NLXujoLnklld z*c)1W*7j2rO;DJcPEtF{#48b_|ihnBA%G?y6W;O-ms+l)ossF!d6dB z&&%rK>i&i2eia9&U6NP6aJE7=%|-h*rW>tu?d9ce%}Py|d>fgw1kgp;mCo(tw)0U_ zfm=eqU|%1*8Mp6yN+=7Kh6c{h5sVMA@mL`~_W(=R1GfS41p~oh_?UN5T!H)e9>9W@ zdm&$o0l-DT(?IO;an@VzufcK;vBz35zaupSZaHe7NzTD6*-1VK`wNPkPEi2N1OS#X z{e8+6{e2wRN8>pc4;S=$$PI?J;5{CT0$=j+#8DK8$3 z1`p{Dp<7-9TO*jAx;lUdP2&MDA{_xhG=+h_=+GAcfR!8pz(wE5(3fHX=D&6^AO%?e zq5&WOFv{sFz+mXRu8pUyt*e)Vo41yvuOwR4l%t-Jw~_i22^%*TkkvCcYg>??i~AoD zfRvvEnsl-Cwqo{kdG6{Z;U~@d7l#Cz{<92bW&VrB+gX~`NL`Cr!Ohc_Sp>un;%Aj1 zU}k2P@_c3|p`)n$PjU1wX;uesZ+8hW*w@z=MGZ`31p(f_!KWJ}-Y) zZ!14OS1-1IDEXHjMO!Z$Pe*reM>kjIKYFdK-ClT0v$Fm%^zY9<{IvCR{EsD9uYZPx z4iNlj2P^>M2mf0)T2$)Ks)UxKpY3yFMMoEOdeAmx1Vs6z{^I}NcK&1WZ<0p;krd(= z`@7`dcK%mMeJ@*21veM8NpG3|JehwA|9$hHf>Pi=k^e0d|48#+tLQw-5J-Xl{mf(t zLRa(*004>sn4+AXAI46ue=G&!D$==Gv77wGK`a5|*u&oeVWQfoUdcQ~e#Wx0D3${e zIyV;UwytF+Y+;N02{hPkBwEY&4`iSRcGwhel$2&}Ze&)QX7fDkOY9r%0!l8+pZNr| zR8(xf{J1{h)~??^@ojv3+)9-+1OUWjM)3jY`7tm_Lqa%03Orb#0L*SuC@O42jW84d zB!yIA;6a&bF!4Lmatv{W@%!Q`9m+wr_}M&@6~225c~9Qcpk3Mme&8y{ z%kHXJvS<&mZ72D}gh{%u2n|?zS6oG9oE}*+7{u*pNRPZA4S|XQgErJ=!l;PldC@V+ zvxOAAnJW5@6-r1BMG5}6$RrL$;W0ZDo;*B-GWP&U>j`~jN)(tO=%5{>qoql|@?!w` zdU6vsNb%wTVN@mw)+9i|Cjhx2_jMbI|4DUazwNg_c0ZPlYML@}PUF2?&kq&}zP+#? z2#U*->wH_c+p?u>$7@pm^|yUz@`sZt)6wJK2b$B34Gmd~udet89EtL|DtttP`u!mV zu0WTwd0){CivUO1#BpbT=iP1K(RZ7KEUrAiFLQ1Wj<=@4m&P(T20yDiZ%u0X%ty2; zk$jEczdXs468~tu{k>+bZd4{lhI%ej%;WuxLs8uGbQMPb-X9+Q42W9M;TnAdV?<^9 z>8y5O@Z|>ARZhICia={jjnDeg!Z~nL8I}D08%eTj+d<#jJ1?Ywl7sea$j?$;v?(-!pl!Dw4qZ|+em=f}8o zwb10c$4|lwHg>Ouz@3U8PIL`(TpEp$U|tdiiEo5VGCzhh1=t4rBLv*qPtvnQ-SU(U zRx>Q^a9{>I$S1g5{PnKbJB5*qf(f#>e)0I1X{*{r%2{mjVyv^BXA6OB4)^1NMO@oY zrrM-u&NKB}>&99KDl1Lpwkj_OTxIvWu-5i_ND`zP)J0}iWQ|WI4kh>6>Sk;+%%49s zCnp|C=MzFd0=WNjoT#U@_SIfz=f*^-CNjLYB*)c>SbT-lbQhgY=iBq;gtGWa1JjZ1 z#yMBJA-*Qa$E&UCP7$Wy>zXVf`*>}D3`|YO-hQ=g_vP9Aw8QUWNbqgY(cq)%%)O2) z5LfFXOUc#p@|PgTTDgP4^mM8^q{LR{?tH7M=6Q;yi~zXf{Jn8UQ1ejsdHVxSEF41q zIoDP=U*JG8$J(T!rErd0NArwLg7mP++;f|HO&|4q8EL1OrBDL!LrW(jq&0& zG*`{FWZm3OjHVdk%5Ylonog(vA_Z*f(x6WfuSIyaQJRm8nn%p_`m_M))KKAS?>R%0 zRJk{n61dE-m-`b$>7Rd+3-Yb!BiS3^%7-+~`{Womdlrjtd`Ni@Xc?-X_nD(@Ph}6$ zK;aP4JwwXg1x<7Y2WLzY(hByvf{i|PnFSpn41T_UjV+S=Eh~6)v!dE{IRJ!QkI#4i zf-h192|Rt?^r)Xxoj^>EoE(9(yyMHo;Ej@7ixoohXP9|L`QP1~&F?1ftqLY3=DoVy zX#Almd-E;2AN`kbrO1H!kX>2!J@3>Y`-4VUd6!5!H`9PF|FEWwl=H_g1%wxpUDc@peXUC^gN@nD} zxIiM!=8`Y$N_Zs+SBHlKE@TlOu57(FyBt4Yr=Ixr5nmbwjqi>jJ>>EA53f;L#G|wo zNAuvD6Y&M78o|~<#k{dJLkmX)?_w2^=nqsZqx7snHGT9YE2HithB}@@a1HH-P9;b9 z!7DvHw!D@0z0b?>W1yvm`_U~w%1lYrdy>xsgox50-^TgJIpDCsjpB?SDuKK*@Zd2e z>MRo3YZT-31^N}K9y8(K@F$?FilY}rzM3M#U%x3EKIbh>zxP!EMOcw+9q2p%BEuyg zDSowGx5KYS-6;k2e}K?QmRNR1>7_?RkTo>YINAG*ydf-yq4|!TCK!U#vi_ievuE z(;Cc*oMelZEQGx{$4arCc*-XOBRQcGwZqR15u@`zAyU51m)_DH*M~#s*K0EcI!`eB z$*L#T;>~#LUWc=5%LeC`RkKtJy>ostNQTSqvhuU48S}CLB?CB}BGN;_2vGqs)8|!! zIrr=~uQLi+eF0t>=jErTt@Jl+cZ05zM2mk_CvUgh-Cpfv%u{ZJ&%Q(kPfJw#={(Rm zU_(?MOB@Xg#YHrzwP>fRb!7f{b+wapR!Ota6^g~?k(8+Vc9~JH+(+Nj%p!vv5>+Xs z*>A$SHSS#9PK7x6A+xX*gLc@2`w3l@s#yKkDGo%mS(~aQ4$&Q?SBKQd*JQPt9TAyC zN0;j}>v+el?CU+r4c1sFc9XmMU6kOtIc)i?6`i!T2cvfdtMp_zT+g%35^*8EyJkhT z!pF&H8QwZw)a28aRqYo(j&`lHVI?qZ#1Tb>E*Uj`b{opvcYacMWcZ!9(5zjN4E{HG z0r&pqZnAtS_|AzW_|gkQr6fe>a;uOP>s!z~WKQ&i~izZ^{EPQrB(@;U6s zO`&{bK!bR+%)O8?o6jynBilLd5|u^{F}H8=@rJ{`rGBgOUGOg*UlOlY26}cL2!DjY zgrnhYx0hSu#vGo}3=F~72R^}j3+*H5jN5mH&la|pFA3~EE+|ZmDA^?r8W!mPzH#?X zo;>I+xc~g1pUI1pRYKC-KdAJ&z@KAvG+%ZR$?ue|X=xDE(b2p6_)#AE$b28iH1E6k zQmJCUyEjr@iQc%c8(l!UiCbU1MxjiH6qkC`)$=~{E6^g68~T8o1}FlL#4_%MUsB2E zsCD$Q8`t~9qvQxFIr{aU`v897)w^SJ=aC|PYZiD5-@j<3qkRLU5 zljvfQkjk+4`U?fP4yUlF==!rLFp+i;uPjyR`6OS{59{5IE7z+*S=rK0m`pt4rBLnM zU77QruXl!v?ZA|8ePQGrqq28xV^1u_%c-8IHI(Yuy+OvrqytCPlOJ|)g7fw6fOJR& zavl6^(c`#hg2z~$CV*-#YglaZ&*D{Yi##=Z_2KHsfyy%3a!-#IX% zxi)C!+UuVw)}+BwIB7@xxcf?L8?5IMll7WAs>#ulSu59`hrP?PmzsWhOLKW&2lHLmj?H?rIC;ODaljKvyC2dd_C|wx|(K4Q8(Et$@xH!QO3xLrC2DS zqd<^tCo-Qc(4?jJnG)B-B6EQ$XkU(=#4`o!P}!{QAt+qJP(cromYQnW!_V<@<3+b~ zca^DawUv~=~EN-N4i^pMDI z%TT?n#!0cJ+!O$*vwnUv8Nj0m_FpUp!fBkj987rOMl)k7Obo&bLEh#`bg!X3MB;Bw zjz(n@e)H@uD?YJQl-{DXbmR0GH#bc9{3KUGSVFT$m&<#${ODL!uh8}$!ST@0M8KzO zsg~a_sHd0aJ}ej~OBD45%%ZHH!Y6dEhdBD7A`WsjRPQ-+zm?&TPgfxqCaX=%t`XFh z-aemycj(+~X{4_+Xa*1t;#&mC&Yi#tHtr0E@9N|sa#xU{qSj2)q12zLdbJJ?&a93DP;6a567j55mR_NY}rkRzJ|uvAGXL(N%OhxKQFb2r7;)I5p~xw)N$c zRLQ@fFjhkM^OV1IylqHPCWvc$Rr;dUdcl0C0%-25XxQiG-@LHzei2X4&B}y5omcl zx@iEAnUoNXH8QJuN%5d)XXySLXF{W2os>5>(|Z2#zU@8=TzaKSiErZUT#?Yijr9l9 z8DbKOw=aF*MXfKiQxfYoB$gqWnNDS)ta&X=1JXiH>JRNMb|N<#~PaJR*dHKgPoq$iT( zj3DYyg8GrbRE;@p7Ae{+n$yx;6uhc!C z5p+Ii^FLBEwRru2&gpbxqW?)YWZ>%rPbv-xquFoLD;7YgAReT?VBT*z&aNv2L)luy zrjO8T%Glm`A_HXZByr@!?yYe=_*Bosz~A1*#l;TY+)`$AN1@*mPfQ{fhg|Hz)m+$c ziF%G5;t8kZeXlR+33A;hNo*=>dsTz>4Ty&7bXF5en}-ybMDhhJKy{(;i%`#gQ4kf~ zETtMqqu5w$gwsH>T&7rs>1F+_zP1dId0+OAW?0}O*gG`=xD%Iuf=NJOA?IVzNA;XT zmVIz&0oBy4^Hgxt5BGX1avVA*p2_!BcP4|3c+WDRT8t)zu6l$TVI@i*4_KTEuRBhi z%eKSo>jY!`Q*&4CnSjh%@1UH(5yWDNX1>L{h|(f59=P;GZJd09)j%M7hZ{pxhaq~1Y%{kA<}?m|Ro6(6;kdnm1h zcbQ9mPGzQ`t=ct3BRaR?z%Xivzbcuqw35~kyXH`oL7PR>+tc>51tBsab;hrz^rEh2 zQuK4^Y+?iHEKq8Q@_4C3)z;7Y_uRHv#H-cix1@xkjQMN=Pr5=ypapb5Is??o&BHZ4 zUX9fdgpH1?rO6&rL1B1&6JwJo3#x#Zjk)Zh?HTHcC?~+4H!pQ$FlzU+cSySe{3|Dv4x?goYLli_@% literal 0 HcmV?d00001 diff --git a/plugins/entity-feedback/docs/like-dislike-table.png b/plugins/entity-feedback/docs/like-dislike-table.png new file mode 100644 index 0000000000000000000000000000000000000000..df38883d2546c38295c3722beb771f1a7f0cca15 GIT binary patch literal 39177 zcmeFZXH--B_AZR5SU|7=(nUm+UZht=MMZjVK|nxigwO*-HVR5rl-@;p3B40kN`L?X zkzPU%y%T!!uI#Oz{Xd(-y&vv}_ug^#7!21=)>^+d>+{T+x2nnt=g!ifB_Sa>_vqn0 zbrOas6KWE{dcE&2V0;#~ zhEkV$sjkYMvVM7%yId;z6%#!@#rfzM0`KxNYtNgZQpT;#JBL#70JzGW7iQu zkv=cT1wpIVzjKqQDqN`f8pho$hPe~Pd;j7+x2JI$H+E2B97_E9=HG4z4l$U>ldN3l z)rlb`X{PTKDssQ|hDH76w;of(!=M$;SHtdid09-Z^G1cge=puHe>(OW?jlK((<{A4 zu+``_QNp9M1Vj6PKRD)N&R2&%yzvM-jZZXKuVrU5lA*4BbUASQ67CZB$5Z!|1XQM(WE(v5RNk4|?N*Q8Ql{B)xa?gh_FjYg-Oht21-FF^ zFL3G2wI!J5IZ5P6@jOnZJu7yW;Qp;C>Q+0=eRQm;p8ma#;^4BoeBu6FYqW0;YSJcl zZ&{acNg zq`AV)9t&1~h=*Nm&X2*rcZU8OOrLz}5DTlaKG; z`o?{Op~8XmhC*vmOha)=Y02@Y`*>yMw`F6Owl12+MfaF5-49uVPPSiGnGbt>>^V1y z+`(9J`wLo^FD z_q3bbX~CD5xsRc~SgVo*e6h%<)_ggfM9+9a;fp}WX=NYC=*4m}d!MS&3o~S1qwH76 zmcQOSaYyV8Md#IX4`~Je;J#|`=46FDLY4nAWy77fs%NkJO?C)A=g~Y7E=S$LoI$pG zM&eAoZ=M`e$MK9)^sh$b5=|~Y`C~R;#Fhf>r^nAg`3KwB$ropHjL6s!+m1)w3YQ#;N76$4+0ucZ{FKC!Wr{84{<_@q<4R9RU%gmkIdWS{9!duFd)l~5=PV>) z>8YBSxs=JP%BKm}sm;dg`DTt~zfV)k>C9NYcPZB@k1nm^9wc)5ep_<%Ms%K#yAZi0 zbL@^Pd5>W4*6+M}_9R}VUL&2)23b(; zt&QcWx4A92vr1`DEc*)tbJH;YgH=6 zecU~m_3Eojh3u1$G9Jy0cNl-mH%T@LH$m6geT#fucE95q&3(oIH43G7Bkg*cq>IbKTAz(WjKin$G&e&}r+xhP`yIr3S^Ki$i-$KKmY02b zcBlOhE^=YoG(M@CH-&GiX56mb5V*0bI!Xzlh8HA9bZz> zJ8zR@`*|v^yI*bKF;{F!>X6sH!FbUg&|yQr-cN)K-M;mdLosPU+Ix=vvyM-=HX%pw608ZZNB*S1WIW++|{MS#xz+S{u?T zGl05wE}>-uysK-GFctZ52Q59}Qi-bFospRuyFJ}KYn;sz-vD9r<+j|`*A-t{>o{v` zN-L%TP4eCrn^ROAj0op?>_d%s^Wg-K2VR|OFEqV38dToO4olKF8m2Nv>nACNzPVcx{bamT4it)A{in~+}mJV`@Y zhq|%Gw=PJWU#zldti3qKdMT>QA+0NAeaJ3xFmma|l3|tPvOTgU1G-gpv9fY`eVIz? zA#7#W1XtIokj-qyOe>@2u8z~3x9Wyl)b_Yax+E^G&Q{>L$NN)2pk);1S*_PB3a0E0 z>VXd$3q6&5Vch{<=?UE7+XX!ag-}xO=k4x==%m5D@pbE=^K}JvUhq^na>UjxdlmOZ za?drFEtyRPV_D5|pt`L#G4WL;N5wADOlB*Tcju2ib$s`N&3ai9I20+^*m&LWmg^^K zIo9LK%4DN$$3Dx39DnITPBOmVjQ6;k)C~LM3@PC)2Xy6(!-=Fy@|R7iBquN=PoXEj zf4_#m)dah9^JHfgX22&j#|LLdGz_JI0zzJGbKOT4 zN=hW0!1Za8WByhoCxEMCz#l#EM?!Ku%#Y+0@b5+7?_Lt=uWwILCmsKFeXN*x;~fq8 zM~{GiHOw5%&Fvx2!A_q`+VX%`^;&7_I_WAskuU?>@tQmXo0{{w*}Wh>LL%iR0bJUd zJDFT{v$M5_NVrK~`|}P7;F|a`-?giM-r{54gLzpR21Yud5I**wK=_>g9qYn?_}b} zV-I2b>m|S5bI%-N=4kc8$qH^tEfmfqwt@*F4SLto}8UJ>=)IfCcgq zzu^<$<>&kTZs1WV;-?a-R&M6DdiSjCfb9Xskhv`+BK7C}|M=!#BmV74-G4nPASNL6 z_ecNs)xSTg1u=J&2ipN-I?4R&XnsEY_b-1wD8)xy`ro$VuYLaWQ(&WI&Pwt9J~WxL zx85OFNJ!*J9^Jd6>2_>k_*A)(R=g-4qXd3;{_fp#=RNq6AHkE^GHxdM-b}hF=-WOc z$vF{p&Iym;G`pi_tZH(CI`jL9yYH_t-GwJ}Tz_@`?n5+TpJr*Itxc(-;*tGc4pw|? zp%6D>19K@K!g`|hvrQ(O-ml+fm3v8YjP%6m^H&eM_;U9|CC{^}w*U0~Uyt4-y?dW< z{y)6puUm9Kzf^U2FXeLa&|!Yg;Hu^Z_^8>C_}o8xnwqxRjN?Dg7Uvx!dBlu;aD4A}K-8SPb~ce>nyus|I8(*JhsX;@iCz8% zX>QwYgqWt`?hT2spR#zEHjwy)a9`D2Xi`xbJaf3d{P}PWi4V=|06$ryV=DFRM+qXg znNQEOC(l{xNQc4rkRu1Cyb26VLiOmA5#DLHB{ok)%)o1Sue81wL`E#Nu% zD!?vtdEltMlz0i8%5kadO4pCtf(T&Zr9WKlj@nBmIp9=|F^Ana%8EW$1SW1US0!@P zUjDx>P9DYnBDlptQL=ONKR%^ZAK(TBoacVfFm-)zQ5qDsA1aR$1%nh-y5@G31`F~p zDaYKtWziZ{kUxwvhnCq7oA%|KY(mQJGtAMJ9dT&+h9?H@XOyFOtLo`2<2pYv>`(E* z=xXly^&Mj!gimH?zC{h>r*2^^pVEiJA&kLI!4ajGyO%D6{#DK(z7U-rNns4 zNB^)EM(lRO8;x9twTzFNX21R~?LUD>cm zyVQECN4Qyt_>CJ+qEwB+fv+hZ^@5;_VvEIHrhAKJp>VH78`Nhy%>J~f*#{+&TiD9! z7@Kh@W^Y7L9RA@5Yv@Gb!^_0UyL7>Pxy}GwQv$MUj}zaVDm83!so9y1-MsNkta8L- z{=Q#;RzEP4@h``zg68w8@&<|xM3!D2vXr6AYL}rTZ`Y^ z73Mj75pr1SrgrW+zjHP?GGr)=vCM}Nvry@4l66CF6T$Bjjab|#-#ct}>mcjjUP9r7 zdvw`AUYp%f!ZzAP*n;;YKDb*Qyz&hc6qfCA757Yi$<77rpVSJMCG4ODUW|TelCwkc zlyR@04PlZj-AIG(Ohqb|$awA6A3MdUn#hqa;Zn6&8aO0sH&DEWvd=B);jDY3y$6{= z@0&-<2jMa%SWdW$pQb{kU zpj+D@eCMXI=W0Xw)(CVW*`GO!GI3dYFhZJF6yv$xRKbwwF_&3B5h6MMniljX4pYbp zJD4}d&R0aQ%T7yuWK#&?MmjH#)GWaESCM8LGo4dA+DH$MLzU4d;!O2skHPyyFHxRu z>@FR%cH%kFT%o65UapC+PDL6syEDI*Q=n;rVYA@~56zvfZ%gd!F@SXQXy5a%cwJ(m zXA6!@HdVCemPd4{$kuo_v4u)q#O(HzwaDjyb9fkChaAi)>nT##BDE*XvOIRq1$s`2 zUSDIl9BW@W>$z!PKIV6_R12BlHvZOJVE$QBH0E2=8d4T7P>4032xA>;=14RYnOaG9 z&ox&Q)Qywz@;GyL-IFd&gqJSNd#ef)yifBG!VZA*_tf-GQ9g8agWJjgE`Yr#-Ynq;Y+M@F{m}ypA2` za(`nSs=&c5cFdtib|Oew2uik>j@Z?OE(bC`)XZJ7!?^$JO*QKE*kh@kh2%H}8 zqJQR_AU|rvw?75$Ai5~ET(yj-Y6AJv4NMgPHj=kyF>BpYrA`X$eVok~RkJlxwb1gi zz$&A!+;R%A7^STq?Tgjx?VEA}d?R9Fs6E-eg`#=8_K_$msTH|1Bt`xf)FVs|^%u;c z?H{7H!fN&l70fns!!|Mz(qWBS@FvHi!0pu?Gz=jXNx@pAiJaO~klpQU0)=XYB}$)z zt@yJ1Ah4l!`$zU86mc<9^EpM18b$2BO`NK&IE?q+Vrtn`j{%rT-k&nq`(U@h6|o+F zQBWm8s-hp#cWCtB6LS4sq8^{^z4C@(g|7EF8Xedp92ija)Cr{!+uriYn=Wh*f^Nn- zYF050^UAWJ3tKp|KXzi*)@K+mtW;nVvauvP;%lt_jOsENwA!M`!1I(Q$_L`~33rot zP6}RctyF{$VFVmluU0Y3BriYdbX`|ZdT9EW;cOV3nBPLa=le(zDg)R z$B(})`F^&l0KB5#BDNd0GbNj&B+~!cd&n6;t&Kt7Uo%qPu05k3PBFF?=>#g{{BT1l zAQp_M(C67(i*(dN0KPKPxUwPvNx+rW<`PoSCh|g>``>60s#%1MblKc8adfowvFxzg z(a6t}<^9+MsJ)^4RJgg@zy>(@QCEeZWO$cQ(g@6#_exoQt zEy1YA&TtK%_2PD!WoWmxaw`SfI8m!%ks6q<5y_PCT(0;2uoa@wrmp5?W>&6Gmyz{H-qT& zy_SQX&-kOBvp1uM;Z#6(DXwFrr#Klng4~K^Mt^bG?6YPtr=i=}>r_j9=k~c|?RnIM zv^-jL#4Tk%47F|vZpgBnTB=$GEvH7ZKEu)2TJ?i#53U)Lb8TT@u>BQ(S#Ifb*%JLW zd}Zd%a)NeQVIRgsC~q;KlXbhT7WYy@W$1}cPh1Hn(aNd~$>`4#wVHV0_#;DY6E!8O zhX;1IySHe|+yyDS`9ouVFzfYx;^T?1bw!J{M1omMucgd-^sZ+lT_xw?VQq(_&%V^w zOiCzd^h+EiKmgeL#Fv~C*EjN(sa|blKz>k>(PN?JldP;>YvI}i1)AAtKx@|9CCw#r z_id#mwF1t=-c&|RJaQV9r1Vd zbemVQ9GZ=v1S@(UH+7HPKN$((@}6X4xfR)>x{8%0xa+m67I5}+IjYq@&Gz8&LZ6X^ zP+<1i4a1SlQ0}#G_S)fsuVf4#P44@9UZnE8oaB6J7@=Do&K{ zFM?s&l$o^{z=pQ@1@to^9HL@t?iZ1J;ZMa9cnkMnxTkFdt6PWe$xINb`2D`HkJg_n z*)s==m6bmLJF6l*T&+3ZPcD#t3xx(VxH3iynm^v*mc-^{%glS@`YlfeD5fqXQM0PP z_Seeq>nClvZ43AzKRfZEsqY`tFse<)QvH|s{I^@fYLm3@HRnxhWkf;tr$lcSD!Nc& z^up)iwFrIN&OI$1Bdz7&=u^{t1B~quewI{ivc=eV==Yu}dUgxj~tzZl&I*Tqu;l3-k z?Ch_j6>vQ^hJw#qci2J!FIQNhk|<-I@QtFQaG|(Mc@;ReD({2+so1*D(^tCtg*JdG zzOb!5z@;v&Z5Mn-vqLXTml zh@VX~#VzzZd_764=?_ftkeE|0{rqz!s`^rrCbVzSkOPv*-0er2T@%_dTM#ncYTYU6 zn_EF|X(L6q626WL zAQ?559irspwArCb+CCQT>Dvu_-U9Rl(!6g?S>6T+%h2|$Q)ZP@Vne|wnZ1QBw-Uq< z;1-*7A}E})lV1p_wwhSV?)9S|2pd164Cd6#>C!tiLzas@{p@)Z8|AcRS#VusoS+Rc z>>C8vN&|s%=M6iE8mS^@hnTAE{&IQI$v~px9+T)_)J zjP#}Syv5#M?$YR+6~EKq%@_BtJ@}C>qg4tnXrOUuxs_hO48%f$PF7?AEPH)O8nGLq zjE+sL4!g7IkzV4pDFC+}8ErQb${@K-GqDxRS&f+!R42Ph|F@pvuVvmA-mV)qH*mvTa+f1erS zlvf*v0vzm8Akp{;UPgsE7ouEnr6~0_y{N$$W@AonUzT9`2FAcjPInbz$gbCxtXmW; zo<0Ud<(D`T+)Q`ajk3Q!cfX2Ms{vUD>B9 zP}|+nOe6Lq9=5AQvCm^wKj{hP#{y}*9w_7?G_!xMQj|Toiwr)8)4Uy3@Y;6NMYfDFUS}VTiT;XH@9jDUc85Ux|w29 zl$m$Kek;^rs&vpkTc`Q_s%Y(wl9#lshW$RBN6Ex0k|or0bG{cIq#v1x(P58dNK6@6 zikCAWezs5R&+` zUwap?e3_K#{#A(o{gVORUfhr3v+SYX;EdN+fs57=7{(?YKk;r)uf?6Th%`GoDf5{K zGa;3DiINjOiXI7!GQ!ZURJ9Pokl04cVx*ztqnh*~7W|6;#c`h5ib&@g#y|-uVRLb? zY{S~~V6!)}yvzhg^CYDjv)_l^9#aTsUtCy|rsm3d@sRF6m?@TgAQo3h2~Jx^_SC$cr2Guu4x-6 z^L+G+k2!B`T8VwlX3rH#7u&A3p4ii$y8y9c5%;vYF@?e7%Gms!+d$#sm*?nha@0ba zu5JS^6YN;5b*QfYiE;Rt^K{thC3fu4Ty_JJcsAd{Wv^u@`BJg@F`os2T_6>b0eSCC z74ktj>=8TD1wabl3s`X2HW1SUE3kMu`Apay>SF$i2XsqGr!@^r6Q*nd+Td+&=|EQN zRHXb186a~I0P?=67pd)DEeol-vFk#_faHpV({q71DR;*pI-xWQe+j^owx1ha`p^4= zdYDuK;RI0gPTv>w|9O?iNEfw|N|HZ~sSM74=;l50#(My;s?7Y#;&2G)uVp=llS&WR z)D;IF8ub8Sp>Fw?vf6{i*UQEJBtFUsEAihc z{dbrCkH}I-N~$X%h2K@ul0RL8SYRToO;fgf@gY^IIlst+zNDkd@HqYiP2r%L@fe#ty_-uau-&e5AR?Z3_FfG%uD?%fqzNa4!#&w? zKwh&wMg_Y9M(kL40wFYf*`|^o;C;61Ib_sib$D64x5rj}s63Obx_5VHI#bNB@vb36 z^iIWl?Zb9gB3={YI+vLqVP*_~`C_x5KbSTK(QSJD_S#%`lN3Uk9j2o#BNPGOi3#jA zhI#p*yq6$}fkd2~NZz=PxLXoa7^43~%2P>SrUki~WXb}lzu3;?2eX-u9uFE4+E73xh5oURa-MJ`9SNkHEt5$FGR%0)^c1rN0?Gm`E z1~-r$X9FaD<`j@kzT-YvWXZ~Of)ipxd+ppM5}A@ zEW6v{--my-hyY$C2wSMcI#3U$Y>S{sttd%ReHBzix;{D~=se6btrC1t3OhDBDYP8NI-Y zb8xMQ>lc`qpL22m0BJBu*1P^{BQL0TryTJhx3_;M+?&ZIzv6&a7{XzoJn-(e!`&Bnj%5J)p2#dj9B31=Q_#b8EPpl{8YgPLmS6)xbn(Bd1@?- z`cmalnGKZV*L2$jR%;0d%Sdr-+$BH;ocFhpvLPis`dn$s@$}+S*}s?ahE(2<;;n|V zI6D9!ohO2xMLwn@Iz1>pTVY;4#I|XXF`11aQt+34q@111pb*#eq@+tU{$`yg1pvbZ z_}zI0?}U;zk-?9AnOOcc@o(CcUIPPR8n|Z}(TR%j(4`6hs|4SMwor(!D{cp)q6ExL z*Cv~TMfHA_DirHK#n+1IdsX(tk4Bk==#8ET#`3qui`Sw780ONS7?SE|a>o2Pk;$@l z!BMH*nG_UDkb86-Mxgdq+OG&q;?ozRu>#|!W5LV-{b!Aglndb@k( zH}NP@E=S!mb$+!iJkH({fKP6*nV(}20U*poy(!P2ogFRZuCACcAJYiNJ2rp?hzE;x zH)7io-tSl&5|a`OLf+qZC6#oMQELf5C1Tkq-;6I=$Y1OPg+u_|)j zF(f$=qiSGR(mnoOf%z?wmPBoODF4d&bVo>c&g}z?o}@NFL2mfmuY0@%vIrgKbs*m^-FRx)m!GLP7vW>>ohh9@+H9gNyFW&Sr1DzI4e@l-h`1_C05`GU zX=ePjfSK#0;zKjQ-ZJ*D^P`A(z?XP)zHfjn=b{uFeYtirH|rY!vFKAB#Q4Fq;@Q2> zCYtL)`Eel}1Pj#rBBFy}mo}9CnFDQ<=NY-;3m?09-bZTb>G>XlDL7{nxa_-s1A*dQ$uviZ4{J$RZpR++QT1h~sYM`)2IWK)pU}1%auQOs?kuZ1F8(!u#Do zfB=#tl9X70vdP|I$qpvE*OHlEG;DtB3Hk>ijN)JiOO))JwQzYJ3Od1O4&94~;20h3 zCj|Ko0kHKGP?DGGYDyM-_Lo_dKKmq2OrX+rnR(~_YU)m*Th&}KowXddG?2+YLaH8fa<39b?)Iaze4zbPJzT{ z>e^LJL*5+a$4A8eN$bR-Gjx#?$B_wjAdm%D-*sEvUlhb=AHKw6dxY0AB!P}9C$gZpsAanrSJ+VLqQfu`&LUz=jE#avLA zoEUJf6eA0yDArFrcbc~c&1FLzO7aC!%*g%3D-xdT>aJKe<={K={zx!djGHV+klRIa z*O+Zk%xiAaZ5lB@k&q3$AYAOR_d7WMn^X90-k)>%03QGT*3xiFa&mID{y>Nb3%*!q z886^e!(%#l9Dhq>WcFPYKdxX#cDv@CebI0T_tpoK;S1>mZZf#cwMOanrxYNF?-l29 zy#jm>v>|7<%XHx5+tiV`{-W{4NAQNYej!D4!#RbJ09xi98!6BA`vUniB+UDn%MFix zdv8i#vP8$Ig}84mJ`z}56m3~UAPG7_QZpYqa}Boi-)*Z>7=Te?Yvi@ui>R~NIS6mP z5yC5Q<3Q|^=C_uS1MLv1gG5ZDM@eZl{+n565twlC$ke<&u~sd&yl|4i=v=l3~W9sN_c&^?-^F!3=;~IcFEd&RXvAH4_}`G zus!=#WRVOFID~~^u=j2gf{QA|0OqPaYt&z(02jlzW}Bg;Lqqo92QYzy__8_V;k5ZL z1-Ni>Kq*6PX~$nNDe8^*z1ddR^u{EU`3IpRUZy3^qJb3<3uL>3XQ_SMynOF)HHDr& zrtkUK6bGIrcG*RfZtk|fqSw@0==iE6U#KX^D@`pI#!X3wu+np1?Ua0+6vZW8ZS5D( zjmW|s?4llzuWC$J(lMQ-pBnvvfj4@bY26)Xbd{8O-JJj z@^E>Qcg`V(-T&cYPe;wh^PJWyXV|ifqjG&NPFlpGT8KUGV5c@*b?v2!wbho2 zPm@z;n`NzQ*QHI1`{x+hXxL?RF>04MM2lJ~dpWO_7o;L5yS6|Kp~JZJLTRY#^iVLk zdd;aO;a5C=sP$yhBF^~WR31%=^1gBq6U4?Av3Kfm)Yc>hZ)nI;u`}K`l>rMmkiiEF zzMAbAi$z*gG0}x$9NaTyZ5pdmM@CCTf{bK0USAQ~{p1)D?w_OOrxd@v_Mx-mpav8| zM{3dhMNmBBS^}kStu1OlLB1XhG*e&Zv2r~o4?kS3wsmnDk1iO*~xSx zZ&QCkn*ryvcU<8F zJP>YXaKpYMRkBn{q^T?GD`_3@G9d*1{^3+p%uTTG+-Y zgAsCS(f+A?UH5L`iDpT7P#H&!w*6v!GhBhvzj8^tD$;CicOnrgX1~7)Ypl}17!EBC z9>p0vtsrmB4W=2$6|sIUFE8(2vhl|`pvX9`tlU@dNo#N1Kz<^Swi_C5(kvQ7>J}#s zjKxGj?sFsMN%zd2bb;8?y6&W~7W5-mu0`G4w#Y(y= zS06NHYjvL-DM~j(&_`N4bTjKFj0(%rShXZmj?q zZ-Wq8>QbbUOaEGR5ac%kSuGd4r5UF_@9x%XE<3mK&itib zG`}9!P9i>R=(9Da{?GmT+b7(wf$Z;A2jf3i`CBRElDN*Crmp(lY|-y@n7asqIl;a|{5m(JWW5D-)YlT!3N{$5tZGaj>@)$`&H_$rc9G zYK#N;P9V^(fdpXVYw+F_g-~_bGC&Bu8~_Zcai{`<68EQMqG#D@QZTK5b72)Ab&$kn zm%Qj2;j$q|6tQ<I#(OpH}}ymnr+^xY!lco||d*D;9Yi2XS+ zpq{h`AiF!piUThxx(f{^3whHMy*V`@#l@seZo<#Ap0%&Y{pJk%gIDnW2q4;X6<2dRNL|B~2;r!V?0VpKr*wdcO zb6fNP>j8ceE5h?9^TF&>0qaP*Gc|CqyBSE>4kf$+09R>ZM?nMd9z)VLifcmK0MfqM zvPyRYqn`EyH+2&j<_63|Yk5jRSIa zYftD)D~{Ob!p_*X>uyXZg}@EipkfAg{wB5m9v@aF$+_gA+P#=uw!477CRvf87j=J9 z7ep$~{gseK>l-2k#cet23a~`Ta2=3dk5IXRbGOz6z!mVaKDBRM;W>`rrkk8P{|TE2 z^Cp&s*rNFPq35)x0O<$@XpgcJA1ipETnRvj3V^Wbd}MyrFTVzGB==`4q96SlT^BHI{J>4~W&G>{r@?`!5N} z*Kq@{0-7Bxa*Dq{elN`_biECTJZlN~Ld=ojjU7+NbX}rFXg%Zi;7IXUH9EqNV%r~b?iRFSoM=l+)MWq4+ zs--_GyoKHL*qo#8&*n#ce)M6^$28CKbX4-w2!LOVOx6;5mGhW6RzA}LjN%3=O4&o( zzE`;}TYosb#_y-yS$v$-Cf~5IsdLh&t@+v2UME-{HttQZ@3%Ch#qzh;;S14y<&%tl zdb05FG1GQPU%4iPeHzcL6bd#Joqwj%l&O*4BPzS{<+%BkZfkjv%8`aq?ZkkTW}KLV z>Flv6Ruk$TyW-9V=FIiP78i5-x`l%+;Jka3AktVSL(Lbu@S)bb%$V}Y{XjZZ3xl<4 zpa;x;Vt6xI31UoHQ<)*?y}#X*@Qz55)#y`(4&2VjSuXyUJwL>a#FIPO%;TmyKGEG^ zCU$=~HUUnpfoPY^kRd$DW4UD`^u!i|oU##*)J$>4IsD!-ONEz}qTd^$mQ{c#B|Uzq zDTH6;_ZM!fI4|1w)E8jvq#t)g)x|Iabm{w=bJ@v{X`P3O^>PB%KQgX}*y?6REXn|E z@$`H}dB#K$?F7)s#|RK3dYZy}N9fGy9DW~><;!>|D)gp$GE8wgR>)C}qooue zn`dWu7c`uF3&L}4KU0u*L7qoLK&KH$UafLsrRiSSv z&R1M&_KVMP6#pkh$px#@Jz{nC#(Xayv0nB&8$Z^P*bY@x_EDM);$3g8++e}Q^UMrr z!MwI?`N%_*ck;5xFZX}g{^{NzjdmsWi3RgPI)fh=y>dD?TpNoO!290607f{^Gt|)e$vNa_JXl9Fxa^ z3IfTtItbfQ{zCheTp6{)h2DQRnEzv4NfSVCvgA@xm*Y{<1Q$@RR(?0i=+&Wl%U_d_ zLsA2UCPS9#Q%6qf4G=56=C3;a`$+$J;S<6IAm!y~Wz;XW_pmqSoIjR4e%8e0!ch}v z(gEsP91`OrjyzOW0CT7Qws7sRVSWWr5_tgTJ|QE?b5!n=e;0_&xL)<&{~vq&Z??k8 z5Gd_Idb#NTB0Uc~pr@|^-a+SdQQ)uf4}0TGIWX~%y@leqBhKZ^*$d}6^Uhn)9%(xr zfJ!2!t$r)?}=f(13k< zlmx~b0}{BCSRi?1H$EpI64~2~PyS6*{(ksL>p+2|Btgi<|0prlX9s@%fI89lD9v&5 z21die8kgQ3AvSW^fGFpVL->Cm|35E$+W7!Q-ADH^9Yw}H4+k_y%aig~nZw@~^=rKy zJAnMf6X>eskJ`)Ji@+~31fahjwE+^fL~cyh%=OSt$e(LS(gGAmdsRH@s13l<0`?4V zxj=c;UKRtT(|w#Wr;f5OGyA}3?S!CV)_-o{?@xTRfduit!t{Sgm?Z9Hlw)PR*g_=d z8+C2EjPwug;Us6FQ-<=rn96Rf_0kFHy$wDrVH9RKFtlV|$pe4S>)uA~K5XuBN%_Gq zsr+ZS*Rgbx`06Lr4D=DRvotP+e!BQxt0nq2I|E$?yCYr0byDew&)?T_idteA8kH5i zWkAr~k(rSq*PuT9%P0Z6$5IDnTocWMgdYp3&`qOTrIM3fsaR8>Z%$Akp=v9}?b*ib zg2g)=$o$Q+w@CXMF_6b(kK?`tl#!{fY(O%ha=mbOhb*Vi!?uKQM!+pM*z`M>3KE0g zsEOKb%r++^bt`;a&naD^>C9C?M+uHKxJ@=<8WltFB@5u09_dn<(N|XxQwg1}Q(9)< zv(fc+y$75i7RfYkyfy2xRd1*#`);n(GlYoNUiOxseqY6AhDzh^Ak%p-vK;lL*;xQ( zMuPXeGQa0SL;LXWG)&`jaY6k;X~;U!IAf-Pg}pFPS--E{kyh|wQX7;Lw=m47ZDiTi z=ZOyeL0WP!5geHq1VFcqO?Aq_=Uk*dt7#AlqF9H?BpDgOJ>RMo9vGh=uG-3Z?V0$d zMAXapiTlB8N5p37Fx>mg8~x$x#`;KRICyaOI6>bafwpTT=6u})+e=W`err>Hz5>sQ zq2);egN=Q)S@lZCjN4p@qSuMUdUt9Ad|5c<&U^xu;68Q`^O&$QII#MHUr}R z!a?(LV~f0hFFKL@+;C-sJgxo!)^vM;l?Fm|c zbUByxr~kO(zKu1VFbWOu^IH-yA6G1xcu!FGld@YfxvHYxgpKGd?P4Z}E$;c}eFVuPC5^RFdcybap=fUcMPU>q8E$&sLPkW`^@UomfR;f(G7LVy4O{gSa~&I#xK zQk}$ogVq?la*ouq_?eLuos{XGU7Ge-TG-wM3^@k?%3b<1Q9fh(C8NBG^73VlL)j|B zM&GKtMf-TkC_pI-(6O(vEzr%0*ZyGMKnS)qB$B13=7b*?Tto`wKAu;OEo5noiCtnG z43a3I2$gUPKBqWLar+d!!~t{@l-rGx6F?pBjWYmM3>DG5uxJJaGc2y*3-?Va>-240 zBczZ57`&ohp10vvmxkGp&{o5n_opI80(NBZ{ih}x^cjr3_d~7-dahr5XE7QD)ZiH= zthO6;RuR6;-JbF?>5Yen{jBsl+*!eiqk%gU@R;~zx?|Cs}Ziz#*hqNqITvo zN6nh%{?5XO@g-R=7{WxUXo)KnqbKR&!J|7Q>}Qv62e6QA=1cXBSUu;(EkA}fJ6{4K zPCjw^d>UZYE~*USk>z7UeD%k52(}1*aLcR67OTgh4Yi3c>X@j4sXRAB3%b3L1TV#p zrP!5>OV+(h#^f|*LxhRt#q3Sp>isHY+g6O!QpLrqd6l?E2V=XaAByPRhl`c6e4D*_ zCsQ;yYV;%4V}?C8xKUo(^o(>aB0N?-3(m3H#Yg4_XNc5bAJI^6nGx6?*vfL^wr5}w zCU+sc-_qFqWdUTS=L0`h+|X=-$);xSLAagxzEwn=Ox2t`55B}k zC0Qa8IpJ@beOv}K@Byh~zO>K}bSCfRZ99l#ElNDJz{o7+iLE#`hbnpHx4Af3Rr8u(dn=J$|C23r5Yb z=;`((Ff;uyETj6zmrQWAwj@5M$(=Pe;t^bi2|Wx|qAPVy zPeG_oo7w7f^s-bhMV3@tUk;&Qp*q+n1oCX{rGG~i%oVuxvJ;HOVWnKbX*I$oKFl$} z=&H}XcAi1zM@7GFXKn*{%UVqytZngNuXLd%5-tvzu7Af$IK4#U&~$ORh1p{dHg~Fo z`6X3jaP4;Q_X#k->$A@o{CMQ}=KGQ~6j|InF<(PoB&B~MV?kW;TZd}~hV>TXW) zV}O!#DZ;if#{dm6Z=*{Nei6lhr^3g(5Pu{Iz{`i-iVj%&QszgVq*r6JED z#Kwd4ZjUoEE~xtgo54DfXCB~2p_6Ht9*uP#S=0l!X2xDM|7@>olLV*kgN?c%0CF2S6()?^GT21B*T(oIu8wp`u)MR8o_3 zl?bi;;X-%RcuZPA=A)Jv=W)u6K=F!9qZh5~Nvz zWoRP3V-QV50qGqDDN-Eioe@#g0l`MEYLq_o-c%Sssfr9`fKhtyZGaihw@p0xo0xgd z#d*%nNv?8%GkexvYwxwb_j`Zu@4hPB>|cFVg+E_{+IcX@k9YuywP16lp8Rce{(MKg zQvAkfwOSj`XEc_5rR}5P#VsI!SRh=s|Dg^A-Q9hZX$;0b=j{wC86(;s?a^e=YyDX3lw3Z zIL_kPYbQE$Ei%iOuw|y9Jo4u#6TW0nwQ9xNjrTbZHwg|KgF2z=O#tyJQpVM`8?!+f zjP5jYZoMFR-=U!M2%&`rK*sdCL7*%tk&X*euY6rVUJ z0NV+X1FD5eCzv_yvrg^YBMd--FGAJhg!L-};#(>SG8U!h$ErriRWKgDFqc7n4 zB+s2Ff@Xp0F$I9tx#2sIR9@2dQ!m+brf+G|ES>O z;nTM-;Vuv(YQYbr85q>4Bt}fwJOnbJ`Fx{fC_RtI0mSf}gMphD3SXI#cNK_IK@)z_ zuPx}3zdqCcoM(SdL4U$7L>&XAlHdsM-96Vp+X@9CS`-L#8GRyPEk+u^^}DHHE8~H4e?r>`lO{UuTyXzSPs}#BBF?_qEiACvs>vbp@)*oO6EA)%3d4^Z%b1PAZTE`f z%h^S@H9jh5&;0?jMkKxSDp+1cyUUdws;N-<2BX!%{vHZ3TP^AA9XEGcu6t}2Q6u7}{l=%(D%Ap!3$kS-%yf-H@1#^0W^(E%(xiDWmngvC-S&z=N{NtVHdwS35GS zU|*uxE}Cq|#Uddu;mt0TF2=}`tA?|tFf7fL>9pu^D}rpD6SZjNt1Yb5lc8g3vnIQLf9yhu%0a~f$=37c?@aux>hI&RTc zT5jygajmiO|8@X=?+NPilm9h`o(?WUv8rmIUWC0pNYBXiBl2`ATlk>LCx(bx=AaCx z(fe}DOd?h@Vno4}yG8Imj2O3UexuAN{gcx#AGrt%fPWHF4nrIed^QuLN(>kH6+v)H zQj06;P#u~D51>28IdOh#rKoxFp@9fh%@2p}Ximbp`;oTZoj=#Zf0whq{?98XcANQl ztn`ynwBLNp3i#)Y-&Aqgih1)L%X<6cBxlfSPKUe?9lD8qvA0@??#0JPuY*ML zZ0u4(7xe~oOa5QTVAg9 zmAyA`MRs_=J)tbqGp@UGt#+E-qSbJZhd7IUk?vx%KIes1jJ#2b!E(bHVeNy z1R5Ny!yMxQ5coym2bD0SDNeRlRk)l*&(zb>u@dy18nBMAo#k>o&E+-n6u)|x!v~SF z`4`G2(7<%D0JJq;EJZqO?1E&E_O@_-rvO+HGEVX}aqhj+734-Vu8yyXW&!@?mbgGB z-iir4y`qPUnrJkpnC;Vz&0D+Dl?_-U$M*_3G`==g6sf|;o^jDhl5Y&LZo3Sx4s(EP zsi<7ir5h5BAmo^z2-QilH0hGA?`m&p(U7xNN#%@iWm=>4uFnfp5}J>|yG0cblHL`F zo2GP>RpnYW+EQJ!CmEQn0aDsg(MHKBdxiF_HS(gqxxHJ@rsQMz)aM_+-s11vegBg? zo}jetnI2qieYtb3YipP2*Uip%X0c50D?@gaZoBQoiNhl_m6N<|C1p+$X_D6O*^}%H z)$KT@#3`E32|M^Bqur&nEDQcJPyi;7H;pOK`lSVIP?OHjTBG%C|6bC+qx63~m;8nJ z*KTl#TBT3$HPI@gC?$q$*G3U$KaI-Jn&nFX@h-TNWBuKY;U62LWD8hR+)VK}T1&x( z3I53Ym^TfHdy~Hmtf_x5>EBWM|2>yRvYz(cQzUEokl)Zhvs*UJ?yU`EBc6?Oyc!eZ zH)?HxwHC*S%yc9TEh*1b{W z;r6C+cBSLu`<7zW3C{sVe672}f#{*8kTvxBqWSaAe51^cbj`4cW#6%Q5_>Iyx9oyX zUu)7?zl!B4q6qoDh{$IqcKpqkoU+ayNQ;v9WQ8cFCf~;}teu`9 zM?HM++~Ys%Ggwl3mhziNv)tvNxTR1NMg=8 zaY<%1!J=RA&ROM%8V~a5T3>TJdqa^dVc;9E^GV&ImtcW!w z0TP)%Xf-Qr#rl@7GNG1y=W;igiPLMvBOhD#pew276TS@`D*AfmiP>|(WoLUOjr{zE z%&7blTsh8V)b;*soA+-zu2!>St#vaEx~!Z1wg#=My?`wk-*uk zv$Qx>d6{dCLSlX0C*MvzH8{3u%a)53CI)_ac)g)q>G zYNykA=08Sp)_WJ~#m8$bh$^?>dc5(UCKU~guWhx3P?MM^#D^_7D3rUr?WP6{q#TV`8+5TKKgjG!piH#X_9DYxdJ)6Xd=Bz z!O6t6b~QlJhkAo)bxzH4mB2@YU)r4DvXP;ZydsHNuEg5njXASD>r;Mp{-G|`DgP;R zqAvd-YwccdQhyU_sb@6?lc8-G5>$ih39@Y-TOcML&YoR~~in^JX)-(&UfzDVk}MJ%vd%_3AzByhN+zXSV1M%7u6d zZ|;j}gtYkf_4(QC=jK%hW!ay0D;HAr7I^biE*_8EJczw@RoRV9H2TDY?tr^}}Hmw3qJ7Q@)wZH{`FkqOqGCMyBpme{xt3zJp%NdL*LG1?>db z2LjXC8#_s%2CYdo#IUQUBifvzTV~tW%aV1wr&p$HLJo%rr|v^j+uDQ9)mob9^(4F| zvB~o8Nsw70zR$2G)m=K7Bw~^yINdY1&Omom@#M=QG47X@OY7!^QKHUs=4*a$<5v9jA{rIv)K|F=-jM~-J+IO;zp4NtY*{)TRhWqig zHTXt$ik4WpWT{jpS#cl#Wjh7Mq*FbM4<5(x=FkWh%3|B?vR}bxW$ndH!2?(DCR9QF ztONTwIgO;8S(#kNSjyMX`UdQd&^AFPXrdo!dAp^hmqxOBhBXN+#!i(J?%xh#(?-o& z2`#Rib@Q9)F3z>CDLcnUnlq$xkiIZVk)+D-6phx+z07fX350tMr+^VZ2*cJzxQ?Gvgz_z^}P^b^8zw-lUflQ&J;NK6${+7GM1m^E<{m0$M zmw%EB?Yk5P8da|ydu%R(fOaS}faV9mr_j!p```MM#MYV5RqXj5X9hn#QwhRWZr{yz z+QOoLPE8m;3(f@@$OB=ABE66b#^vUBDt=$b=~Xndjjb&f>ZfO+c8skIn>-s4R-S0u zL;@R)#ZW`k&v-A66BHV|lVcf5U=~ASU=SbT2(b`d25ha_QW8Z7p(p}E&IgfP5K!#? zPY4(*fSxG?B9R2bU3Hq0Wr#}9x{>MIx5P<8 zBF1#)h&Q}L4cI!P9S~Uw;fdjj`mieyYNCHW(`(`VSy17+_adoCdk>$fMu1*jheM@@ zB0c8b9u3NAur!Ha#UcV7l4>9Vlynb>`3ZV33%&|lu%8KvcrA?dtssVy{@Tz`oJna7 zAhZl_g?&}d9P19=sRqcD$*oYy?(52XJ$SCa+Uy8nO6{xW0W|KJlKc(<TeTPZ~fD!*aaHVqLK5IVu$hk%NZP6f~(H6gwf2f0+wm}l=DjX!p?9!gX!I**Hm z`Vo7ST&^kMNqYH{A874t(vBmiB45C?2W^@G(Dw0{T)sd~#E!iI;V{!9|16K^Z#$?b zcOdS!pe!^nXR^!2!(HAU*D7@xWj-2v{pU#y-D5*yDF)=oNl5F#af6k0%6wd;DMm6= zDtsr7RtMfC2WI{Lod&wQ5kFioCTSbx-8pZd3@S-1F1q5cJv?JXx5BmW1$G;>z zUBX8%vbDPGNc)*|s{Hy)6=I1K^0b}w4)_216#Ke%zPUvNH-9L`BjWNIz&!+|s5zIk z#x5;D0G8<&Ae9}*koIrIXz=Vl90q&MZG5C4@?8>1KQ{vDKZM&zHV-6d6*b3H8rG9N z2eRyuuaUB8NnH65QNaSpG1K?;$m-SI0dCOTm3ZR5Bj@iTctFI01WOx*{3dufu#Ahi zjT17YHV_46E0f#_3GgfRdE;6=KKy!=RVN6~xIwE}cpys~`C^X^%5p8(CRxFc=mwAR z(qzMinHgBQDXvmUO56Z(L!|J0-}=%i#Nb9y?}mBOhhU*+`)g}KAL#?WIqIcBW6Kd5y-?>_E%K?M@Ocu_Ad| zNosh~yNcocncC@Y9=&CrvtU}*sbou#cD<_R>;>G&+9Jn(1?FQzzp9pA%Z?EMgx1GY zRj#?PZ|22co<#mHcBIdWvqpSK>cT<9B^xVNT4xm8L3V2nG>5;%Z_A4)Y97V3^YLFk z@tfJ0Zn7m!mU1AVGGh?HM*7@ka4)>h3mC` zp?`QCBwFl1n&Xg6oG-uzByAM<0CH21zt~kj3Ep-`gy;-LyMFR;LMSx$oj{r|x*R#v zgtCBj%fcSYDT%|!*k`?_dtZnqc|dfPkzD3^dSY5L(um?R-79}4l&8F*eHv&EK0~4j z$Nl=DX8{YXTY|_o#WKD!Z>vd(%RNX}ls~Dx4*5oK#9lU?%)2kyE2TggRY$fC<`6yk zg+%~;Hnz1!&K7AI1z43Jwzf9(WtFwEXB+Z)FRfLVnNbD5_5VY&L%PluB-$qyLnY%$ z$YvRVX2g09MZNFn_z`U0cF4IL0aPRHKz+dI#zH?x@eWpX=$k`;tprq>_+k!6ljX6; zg32UBu1&$E&o~pGH|`OV1Z%2xV<5J*L# zhsk_^(Y0dBhB#SCKk9sfB#Apt);$EXUW*Ba1I@`J>hWA0!M=bj7of%%OjPTxJbLZa zrE4UAt6{NYI5l%rJ&jr6`%M*>GT4z$!$WBUIq&$D!@J{8T>g0iwzjt$k+X-k$siTX z-3O5^eIyv~k>(iH{CZRk!z;)xLL-r~hOxN_`vL=9Y3$1tVEQ%(`mW%TwbY}7&1X0r zv`gEOsG&m-Ql_LPva0&vn0IX!kRk5(ks}=pQT&(wN`ST|#}h6q#@un{SS1)Gc7*%- z!5Iq)`ozM9|4MOxLfbv$RD|qIEBoQJ!Sb5?h}}xbqk8YzYUsx@S)clHocx%gWe;V7 zS%B(FNOWF#jO5L-l?tRC;03_{O1&9XvwH)QpMtOTlnA=1+4;VmRd2ONLR6nB-zgwu z5GNF1#880{0QdRv_xEK4FMosqF$-Opc|#ALo})X)aloqnQ(v2&nP5TM#=vrSWnKXU z(bgjP*hBhX63(f+OUB#M^seZ`);_AuTDr$J-*QtF ztCjTPK(pUc?#g_^hViX??8etmIaZG4x6R9b7zS9g?(y*QeCvdb)%MC7nE%{pI88bk zeBrZ0f7&cj0hS?l)Ag(E+&(j}Rr0S=FT~T^0m{xRBP7a!9gKo^gTtoeg2ZZ=R2sOTQ$fX+&C)hPfadFmz7P`V#E0Gjr zFKq!Rf4o_5Cb`6o?5omsJSmo$+^$(q)m`iU;OXF+E?-ql@Vb+;Alg2HH2ac?&1-@gmdTMiC1lw~ zg*?kNx(0HY?JKjT6piuhW{B2aXDyZd{!aMg3njHvUNE&0qA_;YD`-?r@(5+1%k_ea z`E)VHU^3k3S_*e_i^W^F{&P$BQ)m{UosJ%_1v zeQKw1kO(HIExav@<8CFOR@zMPZd4w<-^!su5bshUy*O%M9j9~tUP+#99cytrHdZV2 zph@{+=Ry+yoT>}s_kUly_!guPw>NMg`Z`jraTsgeR(DA_pk^ooO{&0Cht{Iel9>bV zY_s^%cFue2x(*t;79TOyJ;=x-SCp*XusEBu-w{$;QK%o0V6(1_%K5nIY9w6n8Rjgv ztMlBl{(+j$3xFQGvWZH06f%!vh@>i`%#QsQYRRt2OiYDI+n&Ns?7yp4IjvL zNRzj-lniIs6R}>Avuu|!FZv)A7Zu^Jqq{l0Jgm66INZEBUjA^^ygi4FwYUY9F2Y_~ z9_@OeIhN6b^e#GH9oEaEB*7)$uDq*wv2rp=vmn+~oF9{PJ}RffGlTNN)78d#gW#uT z*PGe9x_+6VCwkYE%2yfXFWm!U8lQHXt^B-q>^|V9^>^b|cNye|`I9CKNj%8O9jOn^ zLO>_m_lL z^q^{oAhWA&4u(ONa3l)acG;lq{>j_-8c9zZ z4w}sSNsvtU`Bp&ebd3Au6ryxKI`D&Z+*Mp=M_F_Mc{@Tm+AUOcz^SX(STZjqCB@C7 zuln9YjH(?H3bHrWIx(`6#8692ZL^Tl3-xW99T)RinHdbZ!stfT*`UW|(DnL$f6m{4 z>fn_hivUp1cFHVJke}#;dJDbc>2r&1!-FLro(aZ8V_n>JJow|OMLS`L?iGLo&vCA5N zRaYkS-RgZ5tKJ!6@jvY@4?WmuCPPauE=Ps#VVbk=;%kE!kvhS4T4}l)gR<6MCv^|N{9#EtJYG&~2=X4mg@+yJ3H<)1>&rh?I*Sl!K0aJDr8NYGzk=*??!h(X z|G1xjy}ZQdyVA9jJ7AK9jD4bcT`v0mZH;7Il=egx)-;&L#ccxJ2*CBf_S5>C&0C;| zwjle>`26kKRQy>PS)JqC+T!f;@$pi$I2Sh{gEjpcq1{r&D~!n?&*tJ@R8xYYBAbBz zo(mT)JR}yI9sbLM{+oM{D7PhQ+I92;AE=?v!I<>EWyUY#b1K_joJMkFrkStOJiXP? zTi8Le;|NXAK1-dw@Wx4EedXA)PMg7JjqKH#^>hWP!rR!CL|W75Sg2C|rL6r&bSpD$ zne@O0az~q2pJLobUm8Md6#Wa>ZSEVRUnt{!G6){miSr&?{yK=?-204!GgNGFhU3v? z+5@kQpppi%ypGda7a2zZz#^~ePIG}BL})us`sFM%uFIdWZ)Kx{FXEz!<zj)I611tdpBML`LYa|X#_$ODXs0!mU8h8#pd$vF?8g$a0g=O-+rr4=7ZOEW4u+L>8co8sX;d>sxaP*HBCevTU7 zd`tT9?x{~N$4||ldV9$OFGXGH+#|-Mmyx8WmRhFHXP;+c(ooC2dOkb*dFJUngZp1! zc-8PoRNTZ^UxX|dU{Q;xJw3sb4`Y1zj7oUm*@5YJAYgIvT zAA3Sxy|rsS9C(T{7ZG2>IGTl!cOtp&U%KaJ5UYHBw^fMs$t^9@Z`XN8X$+&BClJK~_sibuH;OBW)B_6Lw6YmFQ`% zkcD2;mB5|L+m|^$5ZrshqcBS+S?`&x@Ycv?uX5t1Jo&D}74LkZcgh@ZcON{?yUnL_ zkzI44J>DqWNhDj0Q#Og>ywLe0_is&+H#^Ahcg7fLYTfH93@*9L9q!M*P7!d3NS)rh zY1#SqFh%d8OrC%oB~{|*IMKLjskZp-n}Mo78Yp&lAGd!rGysrU-PIHsQj zH9ZCay80krCA8~^dKU7T5Ip#M6u62C)A$$Mk zH;(HxWe)h)W!eg&>kEsDi%uFGVCCswmrP#9Tr!G{>Nj1vAF>Yp(Q!p#F--QvGY&kd z!^y%9dkVY{o_N$+?v57QpNPe=HF!*kjL0(=5>FC6znOb4A95k4uGo!5%zulfDx;(f-caw=Sktc(8hnZ0u& z=i+>`rRcg&ekP!PIWCo8c;)en`CI{OqE0`}TQtNkm?ux$pRc6s@ZFdUwinhp&EQ8f z0a@kW;TpYA{Zd8|FXg3C;-+H64e}NmvKMb;Sdu?|Ci{F>g)05Ls=wufq9ohoawX}{ z3ePyA{medcc4yDwIbDhN*9+3~8GoKF#c)qBkvq{Y8QN7lXGh8VfY8{-;j8_vyvQqU zmmZ%;B`RQm;6pA#D0=#K7#qFZBH<5|lJ3k$0XD|i|i_Ru2y zX<3g_N~^56Y{Em8FyZEy4^m<81;U8mYCR-*XxD6#&olI%R-uE*?%KfH&i4snl5D*n zvOWm6c+P~kgtuI1iEGKZaq7**S5Gt_HYa~j3Q@Lw>Zfv+t$}TvO(&d;Eu4*2wOr+a zibc9W`qgx*bQ%?sFM3LJiBq2&RP@;rq7|}IG` zRl}TC4sJF}Rn zAQ#|N{nQe-nJDvuUOpHJ8V-`6jG=6#%;B@WO@B*Ca5C~o)c0sH0hSn#NG^daUWBn9 zzj0Jb)bi~LQ{ouWNWymZb~~*a@(^;Sz&LWcf?EZ#=C93F+ZXb$Y36ela9VLfGbz=+ zs##@HXX&*I#L`JtxVelh+4U3m&-X*K7={#W@NN1BZ;w>w@t4dDsSS_kF^}vHWffZG zLv8E~xpR@GFr?4ytpUS0>5N)+8CIDu#&Oe$?~{~2_7bOYk;jp>4A+z|1vzXx>dkw$ z?7k07mWycRflKOe>h|i8lo7Y_L@`GexXS0mRM8CBgldt?<~{l`=?Y-i4zKtM4S=qe1$sGF~*Bo z6H9iVau2@B`0{c-%a2E&AI(j5>3_>LOfn2N?5wr<27gs@zl(|dKJ6PfhIz8Go9jv+ zEIx>(^G9EbBh|fpc(s8w^;)W^i_6mbpp`?k!^hH8Hyux>1MJSb-Kvd}4z!&8!y6Av zOKME+bi80EvFrk z_=0y{CrS=+mR)matmib9Yf0>q*0@f4$vu$mUXJp~r><$<4+$TMz7>d|f3KI|)A_JX z=w|Ah-Z~0iXI==e=r!^%{6`ogc)d0SiJb4JebcwrKAATILvG6s%%rZPe~1sQ422Id z!0&Mj$0tWKca+6j#aBp_NOp4DA)jtO9q;Kk^=MV&UexT+t1>@b$YgPUQPwwnmwjJt zH%Fv2x>UqwE119EO18gJo2H;xSYH&T>Wy~ABKyd1P&_0o?=Q<9ITYW6c4L+om;3GX zkFwtCyA?H+f6kn1Ju~i?Avt)Uh^-xL_z}DuLo2vE95lu;?wK=~ykqd%@{!&nbVQjp zwQN+%s}yuG*RV%QTa`6NU`k-Ocx8QJJ$2b{M9}W&>DA0q?RizrYH6#+Jvs)Lbyt^_ z^-#8q> zWvrzou?5|*3gJMD6#)q=ZIyE!>Y;L+=~%qS1Fvo+dlm1^dWF}LW1{3vnOj1OZeyJf zB+){5M3n~d_0JO&~uXmoAp&;?YYr6?MR8Y`)PE zQut8IuOlUP(MI?C-kj&st|-Mfu0nmHa<|GjDlbQG zph?6Y!dCYTw`;p)GU$!zDI}EKpKhxxTJ+_ZRrkA!x+JWu&6i<0riPOB^w6zHlWMQ| zR+zlEUVqMrKA(Z8y=9l(YJcD^_nw}tUI;PSLH6E$hobg?$C)+;9^r*Yic zEn{uFMs(jbi#dr|0cl>zaHzPWG(G)QAydI7!B_$l%C-Aq|0%X_$!en{(Jr)+x1r&h z&P~^kWKvg8%FCabXg~2uGUViQ7ec(LgJ!J9-Na_ti*xu#uUVn1=NwKYmJ>d2O2IpY z#4~`N?&)E|-fV*1xpBI?0)MbWo(Id4Zz4MKNdFqiCw_Ncf$jb)cse|I`hkrN4>B4X zs??a9CGZnjT=R1nDDD#A2_H^x8t9|gR!O3kc8{J;OPb$`_YvPg9k9N4rtO5aDz^fc zSIt!8k=c_ccx>SFS-cbe7I>$?rxW0p8vNqnoecBCBLIIdf!}+H_XZm@E2>6V<%+193^A;y7aVCu?ij2~Bj;4$PT(`JxF-e?f zWMmX`G%*u-dhfxX&B1@-OwXL0>_xb_U0q$dT=}@{9L>3TgoTBT@^XSZI3ez~ zPKIurwh-n&9`e_7?wLZ29WCsgEbMFPQxm^w<^*?>NsB>puue>VR2FaK;P#*KURe-p(Ya{hT02wLL2828_k zCUHLHz|aQ|PYUnRy*nyyCzi$tDpmWU1hJ@|Kzyb*Z$27*9S=YV-Y$M-6lfOox*?L% z{IOZsqnNPx%A?Ag?~RPY)PqGVKPnju77voq7@<#JQM^c+QhOxUI%LkJKH+$A1u?p> zo6tGAl)pW01rwy-I_S{KFsuu>xFLO2>N(yC{8ML18GrF1v6s+keiI+>*Wdox@CN=j zY1qa8-twPv{68p{F|DavFzi8uiaPxFlldIaN8r*k@Us>U7ZS6krWMe&TMMWA#kBwH zO=@__p3zd8#Sgf7J>n|7H)%+A#btSz-(zcmY^=gnKMax~{jZz<*|iiqVOzYos99U& zMF^@RIO0q|dx!g=kdTi1O!#U4tOI-9kbgG%`-+s@seERGS&t!}TXNwT&Sqh98hQZ< zrEMXVW0g&V=M*&x8VsqfFY?ZtG;}tIZ&OSO_jCQ7lH*=rS)XwO!E)h3Muq0oYOY9) z=x>(zjLs(} z4dcGy|Ng!3d^$K8#g;}pkz<#S>FzV(S(3#onln5K(r0yk2>@J;Gx%Tu4sW z+tc!7gx~vMCsGpTEvK;IvnXiO_)%WSqUTejFl6?l3padOx7_LVS6_mG&M|VE&-$as zC|M2f#b>>%_Gxi0Z|uA`VmQm+A&;;ahsjqI#dDFV;WX6LHtOmiVwct`zJal34I1N@4^AWf}GV&%vCY0Xc z>uHMb+()$x*jw1`lIp$zijv%Rfsr~)_0ge6xN)esfFA5{YtKWQ!-TSYd)TURJ}rTM z#HK{|V88lkpVy+nwQ3`dQo_?sc%W!Nk46%^77A~6k9+z1rIF}$-l=6Zw@l_8;+$Q@ zaYT@776lc(n(2V9Yw$^8A;#=#?4D(>qkE^}QyQ9? z+?4abU*|P%IJ>gH)$(EznycayD0O$1fADN-zqNFR>oSrm1WnLWAPg^DUvPaqD3XxamBqdc^`+_~?3VjM zx^c;v%Se+Kx@zBcSCNL-oB$Md`QzDC*%DNx1<0*3Roi2ZgDtD1n=g;&6fP>OpvIq%@3hl-c( zlnt51-0#TR+3Zzl)O8&r<3?;g{c-SKwQM>>lzi@W)CS+I*gNJ2K{pzmmxqg%U{kMI zry{g%Z+4c5^#5kJE_`gz^5Nz?q?aIPA7+p0k{a@YU{*noEPFWmbx!Hjo2HE$r_@Y* z4xm*H)K>SxB{>)LcyrvBiv~XOi!^YiUyv(6=)UsjEb}4S=n$F?+PfMmvG>dqQ-S0p z$*9UJwjXt93>QAn=h;G%*3hW3wN7z)w?$v<2RDxNb{`LYsP&#Lin!m5=g<&D#X{P)Vft*i)P!;`nc?up zx;h;p`w)Z&>WN*4R|nC4+^V~*5G0oBFyy(>&aAJ=OByQ)!{R?c?lcH4Oiof%t-iX{ zU^ccC=eGKl06xJxkg>iN3ae}rb>AK`SC46d7W1IAtZ9499>#7}@3z}<*|!5LkxfrO z>mbZ(jIA9mG>LRy_>%UZc2Mk9$jY61Fh_=%+ z@0>VfGIzR(4Dl-|bJC{AMnIHYnoU4cD!R1C?Q1U>7xk&J@8>fQyipleb&K>-+NRZ3 zY1U`vSg1v@O71?IKO=58UfHDQqS~xyotEJ3ajue=vUU9VkaUg%WzB+Sz&<0u%Qm z$)nxQMVpTCa1!xN#dCZ4jizKhbS{I2rqB-KNK6=FJKx`Ei~Zf^7w-#U4XWIYjs=0c z(}DU2M($ix0%l)AS~1h1k`nn8#^G(|onI5Mn`v9H$b9c&L0C~3f)Tdr%kU%hRRj@j z#>A}=7%I*+V*I_fO_6G5)!ssPnnJ?PBneF8+mGh=tlXQl0+)W}eHh%o)P&BY;Qyu# z!E`(QsGMEkZpPXa52ZTgHose-hSP@I4(1w~Du+CUC-=>`{?Js@G!5sC*70VDV?Gc+ zI@s8vWvrHwm`n6+!R!mmjy<5Uxia+bhD?d_*}@blKc6TH)k%Y1yu9m2b%&D%bs{BMK9Au8oPiCVkp7D3kD`9(o{mC0`J4BHd=l*(a37h`@@IZ^dRW@o3 zNKo&P+m#p-H8}~d+Dv(RI8cpsMzp(kEDfoLA28~Ng-vTEIQMHh%!I2)7@GD5htH_D@p%rOTK5k?;qmO>RSXW4#<5JDfosm$Syt%h6_$3v^ur@z z0)-i?xhxm#v;-R;b&$Y0c3XW3xk?i^Z)Ys1lH_RV)1#?ut9EB&W@G`UMZ|=cJe-y)eO^oatga6TWK&35S`Rw3!Pg+?AsdEWV9}Uu5NFM}&f`#TpG& zQNC4@+k?gqYxNZHUK8$bwAB3m0a+gY0>oEkLTELsb+EiM+^}6aFL9`{nc!Zpyl7Tc zmR1wY{Wh2Ik@5B2UG79ruN6o_MyE{FWcuB|yz>9)*m6=dp&_9n3!gD`k-cuJ$(;y0 za~tUp2{@9(4s3&KxSd0$td*E^x*<3NbJsIZfMq}wU8$VX9W1FLW4rSEi-LC>0Zl;QJl7SE6$T7c&<0sy9joWgxn7&`a%sqz_Zj@r?}8s z@q<9K!^^FWr}2ZFsoTy75?jn+?xqpGG*eni(vz+yhlEVE(;5p(T4${9Ooz%;<^Rax z7Z^0~<*h_@B}uoE=4ry*BNm4H_#Jl!;Cdck#+7r|AQqz$P&A@M;DTdd7? zDOh@B=`czcxxvtO0DU*MT_9tLZGH4h97RgzO4Aoa#3vQzPR>VTsm_ib8NjTS&(Ef4 zb?UtmMre4$MoN8~zJF0}bsZ8;)7jF+Ksv=)g>=|V35xur$S$d!n0iA`o2m(3oKL0I zkPV)C`>_6wca2GBIc+qboHuFFgJ!NNU`rvZGu%x1?9Rj$n&C9IrAb=W-TSKQx~gd1 zD1uo6OXAwyBoeRBo{_WqZLlK@EHw6-Ae2^(#a}>trF7b8F{^}YD}8x4{_5;{;g|9R z!78)jENZjD1)s>;H?s#ps?B*>F%e6{Rk>kFHpJ#J()nht6CCae!dU03d{!gB2pD!F zq4iWvD|4x?Muj!=|5S@V;u_s9 zOaL)@1VReDtYp)&>KI(INjRcDZzzKcDz3IcV@6U+d$-_xbAHBFk9^4PH$v`v+f`ON zyoznRbUz)=c7(?k+s0Wl#RyY>I+p;n7aF>?i1N24wu?4?Xs*zi94a9Kx~zEW>VA;- zsgnhIdNxNb9gnB6+*XUcI4k`<;;H2RP-jFLC*R}t#M`Kt?l>s$sVSe_~RpCf@!=xJxkZcAi-tEDZ!eX>5C!zQP8VdoXX{JGmwUSmI$bhhgg z*bd*S+DC2BdGEIBhcqx0s?KTj*|lPpk~Fs-J}#kUt#B9uYD$yS53g`prrvD{`)b4g z(&mi6u+9<+?0TPPA#GQmyz+Mz`E{uN?6MCL0p!%zgOy^3rZ8n)o9e@D2Vj01+M@VI zKG|@|8az5pP2eAVM4vNv!U#+cgt7zYq~~>BtGJJH%WKX5QQ9J>y*`+_Tn3DloIyB* zXtuOX*wZ3{_Q4kL(lm$VIM+*w#vD7UV>1O>*)lSp=8OnEY;!+FL*Os`$%?{=r_8LR?o`zUtE)lq7d@WV6 zN2@qLO0xr&H|o^;#B{Fb)src0wq4&}h8}c}CklJz0~abLW4Tw=tM^o6kdvcj5ILH3 zbSs1{e`z%zSiW#l9?{9o<&l!dz2Uuzrk!=^#*bqJ^-iAUxM!gB)sT!SyXg-p=v8@g zW*;1)VWD=g{gJ?oo~0_HHC~N$zrusTMhS9hKcd&?E?=(`M#UBkPRDfA!y(J!t2HOr zaQ4SfUo&6crKn>ZqM0sy8lv4hE%(ZFRc3niR^yv&+40^M_8c8G$k{$?;|}4{4w1#W zN33xw5+AMa!y5PL=2 zv?e`)ZqBV$S*5~M{Vvdu#l@Y~TxO$<2v=S)^a>&Exo^$!)7oJ>~+*hB|dHYPPkD zM}PN(`YV5T24N?Q=`OYs&d{rJ8tCyS`riuPt6*mi=Yfd1xLJ@+xNr4ly8&MP-f zTI4VnxxcQ?APh5z$V`xaZq{sIi#^yib=Snco1DOfs>s6?SL3;^q?zwjm1g!kKzHkb zGqEMK(Z+{#ZT7SsN~QhC-@4YwpszQyj41CMjX$x76P3=dp~f!5(-Dma{=0FmkeTff zyBziA+|^Lnfw7l(wX*F2ok!91Yu5Mx&#n31w4l3iBvPFPPLq&4yb>p+O=vzs z`~F#p@Dzl~d!~3sHQsw~e$YI@t7RS%G)HuPgWJr{bZBE0gbmLSX{Ki^hvJb3vx26d zdo3e75BOzQGOmAYzbZ{YOiQ`HT%x}_p{HkK=Q&Pvr&j$TlPwi%8)lm6UJl!Hs|Q5%x82(yRLU$EPg{1^NHP(LJ<;3qVQII&6r&xY3!O{ykFWtI*Hv7o&3>(X zFK#G3ssa zk2(9P_Z(|1sqm8JbtH0s9K+;q+^!cU{Bj<^4w@lNHJDgPhlOLI>hIx09}>2%8Q=Jt zwLtPn2`>*5#_ef_Be(AGr7wggBwgIzYk@p2ON05GP#W9fA+tOXZ1wrp(lYGetZ5@X zG}Alw7;MtVl(}mjC8i?~gpNy5&(X`9iO`NH+jg950}3oK+a6QG!QFkcBOF0&1#xHq zi<2%Rr^9Qr<0R22q+<}}H8a_X#; zijSS=G)T>+-+{H;G%RGyTey`s=2oQ*G{pN%UzkzjQwTyeoGT zK*uR1kZZq;<^K?Y4>1b>#T7$)+mBH~QVow2laoCo!ePgW#QzfD4L&!{n;j=y4#e|S z`}t+sN5Ar={v2nb^f`cwf1h^Z`<--g!-&w6ax2|*3AuK>oL>6VEjW}@{a*i1;LC9{ zis^WW%KS1g|8tykia?gcTS8+*#|bk9&@^0#IOgN@&W{^YuWLt!3eq{|$mFVCe! zNrkXG)7szP_+4av(5C{nqZB|AxYxySc<76Ip56Juxec{Nl3LFcjSorGxah*9`0t&_I z-evp#xN$>({?5K!I*w%QdUOg9Z9nc*JUMRM?O<{K9~4rew)U8LD82a9uvL!kj~UqE zqJCqzx}IjvMg{Vai>rL@qsL(mxS9t5@rF+C?E*It(oSh3_td=fdtU+IyD?2->&sr5 z<8GHUNpPt5X7ZDa{sB7xM-Kw0CRrgtVl6}ekPQd3e#gYQ3|q_$s_T34%LD8S@IPi= z31D{nm=I}V;cEiJ&yt&tiaoHqsA;h6z7`yJ zGk#Uc5PV%K(fHi$+qdgFMA5VrOZjp{l(!hK%g0g*B0V8udvnQjix0*w08+V93eKfF zHE0|fe8=}pI2zUvLRaw(`JRSR%AlTNZX5yi1o#US89WO7j(6Ozz%;iiC$@j9Z4lf7 zG>!PU_x^H2%+xCiJq?4ymzU)O0DLdr5KN<9j5-QX15SBHc6oYccG+w+k5OF!Zj=8R zFO2~3AtQZ8Jk$$>n=NqbGQ&X5;s6lcaj#1fGkEVzK4rzA776ut?w&h~EB?M7iLV(Et28mZoQ@|bpm_I7~r91!dt0G&D?fC=*DgT_{`~jbTy2KK|-wRV1~PK zplZ8lr$xQ$DgMiY`lZiG$?Nv7@O+5b-X3kZb=@K8L)(s5x^J1{g70TmJ_qRceQMgA zE0r4^fP`R|g{;HBXxo;V&cAj$I>eMXU)D{)^O5JuZN45;2hif_rGm~703w7Rp;}k% z54Q#==v~&UX>1dupqH8$UYm2zA6$fbOWedgoEzUNt4PhFC0KBrGN*D~wk<(Y5+q-A z>qV#00SCn1$K@h@2(2*h^(WDVcw0aeFr`g~s$^g#6iZ>HCYo6jI0U04^%TKQ-xYt#ad4Z~OdPtQ zk^&+-Q>C0***d_>*xXb+j4ZH2R^?6l(KP5mm&tI6AUwtmg{B2MF+hi%eGabncgry7 zJ}78m2qz?2ybU-@9QNlH8E3lQn7pg&Onl^xgDn}%ihQqI0@{^MBT@IIzi_r^Z;xBZ z*HKrn;^0^9Bmi{tfcWaL77LW$?5+EEC7He>W?qzj8~4%`+>mPk(s+6IDQ>Xzryb{_ zJx!atFRc@(EoN8PK90PV)aIq(vV%hnmZcaaW8}rw>UzTb={@GWlvN7<=r>N0QRZ{Y zc-JmcS=d#>&mTuW4!@TIQ1@9r;Wy&|TGD;7@Q+R#i9p8`9i@C5P?7Jhc8UIglo7{dQ*SkVaISyxX>6U-^QtZeU=g;6R zgrm85WirrdBi+6|SMcdnaDv9c_;*oa)|TFY&uNg6SbsMNK+0(l-B_1H%d$`!J)L43 zkE7IYz;2G*9@Md=a54IG=cq9{wN98r8*W(h{DdhsmzMJ@EoI<|fKCjLa(TfR{J1>%_#d|E^LqmmU zBTE6jGmS$?3@U&+o-It3^7HGIJn}So7Ma75gV@&6)B_ntt#f=>?R5Tx0IQ30o;U-b z^K|<_s?D7Mwq1}AuJ6w|@33(3PZ~xfTFQIKx#ecshlyJ#i8cn!Ki3mvw(T`wS~;&P z#M5GsFxc)#cIdWAvscxUCAWgC=vgN{9~@ETqm=6yFasF)2!_y5z}0SiD}?~%cqO&{ z0y{iVMGlDmP#hj<8d3`gi?q#qAb|aN6k$oB@QC@WlQnK#Vt=qox+8CWQrC4>)p6>+ zkM3pQGkZ)m?GE0@11UlCmp>hM-vC7Lp{i<{DF+J1-b3Nyq#3-H-#_CxzYJBJwR`65 z6YIi+3Pl3St(AmsJ#Z&BjkR^IJ6Rhc&h-$afu-UDxC%)=_(7bQPppl>bOr?nh`vwp zm7lvNprC_eF{_Y-eVtvyT9*+U^=Kym1{Rz4f(7d%&(y^Qu*#lP3jl5?^gh|zLV}Ee zyp0Y~na+6e#gV_WlSJN2VHa-8NlQx;(Fj=kXv0>@P~;jVKRY5V1txmhm|FU@$+5ZTKI4^>Cm-#U&Cj8RkOu*ks12tiUn+tvHd)v!2 zLo|8ONA}I3YB=W!eeQAe?Joy-;;@(TIkU1AbMAvW%*+47W%40YHt5gPT$_!t%Z>~l zu>4csrDzD-B6*nCQ$Q4z$bY)LaJF725Ihmg$*A?L{ zEz=D;=224nWTf=PNb_XV-*yHbrKJkI&Gb>O2gmr)iHGOUl8m4Wx_N&;?i2V~Y+&I3 zyCBvZ1Rcwmp=VUbi9iiEaJG`bzgFU}B=M{o_^sRf)`iE4AmhA~c2CCP6h*a0Px{|0 z`&Z9n>>@rDB8lB0FZ%d13zovU?qGK#*#o2&I4kv8|Bt!;&#@=coo|a16{M!7UdWk^ zem2?G|atq@I%nguz}pf|@^ zND*JD60+Uv>Uz%YgVWRcf#*6UFL8@`wq6=*iGb2ymKH>^WP2FvJdP1_cpakj`Z$Yh zPWp@zgjxsp$L9XcxI|d)Cp!Bz#xopwRIb;FcV|I62i?+qjb{sQt_?238<PB%-T;AA*C0xJC8v7FZIfH?hgZ*IGsNvjf8a+L=iL74P05gO zf^1C>>W(P!0$RSq%xU3QHuI05Pv@OWhr6CkH|4}rjCk#Q zD&3S}t!taNYaG@ex|;gkrGW#v)4ZbnM zaN&aPR2YLN(|Gi%k+nJ@4HQE|S)#k++oPRtRYLFZ4U_Ylb6bdwzH;TLKFBroduYLN zvutpm^x4L${Q+SpaHaDcpLJ{Yrqw_Hy7-_Z9${4EEEwz#LDhx$dsW#+EoS6YXi`}g zR^@en8)QWXx4VdcBvOj5jSYc1s)#vY$kt{vIt9|VssnxfY@e#>c`s#OqMel`4vd~O zEXqkg?7DzzSj-XAR3pf#zVFUZJXV$0kt!NKW34@~BHrR4eC>CMDnBg%NVdWabR`qx zcQLDLwk=v|_S#Zk8qCD5%6-FfI=A2Na+a*0r>3Js?W^#mb2|%sBn@XqRK23n?+*LB2~5!aN~Ai@M{sx+CTH-3`?Jq8yQDEi}d%^;!xI;Vq7EuCayX z)=9a7+laLMZieGb&~TYljK6|M@TMg4o7EEc+OEp&~kX1@RUbx{WD zoB_YRSW$B|>x!duc|Fhjrc-3l0VCX4r6GZ}ltxPgK}F-9Hd+&a8;57I$hgIvAT~!w zUtakZ7|&KH8+D1)8c$F!Hd5CXzd_NL^Tbyi`Dql8pR%pmmoW|$4@sxvyB1%LUT~X; zM#7UGns>Sh`q@^=MXBdOL&x7uPO>YEUiS5~zCvSNqF*N8QQ~%_YF-~%T}?qxjGTWv zSF)hB_I*sfVdT9YI}!SEJf(2Ze7W|DT1fMvf*bZ->HO$Xz*X&u{>jv2CgMY^de@7tiCJ$L%CV#BxB6oQ?QAO#XERj$FbMO`dQW~X zw7fg>dQsO?!uvD?!K!gYR7i^3YN8Yy@f&<>fA!W+j^oyiYA*-|og@*vg)0{rhP#UY z!_xZ@-^jIYWU@KYRanx{C@mOE(-~4;bz0_&>|df*Joh+?mn9xxi=_watr<_oe*xlq zGWrNCx(gNczh8}Sg{}EeqYeJ-Ny?nuZNi73W!Vm}u5nRc5&tY&;gH5PE+s;L{qoCD z=Pz5WaR$UtrqAcD9A|q(UVu=OS?oUMuU5Z`TMekr0$S?CN9Er{wLc@KxwD|Vkku<= zC;u~m`b#pP3m;QZ)2VYNK>p6ZUHs4c6PeH62JyWS_M@!{$m&o+l)EgKf3_^$gWaS!KUC%wo=M<*KLy`1dRStlH(j=Keps z$Bm2-SI?2_iXL|WAbEpXj14)i7zBU{jkqL{NFL({77G9ipa*#2vrHVq4k}4XL7Buf zC<5TxCl>zk)(s#iMiVtYc_5uV!ngyBcW$J_juw}FybtoysDZY*fNU$)2O+dn?g-nl z^6y}_u<6{7}$|3C^x8}O~5#SM2JSqj4bj_iG6Dw$7U8D!*4J1(KzxRAkQoyF*Foc zyn)kH9GBv@-po1;67jhQ+I|Q^8NG2S?~OmP(ckHgl+}4BU4T7fA&TjJYqLYo-Z^SpisFVr``Y-H>o}fa$^+O|#0=3kc!#Re z^%nM4k26kyqp|edsb%0Y)VFPW%jsLmK{Ytjl>h)@d0Zxhb!!(l^n{w}-sZeRzovOO zBX5Z*y0+7EmTwKDGZk%~ZKDsZ-XBBDD%8b7Z}BJyO}^~ezqM%ocE?}xAn8}Ar}q=SVgYi7f+g4LF5|e97E_Y14J=SrTaa3~^<+pi zm#x68oh^`RPnD&%>G9KybzE++Z|&$dE;kNTXc>dkA#Mz`E~-mM&SER|0QJWNJ!ckm z+u|w6xY;7w=RIiUb(-tqy=LhbtlDf0Is1J{JcUY?>BvVDYak^KbY@^8yb+c*c5g@ zFpdAF57e!4%XQy%VRgLu~bX6w&qIe|+h!Y#YZl5vle*T8=OR3b&0mxY|)tNo<{g)%*23J*{l^`VB_ zpSiv4ydaL|!;xf(k+tvWoxdx+Ll9(KeL&$lCc09}jI&_A1SDL2`D3ggSsP#cB898x zw(JrpvI20cl|$dsafvUvqo;;5QHC8dZnIJ54Iqn7r-OD8RWG4y-N3GoG(SmvW_JJr=$MW>_-(YCHJL zOPFEmQY7pp7k*?wOrrI3ThgI^%c^UU65itJLl|@UmOt4tvKmH(g;@Brw_DMAZFb`d zL4?3^mL;i0Lqv-j#%zgMkLFtRrt<6Q8VH}P#nqeSF8gNRrdZ-HfjJB$2-?L@ z*gHsVAM?OMZ5$&}?AHNmHf$xn_CI&I@DJDLZ^8JGsU_+HEB9@|Lg?>{|NP+N!qL@Z zC|6N94eh@D`=^11T1o((d^5;(oV%JR4pL)AHhQ}Sj(b$r4S-VLw}u~^MHP=jsdwj} z(fo7Fe_!!Yy8=*Zree8cghu+T6NgeCI28sT2Me(ScwPJANXju5<7}ZhNalcgiwqwN z)RTdMX9X-jJ=XXX0EbRolFsJ1Mc4HP3|y_w<>qm+T-F4$5}y!Ke5?rWgMqUfRb2U7 za{v6`v&{i!rBgv>YaRYJjU^;tKyoi1GLK;sL`u<ynQP9sSB02{L5b+g_Py$Rv&A;MBJGZsUwjMox7ffyBT!`7VSy(h(ba zIATgTf_Pjq!{5V_GZa0bn<_YIa*T0XmQU36_it6nNHUCyw^d@b3YdY#z0x%{93k&} zFmjw7;CP%k@=c()p;)zl_?C;%LEzdjA4Ue?rpALV`;Bd`X$^cBJt~E32C&e5YltsEOtCdtzaONE*WKyui9VV z+XYZ%@StP$W#fsr!A3o$=2PR<2STZcUCSX!gJ8oMv5c$=cc=M&@zg4;qnJmp`&x^! z>xaV&y5$XO`w5iNC4PcBA_c0PY zCe5lbOVTacRlqj2EW#ZXI!C?ki#hBk$cA(2R@A!?#8EF=m&vq62{Y4|t;H^My{h7# zcc$>j4L(M;aaxJ(9`r8gAyzeA^Y??+p~jY9hrHKj2h%<(9Q7I3T}`V$Gr~~VTNah{T!@m#biusa+yEGl;o7Swb9SY_iMiiOy? zdsm9iY*C6?FAgrgM}`ueuIT$#RLFQcR;>0#<2L+w0lkL0MN)7FXT_K>+^6FfraDkju`AR<&PR&ewc-OkJ^0G~mck`F zLdVsxapV~P102YL^VI7ls>y%oVgi-rLMw{=(3H@)ox>)2-_GFj)byw01^(kfuGbq0 zNe($5=x+B$@@FK;l^+R?7A61%Zm?JZ{}HW9_YAcAf}r|xxVO6OBdDHEw{S_Q_xplU8!D&Z!HsQ zQwo{54T-J2k}+y)N7WBDqB#&OsE&BDp$bReiv$r;YkT@$T;ow0Sx%umgR2n%T7gmGe4BS3C60g(~$_33j-B|Z7Xt9>NEauhtMuCGyMxo6| zulX%OVMCEUkMGy3MbEiFz6{)PG(!QYezyXYrwXW1mzoV>dTIsXn1xU{eOVDlM~od0 z%A{Lae?y+aC>bDN)LwKEk@E?)g|+e_qb`Z>Z|BG>k5f30oo3VgkA$25v8Zw>eFR8I zQ2idH0$dQY&Kq}h01-rE$0Z#&oBI)vf2NP4R*fpL>&84)0{TYVs~IhF$#z_e(gI^F zd&HDFFDk%Wrwr?kqdInxi>d=F{mJTC*ae3gi|PW}~6dwj_R12V{ zwQ5}hXkGaAjcxag&s{2585J%_mu`XfZdszfWos}0y6E%IxlR=J5s2BywH#zC8ut=b z*N>pJEF6$M$$YYWNq3->h&Es895HJ!R3sa_+w6eU_s*}e|D@?Udf9a#Bu zK65*TVCpE=zIK@;B-DF4Y|s&T8EY>0p%|5$nlq3+Rzl8bn}=jYj;JsCxYdV-XixCF zA8fGP&~aW4p7t4DO@$v$L=HQ{v=?%838m7WcocD<_$!)p%ibgWj;(2(x+3MXJaR((JOe z?V@oH=GJ1`;@ff^zCzgoqvn2Zg_kV0?^$aVQ}50X=YI6B7a)kGUHtCBIeY6%PM^mu zHB{%-$NMCD+ybMMZ!vysS#gO;Nmh^Dyq)IPO854(8v~@}Gun&XOsva}SmmJWJLzpP zd}%~hdo}tn&5kmQEWJKxUV872IO^8ucA~Oz>!ExQw#dpAJ(RW-zqi-QvO{~+cCx!b zp?YxoGSZ`St`rkQoxlv&_83cT)IKf?2+&=VpYjyK6YbKHu|;iba0rQn=OM#5#w5Sd zka#VsHjsYj6`wIm>+oEsxXQxT{86>|njSqwdq@B_KI-P)hD5r?o3B(cJ)k|<9kk8~ zZOo+Vom!DR%-wYK#C~0z&Kii%xIkBKOzYXeV3bTp5h}DT%Q_x>{{qu_v6-kwL+`>r&E!Kkom8Iu$9eBTIq*W6?Z9{j!7J<2ZB9{Bgp{qR9ZTUodC5W>3`HV>Ye4$zR2yGs zP;!Wf@QsgG2Ic8F5<6&#OdJj_+70KSo)*=`#j6->hNafCVKbKaZkN0)cAK` zlzmOTznMB3vHsK2&e`KDr^yGS5?~UzbM{!{oSynuNDAKjlTp#o@(~~;N$d025%(NJ zM--2tMY*8M;_D@l@shDKznJGIryqpU>k3=|iJ9|Uf75UBoLwo(NJPwWi$d!E&STts z{@^;VeEpfFbAeXK9;5*3pTP&mC>Y{SFVypxPcgL@Nc%0o3#O5j2NaF|Q9i^s->-9e zUt8v9mM-9FwA}_pMzeo&Vg_!f%q7L0!vzILDl+Ug$r$adPO>a}9;`Lu5}X0(Z}uT| zcKZ;6lsrR1Pm4PdEXJ-%m>#;6mv0BK^gxh>+xYy%Nh5F=S8x=cc>|8z@Y>sa4bIC- zw1(k`99*?GIK!+Cq|E+BE#Y$TW$4|nWh1tSBL(gBgmFiSX$=>wlrJ_ETJ%nRC1Btf zXd8#eSm!^o21qmRODMD)@y9PIUQ$; zsBfB=@>SiDnjGd@GmwY)<6B6cgq7Ebeuju*!%AR-ehGchDD;4I^=rX`a^{ogD%mXIB1vK5AD``pGY$aEoT3k z{SMd@>>X(SWsIezRPwDa=sp@w4}vWB_(5V>OIA^(4n8R}$|rr6WK&IQct}T#5rha*2RKor)4$D71)x znxQn>$Yb$nS|qLFGi8qk6CO}m3LT*wB!(QgO%=Clj&~UWNhSP|C#h7(x)9M68WCr9 zaSF{lgtxG(3L%d;B#U9sn)*|EtYm*K-N&^JqfviITV9ulPy{kqt{G)-#wxHPaw_xG zByk@l8Z!DXp>jhbrh2}@3m|dvsS?wie{tf}Io$O>_$N{%|NVu$y+vlmO!=&+{Z%Nb z2|uNg3MDIrA>W2$)~|v7a11fd4~TAxB*`YoG=F@?+3`J zHmZE#jvH{AV60*9!qXpEYIy8D_26^!YVEfiTo;6ITJ*X zl;W@!dqOWa9W3@;{S;fV_1VXJ(~hn??`~i2%Jc>l*38vlpIi6eA2mXcL(zbV zlWvByQ=+?z!kqQ3`_uWmDrVOJ?RUR^_&x|pR^!`WVyEAvM9D_lUUpgQX`q=Ni!O*> zM3t@bX+gGn2qM^nRZ*2%Sk&>B-IZYc(#!-d?2X{0?5_3#vB(c9%nfrksVD`6jlCu~nH z74rf}Ih5)FtE9SElIMuORahqi=%Nkxr>;b)Fe*qDufB)vC#m8(XBC3;;?cpo?1`0q zJO&Es(0q{*kFX2fTL9>Z==$IL_TBj(vBrP97KH2(OGKi|pMW6@jD+o>EF?tsoXv^^ zlw8TRC`7ZK`gMac$CCBXMdJZZ%=aV-0ULnMCQPV-#lVC>yV${Y(MhoH^8%H698fbt z)5)iuEglALt$)?hVS_ZC68-DeQkSNv+0!{IUj(dxXx_(2QaI%bkm@zXO8<2N5z_gl zHHV>yV%&V2Vt#+(pgU^A^}c=?3Aw~ovvZdCScwtKo3}?uk8sA934uSE&k}x1+M8^X z?vUPO^RLcewc4jP+%3UsyaF?ii-R4+9C&M|xSM$en!t>-ClOj=Scf9<{!jSaY&4G6T@S1VS8Z4EkoBc zl9wI0f=OrG?WAi()izWga|ny?5{sVf&h~KAvZh)bwp#AK+Zq0dfK@`++hvh8jS zCeEWz4rR~ggaoU;eTKSinP{kzL@IwbV zk6P!S*x}IheHLbbB9XAMcoLOs>Mkj9)}yH{C$)es`;d@= zHl^Z?;hNdTw9{y9MA3yh>f-ZsJrn%{L7_A07^)!eJ&b>ZpdYg_NT$9Ze zGltgc!%#Xc)Ml*x{kiV&iw1yvg(%~?>}ahX10kc{Xb#n=oeer#Mu2=cnnb39lwhB> zS3n&O0$lSpM%{Ub#(wYY|Ita5nvvB*AQD%W^{3Gu0k_U?G<=MLYaQ_y&>UUIU~=Dh zW`|m;z8gm6h@XwdaTF_B$3B=#lKKQxjzlorj9yWSA8q~Hgu>7r%NhJudG`0t@b}_` zu8m@Mb0x*0rPZZWK=0aj+3}y=#J@lCSt{HtnDJs0+B`|(0g*H`2Nf`&uLEnl2A6pq zZEd$6Jjf}nayc38X1{_?p7&lwPXcWz-2m5L@{=4?EWi>`Vy%k$BRFhDM8J2;IQNT@H9e1L+)dV-Uih0b^#kX z;cCG8r12&KOJaqiEbAFJn+Otoc=!6K;wA|`th@Q1pdiI$#q(|1O%qpSgN z?HGfd=kK-F!~KEVo89T>?-sX%9WjA85kS> z;9gY;$;*?=m%4!GTYBT^5x+jBTGcgX&5&35`T4uAbWlHqKa&lJfTsI~k1XUF;md?R zgR4**q6^nD@X~cp%QC#m2ZsEz&nB8?BwaK~+Aj9ndBmz&1;rpFJe)?dc-srnJ)Q!L z=}g4>CMgT!(hWRW{3bx=F8aVwc9(lEbpZivIDv$a z_cdmYg8KO(E}l0~mYqT*`OF!cAoa_vavlzjRKPC0Ih)w;Turk#T|h509pX7Y1k3sX z%!0mTz4}+^pg_yE^f+$CSb!-iS!bFkEwJ{;($ZR%CeZvcjm>}~DQD=Nt=H0-g zm4(nS*i^wwHfQzZnkk!OgH3Vb@l)o!Hl{C~u;BuH2=03s?6NnWj6xWOU*Xl6FVLjE z7gOU%@E0hag0zOTKMcqKUF|1R-hE#n_kr)Wpzp?D*=Q`NlZlqmP0{r?SHKRcU58_A z56Bg7md^YfWuK|_XmG07ON0`rBECs3wrc4rsM;EwDz6+2+sZl0ZIE%JJ7J}#Kwoa> zolwUp2qS(^^yj??E+Cl;YE!PN*mgnHbs?6Y(xF zHQEMdJ)4G`qH2Nx5OWb+Ki|VRQvqqx6I=xghKBdoG`y-niHGK`;F6z|v`u{+8sJ;#!3w)0oVvxmwTIDEkVeqB$vfv(0c-hh@{ zoV6(6kB`rTV_D4oiag|NqgKda5uLXeMd}TCX}DJVNZBu!TJW$N`kpOwKejG z|L{o5Pc)!_>9v{U+83aIy;nzOyGf;{ZP&RPtjsMAb`eb{Oh)~i0Weed))^hj6-nY!}>bTt4^klciEJcXlU8mf9Ftafv9)Z*i7FkZ(RiMteS z&Q$kb1xItSXH&i0oQ3`<#BlfT;1;#&G3N%;Qmx7gIYTVpy2ErQ@iO$r`0g zT=e}*eW<}_b7pw3>7zk3#LXoTsakj6_n^G!{8X&?F49xdz)`@YmE>(mF#pqM=N&w? zeK(T95?Tmba2k94hhuQvj1b8m!$02^rEfqLH$vjs6f7jclIBeMTx z$@&K4=mppot0$u{Z|_|cC5Y>o+Ot!lw}!o9U1S&0P0r&Vpd-?{f$k)KA`YA;Q~S6b5*wv9G*?uL5G z-2PL&IF=r5GUi6n1a+e@S<&&=0?}Dvy;i1Asy3$pj3>QHow%!=2`_6P46yK-G)5k~ zTS1k~oHm0UF9`rb$*zMpUx(FsaZLlYXke;C_{DG>u&QFDsT+1_^E{^Nt44QVXXa3l zrGAeT{^OTxQOscvi!Tc(`1w? z1`ixo>%K+;IB~T)J!oatKf{S6D=}_4J1eExL-jo~`H@Mvm$PGYH(e%gEbY5wmf2BQ`KdV6nR1F~Zq9M4JyAT(|Cl2&5ZDuLkP~?^&^MrFZ*QLj zjK1&>9^(}$U@Ojl#QK{hwNU(khtx&8k57;1>GOox2M%4%_O4zSt-C@LRUC;99QZSE zu!>GvsZr(!=RZR|THfU$$SvcQMbF+NiHPr>fQpOW1&Vi|u&}U^+#=~U-JP7uuLr6- zkOOn`5v0_#0L9fl$S#W|{=M=Mdl4Fw7yNnnwle}GT~k-rOb@gi)y&?mi)BC!A?QxjE9@(OQ3#5%7^bqI}G(n_jdG>x~E|GsK zI)8^8%Bfs%4yKN(xC8a*?*QU|T=4ZCtUx1^emceagI;_Mpf({^=x5~0F+q#XJHj9` zVLH|K<68k-1_$v}z?#lG<{$PB3VYPxj34!^6pe1DtOUWrN*!+YyAHNfAEkI94m#I* zYNx+_Yv#riXf~Ik{tMKM3KN8He0I;#o_7Z$1f81;Ps;ew9%U2+LTtLO!0h^Aqk;k; zqMFAs_6Vaz%Qgu7EiB0%WoYS^RiN2Qe$ReKO=0ludKZd=cZk@eo1qRKx6ZC0(u6-; z%>R;$|J(E1@%}oulw)e^Na?Y=-{vv=xTo+Ce7HM?9u{QeN~aaw6TFhSc9rO0v|?1| zW@}vO=S{52wdX*~tSF}%2EC!|+0Pme0@p)hW8-4Vv(zjei~FNkk`8TH=XojC$43MW z-hPsZ{;u5a_}mTscTq;6#Oi1Kd$CH(Y^7eaJJ3(>+f2-Adt)zo5b2oZ?iQg^{YL2B zj?hmvekP}^45uxKu||aQvCrq+ejZIJ;YLq;6wdC7y6&lPfHAFH?TjI1s0-!oK(H&Q s(tX)Jm!-O#j+(us{ePd~+NSx5Pl)RkZMYJ=3RU&O(`DgXcg literal 0 HcmV?d00001 diff --git a/plugins/entity-feedback/docs/starred-rating.png b/plugins/entity-feedback/docs/starred-rating.png new file mode 100644 index 0000000000000000000000000000000000000000..6198f7ae664d1278bfd6dd5de040c37c0fe5d519 GIT binary patch literal 9677 zcmd6MWmsIn(&j*b;2JCtEJ$#75AL2ofB}L98Qk512MF#CA-GFmaCZqF26uOdJ-PDT z`|SSOU%T@>XHHFbRdsc>y>CyLsT6UG2!tUgE2$0w!3hI$Dl!uAy?B}B3j(38 zSV%~y%1KC2s5;o1Sy-EbK(b*8NiQ`u244GZ!!Ba5W#1#@2f+|_5n^yXKm{MwP~<3b zf|9Wj4hGjy%TcMQv_Di*qL!EYl_FLdN_7Nyixa?^>NCx$&Z7x+9<`ps1dm0{kG!_q zo*zs{hlQUJ{YZxsWG9XAK^)yWlXkwWX4ZN_c(Yg(VlOTIP?;KqQi9&RevOWulKRYY zd`vkL`lp`s`ttbrxkU9Ao)`=C4sMmYH8RQH4vhnRNsM0O0NE{bLMlaY~%?;(31Om z7IGtMmgI!*-}y%+kkhEHa6$b}K{|52rzvN=&vK~GdN$z!bo;5;Ezz>Ha@$)^S-R(K zG;j4q@VkhJsdKm}NK=UWpO#dH(A6vXEWrJ*B5v@m@R;IXN-D9dY`qcf@hVq|`3$*h zS)o@ZxV3-fQ_c5XgDK`#TCs|YQxAtxXKy6)bGeg1xe&8_4k0QZ>a%-ie=_|jfz(*q zXPr-yHK0*uE@8~VZVjc^?I5Jf{3Pi-&MHzw_ZDPZjSM(8D8@+@# zH_D5W^anIL;Bf8O3)QbsiY0@bBvYApGiH<_jvkPr&sZ8w{y7@xEq2AjOtd6T_VBba!!@ZrwRQD%FAN`^l*z&xR`ITJKc}b6 zm>x+*oq2AIzEatbm52Mn1QL5(tsS)^1jT!SUVn0Tu(-;{6n<(4QDsvsBVlB}K=-4s zl&p3{C~wER2@u1ErxGXCMs^cJ=J0#P1UJ-fsR{~jH>`-bHYMq7}KDySgnbM}R5;yZ#t68wO08JfKOBK)HFn#9GZ zS|OIwbvZV9ztkj(RK75!2AkzFPn7R~oL;4dfFr^FFu!s!a!KB7)@<86&+)DuTOtl= zG-H4J4m-B0r{GAZWLc6&qetQ=WW=}?&)ra&u>ntPT5b(Vq;@l zV{6otV`VK8)SD*N3Wnr`<+EfpWBCWt;>BX)cw#YQKFMOq+76ghv(Lwos*F%Vq$4|!7q1qjVWS?biOkT;0AtWgz-LHc zpws%LDXnQy%u`HROk7N&iS-k#_9lC+s8`c~AuCm-tT6M()ubxdi&WlkGP(+j3eB?n zdB(f6PME?8U`f&Uwm+~+)TR%nbEh4CGfXR&ICH9^8zY5$AD!#w>uv125t8sk@(ecY zy(4z!6fpNv&H8!tlSP$Pv*Kf0$&*gt&()Ieg=(b}MW>Q@WftYcg-w!(P&LYUm;@yP?u!vQMnap;kEM|-DsXLYfEnMH(+p^Y?vRDe{5 z)D`?I*byU%c;>YT7Zp)eWRUb? z4ybW3w{c2A${|;?DQ22rGTI2^i0!9#f+zy2hzx=^HEcEM=3(YqBYV}Y(K3J8$E(4G7q`whuc5_)gu${r2*`4t$BcE4=z(Z!{xE5QgxEnU-KP(x!JNa>NXhC7mxpP0TA>!KMn1DP!x=kfVrI~e_cd()J`e#@g6CA=?bX}1zlVY&gQJ_Q|)sb3*Gd*oF1NTzTdWa5g!d;MB^qbWEFyjR);q4xKYuv)1IoX5!xU(gbT)Y%PoB88b05GtV1_E&lGM0 z;d#ZwvPI{ao2cC>dYDZW2D8T{v}s9k-6I$zD>PoHyZ-QzMUxYZ;YlQm184b<$qw_; z7lu!D6LL6nIC2P56U4&HU4KsM(Iv!E2+Y4Xjj{GGrH_c>lAqlyJUiYHo<*Ie($x5G42-ou5+B_^0x#a!NvVVI>HSnfEnN%ysU zO2OBH<9e0_kAmS=>ua7hp4L!{9|;+h=vk(nj4~EuA(AtG>H8J3hT_=vlM8kbr+WLG|BogekbhzsUn(uC5J5b2I_Pynm)e-B$^QGU7*mcKAAfaWt zr6s1tn*~j@*+Hw9SahVV&fVLx8X2ZbnI6*K6KZyvJ{LVIVWLZd1Wu)weEV)oW749> zeBy#?b0F>w9&}z*lIFCvQ~_nAOlyb>MC3GLn)RjfZbq?CnTy91@mk6Qr?L6@XjHB2 zr{K|o^nHl_@4FqZgIhtuPL^5&^j~hbvC9SLkc0Y~q$QTDUuzDV8(K5dy;f1PugeAX zMD4p)d&6A%u7cB)dDCq8mo1Nyr|b)-^3MN2vKEt$?2h!B1&?j|phce7&A7jQ9iJa# z3Ca4N+!usk>l6aS(7?mp^cVTI3A*Ln1QS5=pHML|U$%-XHw z^r~I(-nHy)&Rdmb^A_?))f=_-^$wL%6-bt`$aOT!ZNREelBRBwTFQxkN4RFz5yuk&tY_)Cn)v^*}u^I`U^k^%OFEf z#K}pjC;EP0@pp(5&G2)h%Ir@x)h2?Aat72``P}XtJXbTXKzi&TgNVLf>5{(Q)(>w7 zMBuY&T&pX{3E#g2@jtF#7#eIdoM5FK+&-(Xi<+}#`U~G|KhVWFlaBcgX$%37_k*dn zoSBjmhyjq1L2w}!AOt{y1D@Bw0|LE>4FHM_B}D;aTL_DhiS1`o7B`69UlWj!n*bm}Or4A< z+#uFAjskANRR7Qr0OY^LtW*^LP;s&nrqWhYrI4_7Fs0yOVPj#V5<#V)pb&B}F%wXi zl>V1F@JpELi<6U`04uAjt1F8uCyT9vIV(FqKR+uQ2P+2$GoZoj=x*a=2{`1YSp z{_RK7)X~_%!p_OU)`sG*U!%{q&Q8KqRDT=#pU*$zGk6=07d|m!hM&@6}|6TbnLm}3`J^!yv{4>q}Ciid)q1OgG6 z$VrN8y1^Z0xDLPSdF~5=RZ(a?qK4Dt=4KbYLnV^>hW$+q0j)P6JeCO8^Zutc+h@(n zZr@jk_}?(X^u-YYVst?9j_S?#^4jI=x+gPV&pyWnPgl>e`fKX@Kd^&?VRLZJH7sRp z_(6C{m`%ert-1)*9tTRB5O>!(XmZpg}XneHr?#bh_v zm+@={Bt{J!Y=0-bxmt_3`AVa}`CrZ@KZ8%EG0?K`TN0Ud|?)shLzl5^|{68M3Ct$M<;9jn()bDhhZVYKn=W&m|?JR53>IxKMQ7)?$|b?+bID z(E2UyHkRd%8rP#*bt?3lCLbQJms@vZGyR@l)eW&UH%@D}dNr*YY$2kQ={E3O?msVX z?9Y^OmVB(hbojJ3Wl{$Vvu$M1qPWU+?Z%NwCb4aqXt--p@Llcvx>b+_=BQ{nlmGHu zlc!bk;i#>4!`J@la@L@=UNbdYJH_*;>4*ExYRD25kZ&`ehf|qr&#H`xJef3o*QIH> zvxoDsG#PU5TJ5uLQmfxZ-{&oUWaxP&vFPtTjA@dnmBM(huuyc&0B%F>!{x6%SLKXEM`HZ0p*Ex8)djqF#n*&IQyVY$0qd_+~1)ARgruF}AL!)yOW&}H~mWk=?XbNudX zMV9;d2=9{90=wDPaEjT{pC-(31D{(OPTA^D$HQE9VfaevJ4)$%6D<#CL;TYlZ8=%4 zF!!z6DP_m?X#OptuuO&Zt66 zi{95u4GNzcZ1f#>azawOFa?KG&<$fv4j1aoIsy>4)}uv7PrqFrF3xgU%`lncZi+tN zM(-}SwZ$DT+O|P>Z2s&dPSjdxI09)-1G>JbdR5W(WZ8OuB*+OEbmfc3VCN5~p5+|C zpq?bb?m@Tb+i6%LH|-Bk_s9GLkSEE>^)3;TWQq>o1*oTM4UnlckIOxN;l1OwXP9CN zM^C9i8;lm?K?gMsdbKcg(DwYK3@iCi#zF3Lle7E#XB_`o|JxCt`$O~4Jg{xcX|NUA zlbjxL{&_GEI;>QuruX4$(H8SLbq})M5@!Ot+DttGOT?#%8r6=8+&7kEc@0)TuRcYw zPFTfVtxHhg=e|@9!oqpqkNhCk;!oaRq?V_6e{~3*I1&-=k&B~EsWR?MW!9}vJ|7cZ zcD`Gb)c@tgZjB&084jK;*B_bwXaHHLvoeoM%@p<&xQ`%Y<(W0`g}x0q>VOv%9~>5~ zlZqgS%9^-)b9mYj_)^fPoS4&Wt|(oA{kxGA7VQlK^lC9qSzwpiakn5TmBgm8!|U;K zmS^F*Mw2%5kS0lQZR5TROOy}ZafrEr=no-G%=T%)s=}GJ47-c5qGi%^ZociL6D>o< ztMZRiiyj0DwdZ+Zdk=G-)#rDw(5~uq({UI@B-C5^BR2oMm1aAxL7pLeII|DagvrRqD#UrtWtfGabGg5x%xb73$ZRy@u`OhB% z6SZ$elxEzx`TnTc(F59ZRvM2YT)Jq}Jc85m;NiS8-hocc(M_M3h6!1{JazDsLtl#+ zslBg~W`Z7uHg}T{A(A@uQ`*Eo^s$7`9aES8=)>-BCW|&A?h*(t<*78Y-TVFXs>E@) zIe+!nemQ52`It+TUEklz2tWxYIWGb+a%J?1Ehjx02s#bnS#6|U|JaADd+bb?BoPZZ73GKo z8Al7x;27EHS^qg{sc8s>E+0U!XByd(QE0~<&A;VAQPxl^t;m|lmVKYS=`xJV8fP>vQpyJ7(JI;@beLK6{P7ukHpxikT_Nnr z`ik}KuzHAv6FmpzkK)67ZACKo4V(tTD3vP5?a^`&B~NHw1KpPSNB+KDsLq5$=x)cS z8RROAsX`^k$4DOKtW%m8zKL^*fpKJeqnv7toAT1+C@+RZB*7TJ()g0)} zH)|0ML&2GFrjsQ3Nw4d7yzdVi_)WK1HDN{}ZychweT{Ze*Nl3iQE)ue9k+(rH%8c^ z!6xHjk(J4FSJhWrvk}DimJwullsAN@Z*W%vb|%seC-OqLM_MjtbdOqH)>J6$b3w(0G0|{T>pyo0cC#dw z#~a`JFw#2hKsl`GZl=+y%y5G#MWOVbm^I_p7Y`>H>~L&0fA|{c_Nhx(RfrUyZnwz; zpMR6IK;*oz4GOLw9IkP=7(MjN^#t{-kjdeiMSyMIp=Q<{2fP3AQpQm1r_|d1?M_~_ zgR%tjsVT;5uKqCFKaEwpQ$M25C1?VgIi4u*C5+~J+2&vaV?yVO=DQNgg>bEINx4j) zYTuck>ov@C6gw*oxyviD-z}tG@kTpI8fBirA_xIEiN0!6dfgaUkM#-;zvi>cW^}uO zmjBvgkg)AUVobd999NlHo1X`hZqN7pl!9rq5;T=qgb0XFcr`yg5~6Y1c}~m#F2KaW7>o` z`)ENH>mkax$JIm+&bO`N4;H`)k?sC)+Lyun{E$A3>P5eu4zDv!zoU&9hHR{{LWCliy{k+=M1+mB z6{@hZMy==NgB62s!s@U8JY3cF72#RIHGNnyQ_I~!L$tL`dd2*_oJrmgW24yX+!l=F|wb=Yh5hL z+q)z@9;ZIJA0zAVg$dHvn+4Y+IrTVKx||DQgy4S?!vdauWcfJgf<)u-1$;_{()RVE zL;UQox9s!ivb-jRqjM_pC8+qL`=(Ht=M5bKU{w2?XHzF#*}U!WTiMVS3e#V`!L?lh zmNV>Y(KQ_$*_cd&X6&}(Vab+kRW8#Pa?RCZ_uE;%<-2whd~H{CbW?%XNMv#~xjWxx zeI8JL-yY*3KbIGlwSO?HXe3#v1LK=$O=}SMa{S4c5vz#lD-9TJVK41Sl8DB(KOa^9 zlqVNx5DG?8klT^kM9Wbk+2E8-5kI4+!4NjlLttAg^z)n6oXvI*9_g;oTL>ZJJ(MT0 z(?>$_Db*PpKn0PwRY9H@;5`+yR&fl2{D;D>P#8_*FFFGXy{g6i3It1!^Jj;GqBDB7 zLi!_pRmDe;%JzO&zs^l!$O1c8GR~Ib8rt)WDQ>?cyNp}e)Q}r>4FfwY$R|oG`k6<& zSCBpFe%-*0*`aATG;vQrVe{{*nH+{ckF36SKVl#(J1CJA%l#`-iUCo5 zI=wg&U{B<5VVUHVZwTRVWbxs`z{RN=2{`}PL5meVW0V2Q-)Hl$e?Mdd+RD#8;q4ZI zwCGwFiA*}UwR#13a6t63$Y0z@P+agC;Hj|xHmA9vRSpD14P@ZE;l~^xFKR&lq@=)` z;eN=H@5OQn|DP!%UwV6}X}#YJ7ZdRpaNbM4yWIZ=sMTHi<&0r(9Rzfje{rTvcLd;# z=@4LVQr7bU-(|7@1L0I>zGXF)E&jr|;WJw)h$=WV4`&J5 z;mOSxQRmYy-NJxdIKSlCtW3>xZ}YiA7)ppziJ)%*T+ zJ)6WFj|W6y;c}%;xcnX$np~$i$#Q17FqEbWsEByqB?ELNWMOaai-8WlW$*JyX{uLO zJvaSr!QIyv8G^1n`pquR3jvS(j$7To^i6DS&Vz*ACw^+sO%*5*{=mN49!X2mHAGyl zO!%n&l{nT#I7sK(aw}mk6Sn&!>!|wtsQEkl;_1T9Qglj6IX{>LdT$ee>e_j=nc*-< zUoHjn=B*CMsD$*qN*>J+oMqCf?w+q`7s}Y9jQKRNK0-v7ZWo}dbrlw26$4#tP)vS5 zS*pX?H9muM6^6zbWWmTYzrXsG5X=UQwPX1vpFx|Eed#x^J*Q)sw{8LA=^h09Ypz(U zM81aM){7+wU@ECDhYS4MX9K;6BPZ=7M6hz*hEXPP%iKI)?^7f(=P*ENpmHVkte$~+ zkcr%{t0TPy2n$e|XtF}3G@ellfV#U}g_+ClW1!nMktMR|TLLqCi}dsJl!~bH8r0(P z%Kh*mmD}ne7UJ46cRAkb?aAqOVz`|SoHYx70nORIYcr}QKd|!gM-RM{MW(v%FR&T? z{?Y)#Hhl5@?e(C)WPS!A`pks&RlrvV7AMKbb0kdC9bMU0WQWeVDq{r#p;5-Z52HhE zWM(6&o9O0E#Ex5%{Cj^qr|UUL?WKojiv>@(-*VtL zL9g+b9k=$8r2LZr=`5I0N`!XAB;6+y3OD{`tTs!(5Hlb3+kBu+0O%O5wU`PZPD(GoDS(vBrNHT$=8`oZN7z4D#!=bc~CMv@GCEC3q3$>@a)Q{r7R zF&oP~wAK9nYBQWnXJOxHJX<`f*$iMgTUowO1N7f=PIe~pM#wx5aBeTtjJ5IGG$k(N z9g{Vy9E?mx>f;aB`C| zVIdrH<&jP3db^oqYtCX%8ZmU)oZ*iWCY!L+L24iipft3#Z6b>`Toc>XL}UrsTiP z8jG$>ZH>;D0*kqv4(8bD&=T`1-2=VlyGTCn`4H8s7edK^i=HjT(m6RyTAk4ILi^So zl>r3YHWQk*-Vfs^OY9@ZP(iTc2>0lT9~aYIq(lt#t1cxvWtFh7m#cAaq&*#DC^>My z!+Bxqd$uv~6$8bN8eNyZ7mO8})?payF6ZAPInyT zUwp$#^Z9abnijncJXs#1PLvQ=|2iU0gU*8qc9B+u99x)<#IT)CQI8;}p*+8tj@O+? zVG)oxvM?qOtL=;<_QAs!pL|u5M2Jy&Kof}_q#wg&G>01^MD1b!1#w=r1OdCHhyePs z>|Fri70HKy#EdJaX>90kC6oL|s{T)p*m0E)rqhNY5Zo5am@;rCE_AO-Ym^eFXhSX} zM)6&;QaXh3i&HO_>;;Dp9Cgm!MLv%$j8ssgN)FmG#~o22jw@^+DUbaUo`lyXGLV>` zr+cE1^u=X?G_ae$u6oB|gK&~@dg87JU*A1HOGKz_Un`MI*!SVP5;yKj*<1UQ93zP* z5>-ns?eA5<^=5==O@GmQ1R`~5dcOEFBS_ASoOFvMEAb&Uqc8%|C+UgxykS0!Dq-1L zU3lOKL8*-A5<%F3Oc#RG5#!30*(8i&(81WxGf47pWWJ0W( z%Ku6e`=AmAK3im);uec^dlZc>;kNwUe>SN8s+53P@@A$*u{2gz^ELLsQmcQURz) z0haiyQv(3}kps}8!l#Gde>S(#eK;NPJWe{buCl30^Y zv?e(OJ|b|)f|yq~D_R~GT5q_m(Q`t{q>W0sW5{hXDG32!3+0{QJL=oRqR;`Fq2F{{({ + id: 'plugin.entity-feedback.service', +}); + +/** + * @public + */ +export interface EntityFeedbackApi { + getAllRatings(): Promise; + + getOwnedRatings(ownerRef: string): Promise; + + recordRating(entityRef: string, rating: string): Promise; + + getRatings(entityRef: string): Promise[]>; + + recordResponse( + entityRef: string, + response: Omit, + ): Promise; + + getResponses(entityRef: string): Promise[]>; +} diff --git a/plugins/entity-feedback/src/api/EntityFeedbackClient.test.ts b/plugins/entity-feedback/src/api/EntityFeedbackClient.test.ts new file mode 100644 index 0000000000..694fd66b06 --- /dev/null +++ b/plugins/entity-feedback/src/api/EntityFeedbackClient.test.ts @@ -0,0 +1,175 @@ +/* + * Copyright 2023 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 { EntityFeedbackClient } from './EntityFeedbackClient'; + +const server = setupServer(); + +describe('EntityFeedbackClient', () => { + setupRequestMockHandlers(server); + const mockBaseUrl = 'http://backstage/api/entity-feedback'; + const discoveryApi = { getBaseUrl: async () => mockBaseUrl }; + const fetchApi = new MockFetchApi(); + + let client: EntityFeedbackClient; + beforeEach(() => { + client = new EntityFeedbackClient({ discoveryApi, fetchApi }); + }); + + it('getAllRatings', async () => { + const ratings = [ + { + entityRef: 'component:default/foo', + entityTitle: 'Foo', + ratings: { LIKE: 10 }, + }, + { + entityRef: 'component:default/bar', + entityTitle: 'Bar', + ratings: { DISLIKE: 10 }, + }, + ]; + + server.use( + rest.get(`${mockBaseUrl}/ratings`, (_, res, ctx) => + res(ctx.json(ratings)), + ), + ); + + const response = await client.getAllRatings(); + expect(response).toEqual(ratings); + }); + + it('getOwnedRatings', async () => { + const ratings = [ + { + entityRef: 'component:default/foo', + entityTitle: 'Foo', + ratings: { LIKE: 10 }, + }, + { + entityRef: 'component:default/bar', + entityTitle: 'Bar', + ratings: { DISLIKE: 10 }, + }, + ]; + + server.use( + rest.get( + `${mockBaseUrl}/ratings?ownerRef=${encodeURIComponent( + 'group:default/team', + )}`, + (_, res, ctx) => res(ctx.json(ratings)), + ), + ); + + const response = await client.getOwnedRatings('group:default/team'); + expect(response).toEqual(ratings); + }); + + it('recordRating', async () => { + expect.assertions(1); + + server.use( + rest.post( + `${mockBaseUrl}/ratings/${encodeURIComponent( + 'component:default/service', + )}`, + (req, res) => { + expect(req.body).toEqual({ rating: 'LIKE' }); + return res(); + }, + ), + ); + + await client.recordRating('component:default/service', 'LIKE'); + }); + + it('getRatings', async () => { + const ratings = [ + { userRef: 'user:default/foo', rating: 'LIKE' }, + { userRef: 'user:default/bar', rating: 'LIKE' }, + ]; + + server.use( + rest.get( + `${mockBaseUrl}/ratings/${encodeURIComponent( + 'component:default/service', + )}`, + (_, res, ctx) => res(ctx.json(ratings)), + ), + ); + + const response = await client.getRatings('component:default/service'); + expect(response).toEqual(ratings); + }); + + it('recordResponse', async () => { + expect.assertions(1); + const response = { + response: 'blah', + comments: 'feedback', + consent: false, + }; + + server.use( + rest.post( + `${mockBaseUrl}/responses/${encodeURIComponent( + 'component:default/service', + )}`, + (req, res) => { + expect(req.body).toEqual(response); + return res(); + }, + ), + ); + + await client.recordResponse('component:default/service', response); + }); + + it('getResponses', async () => { + const responses = [ + { + userRef: 'user:default/foo', + response: 'asdf', + comments: 'here is new feedback', + consent: false, + }, + { + userRef: 'user:default/bar', + response: 'noop', + comments: 'here is different feedback', + consent: true, + }, + ]; + + server.use( + rest.get( + `${mockBaseUrl}/responses/${encodeURIComponent( + 'component:default/service', + )}`, + (_, res, ctx) => res(ctx.json(responses)), + ), + ); + + const response = await client.getResponses('component:default/service'); + expect(response).toEqual(responses); + }); +}); diff --git a/plugins/entity-feedback/src/api/EntityFeedbackClient.ts b/plugins/entity-feedback/src/api/EntityFeedbackClient.ts new file mode 100644 index 0000000000..43d3cbe95a --- /dev/null +++ b/plugins/entity-feedback/src/api/EntityFeedbackClient.ts @@ -0,0 +1,136 @@ +/* + * Copyright 2023 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 { + EntityRatingsData, + Rating, + Response, +} from '@backstage/plugin-entity-feedback-common'; + +import { EntityFeedbackApi } from './EntityFeedbackApi'; + +/** + * @public + */ +export class EntityFeedbackClient implements EntityFeedbackApi { + private readonly discoveryApi: DiscoveryApi; + private readonly fetchApi: FetchApi; + + constructor(options: { discoveryApi: DiscoveryApi; fetchApi: FetchApi }) { + this.discoveryApi = options.discoveryApi; + this.fetchApi = options.fetchApi; + } + + async getAllRatings(): Promise { + const baseUrl = await this.discoveryApi.getBaseUrl('entity-feedback'); + const resp = await this.fetchApi.fetch(`${baseUrl}/ratings`, { + method: 'GET', + }); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + + return resp.json(); + } + + async getOwnedRatings(ownerRef: string): Promise { + const baseUrl = await this.discoveryApi.getBaseUrl('entity-feedback'); + const resp = await this.fetchApi.fetch( + `${baseUrl}/ratings?ownerRef=${encodeURIComponent(ownerRef)}`, + { + method: 'GET', + }, + ); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + + return resp.json(); + } + + async recordRating(entityRef: string, rating: string) { + const baseUrl = await this.discoveryApi.getBaseUrl('entity-feedback'); + const resp = await this.fetchApi.fetch( + `${baseUrl}/ratings/${encodeURIComponent(entityRef)}`, + { + headers: { 'Content-Type': 'application/json' }, + method: 'POST', + body: JSON.stringify({ rating }), + }, + ); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + } + + async getRatings(entityRef: string): Promise[]> { + const baseUrl = await this.discoveryApi.getBaseUrl('entity-feedback'); + const resp = await this.fetchApi.fetch( + `${baseUrl}/ratings/${encodeURIComponent(entityRef)}`, + { + method: 'GET', + }, + ); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + + return resp.json(); + } + + async recordResponse( + entityRef: string, + response: Omit, + ) { + const baseUrl = await this.discoveryApi.getBaseUrl('entity-feedback'); + const resp = await this.fetchApi.fetch( + `${baseUrl}/responses/${encodeURIComponent(entityRef)}`, + { + headers: { 'Content-Type': 'application/json' }, + method: 'POST', + body: JSON.stringify(response), + }, + ); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + } + + async getResponses( + entityRef: string, + ): Promise[]> { + const baseUrl = await this.discoveryApi.getBaseUrl('entity-feedback'); + const resp = await this.fetchApi.fetch( + `${baseUrl}/responses/${encodeURIComponent(entityRef)}`, + { + method: 'GET', + }, + ); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + + return resp.json(); + } +} diff --git a/plugins/entity-feedback/src/api/index.ts b/plugins/entity-feedback/src/api/index.ts new file mode 100644 index 0000000000..32c8624425 --- /dev/null +++ b/plugins/entity-feedback/src/api/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 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 './EntityFeedbackClient'; +export * from './EntityFeedbackApi'; diff --git a/plugins/entity-feedback/src/components/FeedbackRatingsTable/FeedbackRatingsTable.test.tsx b/plugins/entity-feedback/src/components/FeedbackRatingsTable/FeedbackRatingsTable.test.tsx new file mode 100644 index 0000000000..b639b2e727 --- /dev/null +++ b/plugins/entity-feedback/src/components/FeedbackRatingsTable/FeedbackRatingsTable.test.tsx @@ -0,0 +1,117 @@ +/* + * Copyright 2023 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, TestApiProvider } from '@backstage/test-utils'; +import React from 'react'; +import { EntityFeedbackApi, entityFeedbackApiRef } from '../../api'; +import { FeedbackRatingsTable } from './FeedbackRatingsTable'; + +describe('FeedbackRatingsTable', () => { + const sampleRatings = [ + { + entityRef: 'component:default/foo', + entityTitle: 'Foo Component', + ratings: { 'Rating 1': 3, 'Rating 2': 1 }, + }, + { + entityRef: 'system:default/bar', + entityTitle: 'Bar Component', + ratings: { 'Rating 1': 5 }, + }, + { + entityRef: 'domain:default/hello-world', + entityTitle: 'Hello World', + ratings: { 'Rating 3': 5 }, + }, + ]; + + const feedbackApi: Partial = { + getAllRatings: jest.fn().mockImplementation(async () => sampleRatings), + getOwnedRatings: jest.fn().mockImplementation(async () => sampleRatings), + }; + + const sampleRatingValues = ['Rating 1', 'Rating 2']; + + const render = async (props: any = {}) => + renderInTestApp( + + + , + { + mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef }, + }, + ); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders all ratings correctly', async () => { + const rendered = await render({ allEntities: true }); + + expect(feedbackApi.getAllRatings).toHaveBeenCalled(); + expect(feedbackApi.getOwnedRatings).not.toHaveBeenCalled(); + + expect(rendered.getByText('Entity Ratings')).toBeInTheDocument(); + + // Columns + expect(rendered.getByText('Entity')).toBeInTheDocument(); + expect(rendered.getByText('Rating 1')).toBeInTheDocument(); + expect(rendered.getByText('Rating 2')).toBeInTheDocument(); + + // Rows + expect(rendered.getByText('Foo Component')).toBeInTheDocument(); + expect(rendered.getByText('component')).toBeInTheDocument(); + expect(rendered.getByText('3')).toBeInTheDocument(); + expect(rendered.getByText('1')).toBeInTheDocument(); + expect(rendered.getByText('Bar Component')).toBeInTheDocument(); + expect(rendered.getByText('system')).toBeInTheDocument(); + expect(rendered.getByText('5')).toBeInTheDocument(); + + expect(rendered.queryByText('Hello World')).toBeNull(); + }); + + it('renders owned entity ratings correctly', async () => { + const rendered = await render({ + ownerRef: 'group:default/test-team', + title: 'Custom Title', + }); + + expect(feedbackApi.getAllRatings).not.toHaveBeenCalled(); + expect(feedbackApi.getOwnedRatings).toHaveBeenCalledWith( + 'group:default/test-team', + ); + + expect(rendered.getByText('Custom Title')).toBeInTheDocument(); + + // Columns + expect(rendered.getByText('Entity')).toBeInTheDocument(); + expect(rendered.getByText('Rating 1')).toBeInTheDocument(); + expect(rendered.getByText('Rating 2')).toBeInTheDocument(); + + // Rows + expect(rendered.getByText('Foo Component')).toBeInTheDocument(); + expect(rendered.getByText('component')).toBeInTheDocument(); + expect(rendered.getByText('3')).toBeInTheDocument(); + expect(rendered.getByText('1')).toBeInTheDocument(); + expect(rendered.getByText('Bar Component')).toBeInTheDocument(); + expect(rendered.getByText('system')).toBeInTheDocument(); + expect(rendered.getByText('5')).toBeInTheDocument(); + + expect(rendered.queryByText('Hello World')).toBeNull(); + }); +}); diff --git a/plugins/entity-feedback/src/components/FeedbackRatingsTable/FeedbackRatingsTable.tsx b/plugins/entity-feedback/src/components/FeedbackRatingsTable/FeedbackRatingsTable.tsx new file mode 100644 index 0000000000..48b2018729 --- /dev/null +++ b/plugins/entity-feedback/src/components/FeedbackRatingsTable/FeedbackRatingsTable.tsx @@ -0,0 +1,123 @@ +/* + * Copyright 2023 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 { ErrorPanel, SubvalueCell, Table } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; +import { EntityRefLink } from '@backstage/plugin-catalog-react'; +import { EntityRatingsData } from '@backstage/plugin-entity-feedback-common'; +import React from 'react'; +import useAsync from 'react-use/lib/useAsync'; + +import { entityFeedbackApiRef } from '../../api'; + +interface FeedbackRatingsTableProps { + allEntities?: boolean; + ownerRef?: string; + ratingValues: string[]; + title?: string; +} + +export const FeedbackRatingsTable = (props: FeedbackRatingsTableProps) => { + const { + allEntities, + ownerRef, + ratingValues, + title = 'Entity Ratings', + } = props; + const feedbackApi = useApi(entityFeedbackApiRef); + + const { + error, + loading, + value: ratings, + } = useAsync(async () => { + if (allEntities) { + return feedbackApi.getAllRatings(); + } + + if (!ownerRef) { + return []; + } + + return feedbackApi.getOwnedRatings(ownerRef); + }, [allEntities, feedbackApi, ownerRef]); + + const columns = [ + { title: 'Title', field: 'entityTitle', hidden: true, searchable: true }, + { + title: 'Entity', + field: 'entityRef', + highlight: true, + customSort: (a: EntityRatingsData, b: EntityRatingsData) => { + const titleA = a.entityTitle ?? parseEntityRef(a.entityRef).name; + const titleB = b.entityTitle ?? parseEntityRef(b.entityRef).name; + return titleA.localeCompare(titleB); + }, + render: (rating: EntityRatingsData) => { + const compoundRef = parseEntityRef(rating.entityRef); + return ( + + } + subvalue={compoundRef.kind} + /> + ); + }, + }, + ...ratingValues.map(ratingVal => ({ + title: ratingVal, + field: `ratings.${ratingVal}`, + })), + ]; + + // Exclude entities that don't have applicable ratings + const ratingsRows = ratings?.filter(r => + Object.keys(r.ratings).some(v => ratingValues.includes(v)), + ); + + if (error) { + return ( + + ); + } + + return ( + + columns={columns} + data={ratingsRows ?? []} + isLoading={loading} + options={{ + emptyRowsWhenPaging: false, + loadingType: 'linear', + pageSize: 20, + pageSizeOptions: [20, 50, 100], + paging: true, + showEmptyDataSourceMessage: !loading, + }} + title={title} + /> + ); +}; diff --git a/plugins/entity-feedback/src/components/FeedbackRatingsTable/index.ts b/plugins/entity-feedback/src/components/FeedbackRatingsTable/index.ts new file mode 100644 index 0000000000..565063b3fa --- /dev/null +++ b/plugins/entity-feedback/src/components/FeedbackRatingsTable/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './FeedbackRatingsTable'; diff --git a/plugins/entity-feedback/src/components/FeedbackResponseDialog/FeedbackResponseDialog.test.tsx b/plugins/entity-feedback/src/components/FeedbackResponseDialog/FeedbackResponseDialog.test.tsx new file mode 100644 index 0000000000..631738d6f9 --- /dev/null +++ b/plugins/entity-feedback/src/components/FeedbackResponseDialog/FeedbackResponseDialog.test.tsx @@ -0,0 +1,118 @@ +/* + * Copyright 2023 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 { ErrorApi, errorApiRef } from '@backstage/core-plugin-api'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { getByRole, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; + +import { EntityFeedbackApi, entityFeedbackApiRef } from '../../api'; +import { FeedbackResponseDialog } from './FeedbackResponseDialog'; + +describe('FeedbackResponseDialog', () => { + const testEntity: Partial = { + kind: 'component', + metadata: { name: 'test', namespace: 'default' }, + }; + const errorApi: Partial = { post: jest.fn() }; + const feedbackApi: Partial = { + recordResponse: jest.fn().mockImplementation(() => Promise.resolve()), + }; + + const render = async (props: any = {}) => + renderInTestApp( + + + , + ); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('allows customization of the dialog title', async () => { + const rendered = await render(); + expect( + rendered.getByText('Please provide feedback on what can be improved'), + ).toBeInTheDocument(); + + const customRendered = await render({ feedbackDialogTitle: 'Test Title' }); + expect(customRendered.getByText('Test Title')).toBeInTheDocument(); + }); + + it('allows customization of the reponse options', async () => { + const rendered = await render(); + expect(rendered.getByText('Incorrect info')).toBeInTheDocument(); + expect(rendered.getByText('Missing info')).toBeInTheDocument(); + expect( + rendered.getByText('Other (please specify below)'), + ).toBeInTheDocument(); + + const customResponses = [ + { id: 'foo', label: 'Foo option' }, + { id: 'bar', label: 'Bar option' }, + ]; + const customRendered = await render({ + feedbackDialogResponses: customResponses, + }); + expect(customRendered.getByText('Foo option')).toBeInTheDocument(); + expect(customRendered.getByText('Bar option')).toBeInTheDocument(); + }); + + it('handles saving user responses', async () => { + const rendered = await render(); + + await userEvent.click( + rendered.getByRole('checkbox', { name: 'Incorrect info' }), + ); + await userEvent.click( + rendered.getByRole('checkbox', { name: 'Other (please specify below)' }), + ); + await userEvent.type( + getByRole( + rendered.getByTestId('feedback-response-dialog-comments-input'), + 'textbox', + ), + 'test comments', + ); + await userEvent.click( + rendered.getByTestId('feedback-response-dialog-submit-button'), + ); + + await waitFor(() => { + expect(feedbackApi.recordResponse).toHaveBeenCalledWith( + 'component:default/test', + { + comments: 'test comments', + consent: true, + response: 'incorrect,other', + }, + ); + }); + }); +}); diff --git a/plugins/entity-feedback/src/components/FeedbackResponseDialog/FeedbackResponseDialog.tsx b/plugins/entity-feedback/src/components/FeedbackResponseDialog/FeedbackResponseDialog.tsx new file mode 100644 index 0000000000..c3f935e432 --- /dev/null +++ b/plugins/entity-feedback/src/components/FeedbackResponseDialog/FeedbackResponseDialog.tsx @@ -0,0 +1,176 @@ +/* + * Copyright 2023 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, stringifyEntityRef } from '@backstage/catalog-model'; +import { Progress } from '@backstage/core-components'; +import { ErrorApiError, errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { + Button, + Checkbox, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + FormControl, + FormControlLabel, + FormGroup, + FormLabel, + Grid, + makeStyles, + Switch, + TextField, + Typography, +} from '@material-ui/core'; +import React, { ReactNode, useState } from 'react'; +import useAsyncFn from 'react-use/lib/useAsyncFn'; + +import { entityFeedbackApiRef } from '../../api'; + +/** + * @public + */ +export interface EntityFeedbackResponse { + id: string; + label: string; +} + +const defaultFeedbackResponses: EntityFeedbackResponse[] = [ + { id: 'incorrect', label: 'Incorrect info' }, + { id: 'missing', label: 'Missing info' }, + { id: 'other', label: 'Other (please specify below)' }, +]; + +/** + * @public + */ +export interface FeedbackResponseDialogProps { + entity: Entity; + feedbackDialogResponses?: EntityFeedbackResponse[]; + feedbackDialogTitle?: ReactNode; + open: boolean; + onClose: () => void; +} + +const useStyles = makeStyles({ + contactConsent: { + marginTop: '5px', + }, +}); + +export const FeedbackResponseDialog = (props: FeedbackResponseDialogProps) => { + const { + entity, + feedbackDialogResponses = defaultFeedbackResponses, + feedbackDialogTitle = 'Please provide feedback on what can be improved', + open, + onClose, + } = props; + const classes = useStyles(); + const errorApi = useApi(errorApiRef); + const feedbackApi = useApi(entityFeedbackApiRef); + const [responseSelections, setResponseSelections] = useState( + Object.fromEntries(feedbackDialogResponses.map(r => [r.id, false])), + ); + const [comments, setComments] = useState(''); + const [consent, setConsent] = useState(true); + + const [{ loading: saving }, saveResponse] = useAsyncFn(async () => { + try { + await feedbackApi.recordResponse(stringifyEntityRef(entity), { + comments, + consent, + response: Object.keys(responseSelections) + .filter(id => responseSelections[id]) + .join(','), + }); + onClose(); + } catch (e) { + errorApi.post(e as ErrorApiError); + } + }, [comments, consent, entity, feedbackApi, onClose, responseSelections]); + + return ( + !saving && onClose()}> + {saving && } + {feedbackDialogTitle} + + + Choose all that applies + + {feedbackDialogResponses.map(response => ( + + setResponseSelections({ + ...responseSelections, + [e.target.name]: e.target.checked, + }) + } + /> + } + label={response.label} + /> + ))} + + + + setComments(e.target.value)} + variant="outlined" + value={comments} + /> + + + Can we reach out to you for more info? + + No + + setConsent(e.target.checked)} + /> + + Yes + + + + + + + + + ); +}; diff --git a/plugins/entity-feedback/src/components/FeedbackResponseDialog/index.ts b/plugins/entity-feedback/src/components/FeedbackResponseDialog/index.ts new file mode 100644 index 0000000000..8ce88f4b87 --- /dev/null +++ b/plugins/entity-feedback/src/components/FeedbackResponseDialog/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './FeedbackResponseDialog'; diff --git a/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.test.tsx b/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.test.tsx new file mode 100644 index 0000000000..c5d3d51884 --- /dev/null +++ b/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.test.tsx @@ -0,0 +1,76 @@ +/* + * Copyright 2023 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 React from 'react'; +import { EntityFeedbackApi, entityFeedbackApiRef } from '../../api'; +import { FeedbackResponseTable } from './FeedbackResponseTable'; + +describe('FeedbackResponseTable', () => { + const sampleResponses = [ + { + userRef: 'user:default/foo', + consent: true, + response: 'resp1,resp2', + comments: 'test comment 1', + }, + { + userRef: 'user:default/bar', + consent: false, + response: 'resp3,resp4', + comments: 'test comment 2', + }, + ]; + + const feedbackApi: Partial = { + getResponses: jest.fn().mockImplementation(async () => sampleResponses), + }; + + const render = async (props: any = {}) => + renderInTestApp( + + + , + ); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders all responses correctly', async () => { + const rendered = await render(); + + expect(feedbackApi.getResponses).toHaveBeenCalledWith( + 'component:default/test', + ); + + expect(rendered.getByText('Entity Responses')).toBeInTheDocument(); + + expect(rendered.getByText('foo')).toBeInTheDocument(); + expect(rendered.getByText('resp1')).toBeInTheDocument(); + expect(rendered.getByText('resp2')).toBeInTheDocument(); + expect(rendered.getByText('test comment 1')).toBeInTheDocument(); + expect(rendered.getByText('bar')).toBeInTheDocument(); + expect(rendered.getByText('resp3')).toBeInTheDocument(); + expect(rendered.getByText('resp4')).toBeInTheDocument(); + expect(rendered.getByText('test comment 2')).toBeInTheDocument(); + }); + + it('renders a custom title correctly', async () => { + const rendered = await render({ title: 'Custom Title' }); + expect(rendered.getByText('Custom Title')).toBeInTheDocument(); + }); +}); diff --git a/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.tsx b/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.tsx new file mode 100644 index 0000000000..2bc03b8537 --- /dev/null +++ b/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.tsx @@ -0,0 +1,121 @@ +/* + * Copyright 2023 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 { ErrorPanel, Table } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; +import { humanizeEntityRef } from '@backstage/plugin-catalog-react'; +import { Response } from '@backstage/plugin-entity-feedback-common'; +import { BackstageTheme } from '@backstage/theme'; +import { Chip, makeStyles } from '@material-ui/core'; +import CheckIcon from '@material-ui/icons/Check'; +import React from 'react'; +import useAsync from 'react-use/lib/useAsync'; + +import { entityFeedbackApiRef } from '../../api'; + +type ResponseRow = Omit; + +const useStyles = makeStyles(theme => ({ + consentCheck: { + color: theme.palette.status.ok, + }, +})); + +/** + * @public + */ +export interface FeedbackResponseTableProps { + entityRef: string; + title?: string; +} + +export const FeedbackResponseTable = (props: FeedbackResponseTableProps) => { + const { entityRef, title = 'Entity Responses' } = props; + const classes = useStyles(); + const feedbackApi = useApi(entityFeedbackApiRef); + + const { + error, + loading, + value: responses, + } = useAsync(async () => { + if (!entityRef) { + return []; + } + + return feedbackApi.getResponses(entityRef); + }, [entityRef, feedbackApi]); + + const columns = [ + { + title: 'User', + field: 'userRef', + width: '15%', + render: (response: ResponseRow) => + humanizeEntityRef(parseEntityRef(response.userRef), { + defaultKind: 'user', + }), + }, + { + title: 'OK to contact?', + field: 'consent', + width: '10%', + render: (response: ResponseRow) => + response.consent ? : '', + }, + { + title: 'Responses', + field: 'response', + width: '35%', + render: (response: ResponseRow) => ( + <> + {response.response?.split(',').map(res => ( + + ))} + + ), + }, + { title: 'Comments', field: 'comments', width: '40%' }, + ]; + + if (error) { + return ( + + ); + } + + return ( + + columns={columns} + data={(responses ?? []) as ResponseRow[]} + isLoading={loading} + options={{ + emptyRowsWhenPaging: false, + loadingType: 'linear', + pageSize: 20, + pageSizeOptions: [20, 50, 100], + paging: true, + showEmptyDataSourceMessage: !loading, + }} + title={title} + /> + ); +}; diff --git a/plugins/entity-feedback/src/components/FeedbackResponseTable/index.ts b/plugins/entity-feedback/src/components/FeedbackResponseTable/index.ts new file mode 100644 index 0000000000..73f4632fbf --- /dev/null +++ b/plugins/entity-feedback/src/components/FeedbackResponseTable/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './FeedbackResponseTable'; diff --git a/plugins/entity-feedback/src/components/LikeDislikeButtons/LikeDislikeButtons.test.tsx b/plugins/entity-feedback/src/components/LikeDislikeButtons/LikeDislikeButtons.test.tsx new file mode 100644 index 0000000000..1edf578d3e --- /dev/null +++ b/plugins/entity-feedback/src/components/LikeDislikeButtons/LikeDislikeButtons.test.tsx @@ -0,0 +1,147 @@ +/* + * Copyright 2023 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 { + ErrorApi, + errorApiRef, + IdentityApi, + identityApiRef, +} from '@backstage/core-plugin-api'; +import { AsyncEntityProvider } from '@backstage/plugin-catalog-react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; + +import { EntityFeedbackApi, entityFeedbackApiRef } from '../../api'; +import { FeedbackRatings, LikeDislikeButtons } from './LikeDislikeButtons'; + +jest.mock('../FeedbackResponseDialog', () => ({ + FeedbackResponseDialog: ({ open }: { open: boolean }) => { + return <>{open && dialog is open}; + }, +})); + +describe('LikeDislikeButtons', () => { + const sampleRatings = [ + { + userRef: 'user:default/me', + rating: FeedbackRatings.like, + }, + { + userRef: 'user:default/someone', + rating: FeedbackRatings.dislike, + }, + ]; + + const testEntity = { + kind: 'component', + metadata: { name: 'test', namespace: 'default' }, + } as Entity; + + const errorApi: Partial = { post: jest.fn() }; + + const feedbackApi: Partial = { + getRatings: jest.fn().mockImplementation(async () => sampleRatings), + recordRating: jest.fn().mockImplementation(() => Promise.resolve()), + }; + + const identityApi: Partial = { + getBackstageIdentity: async () => ({ + type: 'user', + userEntityRef: 'user:default/me', + ownershipEntityRefs: [], + }), + }; + + const render = async (props: any = {}) => + renderInTestApp( + + + + + , + ); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('loads the previous rating if it exists', async () => { + await render(); + expect(feedbackApi.getRatings).toHaveBeenCalledWith( + 'component:default/test', + ); + }); + + it('applies a rating correctly', async () => { + const rendered = await render(); + + await userEvent.click( + rendered.getByTestId('entity-feedback-dislike-button'), + ); + expect(feedbackApi.recordRating).toHaveBeenCalledWith( + 'component:default/test', + FeedbackRatings.dislike, + ); + + jest.clearAllMocks(); + + await userEvent.click(rendered.getByTestId('entity-feedback-like-button')); + expect(feedbackApi.recordRating).toHaveBeenCalledWith( + 'component:default/test', + FeedbackRatings.like, + ); + }); + + it('removes an existing rating correctly', async () => { + const rendered = await render(); + + await userEvent.click(rendered.getByTestId('entity-feedback-like-button')); + expect(feedbackApi.recordRating).toHaveBeenCalledWith( + 'component:default/test', + FeedbackRatings.neutral, + ); + }); + + it('opens a response dialog if dislike is selected', async () => { + const rendered = await render(); + + expect(rendered.queryByText('dialog is open')).toBeNull(); + + await userEvent.click( + rendered.getByTestId('entity-feedback-dislike-button'), + ); + expect(rendered.getByText('dialog is open')).toBeInTheDocument(); + }); + + it('does not open a response dialog on dislike if configured not to', async () => { + const rendered = await render({ requestResponse: false }); + + expect(rendered.queryByText('dialog is open')).toBeNull(); + + await userEvent.click( + rendered.getByTestId('entity-feedback-dislike-button'), + ); + expect(rendered.queryByText('dialog is open')).toBeNull(); + }); +}); diff --git a/plugins/entity-feedback/src/components/LikeDislikeButtons/LikeDislikeButtons.tsx b/plugins/entity-feedback/src/components/LikeDislikeButtons/LikeDislikeButtons.tsx new file mode 100644 index 0000000000..2d38e60ac2 --- /dev/null +++ b/plugins/entity-feedback/src/components/LikeDislikeButtons/LikeDislikeButtons.tsx @@ -0,0 +1,154 @@ +/* + * Copyright 2023 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 { stringifyEntityRef } from '@backstage/catalog-model'; +import { Progress } from '@backstage/core-components'; +import { + ErrorApiError, + errorApiRef, + identityApiRef, + useApi, +} from '@backstage/core-plugin-api'; +import { useAsyncEntity } from '@backstage/plugin-catalog-react'; +import { IconButton } from '@material-ui/core'; +import ThumbDownIcon from '@material-ui/icons/ThumbDown'; +import ThumbUpIcon from '@material-ui/icons/ThumbUp'; +import ThumbDownOutlinedIcon from '@material-ui/icons/ThumbDownOutlined'; +import ThumbUpOutlinedIcon from '@material-ui/icons/ThumbUpOutlined'; +import React, { ReactNode, useCallback, useState } from 'react'; +import useAsync from 'react-use/lib/useAsync'; +import useAsyncFn from 'react-use/lib/useAsyncFn'; + +import { entityFeedbackApiRef } from '../../api'; +import { + EntityFeedbackResponse, + FeedbackResponseDialog, +} from '../FeedbackResponseDialog'; + +export enum FeedbackRatings { + like = 'LIKE', + dislike = 'DISLIKE', + neutral = 'NEUTRAL', +} + +/** + * @public + */ +export interface LikeDislikeButtonsProps { + feedbackDialogResponses?: EntityFeedbackResponse[]; + feedbackDialogTitle?: ReactNode; + requestResponse?: boolean; +} + +export const LikeDislikeButtons = (props: LikeDislikeButtonsProps) => { + const { + feedbackDialogResponses, + feedbackDialogTitle, + requestResponse = true, + } = props; + const errorApi = useApi(errorApiRef); + const feedbackApi = useApi(entityFeedbackApiRef); + const identityApi = useApi(identityApiRef); + const [rating, setRating] = useState( + FeedbackRatings.neutral, + ); + const [openFeedbackDialog, setOpenFeedbackDialog] = useState(false); + const { entity, loading: loadingEntity } = useAsyncEntity(); + + const { loading: loadingFeedback } = useAsync(async () => { + // Wait until entity is loaded + if (!entity) { + return; + } + + try { + const identity = await identityApi.getBackstageIdentity(); + const prevFeedback = await feedbackApi.getRatings( + stringifyEntityRef(entity), + ); + setRating( + (prevFeedback.find(r => r.userRef === identity.userEntityRef)?.rating ?? + rating) as FeedbackRatings, + ); + } catch (e) { + errorApi.post(e as ErrorApiError); + } + }, [entity, feedbackApi, setRating]); + + const [{ loading: savingFeedback }, saveFeedback] = useAsyncFn( + async (feedback: FeedbackRatings) => { + try { + await feedbackApi.recordRating(stringifyEntityRef(entity!), feedback); + setRating(feedback); + } catch (e) { + errorApi.post(e as ErrorApiError); + } + }, + [entity, feedbackApi, setRating], + ); + + const applyRating = useCallback( + (feedback: FeedbackRatings) => { + // Clear rating if feedback is same as current + if (feedback === rating) { + saveFeedback(FeedbackRatings.neutral); + return; + } + + saveFeedback(feedback); + if (feedback === FeedbackRatings.dislike && requestResponse) { + setOpenFeedbackDialog(true); + } + }, + [rating, requestResponse, saveFeedback, setOpenFeedbackDialog], + ); + + if (loadingEntity || loadingFeedback || savingFeedback) { + return ; + } + + return ( + <> + applyRating(FeedbackRatings.like)} + > + {rating === FeedbackRatings.like ? ( + + ) : ( + + )} + + applyRating(FeedbackRatings.dislike)} + > + {rating === FeedbackRatings.dislike ? ( + + ) : ( + + )} + + setOpenFeedbackDialog(false)} + feedbackDialogResponses={feedbackDialogResponses} + feedbackDialogTitle={feedbackDialogTitle} + /> + + ); +}; diff --git a/plugins/entity-feedback/src/components/LikeDislikeButtons/index.ts b/plugins/entity-feedback/src/components/LikeDislikeButtons/index.ts new file mode 100644 index 0000000000..58038c32e1 --- /dev/null +++ b/plugins/entity-feedback/src/components/LikeDislikeButtons/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './LikeDislikeButtons'; diff --git a/plugins/entity-feedback/src/components/LikeDislikeRatingsTable/LikeDislikeRatingsTable.test.tsx b/plugins/entity-feedback/src/components/LikeDislikeRatingsTable/LikeDislikeRatingsTable.test.tsx new file mode 100644 index 0000000000..9f04d32ece --- /dev/null +++ b/plugins/entity-feedback/src/components/LikeDislikeRatingsTable/LikeDislikeRatingsTable.test.tsx @@ -0,0 +1,42 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { renderInTestApp } from '@backstage/test-utils'; +import React from 'react'; + +import { FeedbackRatings } from '../LikeDislikeButtons'; +import { LikeDislikeRatingsTable } from './LikeDislikeRatingsTable'; + +jest.mock('../FeedbackRatingsTable', () => ({ + FeedbackRatingsTable: ({ ratingValues }: { ratingValues: string[] }) => { + return ( + + {ratingValues.map(v => ( + {v} + ))} + + ); + }, +})); + +describe('LikeDislikeRatingsTable', () => { + it('renders like-dislike ratings correctly', async () => { + const rendered = await renderInTestApp(); + expect(rendered.getByText(FeedbackRatings.like)).toBeInTheDocument(); + expect(rendered.queryByText(FeedbackRatings.neutral)).toBeNull(); + expect(rendered.getByText(FeedbackRatings.dislike)).toBeInTheDocument(); + }); +}); diff --git a/plugins/entity-feedback/src/components/LikeDislikeRatingsTable/LikeDislikeRatingsTable.tsx b/plugins/entity-feedback/src/components/LikeDislikeRatingsTable/LikeDislikeRatingsTable.tsx new file mode 100644 index 0000000000..5466ba2b03 --- /dev/null +++ b/plugins/entity-feedback/src/components/LikeDislikeRatingsTable/LikeDislikeRatingsTable.tsx @@ -0,0 +1,46 @@ +/* + * Copyright 2023 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 { FeedbackRatingsTable } from '../FeedbackRatingsTable'; +import { FeedbackRatings } from '../LikeDislikeButtons'; + +/** + * @public + */ +export interface LikeDislikeRatingsTableProps { + allEntities?: boolean; + ownerRef?: string; + title?: string; +} + +export const LikeDislikeRatingsTable = ( + props: LikeDislikeRatingsTableProps, +) => { + const { allEntities, ownerRef, title } = props; + + return ( + r !== FeedbackRatings.neutral, + )} + title={title} + /> + ); +}; diff --git a/plugins/entity-feedback/src/components/LikeDislikeRatingsTable/index.ts b/plugins/entity-feedback/src/components/LikeDislikeRatingsTable/index.ts new file mode 100644 index 0000000000..d093b8bd2c --- /dev/null +++ b/plugins/entity-feedback/src/components/LikeDislikeRatingsTable/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './LikeDislikeRatingsTable'; diff --git a/plugins/entity-feedback/src/components/StarredRatingButtons/StarredRatingButtons.test.tsx b/plugins/entity-feedback/src/components/StarredRatingButtons/StarredRatingButtons.test.tsx new file mode 100644 index 0000000000..82fc843494 --- /dev/null +++ b/plugins/entity-feedback/src/components/StarredRatingButtons/StarredRatingButtons.test.tsx @@ -0,0 +1,159 @@ +/* + * Copyright 2023 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 { + ErrorApi, + errorApiRef, + IdentityApi, + identityApiRef, +} from '@backstage/core-plugin-api'; +import { AsyncEntityProvider } from '@backstage/plugin-catalog-react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; + +import { EntityFeedbackApi, entityFeedbackApiRef } from '../../api'; +import { FeedbackRatings, StarredRatingButtons } from './StarredRatingButtons'; + +jest.mock('../FeedbackResponseDialog', () => ({ + FeedbackResponseDialog: ({ open }: { open: boolean }) => { + return <>{open && dialog is open}; + }, +})); + +describe('StarredRatingButtons', () => { + const sampleRatings = [ + { + userRef: 'user:default/me', + rating: FeedbackRatings.two, + }, + { + userRef: 'user:default/someone', + rating: FeedbackRatings.five, + }, + ]; + + const testEntity = { + kind: 'component', + metadata: { name: 'test', namespace: 'default' }, + } as Entity; + + const errorApi: Partial = { post: jest.fn() }; + + const feedbackApi: Partial = { + getRatings: jest.fn().mockImplementation(async () => sampleRatings), + recordRating: jest.fn().mockImplementation(() => Promise.resolve()), + }; + + const identityApi: Partial = { + getBackstageIdentity: async () => ({ + type: 'user', + userEntityRef: 'user:default/me', + ownershipEntityRefs: [], + }), + }; + + const render = async (props: any = {}) => + renderInTestApp( + + + + + , + ); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('loads the previous rating if it exists', async () => { + await render(); + expect(feedbackApi.getRatings).toHaveBeenCalledWith( + 'component:default/test', + ); + }); + + it('applies a rating correctly', async () => { + const rendered = await render(); + + await userEvent.click( + rendered.getByTestId('entity-feedback-star-button-3'), + ); + expect(feedbackApi.recordRating).toHaveBeenCalledWith( + 'component:default/test', + FeedbackRatings.three.toString(), + ); + + jest.clearAllMocks(); + + await userEvent.click( + rendered.getByTestId('entity-feedback-star-button-5'), + ); + expect(feedbackApi.recordRating).toHaveBeenCalledWith( + 'component:default/test', + FeedbackRatings.five.toString(), + ); + }); + + it('ignores an existing rating correctly', async () => { + const rendered = await render(); + + await userEvent.click( + rendered.getByTestId('entity-feedback-star-button-2'), + ); + expect(feedbackApi.recordRating).not.toHaveBeenCalled(); + }); + + it('opens a response dialog if a rating under the threshold is selected', async () => { + const rendered = await render(); + + expect(rendered.queryByText('dialog is open')).toBeNull(); + + await userEvent.click( + rendered.getByTestId('entity-feedback-star-button-1'), + ); + expect(rendered.getByText('dialog is open')).toBeInTheDocument(); + }); + + it('opens a response dialog if a rating under a custom threshold is selected', async () => { + const rendered = await render({ requestResponseThreshold: 4 }); + + expect(rendered.queryByText('dialog is open')).toBeNull(); + + await userEvent.click( + rendered.getByTestId('entity-feedback-star-button-3'), + ); + expect(rendered.getByText('dialog is open')).toBeInTheDocument(); + }); + + it('does not open a response dialog if configured not to', async () => { + const rendered = await render({ requestResponse: false }); + + expect(rendered.queryByText('dialog is open')).toBeNull(); + + await userEvent.click( + rendered.getByTestId('entity-feedback-star-button-1'), + ); + expect(rendered.queryByText('dialog is open')).toBeNull(); + }); +}); diff --git a/plugins/entity-feedback/src/components/StarredRatingButtons/StarredRatingButtons.tsx b/plugins/entity-feedback/src/components/StarredRatingButtons/StarredRatingButtons.tsx new file mode 100644 index 0000000000..51f7da1099 --- /dev/null +++ b/plugins/entity-feedback/src/components/StarredRatingButtons/StarredRatingButtons.tsx @@ -0,0 +1,160 @@ +/* + * Copyright 2023 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 { stringifyEntityRef } from '@backstage/catalog-model'; +import { Progress } from '@backstage/core-components'; +import { + ErrorApiError, + errorApiRef, + identityApiRef, + useApi, +} from '@backstage/core-plugin-api'; +import { useAsyncEntity } from '@backstage/plugin-catalog-react'; +import { IconButton } from '@material-ui/core'; +import StarOutlineIcon from '@material-ui/icons/StarOutline'; +import StarIcon from '@material-ui/icons/Star'; +import React, { ReactNode, useCallback, useState } from 'react'; +import useAsync from 'react-use/lib/useAsync'; +import useAsyncFn from 'react-use/lib/useAsyncFn'; + +import { entityFeedbackApiRef } from '../../api'; +import { + EntityFeedbackResponse, + FeedbackResponseDialog, +} from '../FeedbackResponseDialog'; + +export enum FeedbackRatings { + one = 1, + two = 2, + three = 3, + four = 4, + five = 5, +} + +/** + * @public + */ +export interface StarredRatingButtonsProps { + feedbackDialogResponses?: EntityFeedbackResponse[]; + feedbackDialogTitle?: ReactNode; + requestResponse?: boolean; + requestResponseThreshold?: number; +} + +export const StarredRatingButtons = (props: StarredRatingButtonsProps) => { + const { + feedbackDialogResponses, + feedbackDialogTitle, + requestResponse = true, + requestResponseThreshold = FeedbackRatings.two, + } = props; + const errorApi = useApi(errorApiRef); + const feedbackApi = useApi(entityFeedbackApiRef); + const identityApi = useApi(identityApiRef); + const [rating, setRating] = useState(); + const [openFeedbackDialog, setOpenFeedbackDialog] = useState(false); + const { entity, loading: loadingEntity } = useAsyncEntity(); + + const { loading: loadingFeedback } = useAsync(async () => { + // Wait until entity is loaded + if (!entity) { + return; + } + + try { + const identity = await identityApi.getBackstageIdentity(); + const prevFeedback = await feedbackApi.getRatings( + stringifyEntityRef(entity), + ); + + const prevRating = prevFeedback.find( + r => r.userRef === identity.userEntityRef, + )?.rating; + if (prevRating) { + setRating(parseInt(prevRating, 10)); + } + } catch (e) { + errorApi.post(e as ErrorApiError); + } + }, [entity, feedbackApi, setRating]); + + const [{ loading: savingFeedback }, saveFeedback] = useAsyncFn( + async (feedback: FeedbackRatings) => { + try { + await feedbackApi.recordRating( + stringifyEntityRef(entity!), + feedback.toString(), + ); + setRating(feedback); + } catch (e) { + errorApi.post(e as ErrorApiError); + } + }, + [entity, feedbackApi, setRating], + ); + + const applyRating = useCallback( + (feedback: FeedbackRatings) => { + // Ignore rating if feedback is same as current + if (feedback === rating) { + return; + } + + saveFeedback(feedback); + if (feedback <= requestResponseThreshold && requestResponse) { + setOpenFeedbackDialog(true); + } + }, + [ + rating, + requestResponse, + requestResponseThreshold, + saveFeedback, + setOpenFeedbackDialog, + ], + ); + + if (loadingEntity || loadingFeedback || savingFeedback) { + return ; + } + + return ( + <> + {Object.values(FeedbackRatings) + .filter(o => typeof o === 'number') + .map(starRating => ( + applyRating(starRating as FeedbackRatings)} + > + {rating && rating >= starRating ? ( + + ) : ( + + )} + + ))} + setOpenFeedbackDialog(false)} + feedbackDialogResponses={feedbackDialogResponses} + feedbackDialogTitle={feedbackDialogTitle} + /> + + ); +}; diff --git a/plugins/entity-feedback/src/components/StarredRatingButtons/index.ts b/plugins/entity-feedback/src/components/StarredRatingButtons/index.ts new file mode 100644 index 0000000000..659c914749 --- /dev/null +++ b/plugins/entity-feedback/src/components/StarredRatingButtons/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './StarredRatingButtons'; diff --git a/plugins/entity-feedback/src/components/StarredRatingsTable/StarredRatingsTable.test.tsx b/plugins/entity-feedback/src/components/StarredRatingsTable/StarredRatingsTable.test.tsx new file mode 100644 index 0000000000..be53d59d5f --- /dev/null +++ b/plugins/entity-feedback/src/components/StarredRatingsTable/StarredRatingsTable.test.tsx @@ -0,0 +1,44 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { renderInTestApp } from '@backstage/test-utils'; +import React from 'react'; + +import { FeedbackRatings } from '../StarredRatingButtons'; +import { StarredRatingsTable } from './StarredRatingsTable'; + +jest.mock('../FeedbackRatingsTable', () => ({ + FeedbackRatingsTable: ({ ratingValues }: { ratingValues: string[] }) => { + return ( + + {ratingValues.map(v => ( + {v} + ))} + + ); + }, +})); + +describe('StarredRatingsTable', () => { + it('renders starred ratings correctly', async () => { + const rendered = await renderInTestApp(); + expect(rendered.getByText(FeedbackRatings.one)).toBeInTheDocument(); + expect(rendered.getByText(FeedbackRatings.two)).toBeInTheDocument(); + expect(rendered.getByText(FeedbackRatings.three)).toBeInTheDocument(); + expect(rendered.getByText(FeedbackRatings.four)).toBeInTheDocument(); + expect(rendered.getByText(FeedbackRatings.five)).toBeInTheDocument(); + }); +}); diff --git a/plugins/entity-feedback/src/components/StarredRatingsTable/StarredRatingsTable.tsx b/plugins/entity-feedback/src/components/StarredRatingsTable/StarredRatingsTable.tsx new file mode 100644 index 0000000000..d52fd64640 --- /dev/null +++ b/plugins/entity-feedback/src/components/StarredRatingsTable/StarredRatingsTable.tsx @@ -0,0 +1,44 @@ +/* + * Copyright 2023 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 { FeedbackRatingsTable } from '../FeedbackRatingsTable'; +import { FeedbackRatings } from '../StarredRatingButtons'; + +/** + * @public + */ +export interface StarredRatingsTableProps { + allEntities?: boolean; + ownerRef?: string; + title?: string; +} + +export const StarredRatingsTable = (props: StarredRatingsTableProps) => { + const { allEntities, ownerRef, title } = props; + + return ( + typeof o === 'number') + .map(r => r.toString())} + title={title} + /> + ); +}; diff --git a/plugins/entity-feedback/src/components/StarredRatingsTable/index.ts b/plugins/entity-feedback/src/components/StarredRatingsTable/index.ts new file mode 100644 index 0000000000..9621712e0b --- /dev/null +++ b/plugins/entity-feedback/src/components/StarredRatingsTable/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './StarredRatingsTable'; diff --git a/plugins/entity-feedback/src/components/index.ts b/plugins/entity-feedback/src/components/index.ts new file mode 100644 index 0000000000..a88d525f09 --- /dev/null +++ b/plugins/entity-feedback/src/components/index.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2023 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 type { + EntityFeedbackResponse, + FeedbackResponseDialogProps, +} from './FeedbackResponseDialog'; +export type { FeedbackResponseTableProps } from './FeedbackResponseTable'; +export type { LikeDislikeButtonsProps } from './LikeDislikeButtons'; +export type { LikeDislikeRatingsTableProps } from './LikeDislikeRatingsTable'; +export type { StarredRatingButtonsProps } from './StarredRatingButtons'; +export type { StarredRatingsTableProps } from './StarredRatingsTable'; diff --git a/plugins/entity-feedback/src/index.ts b/plugins/entity-feedback/src/index.ts new file mode 100644 index 0000000000..bbcf6bc626 --- /dev/null +++ b/plugins/entity-feedback/src/index.ts @@ -0,0 +1,32 @@ +/* + * Copyright 2023 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. + */ + +/** + * Entity Feedback frontend plugin + * + * @packageDocumentation + */ +export type { + LikeDislikeButtonsProps, + LikeDislikeRatingsTableProps, + EntityFeedbackResponse, + FeedbackResponseDialogProps, + FeedbackResponseTableProps, + StarredRatingButtonsProps, + StarredRatingsTableProps, +} from './components'; +export * from './plugin'; +export * from './api'; diff --git a/plugins/entity-feedback/src/plugin.test.ts b/plugins/entity-feedback/src/plugin.test.ts new file mode 100644 index 0000000000..a56d37f9ab --- /dev/null +++ b/plugins/entity-feedback/src/plugin.test.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2023 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 { entityFeedbackPlugin } from './plugin'; + +describe('entity-feedback', () => { + it('should export plugin', () => { + expect(entityFeedbackPlugin).toBeDefined(); + }); +}); diff --git a/plugins/entity-feedback/src/plugin.tsx b/plugins/entity-feedback/src/plugin.tsx new file mode 100644 index 0000000000..9ebdc5d7af --- /dev/null +++ b/plugins/entity-feedback/src/plugin.tsx @@ -0,0 +1,212 @@ +/* + * Copyright 2023 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 { stringifyEntityRef } from '@backstage/catalog-model'; +import { + createApiFactory, + createComponentExtension, + createPlugin, + createRoutableExtension, + discoveryApiRef, + fetchApiRef, +} from '@backstage/core-plugin-api'; +import { useAsyncEntity } from '@backstage/plugin-catalog-react'; +import React from 'react'; + +import { entityFeedbackApiRef, EntityFeedbackClient } from './api'; +import { rootRouteRef } from './routes'; + +/** + * @public + */ +export const entityFeedbackPlugin = createPlugin({ + id: 'entity-feedback', + routes: { + root: rootRouteRef, + }, + apis: [ + createApiFactory({ + api: entityFeedbackApiRef, + deps: { + discoveryApi: discoveryApiRef, + fetchApi: fetchApiRef, + }, + factory: ({ discoveryApi, fetchApi }) => + new EntityFeedbackClient({ discoveryApi, fetchApi }), + }), + ], +}); + +/** + * @public + */ +export const LikeDislikeButtons = entityFeedbackPlugin.provide( + createComponentExtension({ + name: 'LikeDislikeButtons', + component: { + lazy: () => + import('./components/LikeDislikeButtons').then( + m => m.LikeDislikeButtons, + ), + }, + }), +); + +/** + * @public + */ +export const StarredRatingButtons = entityFeedbackPlugin.provide( + createComponentExtension({ + name: 'StarredRatingButtons', + component: { + lazy: () => + import('./components/StarredRatingButtons').then( + m => m.StarredRatingButtons, + ), + }, + }), +); + +/** + * @public + */ +export const FeedbackResponseDialog = entityFeedbackPlugin.provide( + createComponentExtension({ + name: 'FeedbackResponseDialog', + component: { + lazy: () => + import('./components/FeedbackResponseDialog').then( + m => m.FeedbackResponseDialog, + ), + }, + }), +); + +/** + * @public + */ +export const EntityFeedbackResponseContent = entityFeedbackPlugin.provide( + createRoutableExtension({ + name: 'EntityFeedbackResponseContent', + mountPoint: rootRouteRef, + component: () => + import('./components/FeedbackResponseTable').then( + ({ FeedbackResponseTable }) => { + return () => { + const { entity } = useAsyncEntity(); + return ( + + ); + }; + }, + ), + }), +); + +/** + * @public + */ +export const FeedbackResponseTable = entityFeedbackPlugin.provide( + createComponentExtension({ + name: 'FeedbackResponseTable', + component: { + lazy: () => + import('./components/FeedbackResponseTable').then( + m => m.FeedbackResponseTable, + ), + }, + }), +); + +/** + * @public + */ +export const EntityLikeDislikeRatingsCard = entityFeedbackPlugin.provide( + createComponentExtension({ + name: 'EntityLikeDislikeRatingsCard', + component: { + lazy: () => + import('./components/LikeDislikeRatingsTable').then( + ({ LikeDislikeRatingsTable }) => { + return () => { + const { entity } = useAsyncEntity(); + return ( + + ); + }; + }, + ), + }, + }), +); + +/** + * @public + */ +export const LikeDislikeRatingsTable = entityFeedbackPlugin.provide( + createComponentExtension({ + name: 'LikeDislikeRatingsTable', + component: { + lazy: () => + import('./components/LikeDislikeRatingsTable').then( + m => m.LikeDislikeRatingsTable, + ), + }, + }), +); + +/** + * @public + */ +export const EntityStarredRatingsCard = entityFeedbackPlugin.provide( + createComponentExtension({ + name: 'EntityStarredRatingsCard', + component: { + lazy: () => + import('./components/StarredRatingsTable').then( + ({ StarredRatingsTable }) => { + return () => { + const { entity } = useAsyncEntity(); + return ( + + ); + }; + }, + ), + }, + }), +); + +/** + * @public + */ +export const StarredRatingsTable = entityFeedbackPlugin.provide( + createComponentExtension({ + name: 'StarredRatingsTable', + component: { + lazy: () => + import('./components/StarredRatingsTable').then( + m => m.StarredRatingsTable, + ), + }, + }), +); diff --git a/plugins/entity-feedback/src/routes.ts b/plugins/entity-feedback/src/routes.ts new file mode 100644 index 0000000000..cde7241931 --- /dev/null +++ b/plugins/entity-feedback/src/routes.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2023 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 } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + id: 'entity-feedback', +}); diff --git a/plugins/entity-feedback/src/setupTests.ts b/plugins/entity-feedback/src/setupTests.ts new file mode 100644 index 0000000000..bf4855cb6e --- /dev/null +++ b/plugins/entity-feedback/src/setupTests.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 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/yarn.lock b/yarn.lock index 1621cdc5b1..148b33fa81 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5845,6 +5845,72 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-entity-feedback-backend@workspace:^, @backstage/plugin-entity-feedback-backend@workspace:plugins/entity-feedback-backend": + version: 0.0.0-use.local + resolution: "@backstage/plugin-entity-feedback-backend@workspace:plugins/entity-feedback-backend" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/catalog-client": "workspace:^" + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" + "@backstage/plugin-entity-feedback-common": "workspace:^" + "@types/express": "*" + "@types/supertest": ^2.0.12 + express: ^4.18.1 + express-promise-router: ^4.1.0 + knex: ^2.0.0 + msw: ^0.49.0 + node-fetch: ^2.6.7 + supertest: ^6.2.4 + winston: ^3.2.1 + yn: ^4.0.0 + languageName: unknown + linkType: soft + +"@backstage/plugin-entity-feedback-common@workspace:^, @backstage/plugin-entity-feedback-common@workspace:plugins/entity-feedback-common": + version: 0.0.0-use.local + resolution: "@backstage/plugin-entity-feedback-common@workspace:plugins/entity-feedback-common" + dependencies: + "@backstage/cli": "workspace:^" + languageName: unknown + linkType: soft + +"@backstage/plugin-entity-feedback@workspace:^, @backstage/plugin-entity-feedback@workspace:plugins/entity-feedback": + version: 0.0.0-use.local + resolution: "@backstage/plugin-entity-feedback@workspace:plugins/entity-feedback" + dependencies: + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-catalog-react": "workspace:^" + "@backstage/plugin-entity-feedback-common": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@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.1 + "@testing-library/user-event": ^14.0.0 + "@types/node": "*" + cross-fetch: ^3.1.5 + msw: ^0.49.0 + react-use: ^17.2.4 + peerDependencies: + "@types/react": ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + languageName: unknown + linkType: soft + "@backstage/plugin-entity-validation@workspace:plugins/entity-validation": version: 0.0.0-use.local resolution: "@backstage/plugin-entity-validation@workspace:plugins/entity-validation" @@ -11211,7 +11277,7 @@ __metadata: languageName: node linkType: hard -"@material-ui/core@npm:^4.11.0, @material-ui/core@npm:^4.11.3, @material-ui/core@npm:^4.12.1, @material-ui/core@npm:^4.12.2, @material-ui/core@npm:^4.12.4": +"@material-ui/core@npm:^4.11.0, @material-ui/core@npm:^4.11.3, @material-ui/core@npm:^4.12.1, @material-ui/core@npm:^4.12.2, @material-ui/core@npm:^4.12.4, @material-ui/core@npm:^4.9.13": version: 4.12.4 resolution: "@material-ui/core@npm:4.12.4" dependencies: @@ -13595,7 +13661,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/react-hooks@npm:^8.0.0": +"@testing-library/react-hooks@npm:^8.0.0, @testing-library/react-hooks@npm:^8.0.1": version: 8.0.1 resolution: "@testing-library/react-hooks@npm:8.0.1" dependencies: @@ -22190,6 +22256,7 @@ __metadata: "@backstage/plugin-code-coverage": "workspace:^" "@backstage/plugin-cost-insights": "workspace:^" "@backstage/plugin-dynatrace": "workspace:^" + "@backstage/plugin-entity-feedback": "workspace:^" "@backstage/plugin-explore": "workspace:^" "@backstage/plugin-gcalendar": "workspace:^" "@backstage/plugin-gcp-projects": "workspace:^" @@ -22291,6 +22358,7 @@ __metadata: "@backstage/plugin-catalog-backend": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-code-coverage-backend": "workspace:^" + "@backstage/plugin-entity-feedback-backend": "workspace:^" "@backstage/plugin-events-backend": "workspace:^" "@backstage/plugin-events-node": "workspace:^" "@backstage/plugin-explore-backend": "workspace:^" From 3951fa0b31a09d20d959768450c0bc1e3bf1e00f Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Tue, 7 Feb 2023 17:37:56 -0500 Subject: [PATCH 289/423] Use 3.1 Signed-off-by: Aramis Sennyey --- plugins/catalog-backend/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-backend/openapi.yaml b/plugins/catalog-backend/openapi.yaml index a058831d55..fdd1532f89 100644 --- a/plugins/catalog-backend/openapi.yaml +++ b/plugins/catalog-backend/openapi.yaml @@ -389,7 +389,7 @@ info: license: name: Apache-2.0 contact: {} -openapi: 3.0.3 +openapi: 3.1.0 paths: /refresh: post: From 1fd29bffc72cf4984af87af5e3a8406226c7f8ac Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Tue, 7 Feb 2023 17:42:40 -0500 Subject: [PATCH 290/423] Formatting and make security optional Signed-off-by: Aramis Sennyey --- plugins/catalog-backend/openapi.yaml | 31 +++++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/plugins/catalog-backend/openapi.yaml b/plugins/catalog-backend/openapi.yaml index fdd1532f89..beef95b0b7 100644 --- a/plugins/catalog-backend/openapi.yaml +++ b/plugins/catalog-backend/openapi.yaml @@ -1,3 +1,11 @@ +openapi: 3.1.0 +info: + title: '@backstage/plugin-catalog-backend' + version: '1' + description: The Backstage backend plugin that provides the Backstage catalog + license: + name: Apache-2.0 + contact: {} components: examples: {} headers: {} @@ -382,14 +390,7 @@ components: type: http scheme: bearer bearerFormat: JWT -info: - title: '@backstage/plugin-catalog-backend' - version: 1.6.0-next.1 - description: The Backstage backend plugin that provides the Backstage catalog - license: - name: Apache-2.0 - contact: {} -openapi: 3.1.0 + paths: /refresh: post: @@ -398,6 +399,7 @@ paths: '200': description: Refreshed security: + - {} - JWT: [] parameters: [] requestBody: @@ -419,6 +421,7 @@ paths: $ref: '#/components/schemas/Entity' type: array security: + - {} - JWT: [] parameters: - in: query @@ -457,6 +460,7 @@ paths: schema: $ref: '#/components/schemas/Entity' security: + - {} - JWT: [] parameters: - in: path @@ -470,6 +474,7 @@ paths: '204': description: Deleted successfully. security: + - {} - JWT: [] parameters: - in: path @@ -489,6 +494,7 @@ paths: schema: $ref: '#/components/schemas/Entity' security: + - {} - JWT: [] parameters: - in: path @@ -517,6 +523,7 @@ paths: schema: $ref: '#/components/schemas/EntityAncestryResponse' security: + - {} - JWT: [] parameters: - in: path @@ -545,6 +552,7 @@ paths: schema: $ref: '#/components/schemas/EntitiesBatchResponse' security: + - {} - JWT: [] parameters: - in: query @@ -571,6 +579,7 @@ paths: schema: $ref: '#/components/schemas/EntityFacetsResponse' security: + - {} - JWT: [] parameters: - in: query @@ -606,6 +615,7 @@ paths: - location type: object security: + - {} - JWT: [] parameters: - in: query @@ -650,6 +660,7 @@ paths: type: object type: array security: + - {} - JWT: [] parameters: [] /locations/{id}: @@ -663,6 +674,7 @@ paths: schema: $ref: '#/components/schemas/Location' security: + - {} - JWT: [] parameters: - in: path @@ -676,6 +688,7 @@ paths: '204': description: No content security: + - {} - JWT: [] parameters: - in: path @@ -694,6 +707,7 @@ paths: schema: $ref: '#/components/schemas/AnalyzeLocationResponse' security: + - {} - JWT: [] parameters: [] requestBody: @@ -735,6 +749,7 @@ paths: - errors type: object security: + - {} - JWT: [] parameters: [] requestBody: From 5cc2a75994ad92cfa3ef835a71775146bf6a9059 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Tue, 7 Feb 2023 17:44:30 -0500 Subject: [PATCH 291/423] Add comment to yaml Signed-off-by: Aramis Sennyey --- plugins/catalog-backend/openapi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/catalog-backend/openapi.yaml b/plugins/catalog-backend/openapi.yaml index beef95b0b7..9215f562f5 100644 --- a/plugins/catalog-backend/openapi.yaml +++ b/plugins/catalog-backend/openapi.yaml @@ -399,6 +399,7 @@ paths: '200': description: Refreshed security: + # From https://stackoverflow.com/questions/47659324/how-to-specify-an-endpoints-authorization-is-optional-in-openapi-v3 - {} - JWT: [] parameters: [] From 8c5abb388ac8770ed61edcc9189f0b44e373f788 Mon Sep 17 00:00:00 2001 From: Jen Evans Date: Tue, 7 Feb 2023 16:58:16 -0800 Subject: [PATCH 292/423] Check for empty costs array and allow title override Signed-off-by: Jen Evans --- .../src/components/CostInsightsLayout/CostInsightsLayout.tsx | 3 ++- .../cost-insights/src/components/EntityCosts/EntityCosts.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/cost-insights/src/components/CostInsightsLayout/CostInsightsLayout.tsx b/plugins/cost-insights/src/components/CostInsightsLayout/CostInsightsLayout.tsx index 0a583aae0d..55d5668189 100644 --- a/plugins/cost-insights/src/components/CostInsightsLayout/CostInsightsLayout.tsx +++ b/plugins/cost-insights/src/components/CostInsightsLayout/CostInsightsLayout.tsx @@ -37,6 +37,7 @@ type CostInsightsLayoutProps = { }; export const CostInsightsLayout = ({ + title = 'Cost Insights', groups, children, }: PropsWithChildren) => { @@ -46,7 +47,7 @@ export const CostInsightsLayout = ({
    diff --git a/plugins/cost-insights/src/components/EntityCosts/EntityCosts.tsx b/plugins/cost-insights/src/components/EntityCosts/EntityCosts.tsx index 9dda1c65e3..69bf8885e7 100644 --- a/plugins/cost-insights/src/components/EntityCosts/EntityCosts.tsx +++ b/plugins/cost-insights/src/components/EntityCosts/EntityCosts.tsx @@ -120,7 +120,7 @@ export const EntityCostsCard = () => { return {error.message}; } - if (!dailyCost) { + if (!dailyCost || !dailyCost.aggregation.length) { return No daily costs; } From dfa0bb737ee4cd579c2117843b5f309d58e0c4a0 Mon Sep 17 00:00:00 2001 From: Jen Evans Date: Tue, 7 Feb 2023 17:04:26 -0800 Subject: [PATCH 293/423] Add changeset Signed-off-by: Jen Evans --- .changeset/sweet-yaks-taste.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sweet-yaks-taste.md diff --git a/.changeset/sweet-yaks-taste.md b/.changeset/sweet-yaks-taste.md new file mode 100644 index 0000000000..cbbbaea497 --- /dev/null +++ b/.changeset/sweet-yaks-taste.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cost-insights': patch +--- + +Fix bug in EntityCostsCard if cost aggregation array is empty. Allow title override on the Cost Insights Page From 111f5d475b018411cd8e0e0a2c074917746584d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 8 Feb 2023 09:45:30 +0100 Subject: [PATCH 294/423] prettier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- plugins/catalog-backend/openapi.yaml | 108 +++++++++++++++------------ 1 file changed, 60 insertions(+), 48 deletions(-) diff --git a/plugins/catalog-backend/openapi.yaml b/plugins/catalog-backend/openapi.yaml index 9215f562f5..ea09f5da10 100644 --- a/plugins/catalog-backend/openapi.yaml +++ b/plugins/catalog-backend/openapi.yaml @@ -1,4 +1,5 @@ openapi: 3.1.0 + info: title: '@backstage/plugin-catalog-backend' version: '1' @@ -6,6 +7,10 @@ info: license: name: Apache-2.0 contact: {} + +servers: + - url: / + components: examples: {} headers: {} @@ -14,6 +19,7 @@ components: responses: {} schemas: RefreshOptions: + type: object properties: authorizationToken: type: string @@ -22,19 +28,19 @@ components: description: The reference to a single entity that should be refreshed required: - entityRef - type: object description: Options for requesting a refresh of entities in the catalog. JsonObject: - properties: {} type: object + properties: {} description: A type representing all allowed JSON object values. MapStringString: - properties: {} type: object + properties: {} additionalProperties: type: string description: Construct a type with a set of properties K of type T EntityLink: + type: object properties: type: type: string @@ -50,21 +56,21 @@ components: description: The url to the external site, document, etc. required: - url - type: object description: A link to external information that is related to the entity. EntityMeta: allOf: - $ref: '#/components/schemas/JsonObject' - - properties: + - type: object + properties: links: + type: array items: $ref: '#/components/schemas/EntityLink' - type: array description: A list of external hyperlinks related to the entity. tags: + type: array items: type: string - type: array description: |- A list of single-valued strings, to for example classify catalog entities in various ways. @@ -126,9 +132,9 @@ components: that do so in such a way that it breaks semantics. required: - name - type: object description: Metadata fields common to all versions/kinds of entity. EntityRelation: + type: object properties: targetRef: type: string @@ -139,14 +145,14 @@ components: required: - targetRef - type - type: object description: A relation of a specific type to another entity in the catalog. Entity: + type: object properties: relations: + type: array items: $ref: '#/components/schemas/EntityRelation' - type: array description: The relations that this entity has with other entities. spec: $ref: '#/components/schemas/JsonObject' @@ -164,12 +170,14 @@ components: - metadata - kind - apiVersion - type: object description: The parts of the format that's common to all versions/kinds of entity. EntityAncestryResponse: + type: object properties: items: + type: array items: + type: object properties: parentEntityRefs: items: @@ -180,44 +188,42 @@ components: required: - parentEntityRefs - entity - type: object - type: array rootEntityRef: type: string required: - items - rootEntityRef - type: object EntitiesBatchResponse: + type: object properties: items: + type: array items: allOf: - $ref: '#/components/schemas/Entity' nullable: true - type: array description: |- The list of entities, in the same order as the refs in the request. Entries that are null signify that no entity existed with that ref. required: - items - type: object EntityFacets: type: object - properties: - value: + properties: + value: type: string - count: + count: type: number description: Construct a type with a set of properties K of type T EntityFacetsResponse: - properties: {} type: object + properties: {} additionalProperties: - $ref: '#/components/schemas/EntityFacets' + $ref: '#/components/schemas/EntityFacets' required: - facets Location: + type: object properties: target: type: string @@ -229,9 +235,9 @@ components: - target - type - id - type: object description: Entity location for a specific entity. LocationSpec: + type: object properties: presence: type: string @@ -245,9 +251,9 @@ components: required: - target - type - type: object description: Holds the entity location information. AnalyzeLocationExistingEntity: + type: object properties: entity: $ref: '#/components/schemas/Entity' @@ -259,13 +265,13 @@ components: - entity - isRegistered - location - type: object description: |- If the folder pointed to already contained catalog info yaml files, they are read and emitted like this so that the frontend can inform the user that it located them and can make sure to register them as well if they weren't already RecursivePartial_Entity_: + type: object properties: apiVersion: type: string @@ -280,13 +286,13 @@ components: spec: $ref: '#/components/schemas/JsonObject' relations: + type: array items: $ref: '#/components/schemas/EntityRelation' - type: array description: The relations that this entity has with other entities. - type: object description: Makes all keys of an entire hierarchy optional. AnalyzeLocationEntityField: + type: object properties: description: type: string @@ -315,19 +321,18 @@ components: - value - state - field - type: object AnalyzeLocationGenerateEntity: + type: object properties: fields: + type: array items: $ref: '#/components/schemas/AnalyzeLocationEntityField' - type: array entity: $ref: '#/components/schemas/RecursivePartial_Entity_' required: - fields - entity - type: object description: |- This is some form of representation of what the analyzer could deduce. We should probably have a chat about how this can best be conveyed to @@ -335,6 +340,7 @@ components: enough info for the frontend to know what form data to show to the user for overriding/completing the info. AnalyzeLocationResponse: + type: object properties: generateEntities: items: @@ -347,8 +353,8 @@ components: required: - generateEntities - existingEntityFiles - type: object LocationInput: + type: object properties: type: type: string @@ -363,11 +369,11 @@ components: - type - target - presence - type: object SerializedError: allOf: - $ref: '#/components/schemas/JsonObject' - - properties: + - type: object + properties: code: type: string description: A custom code (not necessarily the same as an HTTP response code); may not be present @@ -383,7 +389,6 @@ components: required: - message - name - type: object description: The serialized form of an Error. securitySchemes: JWT: @@ -409,6 +414,7 @@ paths: application/json: schema: $ref: '#/components/schemas/RefreshOptions' + /entities: get: operationId: GetEntities @@ -418,9 +424,9 @@ paths: content: application/json: schema: + type: array items: $ref: '#/components/schemas/Entity' - type: array security: - {} - JWT: [] @@ -450,6 +456,7 @@ paths: required: false schema: type: string + /entities/by-uid/{uid}: get: operationId: GetEntityByUid @@ -513,6 +520,7 @@ paths: required: true schema: type: string + /entities/by-name/{kind}/{namespace}/{name}/ancestry: get: operationId: GetEntityAncestryByName @@ -542,6 +550,7 @@ paths: required: true schema: type: string + /entities/by-refs: post: operationId: GetEntitiesByRefs @@ -566,9 +575,10 @@ paths: content: application/json: schema: + type: array items: type: string - type: array + /entity-facets: get: operationId: GetEntityFacets @@ -593,6 +603,7 @@ paths: required: false schema: type: string + /locations: post: operationId: CreateLocation @@ -602,6 +613,7 @@ paths: content: application/json: schema: + type: object properties: exists: type: boolean @@ -614,7 +626,6 @@ paths: required: - entities - location - type: object security: - {} - JWT: [] @@ -629,6 +640,7 @@ paths: content: application/json: schema: + type: object properties: presence: type: string @@ -643,7 +655,6 @@ paths: - presence - target - type - type: object get: operationId: GetLocations responses: @@ -652,18 +663,19 @@ paths: content: application/json: schema: + type: array items: + type: object properties: data: $ref: '#/components/schemas/Location' required: - data - type: object - type: array security: - {} - JWT: [] parameters: [] + /locations/{id}: get: operationId: GetLocation @@ -697,6 +709,7 @@ paths: required: true schema: type: string + /analyze-location: post: operationId: AnalyzeLocation @@ -716,6 +729,7 @@ paths: content: application/json: schema: + type: object properties: catalogFileName: type: string @@ -724,7 +738,7 @@ paths: required: - catalogFileName - location - type: object + /validate-entity: post: operationId: ValidateEntity @@ -735,20 +749,20 @@ paths: application/json: schema: anyOf: - - properties: + - type: object + properties: errors: $ref: '#/components/schemas/SerializedError' required: - errors - type: object - - properties: + - type: object + properties: errors: + type: array items: $ref: '#/components/schemas/SerializedError' - type: array required: - errors - type: object security: - {} - JWT: [] @@ -758,6 +772,7 @@ paths: content: application/json: schema: + type: object properties: location: type: string @@ -766,6 +781,3 @@ paths: required: - location - entity - type: object -servers: - - url: / From 7a414a855cfbe24c1ca07bae8d29f68f143b4e15 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 10:24:12 +0000 Subject: [PATCH 295/423] chore(deps): update dependency lint-staged to v13.1.1 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 336efa3f38..2153506078 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27675,8 +27675,8 @@ __metadata: linkType: hard "lint-staged@npm:^13.0.0": - version: 13.1.0 - resolution: "lint-staged@npm:13.1.0" + version: 13.1.1 + resolution: "lint-staged@npm:13.1.1" dependencies: cli-truncate: ^3.1.0 colorette: ^2.0.19 @@ -27693,7 +27693,7 @@ __metadata: yaml: ^2.1.3 bin: lint-staged: bin/lint-staged.js - checksum: adf20c4ca9285c4a93b06598b970d71b04cfe58a1a4c9006f753b83e02c1c622d1866c32a4f1e7e29a98091c501eac3345f7678af247b4f97d5be88b3d8727c1 + checksum: 8e5093c7e982a2f6d6449927a40156a812644479df1d2760aee8bf05df3a314e022d8f7e275e57fd61769ee57e3cf7b062ed3c6e4934a63848300b877e269daa languageName: node linkType: hard From cd9db2a5c0958d8be6f73959cf95925689f6a94f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 10:25:25 +0000 Subject: [PATCH 296/423] fix(deps): update dependency @keyv/redis to v2.5.5 Signed-off-by: Renovate Bot --- yarn.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/yarn.lock b/yarn.lock index 336efa3f38..852c538d48 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11036,11 +11036,11 @@ __metadata: linkType: hard "@keyv/redis@npm:^2.5.3": - version: 2.5.4 - resolution: "@keyv/redis@npm:2.5.4" + version: 2.5.5 + resolution: "@keyv/redis@npm:2.5.5" dependencies: - ioredis: ^5.2.4 - checksum: 02f557e0bc0343aea44b8dd4b6ff273da5833b935236c4036fa89e90b1d92d9688dafa064d5318d26744a6c72497cd4c41dcac825cb8d5919271e3a25a3cadbb + ioredis: ^5.3.0 + checksum: dc4c4e9c0a44dec1166a6a4481a42342289b4618136c2f640306bee381cf30d737346b064ecc369fc8ebdd2baaaba47e099aabe9f37839911171a9c006d75e62 languageName: node linkType: hard @@ -20465,10 +20465,10 @@ __metadata: languageName: node linkType: hard -"denque@npm:^2.0.1": - version: 2.0.1 - resolution: "denque@npm:2.0.1" - checksum: ec398d1e3c6c8d4f5213dcf9ad74d7faa3b461e29a0019c9742b49a97ac5e16aa7134db45fa9d841e318e7722dd1ba670a474fde9a5b0d870b3a5fc6fe914c30 +"denque@npm:^2.0.1, denque@npm:^2.1.0": + version: 2.1.0 + resolution: "denque@npm:2.1.0" + checksum: 1d4ae1d05e59ac3a3481e7b478293f4b4c813819342273f3d5b826c7ffa9753c520919ba264f377e09108d24ec6cf0ec0ac729a5686cbb8f32d797126c5dae74 languageName: node linkType: hard @@ -25064,20 +25064,20 @@ __metadata: languageName: node linkType: hard -"ioredis@npm:^5.2.4": - version: 5.2.4 - resolution: "ioredis@npm:5.2.4" +"ioredis@npm:^5.3.0": + version: 5.3.0 + resolution: "ioredis@npm:5.3.0" dependencies: "@ioredis/commands": ^1.1.1 cluster-key-slot: ^1.1.0 debug: ^4.3.4 - denque: ^2.0.1 + denque: ^2.1.0 lodash.defaults: ^4.2.0 lodash.isarguments: ^3.1.0 redis-errors: ^1.2.0 redis-parser: ^3.0.0 standard-as-callback: ^2.1.0 - checksum: c3a7df407a41ae516bede8b6db853c568198b13fe4a4785f66be5cd541087121b9d45fb9a6b1b6a5fb668c29ce52ab4685642b994803bdfa0a35f794ea8ef7ae + checksum: d3a1fd8f1b5d9ce6d4b7dd083773dbe0936ea3d1f55f07d36daa3d0b59c4636e95640f90bc003a08bc900a9803307e7d7e191817a2c2970696e204dae6f3dc35 languageName: node linkType: hard From 76cddc6f859a2c602517185204e1cd70f79ec233 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 10:27:38 +0000 Subject: [PATCH 297/423] fix(deps): update dependency @swc/core to v1.3.34 Signed-off-by: Renovate Bot --- storybook/yarn.lock | 86 ++++++++++++++++++++++----------------------- yarn.lock | 86 ++++++++++++++++++++++----------------------- 2 files changed, 86 insertions(+), 86 deletions(-) diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 8e5b2b8c56..f2e0f1c96a 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -2966,90 +2966,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-darwin-arm64@npm:1.3.30" +"@swc/core-darwin-arm64@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-darwin-arm64@npm:1.3.34" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-darwin-x64@npm:1.3.30" +"@swc/core-darwin-x64@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-darwin-x64@npm:1.3.34" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.30" +"@swc/core-linux-arm-gnueabihf@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.34" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.30" +"@swc/core-linux-arm64-gnu@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.34" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.30" +"@swc/core-linux-arm64-musl@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.34" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.30" +"@swc/core-linux-x64-gnu@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.34" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-x64-musl@npm:1.3.30" +"@swc/core-linux-x64-musl@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-x64-musl@npm:1.3.34" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.30" +"@swc/core-win32-arm64-msvc@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.34" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.30" +"@swc/core-win32-ia32-msvc@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.34" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.30" +"@swc/core-win32-x64-msvc@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.34" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.9": - version: 1.3.30 - resolution: "@swc/core@npm:1.3.30" + version: 1.3.34 + resolution: "@swc/core@npm:1.3.34" dependencies: - "@swc/core-darwin-arm64": 1.3.30 - "@swc/core-darwin-x64": 1.3.30 - "@swc/core-linux-arm-gnueabihf": 1.3.30 - "@swc/core-linux-arm64-gnu": 1.3.30 - "@swc/core-linux-arm64-musl": 1.3.30 - "@swc/core-linux-x64-gnu": 1.3.30 - "@swc/core-linux-x64-musl": 1.3.30 - "@swc/core-win32-arm64-msvc": 1.3.30 - "@swc/core-win32-ia32-msvc": 1.3.30 - "@swc/core-win32-x64-msvc": 1.3.30 + "@swc/core-darwin-arm64": 1.3.34 + "@swc/core-darwin-x64": 1.3.34 + "@swc/core-linux-arm-gnueabihf": 1.3.34 + "@swc/core-linux-arm64-gnu": 1.3.34 + "@swc/core-linux-arm64-musl": 1.3.34 + "@swc/core-linux-x64-gnu": 1.3.34 + "@swc/core-linux-x64-musl": 1.3.34 + "@swc/core-win32-arm64-msvc": 1.3.34 + "@swc/core-win32-ia32-msvc": 1.3.34 + "@swc/core-win32-x64-msvc": 1.3.34 dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -3071,7 +3071,7 @@ __metadata: optional: true "@swc/core-win32-x64-msvc": optional: true - checksum: 157a8ae43ebc73fa28d53e913fd7fc879289d5479ba5ea0c5e9abad0b379ca7e292d45f4f07bfd3ec0ff1998b55f300737724dfe463f1f7b361661e083db950c + checksum: a77c286b6b34d40f634ae882aac66f882cf806c165453878c31311070c46f020c607925bd454f64959504f08852b204cc37feba93fc6a3c1a64b295a9b5007d6 languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index 336efa3f38..090ae80bd7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13350,90 +13350,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-darwin-arm64@npm:1.3.30" +"@swc/core-darwin-arm64@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-darwin-arm64@npm:1.3.34" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-darwin-x64@npm:1.3.30" +"@swc/core-darwin-x64@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-darwin-x64@npm:1.3.34" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.30" +"@swc/core-linux-arm-gnueabihf@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.34" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.30" +"@swc/core-linux-arm64-gnu@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.34" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.30" +"@swc/core-linux-arm64-musl@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.34" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.30" +"@swc/core-linux-x64-gnu@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.34" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-x64-musl@npm:1.3.30" +"@swc/core-linux-x64-musl@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-x64-musl@npm:1.3.34" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.30" +"@swc/core-win32-arm64-msvc@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.34" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.30" +"@swc/core-win32-ia32-msvc@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.34" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.30" +"@swc/core-win32-x64-msvc@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.34" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.9": - version: 1.3.30 - resolution: "@swc/core@npm:1.3.30" + version: 1.3.34 + resolution: "@swc/core@npm:1.3.34" dependencies: - "@swc/core-darwin-arm64": 1.3.30 - "@swc/core-darwin-x64": 1.3.30 - "@swc/core-linux-arm-gnueabihf": 1.3.30 - "@swc/core-linux-arm64-gnu": 1.3.30 - "@swc/core-linux-arm64-musl": 1.3.30 - "@swc/core-linux-x64-gnu": 1.3.30 - "@swc/core-linux-x64-musl": 1.3.30 - "@swc/core-win32-arm64-msvc": 1.3.30 - "@swc/core-win32-ia32-msvc": 1.3.30 - "@swc/core-win32-x64-msvc": 1.3.30 + "@swc/core-darwin-arm64": 1.3.34 + "@swc/core-darwin-x64": 1.3.34 + "@swc/core-linux-arm-gnueabihf": 1.3.34 + "@swc/core-linux-arm64-gnu": 1.3.34 + "@swc/core-linux-arm64-musl": 1.3.34 + "@swc/core-linux-x64-gnu": 1.3.34 + "@swc/core-linux-x64-musl": 1.3.34 + "@swc/core-win32-arm64-msvc": 1.3.34 + "@swc/core-win32-ia32-msvc": 1.3.34 + "@swc/core-win32-x64-msvc": 1.3.34 dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -13455,7 +13455,7 @@ __metadata: optional: true "@swc/core-win32-x64-msvc": optional: true - checksum: 157a8ae43ebc73fa28d53e913fd7fc879289d5479ba5ea0c5e9abad0b379ca7e292d45f4f07bfd3ec0ff1998b55f300737724dfe463f1f7b361661e083db950c + checksum: a77c286b6b34d40f634ae882aac66f882cf806c165453878c31311070c46f020c607925bd454f64959504f08852b204cc37feba93fc6a3c1a64b295a9b5007d6 languageName: node linkType: hard From b88182e22605919700d1806c90c92203da8ff649 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 11:07:18 +0000 Subject: [PATCH 298/423] chore(deps): update dependency prettier to v2.8.4 Signed-off-by: Renovate Bot --- microsite-next/yarn.lock | 6 +++--- microsite/yarn.lock | 6 +++--- yarn.lock | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index d81c348bc3..e03c6d93c5 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -8361,11 +8361,11 @@ __metadata: linkType: hard "prettier@npm:^2.6.2": - version: 2.8.2 - resolution: "prettier@npm:2.8.2" + version: 2.8.4 + resolution: "prettier@npm:2.8.4" bin: prettier: bin-prettier.js - checksum: 740c56c2128d587d656ea1dde9bc9c3503dfc94db4f3ac387259215eeb2e216680bdad9d18a0c9feecc6b42cfa188d6fa777df4c36c1d00cedd4199074fbfbd2 + checksum: c173064bf3df57b6d93d19aa98753b9b9dd7657212e33b41ada8e2e9f9884066bb9ca0b4005b89b3ab137efffdf8fbe0b462785aba20364798ff4303aadda57e languageName: node linkType: hard diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 34ed76e9e4..95b0c2885b 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -7369,11 +7369,11 @@ __metadata: linkType: hard "prettier@npm:^2.6.2": - version: 2.8.2 - resolution: "prettier@npm:2.8.2" + version: 2.8.4 + resolution: "prettier@npm:2.8.4" bin: prettier: bin-prettier.js - checksum: 740c56c2128d587d656ea1dde9bc9c3503dfc94db4f3ac387259215eeb2e216680bdad9d18a0c9feecc6b42cfa188d6fa777df4c36c1d00cedd4199074fbfbd2 + checksum: c173064bf3df57b6d93d19aa98753b9b9dd7657212e33b41ada8e2e9f9884066bb9ca0b4005b89b3ab137efffdf8fbe0b462785aba20364798ff4303aadda57e languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index 2153506078..0e02029c72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32113,11 +32113,11 @@ __metadata: linkType: hard "prettier@npm:^2.2.1, prettier@npm:^2.7.1": - version: 2.8.2 - resolution: "prettier@npm:2.8.2" + version: 2.8.4 + resolution: "prettier@npm:2.8.4" bin: prettier: bin-prettier.js - checksum: 740c56c2128d587d656ea1dde9bc9c3503dfc94db4f3ac387259215eeb2e216680bdad9d18a0c9feecc6b42cfa188d6fa777df4c36c1d00cedd4199074fbfbd2 + checksum: c173064bf3df57b6d93d19aa98753b9b9dd7657212e33b41ada8e2e9f9884066bb9ca0b4005b89b3ab137efffdf8fbe0b462785aba20364798ff4303aadda57e languageName: node linkType: hard From aef888fc8bd76a40a64bdd78997986456bd4b4d6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 12:16:30 +0000 Subject: [PATCH 299/423] fix(deps): update dependency jose to v4.11.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 0e02029c72..3072ac7386 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26586,9 +26586,9 @@ __metadata: linkType: hard "jose@npm:^4.10.0, jose@npm:^4.6.0": - version: 4.11.2 - resolution: "jose@npm:4.11.2" - checksum: bc9b2271c31683603857b2fd2903afa29f826fffd4bcefc0845355ed86995def87eaadf502033207996109d76698c912e5a986e279326d9629321a50504fe466 + version: 4.11.4 + resolution: "jose@npm:4.11.4" + checksum: ab870d61e3721cfa1059b1a79cfc2fce06586c8afd4164362e1725934a635191bd938893ebdfac55a0811efbe9b6fd650bbf82d36d87e8a0b7cb4b0379328dab languageName: node linkType: hard From d646a84f2f3f232693fb42d6199d46b5c2672bb3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 12:27:48 +0000 Subject: [PATCH 300/423] fix(deps): update dependency js-base64 to v3.7.5 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0e02029c72..f2d4931d11 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26600,9 +26600,9 @@ __metadata: linkType: hard "js-base64@npm:^3.6.0": - version: 3.7.4 - resolution: "js-base64@npm:3.7.4" - checksum: b8f6b10033b57bbb87fa34629f44bc665cb8b7bcba49610a29b296592616e633e9c186afaa02de5a54d60c08aaa36c8c8ad585db095a96fb331fe022f54792a2 + version: 3.7.5 + resolution: "js-base64@npm:3.7.5" + checksum: 67a78c8b1c47b73f1c6fba1957e9fe6fd9dc78ac93ac46cc2e43472dcb9cf150d126fb0e593192e88e0497354fa634d17d255add7cc6ee3c7b4d29870faa8e18 languageName: node linkType: hard From 7f2376ca298749df4dc967cad4121ea1323726a0 Mon Sep 17 00:00:00 2001 From: Henrique Oliveira Date: Wed, 8 Feb 2023 09:42:34 -0300 Subject: [PATCH 301/423] update contact info Signed-off-by: Henrique Oliveira --- ADOPTERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ADOPTERS.md b/ADOPTERS.md index 965cf06727..4329a00664 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -186,7 +186,7 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [Cho Tot](https://www.chotot.com) | [Chotot Team](mailto:sre@chotot.vn) | Internal developer portal, service catalog with CI/CD tools. | | [William Hill](https://www.williamhillgroup.com/) | [Pat Mills](mailto:pat.mills@williamhill.com), [Nathan Flynn](mailto:nflynn@williamhill.co.uk), and [Nishkarsh Raj](mailto:nishkarsh.raj@williamhill.co.uk) | William Hill are leveraging Backstage to build our Engineering Portal. Our mission is to centralize the software catalog inventory to enable service discoverability, reduce the onboarding time for new Engineers, provide a single pane of glass to accelerate Developer Productivity and Save Engineers time. Our aspiration is to create an InnerSource community focussed on organization-wide patterns that are re-usable and can be self-served with the Scaffolder. | | [Vodafone NewZealand Limited](https://vodafone.co.nz) | [Ankit Gupta](mailto:ankit.gupta@vodafone.nz), [DevOps COE](mailto:devopstooling@vodafone.nz) | Vodafone NZ are leveraging Backstage to build centralised and self service Engineering Portal. Our mission is to standardised Pipeline templates across the Engineering teams, One shop stop to create the pipelines and repository with a template approach which reduces creation part from days to minutes and no wait time for developers. A unified view for Azure DevOps pipeline, Azure Repo pull requests, Deployment status from Azure RedHat Openshift-ArgoCD and SonarQube Security and code quality scans report on a single pan to provide a streamlined view for all microservices across the app stack. | -| [Coamo](http://www.coamo.com.br) | [@holiiveira](https://github.com/holiiveira), [@gpxlnx](https://github.com/gpxlnx) | We're starting to use it as the main tool of a DevOps platform. Our goal is to provide software templates, centralize our software catalog enabling efficient service discovery, and make it easy to manage the entire software ecosystem in one place. | +| [Coamo](http://www.coamo.com.br) | [Henrique Oliveira](https://www.linkedin.com/in/oliveirah/), [Guilherme Xavier](https://br.linkedin.com/in/guilhermexavierlnx) | We're starting to use it as the main tool of a DevOps platform. Our goal is to provide software templates, centralize our software catalog enabling efficient service discovery, and make it easy to manage the entire software ecosystem in one place. | | [Exclaimer](https://www.exclaimer.com/) | [Marley Powell](mailto:marley.powell@exclaimer.com) | Developer portal, service catalog and documentation | | [Edge Consulting](https://egde.no/) | [Øyvind Brekkhus Sandåker](mailto:oyvindbs@egde.no) | Using it as a Software Catalog to get an overview of our systems, for ourselves and our customers. | | [CRV](https://crv4all.com) | [Pepijn Schildkamp](mailto:pepijn.schildkamp@crv4all.com) | From 3ff9581a3fb2876cadd214798f9ab4337ff3dcc1 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 8 Feb 2023 14:04:25 +0100 Subject: [PATCH 302/423] chore: turn off the auto assign functionality of our workflows Signed-off-by: blam --- .github/workflows/pr.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 1cde52bfbb..d7ae00d3a9 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -18,12 +18,12 @@ jobs: if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) steps: - name: PR sync - uses: backstage/actions/pr-sync@v0.6.0 + uses: backstage/actions/pr-sync@v0.6.1 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} installation-id: ${{ secrets.BACKSTAGE_GOALIE_INSTALLATION_ID }} project-id: PVT_kwDOBFKqdc02LQ - excluded-users: ${{ secrets.OOO_USERS }} + auto-assign: false owning-teams: '@backstage/techdocs-core' From 3c6636c000a7f8ed4a55e758f9ebff3773aec789 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 13:11:33 +0000 Subject: [PATCH 303/423] fix(deps): update dependency vm2 to v3.9.14 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3072ac7386..7c65c54e5f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -37849,14 +37849,14 @@ __metadata: linkType: hard "vm2@npm:^3.9.11": - version: 3.9.13 - resolution: "vm2@npm:3.9.13" + version: 3.9.14 + resolution: "vm2@npm:3.9.14" dependencies: acorn: ^8.7.0 acorn-walk: ^8.2.0 bin: vm2: bin/vm2 - checksum: ee82c130a9d1b45558fac4e95133ae022e69fafd4bec8aada44bb2f0aebe6ff8ae9b1176e7cbafceffec35267e009b518c121ad81a5565da06aa7a50ed3a09bc + checksum: 1ed7481e07ce8e03055101b382bfbf0d725a5c9b9bbe8bf75f71501cb43a6bd22f6a0a151975ff7cea8cad136d47e66d64f0a3248913f6d3ca3c405db12bacc0 languageName: node linkType: hard From b86efa2d04a4e8475aeca0845beafdd9bd4ddd71 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 8 Feb 2023 11:13:58 +0100 Subject: [PATCH 304/423] backend-plugin-api: make ServiceFactory opaque Signed-off-by: Patrik Oldsberg --- .changeset/quiet-pets-count.md | 6 ++ .changeset/wild-melons-shout.md | 5 + packages/backend-app-api/api-report.md | 60 +++++++++--- .../httpRouterServiceFactory.test.ts | 11 +-- .../tokenManagerServiceFactory.test.ts | 11 +-- .../src/wiring/ServiceRegistry.ts | 82 +++++++++++------ packages/backend-plugin-api/api-report.md | 54 ++++------- .../src/services/system/types.ts | 91 ++++++++++++------- packages/backend-test-utils/api-report.md | 30 +++--- .../src/next/services/mockServices.ts | 12 ++- 10 files changed, 212 insertions(+), 150 deletions(-) create mode 100644 .changeset/quiet-pets-count.md create mode 100644 .changeset/wild-melons-shout.md diff --git a/.changeset/quiet-pets-count.md b/.changeset/quiet-pets-count.md new file mode 100644 index 0000000000..bc7da8f3e7 --- /dev/null +++ b/.changeset/quiet-pets-count.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-test-utils': patch +'@backstage/backend-app-api': patch +--- + +Updated usage of `ServiceFactory`. diff --git a/.changeset/wild-melons-shout.md b/.changeset/wild-melons-shout.md new file mode 100644 index 0000000000..5a79612f22 --- /dev/null +++ b/.changeset/wild-melons-shout.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +Switch `ServiceFactory` to be an opaque type, keeping only the `service` field as public API, but also adding a type parameter for the service scope. diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index e4c3e34751..9329610a4c 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -48,7 +48,10 @@ export interface Backend { } // @public (undocumented) -export const cacheServiceFactory: () => ServiceFactory; +export const cacheServiceFactory: () => ServiceFactory< + PluginCacheManager, + 'plugin' +>; // @public (undocumented) export interface ConfigFactoryOptions { @@ -59,7 +62,7 @@ export interface ConfigFactoryOptions { // @public (undocumented) export const configServiceFactory: ( options?: ConfigFactoryOptions | undefined, -) => ServiceFactory; +) => ServiceFactory; // @public (undocumented) export function createConfigSecretEnumerator(options: { @@ -88,7 +91,10 @@ export interface CreateSpecializedBackendOptions { } // @public (undocumented) -export const databaseServiceFactory: () => ServiceFactory; +export const databaseServiceFactory: () => ServiceFactory< + PluginDatabaseManager, + 'plugin' +>; // @public export class DefaultRootHttpRouter implements RootHttpRouterService { @@ -106,7 +112,10 @@ export interface DefaultRootHttpRouterOptions { } // @public (undocumented) -export const discoveryServiceFactory: () => ServiceFactory; +export const discoveryServiceFactory: () => ServiceFactory< + PluginEndpointDiscovery, + 'plugin' +>; // @public export interface ExtendedHttpServer extends http.Server { @@ -126,7 +135,7 @@ export interface HttpRouterFactoryOptions { // @public (undocumented) export const httpRouterServiceFactory: ( options?: HttpRouterFactoryOptions | undefined, -) => ServiceFactory; +) => ServiceFactory; // @public export type HttpServerCertificateOptions = @@ -160,10 +169,13 @@ export type IdentityFactoryOptions = { // @public (undocumented) export const identityServiceFactory: ( options?: IdentityFactoryOptions | undefined, -) => ServiceFactory; +) => ServiceFactory; // @public -export const lifecycleServiceFactory: () => ServiceFactory; +export const lifecycleServiceFactory: () => ServiceFactory< + LifecycleService, + 'plugin' +>; // @public export function loadBackendConfig(options: { @@ -174,7 +186,10 @@ export function loadBackendConfig(options: { }>; // @public (undocumented) -export const loggerServiceFactory: () => ServiceFactory; +export const loggerServiceFactory: () => ServiceFactory< + LoggerService, + 'plugin' +>; // @public export class MiddlewareFactory { @@ -202,7 +217,10 @@ export interface MiddlewareFactoryOptions { } // @public (undocumented) -export const permissionsServiceFactory: () => ServiceFactory; +export const permissionsServiceFactory: () => ServiceFactory< + PermissionsService, + 'plugin' +>; // @public export function readCorsOptions(config?: Config): CorsOptions; @@ -238,22 +256,34 @@ export type RootHttpRouterFactoryOptions = { // @public (undocumented) export const rootHttpRouterServiceFactory: ( options?: RootHttpRouterFactoryOptions | undefined, -) => ServiceFactory; +) => ServiceFactory; // @public -export const rootLifecycleServiceFactory: () => ServiceFactory; +export const rootLifecycleServiceFactory: () => ServiceFactory< + RootLifecycleService, + 'root' +>; // @public (undocumented) -export const rootLoggerServiceFactory: () => ServiceFactory; +export const rootLoggerServiceFactory: () => ServiceFactory< + RootLoggerService, + 'root' +>; // @public (undocumented) -export const schedulerServiceFactory: () => ServiceFactory; +export const schedulerServiceFactory: () => ServiceFactory< + SchedulerService, + 'plugin' +>; // @public (undocumented) -export const tokenManagerServiceFactory: () => ServiceFactory; +export const tokenManagerServiceFactory: () => ServiceFactory< + TokenManagerService, + 'plugin' +>; // @public (undocumented) -export const urlReaderServiceFactory: () => ServiceFactory; +export const urlReaderServiceFactory: () => ServiceFactory; // @public export class WinstonLogger implements RootLoggerService { diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.test.ts b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.test.ts index 2e124c98b6..e52b4c9a36 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.test.ts @@ -14,19 +14,12 @@ * limitations under the License. */ -import { - HttpRouterService, - ServiceFactory, -} from '@backstage/backend-plugin-api'; import { httpRouterServiceFactory } from './httpRouterServiceFactory'; describe('httpRouterFactory', () => { it('should register plugin paths', async () => { const rootHttpRouter = { use: jest.fn() }; - const factory = httpRouterServiceFactory() as Exclude< - ServiceFactory, - { scope: 'root' } - >; + const factory = httpRouterServiceFactory() as any; const handler1 = () => {}; const router1 = await factory.factory( @@ -57,7 +50,7 @@ describe('httpRouterFactory', () => { const rootHttpRouter = { use: jest.fn() }; const factory = httpRouterServiceFactory({ getPath: id => `/some/${id}/path`, - }) as Exclude, { scope: 'root' }>; + }) as any; const handler1 = () => {}; const router1 = await factory.factory( diff --git a/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.test.ts b/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.test.ts index 6c33829967..aca5211e2e 100644 --- a/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.test.ts @@ -14,11 +14,7 @@ * limitations under the License. */ -import { - LoggerService, - ServiceFactory, - TokenManagerService, -} from '@backstage/backend-plugin-api'; +import { LoggerService } from '@backstage/backend-plugin-api'; import { ConfigReader } from '@backstage/config'; import { tokenManagerServiceFactory } from './tokenManagerServiceFactory'; @@ -26,10 +22,7 @@ describe('tokenManagerFactory', () => { it('should create managers that can share tokens in development', async () => { (process.env as { NODE_ENV?: string }).NODE_ENV = 'development'; - const factory = tokenManagerServiceFactory() as Exclude< - ServiceFactory, - { scope: 'root' } - >; + const factory = tokenManagerServiceFactory() as any; const deps = { config: new ConfigReader({}), logger: { warn() {} } as unknown as LoggerService, diff --git a/packages/backend-app-api/src/wiring/ServiceRegistry.ts b/packages/backend-app-api/src/wiring/ServiceRegistry.ts index 68dff3f7c3..b5b55f67cf 100644 --- a/packages/backend-app-api/src/wiring/ServiceRegistry.ts +++ b/packages/backend-app-api/src/wiring/ServiceRegistry.ts @@ -18,36 +18,66 @@ import { ServiceFactory, ServiceRef, coreServices, + createServiceFactory, } from '@backstage/backend-plugin-api'; import { stringifyError } from '@backstage/errors'; import { EnumerableServiceHolder } from './types'; +// Direct internal import to avoid duplication +// eslint-disable-next-line @backstage/no-forbidden-package-imports +import { InternalServiceFactory } from '@backstage/backend-plugin-api/src/services/system/types'; /** * Keep in sync with `@backstage/backend-plugin-api/src/services/system/types.ts` * @internal */ -export type InternalServiceRef = ServiceRef & { +export type InternalServiceRef = ServiceRef & { __defaultFactory?: ( - service: ServiceRef, - ) => Promise | (() => ServiceFactory)>; + service: ServiceRef, + ) => Promise ServiceFactory)>; }; +function toInternalServiceFactory( + factory: ServiceFactory, +): InternalServiceFactory { + const f = factory as InternalServiceFactory; + if (f.$$type !== '@backstage/ServiceFactory') { + throw new Error(`Invalid service factory, bad type '${f.$$type}'`); + } + if (f.version !== 'v1') { + throw new Error(`Invalid service factory, bad version '${f.version}'`); + } + return f; +} + +const pluginMetadataServiceFactory = createServiceFactory( + (options: { pluginId: string }) => ({ + service: coreServices.pluginMetadata, + deps: {}, + factory: async () => ({ getId: () => options.pluginId }), + }), +); + export class ServiceRegistry implements EnumerableServiceHolder { - readonly #providedFactories: Map; - readonly #loadedDefaultFactories: Map>; + readonly #providedFactories: Map; + readonly #loadedDefaultFactories: Map< + Function, + Promise + >; readonly #implementations: Map< - ServiceFactory, + InternalServiceFactory, { context: Promise; byPlugin: Map>; } >; readonly #rootServiceImplementations = new Map< - ServiceFactory, + InternalServiceFactory, Promise >(); - constructor(factories: Array>) { - this.#providedFactories = new Map(factories.map(f => [f.service.id, f])); + constructor(factories: Array) { + this.#providedFactories = new Map( + factories.map(sf => [sf.service.id, toInternalServiceFactory(sf)]), + ); this.#loadedDefaultFactories = new Map(); this.#implementations = new Map(); } @@ -55,23 +85,19 @@ export class ServiceRegistry implements EnumerableServiceHolder { #resolveFactory( ref: ServiceRef, pluginId: string, - ): Promise | undefined { + ): Promise | undefined { // Special case handling of the plugin metadata service, generating a custom factory for it each time if (ref.id === coreServices.pluginMetadata.id) { - return Promise.resolve< - ServiceFactory - >({ - scope: 'plugin', - service: coreServices.pluginMetadata, - deps: {}, - factory: async () => ({ getId: () => pluginId }), - }); + return Promise.resolve( + toInternalServiceFactory(pluginMetadataServiceFactory({ pluginId })), + ); } - let resolvedFactory: Promise | ServiceFactory | undefined = - this.#providedFactories.get(ref.id); - const { __defaultFactory: defaultFactory } = - ref as InternalServiceRef; + let resolvedFactory: + | Promise + | InternalServiceFactory + | undefined = this.#providedFactories.get(ref.id); + const { __defaultFactory: defaultFactory } = ref as InternalServiceRef; if (!resolvedFactory && !defaultFactory) { return undefined; } @@ -82,8 +108,8 @@ export class ServiceRegistry implements EnumerableServiceHolder { loadedFactory = Promise.resolve() .then(() => defaultFactory!(ref)) .then(f => - typeof f === 'function' ? f() : f, - ) as Promise; + toInternalServiceFactory(typeof f === 'function' ? f() : f), + ); this.#loadedDefaultFactories.set(defaultFactory!, loadedFactory); } resolvedFactory = loadedFactory.catch(error => { @@ -100,7 +126,7 @@ export class ServiceRegistry implements EnumerableServiceHolder { return Promise.resolve(resolvedFactory); } - #checkForMissingDeps(factory: ServiceFactory, pluginId: string) { + #checkForMissingDeps(factory: InternalServiceFactory, pluginId: string) { const missingDeps = Object.values(factory.deps).filter(ref => { if (ref.id === coreServices.pluginMetadata.id) { return false; @@ -109,7 +135,7 @@ export class ServiceRegistry implements EnumerableServiceHolder { return false; } - return !(ref as InternalServiceRef).__defaultFactory; + return !(ref as InternalServiceRef).__defaultFactory; }); if (missingDeps.length) { @@ -126,7 +152,7 @@ export class ServiceRegistry implements EnumerableServiceHolder { get(ref: ServiceRef, pluginId: string): Promise | undefined { return this.#resolveFactory(ref, pluginId)?.then(factory => { - if (factory.scope === 'root') { + if (factory.service.scope === 'root') { let existing = this.#rootServiceImplementations.get(factory); if (!existing) { this.#checkForMissingDeps(factory, pluginId); @@ -143,7 +169,7 @@ export class ServiceRegistry implements EnumerableServiceHolder { } existing = Promise.all(rootDeps).then(entries => - factory.factory(Object.fromEntries(entries)), + factory.factory(Object.fromEntries(entries), undefined), ); this.#rootServiceImplementations.set(factory, existing); } diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index 1219bdaf3f..6a0b5e51e7 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -145,7 +145,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: RootServiceFactoryConfig, -): () => ServiceFactory; +): () => ServiceFactory; // @public export function createServiceFactory< @@ -157,7 +157,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: (options?: TOpts) => RootServiceFactoryConfig, -): (options?: TOpts) => ServiceFactory; +): (options?: TOpts) => ServiceFactory; // @public export function createServiceFactory< @@ -169,7 +169,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: (options: TOpts) => RootServiceFactoryConfig, -): (options: TOpts) => ServiceFactory; +): (options: TOpts) => ServiceFactory; // @public export function createServiceFactory< @@ -182,7 +182,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: PluginServiceFactoryConfig, -): () => ServiceFactory; +): () => ServiceFactory; // @public export function createServiceFactory< @@ -197,7 +197,7 @@ export function createServiceFactory< config: ( options?: TOpts, ) => PluginServiceFactoryConfig, -): (options?: TOpts) => ServiceFactory; +): (options?: TOpts) => ServiceFactory; // @public export function createServiceFactory< @@ -214,7 +214,7 @@ export function createServiceFactory< | (( options: TOpts, ) => PluginServiceFactoryConfig), -): (options: TOpts) => ServiceFactory; +): (options: TOpts) => ServiceFactory; // @public export function createServiceRef( @@ -427,38 +427,18 @@ export type SearchResponseFile = { }; // @public (undocumented) -export type ServiceFactory = - | { - scope: 'root'; - service: ServiceRef; - deps: { - [key in string]: ServiceRef; - }; - factory(deps: { - [key in string]: unknown; - }): Promise; - } - | { - scope: 'plugin'; - service: ServiceRef; - deps: { - [key in string]: ServiceRef; - }; - createRootContext?(deps: { - [key in string]: unknown; - }): Promise; - factory( - deps: { - [key in string]: unknown; - }, - context: unknown, - ): Promise; - }; +export interface ServiceFactory< + TService = unknown, + TScope extends 'plugin' | 'root' = 'plugin' | 'root', +> { + // (undocumented) + $$type: '@backstage/ServiceFactory'; + // (undocumented) + service: ServiceRef; +} // @public -export type ServiceFactoryOrFunction = - | ServiceFactory - | (() => ServiceFactory); +export type ServiceFactoryOrFunction = ServiceFactory | (() => ServiceFactory); // @public export type ServiceRef< @@ -477,7 +457,7 @@ export interface ServiceRefConfig { // (undocumented) defaultFactory?: ( service: ServiceRef, - ) => Promise>; + ) => Promise; // (undocumented) id: string; // (undocumented) diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index ea151e00b9..190ef7c13e 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -48,34 +48,35 @@ export type ServiceRef< }; /** @public */ -export type ServiceFactory = - | { - // This scope prop is needed in addition to the service ref, as TypeScript - // can't properly discriminate the two factory types otherwise. - scope: 'root'; - service: ServiceRef; - deps: { [key in string]: ServiceRef }; - factory(deps: { [key in string]: unknown }): Promise; - } - | { - scope: 'plugin'; - service: ServiceRef; - deps: { [key in string]: ServiceRef }; - createRootContext?(deps: { [key in string]: unknown }): Promise; - factory( - deps: { [key in string]: unknown }, - context: unknown, - ): Promise; - }; +export interface ServiceFactory< + TService = unknown, + TScope extends 'plugin' | 'root' = 'plugin' | 'root', +> { + $$type: '@backstage/ServiceFactory'; + + service: ServiceRef; +} + +/** @internal */ +export interface InternalServiceFactory< + TService = unknown, + TScope extends 'plugin' | 'root' = 'plugin' | 'root', +> extends ServiceFactory { + version: 'v1'; + deps: { [key in string]: ServiceRef }; + createRootContext?(deps: { [key in string]: unknown }): Promise; + factory( + deps: { [key in string]: unknown }, + context: unknown, + ): Promise; +} /** * Represents either a {@link ServiceFactory} or a function that returns one. * * @public */ -export type ServiceFactoryOrFunction = - | ServiceFactory - | (() => ServiceFactory); +export type ServiceFactoryOrFunction = ServiceFactory | (() => ServiceFactory); /** @public */ export interface ServiceRefConfig { @@ -83,7 +84,7 @@ export interface ServiceRefConfig { scope?: TScope; defaultFactory?: ( service: ServiceRef, - ) => Promise>; + ) => Promise; } /** @@ -175,7 +176,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: RootServiceFactoryConfig, -): () => ServiceFactory; +): () => ServiceFactory; /** * Creates a root scoped service factory with optional options. * @@ -189,7 +190,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: (options?: TOpts) => RootServiceFactoryConfig, -): (options?: TOpts) => ServiceFactory; +): (options?: TOpts) => ServiceFactory; /** * Creates a root scoped service factory with required options. * @@ -203,7 +204,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: (options: TOpts) => RootServiceFactoryConfig, -): (options: TOpts) => ServiceFactory; +): (options: TOpts) => ServiceFactory; /** * Creates a plugin scoped service factory without options. * @@ -218,7 +219,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: PluginServiceFactoryConfig, -): () => ServiceFactory; +): () => ServiceFactory; /** * Creates a plugin scoped service factory with optional options. * @@ -235,7 +236,7 @@ export function createServiceFactory< config: ( options?: TOpts, ) => PluginServiceFactoryConfig, -): (options?: TOpts) => ServiceFactory; +): (options?: TOpts) => ServiceFactory; /** * Creates a plugin scoped service factory with required options. * @@ -254,7 +255,7 @@ export function createServiceFactory< | (( options: TOpts, ) => PluginServiceFactoryConfig), -): (options: TOpts) => ServiceFactory; +): (options: TOpts) => ServiceFactory; export function createServiceFactory< TService, TImpl extends TService, @@ -271,20 +272,40 @@ export function createServiceFactory< ) => PluginServiceFactoryConfig) | (() => RootServiceFactoryConfig) | (() => PluginServiceFactoryConfig), -): (options: TOpts) => ServiceFactory { +): (options: TOpts) => ServiceFactory { const configCallback = typeof config === 'function' ? config : () => config; - return (options: TOpts) => { - const c = configCallback(options); + return ( + options: TOpts, + ): InternalServiceFactory => { + const anyConf = configCallback(options); + if (anyConf.service.scope === 'root') { + const c = anyConf as RootServiceFactoryConfig; + return { + $$type: '@backstage/ServiceFactory', + version: 'v1', + service: c.service, + deps: c.deps, + factory: async (deps: TDeps) => c.factory(deps), + }; + } + const c = anyConf as PluginServiceFactoryConfig< + TService, + TContext, + TImpl, + TDeps + >; return { - ...c, + $$type: '@backstage/ServiceFactory', + version: 'v1', + service: c.service, ...('createRootContext' in c ? { createRootContext: async (deps: TDeps) => c?.createRootContext?.(deps), } : {}), + deps: c.deps, factory: async (deps: TDeps, ctx: TContext) => c.factory(deps, ctx), - scope: c.service.scope, - } as ServiceFactory; + }; }; } diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index d99cf51866..0b3d7dd843 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -33,7 +33,7 @@ export namespace mockServices { // (undocumented) export namespace cache { const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export function config(options?: config.Options): ConfigService; @@ -44,46 +44,48 @@ export namespace mockServices { data?: JsonObject; }; const // (undocumented) - factory: (options?: Options | undefined) => ServiceFactory; + factory: ( + options?: Options | undefined, + ) => ServiceFactory; } // (undocumented) export namespace database { const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export namespace httpRouter { const // (undocumented) factory: ( options?: HttpRouterFactoryOptions | undefined, - ) => ServiceFactory; + ) => ServiceFactory; } // (undocumented) export function identity(): IdentityService; // (undocumented) export namespace identity { const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export namespace lifecycle { const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export namespace logger { const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export namespace permissions { const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export namespace rootLifecycle { const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export function rootLogger(options?: rootLogger.Options): LoggerService; @@ -94,24 +96,26 @@ export namespace mockServices { level?: 'none' | 'error' | 'warn' | 'info' | 'debug'; }; const // (undocumented) - factory: (options?: Options | undefined) => ServiceFactory; + factory: ( + options?: Options | undefined, + ) => ServiceFactory; } // (undocumented) export namespace scheduler { const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export function tokenManager(): TokenManagerService; // (undocumented) export namespace tokenManager { const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export namespace urlReader { const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } } diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index e5b3b32be7..2e97cc63fb 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -40,17 +40,21 @@ import { JsonObject } from '@backstage/types'; import { MockIdentityService } from './MockIdentityService'; import { MockRootLoggerService } from './MockRootLoggerService'; -function simpleFactory( - ref: ServiceRef, +function simpleFactory< + TService, + TScope extends 'root' | 'plugin', + TOptions extends [options?: object] = [], +>( + ref: ServiceRef, factory: (...options: TOptions) => TService, -): (...options: TOptions) => ServiceFactory { +): (...options: TOptions) => ServiceFactory { return createServiceFactory((options: unknown) => ({ service: ref as ServiceRef, deps: {}, async factory() { return (factory as any)(options); }, - })); + })) as (...options: TOptions) => ServiceFactory; } /** From 7d46ca2f68f500fcb14215c32ec4c0a681a270de Mon Sep 17 00:00:00 2001 From: Ilya Savich Date: Wed, 8 Feb 2023 14:26:47 +0100 Subject: [PATCH 305/423] Make catalog search result list a bit more customizable Signed-off-by: Ilya Savich --- .changeset/spotty-spiders-love.md | 5 ++++ .../CatalogSearchResultListItem.tsx | 26 +++++++++++-------- 2 files changed, 20 insertions(+), 11 deletions(-) create mode 100644 .changeset/spotty-spiders-love.md diff --git a/.changeset/spotty-spiders-love.md b/.changeset/spotty-spiders-love.md new file mode 100644 index 0000000000..e0ac3b3cc7 --- /dev/null +++ b/.changeset/spotty-spiders-love.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Make catalog search result list a bit more customizable diff --git a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx index 541d7c7d3a..a277584d2f 100644 --- a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx +++ b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx @@ -29,16 +29,20 @@ import { } from '@backstage/plugin-search-common'; import { HighlightedSearchResultText } from '@backstage/plugin-search-react'; -const useStyles = makeStyles({ - flexContainer: { - flexWrap: 'wrap', +const useStyles = makeStyles( + { + item: {}, + flexContainer: { + flexWrap: 'wrap', + }, + itemText: { + width: '100%', + wordBreak: 'break-all', + marginBottom: '1rem', + }, }, - itemText: { - width: '100%', - wordBreak: 'break-all', - marginBottom: '1rem', - }, -}); + { name: 'CatalogSearchResultListItem' }, +); /** * Props for {@link CatalogSearchResultListItem}. @@ -64,7 +68,7 @@ export function CatalogSearchResultListItem( if (!result) return null; return ( - <> +
    {props.icon && {props.icon}}
    - +
    ); } From a32da1e3811e7617ef6c4e74004f82af6023c846 Mon Sep 17 00:00:00 2001 From: Harry Hogg Date: Wed, 8 Feb 2023 13:43:39 +0000 Subject: [PATCH 306/423] Updated permission rule descriptions with a couple of fixes, grammar improvements and consistency Signed-off-by: Harry Hogg --- .../src/permissions/rules/createPropertyRule.ts | 2 +- .../catalog-backend/src/permissions/rules/hasAnnotation.ts | 3 +-- plugins/catalog-backend/src/permissions/rules/hasLabel.ts | 4 ++-- .../catalog-backend/src/permissions/rules/isEntityKind.ts | 2 +- .../catalog-backend/src/permissions/rules/isEntityOwner.ts | 2 +- plugins/playlist-backend/src/permissions/rules.ts | 6 +++--- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts index 19a4423846..fd51a1a060 100644 --- a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts +++ b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts @@ -22,7 +22,7 @@ import { z } from 'zod'; export const createPropertyRule = (propertyType: 'metadata' | 'spec') => createCatalogPermissionRule({ name: `HAS_${propertyType.toUpperCase()}`, - description: `Allow entities which have the specified ${propertyType} subfield.`, + description: `Allow entities with the specified ${propertyType} subfield`, resourceType: RESOURCE_TYPE_CATALOG_ENTITY, paramsSchema: z.object({ key: z diff --git a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts index c24620f41c..ae9b1c3963 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts @@ -28,8 +28,7 @@ import { createCatalogPermissionRule } from './util'; */ export const hasAnnotation = createCatalogPermissionRule({ name: 'HAS_ANNOTATION', - description: - 'Allow entities which are annotated with the specified annotation', + description: 'Allow entities with the specified annotation', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, paramsSchema: z.object({ annotation: z.string().describe('Name of the annotation to match on'), diff --git a/plugins/catalog-backend/src/permissions/rules/hasLabel.ts b/plugins/catalog-backend/src/permissions/rules/hasLabel.ts index 376534ca6f..16c5917585 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasLabel.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasLabel.ts @@ -25,10 +25,10 @@ import { createCatalogPermissionRule } from './util'; */ export const hasLabel = createCatalogPermissionRule({ name: 'HAS_LABEL', - description: 'Allow entities which have the specified label metadata.', + description: 'Allow entities with the specified label', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, paramsSchema: z.object({ - label: z.string().describe('Name of the label to match one'), + label: z.string().describe('Name of the label to match on'), }), apply: (resource, { label }) => !!resource.metadata.labels?.hasOwnProperty(label), diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts index eee7a790b2..94aaa63567 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts @@ -25,7 +25,7 @@ import { createCatalogPermissionRule } from './util'; */ export const isEntityKind = createCatalogPermissionRule({ name: 'IS_ENTITY_KIND', - description: 'Allow entities with the specified kind', + description: 'Allow entities matching a specified kind', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, paramsSchema: z.object({ kinds: z diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts index c3bfff5c2e..d0cc1d9280 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts @@ -27,7 +27,7 @@ import { createCatalogPermissionRule } from './util'; */ export const isEntityOwner = createCatalogPermissionRule({ name: 'IS_ENTITY_OWNER', - description: 'Allow entities owned by the current user', + description: 'Allow entities owned by a specified claim', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, paramsSchema: z.object({ claims: z diff --git a/plugins/playlist-backend/src/permissions/rules.ts b/plugins/playlist-backend/src/permissions/rules.ts index 99f4725972..e29465ed0f 100644 --- a/plugins/playlist-backend/src/permissions/rules.ts +++ b/plugins/playlist-backend/src/permissions/rules.ts @@ -31,10 +31,10 @@ const createPlaylistPermissionRule = makeCreatePermissionRule< const isOwner = createPlaylistPermissionRule({ name: 'IS_OWNER', - description: 'Should allow only if the playlist belongs to the user', + description: 'Allow playlists owned by the given entity refs', resourceType: PLAYLIST_LIST_RESOURCE_TYPE, paramsSchema: z.object({ - owners: z.array(z.string()).describe('List of owner entity refs'), + owners: z.array(z.string()).describe('List of entity refs to match on'), }), apply: (list: PlaylistMetadata, { owners }) => owners.includes(list.owner), toQuery: ({ owners }) => ({ @@ -45,7 +45,7 @@ const isOwner = createPlaylistPermissionRule({ const isPublic = createPlaylistPermissionRule({ name: 'IS_PUBLIC', - description: 'Should allow only if the playlist is public', + description: 'Allow playlists that are set as public', resourceType: PLAYLIST_LIST_RESOURCE_TYPE, apply: (list: PlaylistMetadata) => list.public, toQuery: () => ({ key: 'public', values: [true] }), From b977c2e69ffa4b5c5ce53083fefbb94854521c7d Mon Sep 17 00:00:00 2001 From: Harry Hogg Date: Wed, 8 Feb 2023 13:46:27 +0000 Subject: [PATCH 307/423] Added changeset Signed-off-by: Harry Hogg --- .changeset/brave-lemons-chew.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/brave-lemons-chew.md diff --git a/.changeset/brave-lemons-chew.md b/.changeset/brave-lemons-chew.md new file mode 100644 index 0000000000..61bf7cc6af --- /dev/null +++ b/.changeset/brave-lemons-chew.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-playlist-backend': patch +'@backstage/plugin-catalog-backend': patch +--- + +Minor improvements to the descriptions provided with permission rules schemas From 418bd9234f69fdad46125a698efa0d0a9111ef07 Mon Sep 17 00:00:00 2001 From: Harry Hogg Date: Wed, 8 Feb 2023 13:49:43 +0000 Subject: [PATCH 308/423] Updated tests Signed-off-by: Harry Hogg --- .../src/permissions/rules/createPropertyRule.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts index 5b34c98ca6..b2630f0f73 100644 --- a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts +++ b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts @@ -25,7 +25,7 @@ describe('createPropertyRule', () => { it('formats the rule description correctly', () => { expect(description).toBe( - 'Allow entities which have the specified metadata subfield.', + 'Allow entities with the specified metadata subfield', ); }); From 5ab195fc543bad4837cc051c56f84f4fb12e7d63 Mon Sep 17 00:00:00 2001 From: Marco Jorge Date: Wed, 8 Feb 2023 08:57:31 -0500 Subject: [PATCH 309/423] Fix #16245: Fix CatalogGraphCard parameter naming errors to CatalogGraphPage Signed-off-by: Marco Jorge --- .../src/components/CatalogGraphCard/CatalogGraphCard.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx index b9a15eb569..9a46d89da6 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx @@ -113,8 +113,8 @@ export const CatalogGraphCard = (props: { rootEntityRefs: [stringifyEntityRef(entity)], unidirectional, mergeRelations, - kinds, - relations, + selectedKinds: kinds, + selectedRelations: relations, direction, }, { arrayFormat: 'brackets', addQueryPrefix: true }, From fe19058b742c69f1b3796c3de83d21deafb21613 Mon Sep 17 00:00:00 2001 From: Marco Jorge Date: Wed, 8 Feb 2023 09:18:07 -0500 Subject: [PATCH 310/423] Fix #16245: Fix CatalogGraphCard parameter naming errors to CatalogGraphPage Signed-off-by: Marco Jorge --- .changeset/odd-kangaroos-itch.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/odd-kangaroos-itch.md diff --git a/.changeset/odd-kangaroos-itch.md b/.changeset/odd-kangaroos-itch.md new file mode 100644 index 0000000000..8529e5fe04 --- /dev/null +++ b/.changeset/odd-kangaroos-itch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-graph': patch +--- + +Fix #16245: The CatalogGraphCard has parameter naming errors for CatalogGraphPage From 339d9a5b5cbc9d05ffd14b5e502be33729e5a050 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Fri, 23 Dec 2022 13:04:41 -0600 Subject: [PATCH 311/423] Use default when no mkdocs config found Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .changeset/perfect-pears-care.md | 6 +++ .../src/DocsBuilder/builder.ts | 1 + plugins/techdocs-node/api-report.md | 1 + .../generate/__fixtures__/mkdocs_default.yml | 4 ++ .../src/stages/generate/helpers.test.ts | 31 ++++++++++++--- .../src/stages/generate/helpers.ts | 39 ++++++++++++++----- .../src/stages/generate/techdocs.ts | 6 ++- .../src/stages/generate/types.ts | 1 + 8 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 .changeset/perfect-pears-care.md create mode 100644 plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml diff --git a/.changeset/perfect-pears-care.md b/.changeset/perfect-pears-care.md new file mode 100644 index 0000000000..13db9ad0c1 --- /dev/null +++ b/.changeset/perfect-pears-care.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-techdocs-backend': patch +'@backstage/plugin-techdocs-node': patch +--- + +Added support for using a default `mkdocs.yml` configuration file when none is provided diff --git a/plugins/techdocs-backend/src/DocsBuilder/builder.ts b/plugins/techdocs-backend/src/DocsBuilder/builder.ts index 09eee1fc12..2ae1462ad9 100644 --- a/plugins/techdocs-backend/src/DocsBuilder/builder.ts +++ b/plugins/techdocs-backend/src/DocsBuilder/builder.ts @@ -186,6 +186,7 @@ export class DocsBuilder { etag: newEtag, logger: this.logger, logStream: this.logStream, + entity: this.entity, }); // Remove Prepared directory since it is no longer needed. diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index e27b406478..253f1c29fa 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -54,6 +54,7 @@ export type GeneratorRunOptions = { etag?: string; logger: Logger; logStream?: Writable; + entity: Entity; }; // @public diff --git a/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml b/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml new file mode 100644 index 0000000000..f6d2b01ce4 --- /dev/null +++ b/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml @@ -0,0 +1,4 @@ +site_name: Test site name +docs_dir: docs +plugins: + - techdocs-core \ No newline at end of file diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index e894b0602e..fb21643e46 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -42,12 +42,16 @@ const mockEntity = { kind: 'TestKind', metadata: { name: 'testName', + title: 'Test site name', }, }; const mkdocsYml = fs.readFileSync( resolvePath(__filename, '../__fixtures__/mkdocs.yml'), ); +const mkdocsDefaultYml = fs.readFileSync( + resolvePath(__filename, '../__fixtures__/mkdocs_default.yml'), +); const mkdocsYmlWithExtensions = fs.readFileSync( resolvePath(__filename, '../__fixtures__/mkdocs_with_extensions.yml'), ); @@ -518,7 +522,10 @@ describe('helpers', () => { it('returns expected contents when .yml file is present', async () => { const key = path.join(inputDir, 'mkdocs.yml'); mockFs({ [key]: mkdocsYml }); - const { path: mkdocsPath, content } = await getMkdocsYml(inputDir); + const { path: mkdocsPath, content } = await getMkdocsYml( + inputDir, + mockEntity, + ); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); @@ -527,15 +534,29 @@ describe('helpers', () => { it('returns expected contents when .yaml file is present', async () => { const key = path.join(inputDir, 'mkdocs.yaml'); mockFs({ [key]: mkdocsYml }); - const { path: mkdocsPath, content } = await getMkdocsYml(inputDir); + const { path: mkdocsPath, content } = await getMkdocsYml( + inputDir, + mockEntity, + ); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); }); - it('throws when neither .yml nor .yaml file is present', async () => { + it('returns expected contents when default file is present', async () => { + const key = path.join(inputDir, 'mkdocs.yml'); + mockFs({ [key]: mkdocsDefaultYml }); + const { path: mkdocsPath, content } = await getMkdocsYml( + inputDir, + mockEntity, + ); + expect(mkdocsPath).toBe(key); + expect(content).toBe(mkdocsDefaultYml.toString()); + }); + + it('throws when neither .yml nor .yaml nor default file is present', async () => { const invalidInputDir = resolvePath(__filename); - await expect(getMkdocsYml(invalidInputDir)).rejects.toThrow( - /Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml for validation/, + await expect(getMkdocsYml(invalidInputDir, mockEntity)).rejects.toThrow( + /Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml or default for validation/, ); }); }); diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index 50db0eb86a..ebb72c420c 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -159,22 +159,43 @@ export const MKDOCS_SCHEMA = DEFAULT_SCHEMA.extend([ */ export const getMkdocsYml = async ( inputDir: string, + entity: Entity, ): Promise<{ path: string; content: string }> => { let mkdocsYmlPath: string; let mkdocsYmlFileString: string; try { mkdocsYmlPath = path.join(inputDir, 'mkdocs.yaml'); - mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); - } catch { - try { - mkdocsYmlPath = path.join(inputDir, 'mkdocs.yml'); + if (await fs.pathExists(mkdocsYmlPath)) { mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); - } catch (error) { - throw new ForwardedError( - 'Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml for validation', - error, - ); + return { + path: mkdocsYmlPath, + content: mkdocsYmlFileString, + }; } + + mkdocsYmlPath = path.join(inputDir, 'mkdocs.yml'); + if (await fs.pathExists(mkdocsYmlPath)) { + mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); + return { + path: mkdocsYmlPath, + content: mkdocsYmlFileString, + }; + } + + // No mkdocs file, use default + const defaultMkdocsContent = + `site_name: ${entity.metadata.title ?? entity.metadata.name}\n` + + 'docs_dir: docs\n' + + 'plugins:\n' + + ' - techdocs-core\n'; + + await fs.writeFile(mkdocsYmlPath, defaultMkdocsContent); + mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); + } catch (error) { + throw new ForwardedError( + 'Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml or default for validation', + error, + ); } return { diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index 9bbc58ebdc..45b2f9689e 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -96,10 +96,14 @@ export class TechdocsGenerator implements GeneratorBase { etag, logger: childLogger, logStream, + entity, } = options; // Do some updates to mkdocs.yml before generating docs e.g. adding repo_url - const { path: mkdocsYmlPath, content } = await getMkdocsYml(inputDir); + const { path: mkdocsYmlPath, content } = await getMkdocsYml( + inputDir, + entity, + ); // validate the docs_dir first const docsDir = await validateMkdocsYaml(inputDir, content); diff --git a/plugins/techdocs-node/src/stages/generate/types.ts b/plugins/techdocs-node/src/stages/generate/types.ts index 2b2bbb21c9..26c26f4410 100644 --- a/plugins/techdocs-node/src/stages/generate/types.ts +++ b/plugins/techdocs-node/src/stages/generate/types.ts @@ -61,6 +61,7 @@ export type GeneratorRunOptions = { etag?: string; logger: Logger; logStream?: Writable; + entity: Entity; }; /** From 15b6eaf533169062c79470f87b2a71bf515c3a29 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Tue, 27 Dec 2022 10:43:36 -0600 Subject: [PATCH 312/423] Large refactor Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .changeset/perfect-pears-care.md | 1 + packages/techdocs-cli/cli-report.md | 3 ++ .../src/commands/generate/generate.ts | 1 + packages/techdocs-cli/src/commands/index.ts | 15 ++++++ .../techdocs-cli/src/commands/serve/mkdocs.ts | 4 ++ .../techdocs-cli/src/commands/serve/serve.ts | 3 ++ .../src/DocsBuilder/builder.ts | 2 +- plugins/techdocs-node/api-report.md | 11 ++++- .../generate/__fixtures__/mkdocs_default.yml | 2 +- .../src/stages/generate/helpers.test.ts | 10 ++-- .../src/stages/generate/helpers.ts | 46 +++++++++++++++---- .../src/stages/generate/index.ts | 1 + .../src/stages/generate/techdocs.ts | 4 +- .../src/stages/generate/types.ts | 3 +- 14 files changed, 87 insertions(+), 19 deletions(-) diff --git a/.changeset/perfect-pears-care.md b/.changeset/perfect-pears-care.md index 13db9ad0c1..2ea9f54a7f 100644 --- a/.changeset/perfect-pears-care.md +++ b/.changeset/perfect-pears-care.md @@ -1,6 +1,7 @@ --- '@backstage/plugin-techdocs-backend': patch '@backstage/plugin-techdocs-node': patch +'@techdocs/cli': patch --- Added support for using a default `mkdocs.yml` configuration file when none is provided diff --git a/packages/techdocs-cli/cli-report.md b/packages/techdocs-cli/cli-report.md index 861dad4605..846ccc88ca 100644 --- a/packages/techdocs-cli/cli-report.md +++ b/packages/techdocs-cli/cli-report.md @@ -33,6 +33,7 @@ Options: --no-docker --techdocs-ref --etag + --site-name -v --verbose --omitTechdocsCoreMkdocsPlugin --legacyCopyReadmeMdToIndexMd @@ -98,6 +99,7 @@ Options: --docker-entrypoint --docker-option --no-docker + --site-name --mkdocs-port -v --verbose --preview-app-bundle-path @@ -115,6 +117,7 @@ Options: --docker-entrypoint --docker-option --no-docker + --site-name -p, --port -v --verbose -h, --help diff --git a/packages/techdocs-cli/src/commands/generate/generate.ts b/packages/techdocs-cli/src/commands/generate/generate.ts index 874b904d86..c409992050 100644 --- a/packages/techdocs-cli/src/commands/generate/generate.ts +++ b/packages/techdocs-cli/src/commands/generate/generate.ts @@ -106,6 +106,7 @@ export default async function generate(opts: OptionValues) { logger, etag: opts.etag, ...(process.env.LOG_LEVEL === 'debug' ? { logStream: stdout } : {}), + siteName: opts.siteName, }); logger.info('Done!'); diff --git a/packages/techdocs-cli/src/commands/index.ts b/packages/techdocs-cli/src/commands/index.ts index caa7d8efbd..0ff52eee36 100644 --- a/packages/techdocs-cli/src/commands/index.ts +++ b/packages/techdocs-cli/src/commands/index.ts @@ -54,6 +54,11 @@ export function registerCommands(program: Command) { '--etag ', 'A unique identifier for the prepared tree e.g. commit SHA. If provided it will be stored in techdocs_metadata.json.', ) + .option( + '--site-name', + 'Name for site when using default MkDocs config', + 'Table of Contents', + ) .option('-v --verbose', 'Enable verbose output.', false) .option( '--omitTechdocsCoreMkdocsPlugin', @@ -224,6 +229,11 @@ export function registerCommands(program: Command) { '--no-docker', 'Do not use Docker, run `mkdocs serve` in current user environment.', ) + .option( + '--site-name', + 'Name for site when using default MkDocs config', + 'Table of Contents', + ) .option('-p, --port ', 'Port to serve documentation locally', '8000') .option('-v --verbose', 'Enable verbose output.', false) .action(lazy(() => import('./serve/mkdocs').then(m => m.default))); @@ -250,6 +260,11 @@ export function registerCommands(program: Command) { '--no-docker', 'Do not use Docker, use MkDocs executable in current user environment.', ) + .option( + '--site-name', + 'Name for site when using default MkDocs config', + 'Table of Contents', + ) .option('--mkdocs-port ', 'Port for MkDocs server to use', '8000') .option('-v --verbose', 'Enable verbose output.', false) .option( diff --git a/packages/techdocs-cli/src/commands/serve/mkdocs.ts b/packages/techdocs-cli/src/commands/serve/mkdocs.ts index 9cc0aef3be..6c84298c2b 100644 --- a/packages/techdocs-cli/src/commands/serve/mkdocs.ts +++ b/packages/techdocs-cli/src/commands/serve/mkdocs.ts @@ -19,6 +19,7 @@ import openBrowser from 'react-dev-utils/openBrowser'; import { createLogger } from '../../lib/utility'; import { runMkdocsServer } from '../../lib/mkdocsServer'; import { LogFunc, waitForSignal } from '../../lib/run'; +import { getMkdocsYml } from '@backstage/plugin-techdocs-node'; export default async function serveMkdocs(opts: OptionValues) { const logger = createLogger({ verbose: opts.verbose }); @@ -26,6 +27,9 @@ export default async function serveMkdocs(opts: OptionValues) { const dockerAddr = `http://0.0.0.0:${opts.port}`; const localAddr = `http://127.0.0.1:${opts.port}`; const expectedDevAddr = opts.docker ? dockerAddr : localAddr; + + await getMkdocsYml('./', opts.siteName); + // We want to open browser only once based on a log. let boolOpenBrowserTriggered = false; diff --git a/packages/techdocs-cli/src/commands/serve/serve.ts b/packages/techdocs-cli/src/commands/serve/serve.ts index d46c70678a..1e835c2c8d 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -22,6 +22,7 @@ import HTTPServer from '../../lib/httpServer'; import { runMkdocsServer } from '../../lib/mkdocsServer'; import { LogFunc, waitForSignal } from '../../lib/run'; import { createLogger } from '../../lib/utility'; +import { getMkdocsYml } from '@backstage/plugin-techdocs-node'; function findPreviewBundlePath(): string { try { @@ -64,6 +65,8 @@ export default async function serve(opts: OptionValues) { ? mkdocsDockerAddr : mkdocsLocalAddr; + await getMkdocsYml('./', opts.siteName); + let mkdocsServerHasStarted = false; const mkdocsLogFunc: LogFunc = data => { // Sometimes the lines contain an unnecessary extra new line diff --git a/plugins/techdocs-backend/src/DocsBuilder/builder.ts b/plugins/techdocs-backend/src/DocsBuilder/builder.ts index 2ae1462ad9..43d05f7b6f 100644 --- a/plugins/techdocs-backend/src/DocsBuilder/builder.ts +++ b/plugins/techdocs-backend/src/DocsBuilder/builder.ts @@ -186,7 +186,7 @@ export class DocsBuilder { etag: newEtag, logger: this.logger, logStream: this.logStream, - entity: this.entity, + siteName: this.entity.metadata.title ?? this.entity.metadata.name, }); // Remove Prepared directory since it is no longer needed. diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index 253f1c29fa..68a7b80152 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -54,7 +54,7 @@ export type GeneratorRunOptions = { etag?: string; logger: Logger; logStream?: Writable; - entity: Entity; + siteName?: string; }; // @public @@ -86,6 +86,15 @@ export const getLocationForEntity: ( scmIntegration: ScmIntegrationRegistry, ) => ParsedLocationAnnotation; +// @public +export const getMkdocsYml: ( + inputDir: string, + siteName?: string, +) => Promise<{ + path: string; + content: string; +}>; + // @public export type MigrateRequest = { removeOriginal?: boolean; diff --git a/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml b/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml index f6d2b01ce4..c0c5a203df 100644 --- a/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml +++ b/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml @@ -1,4 +1,4 @@ site_name: Test site name docs_dir: docs plugins: - - techdocs-core \ No newline at end of file + - techdocs-core diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index fb21643e46..158e8710f2 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -524,7 +524,7 @@ describe('helpers', () => { mockFs({ [key]: mkdocsYml }); const { path: mkdocsPath, content } = await getMkdocsYml( inputDir, - mockEntity, + mockEntity.metadata.title, ); expect(mkdocsPath).toBe(key); @@ -536,7 +536,7 @@ describe('helpers', () => { mockFs({ [key]: mkdocsYml }); const { path: mkdocsPath, content } = await getMkdocsYml( inputDir, - mockEntity, + mockEntity.metadata.title, ); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); @@ -547,7 +547,7 @@ describe('helpers', () => { mockFs({ [key]: mkdocsDefaultYml }); const { path: mkdocsPath, content } = await getMkdocsYml( inputDir, - mockEntity, + mockEntity.metadata.title, ); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsDefaultYml.toString()); @@ -555,7 +555,9 @@ describe('helpers', () => { it('throws when neither .yml nor .yaml nor default file is present', async () => { const invalidInputDir = resolvePath(__filename); - await expect(getMkdocsYml(invalidInputDir, mockEntity)).rejects.toThrow( + await expect( + getMkdocsYml(invalidInputDir, mockEntity.metadata.title), + ).rejects.toThrow( /Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml or default for validation/, ); }); diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index ebb72c420c..198b48cf00 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -150,16 +150,50 @@ export const MKDOCS_SCHEMA = DEFAULT_SCHEMA.extend([ }), ]); +/** + * Generates a mkdocs.yml configuration file + * + * @param inputDir - base dir to where the mkdocs.yml file will be created + * @param siteName - name of site to be used in mkdocs.yml for the + * required `site_name` property, default value is "Table of Contents" + */ +export const generateMkdocsYml = async ( + inputDir: string, + siteName?: string, +) => { + try { + // TODO(awanlin): Use a provided default mkdocs.yml + // from config or some specified location. If this is + // not provided then fall back to generating bare + // minimum mkdocs.yml file + + const mkdocsYmlPath = path.join(inputDir, 'mkdocs.yml'); + const defaultSiteName = siteName ?? 'Table of Contents'; + const defaultMkdocsContent = + `site_name: ${defaultSiteName}\n` + + 'docs_dir: docs\n' + + 'plugins:\n' + + ' - techdocs-core\n'; + + await fs.writeFile(mkdocsYmlPath, defaultMkdocsContent); + } catch (error) { + throw new ForwardedError('Could not generate mkdocs.yml file', error); + } +}; + /** * Finds and loads the contents of either an mkdocs.yml or mkdocs.yaml file, * depending on which is present (MkDocs supports both as of v1.2.2). + * @public * * @param inputDir - base dir to be searched for either an mkdocs.yml or * mkdocs.yaml file. + * @param siteName - name of site to be used in mkdocs.yml for the + * required `site_name` property, default value is "Table of Contents" */ export const getMkdocsYml = async ( inputDir: string, - entity: Entity, + siteName?: string, ): Promise<{ path: string; content: string }> => { let mkdocsYmlPath: string; let mkdocsYmlFileString: string; @@ -182,14 +216,8 @@ export const getMkdocsYml = async ( }; } - // No mkdocs file, use default - const defaultMkdocsContent = - `site_name: ${entity.metadata.title ?? entity.metadata.name}\n` + - 'docs_dir: docs\n' + - 'plugins:\n' + - ' - techdocs-core\n'; - - await fs.writeFile(mkdocsYmlPath, defaultMkdocsContent); + // No mkdocs file, generate it + await generateMkdocsYml(inputDir, siteName); mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); } catch (error) { throw new ForwardedError( diff --git a/plugins/techdocs-node/src/stages/generate/index.ts b/plugins/techdocs-node/src/stages/generate/index.ts index 1c20c58887..3bd42643c1 100644 --- a/plugins/techdocs-node/src/stages/generate/index.ts +++ b/plugins/techdocs-node/src/stages/generate/index.ts @@ -15,6 +15,7 @@ */ export { TechdocsGenerator } from './techdocs'; export { Generators } from './generators'; +export { getMkdocsYml } from './helpers'; export type { GeneratorBase, GeneratorOptions, diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index 45b2f9689e..82857e9f73 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -96,13 +96,13 @@ export class TechdocsGenerator implements GeneratorBase { etag, logger: childLogger, logStream, - entity, + siteName, } = options; // Do some updates to mkdocs.yml before generating docs e.g. adding repo_url const { path: mkdocsYmlPath, content } = await getMkdocsYml( inputDir, - entity, + siteName, ); // validate the docs_dir first diff --git a/plugins/techdocs-node/src/stages/generate/types.ts b/plugins/techdocs-node/src/stages/generate/types.ts index 26c26f4410..86f8f96d44 100644 --- a/plugins/techdocs-node/src/stages/generate/types.ts +++ b/plugins/techdocs-node/src/stages/generate/types.ts @@ -53,6 +53,7 @@ export type GeneratorConfig = { * @param etag - A unique identifier for the prepared tree e.g. commit SHA. If provided it will be stored in techdocs_metadata.json. * @param logger - A logger that forwards the messages to the caller to be displayed outside of the backend. * @param logStream - A log stream that can send raw log messages to the caller to be displayed outside of the backend. + * @param siteName - Name of the site to be used in mkdocs.yml for the required `site_name` property, default value is "Table of Contents" */ export type GeneratorRunOptions = { inputDir: string; @@ -61,7 +62,7 @@ export type GeneratorRunOptions = { etag?: string; logger: Logger; logStream?: Writable; - entity: Entity; + siteName?: string; }; /** From 943c245b6f05bd499028cfd79c0d36579c948faa Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Tue, 10 Jan 2023 13:54:02 -0600 Subject: [PATCH 313/423] Updated to use siteOptions object Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .../techdocs-cli/src/commands/generate/generate.ts | 2 +- plugins/techdocs-backend/src/DocsBuilder/builder.ts | 4 +++- .../src/stages/generate/helpers.test.ts | 13 +++++++------ .../techdocs-node/src/stages/generate/helpers.ts | 8 ++++---- .../techdocs-node/src/stages/generate/techdocs.ts | 4 ++-- plugins/techdocs-node/src/stages/generate/types.ts | 2 +- 6 files changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/techdocs-cli/src/commands/generate/generate.ts b/packages/techdocs-cli/src/commands/generate/generate.ts index c409992050..53735d628a 100644 --- a/packages/techdocs-cli/src/commands/generate/generate.ts +++ b/packages/techdocs-cli/src/commands/generate/generate.ts @@ -106,7 +106,7 @@ export default async function generate(opts: OptionValues) { logger, etag: opts.etag, ...(process.env.LOG_LEVEL === 'debug' ? { logStream: stdout } : {}), - siteName: opts.siteName, + siteOptions: { name: opts.siteName }, }); logger.info('Done!'); diff --git a/plugins/techdocs-backend/src/DocsBuilder/builder.ts b/plugins/techdocs-backend/src/DocsBuilder/builder.ts index 43d05f7b6f..b4c2d2ee26 100644 --- a/plugins/techdocs-backend/src/DocsBuilder/builder.ts +++ b/plugins/techdocs-backend/src/DocsBuilder/builder.ts @@ -186,7 +186,9 @@ export class DocsBuilder { etag: newEtag, logger: this.logger, logStream: this.logStream, - siteName: this.entity.metadata.title ?? this.entity.metadata.name, + siteOptions: { + name: this.entity.metadata.title ?? this.entity.metadata.name, + }, }); // Remove Prepared directory since it is no longer needed. diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index 158e8710f2..a7fa11f3fd 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -518,13 +518,16 @@ describe('helpers', () => { describe('getMkdocsYml', () => { const inputDir = resolvePath(__filename, '../__fixtures__/'); + const siteOptions = { + name: mockEntity.metadata.title, + }; it('returns expected contents when .yml file is present', async () => { const key = path.join(inputDir, 'mkdocs.yml'); mockFs({ [key]: mkdocsYml }); const { path: mkdocsPath, content } = await getMkdocsYml( inputDir, - mockEntity.metadata.title, + siteOptions, ); expect(mkdocsPath).toBe(key); @@ -536,7 +539,7 @@ describe('helpers', () => { mockFs({ [key]: mkdocsYml }); const { path: mkdocsPath, content } = await getMkdocsYml( inputDir, - mockEntity.metadata.title, + siteOptions, ); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); @@ -547,7 +550,7 @@ describe('helpers', () => { mockFs({ [key]: mkdocsDefaultYml }); const { path: mkdocsPath, content } = await getMkdocsYml( inputDir, - mockEntity.metadata.title, + siteOptions, ); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsDefaultYml.toString()); @@ -555,9 +558,7 @@ describe('helpers', () => { it('throws when neither .yml nor .yaml nor default file is present', async () => { const invalidInputDir = resolvePath(__filename); - await expect( - getMkdocsYml(invalidInputDir, mockEntity.metadata.title), - ).rejects.toThrow( + await expect(getMkdocsYml(invalidInputDir, siteOptions)).rejects.toThrow( /Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml or default for validation/, ); }); diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index 198b48cf00..ee0ba8b6fd 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -159,7 +159,7 @@ export const MKDOCS_SCHEMA = DEFAULT_SCHEMA.extend([ */ export const generateMkdocsYml = async ( inputDir: string, - siteName?: string, + siteOptions?: { name?: string }, ) => { try { // TODO(awanlin): Use a provided default mkdocs.yml @@ -168,7 +168,7 @@ export const generateMkdocsYml = async ( // minimum mkdocs.yml file const mkdocsYmlPath = path.join(inputDir, 'mkdocs.yml'); - const defaultSiteName = siteName ?? 'Table of Contents'; + const defaultSiteName = siteOptions?.name ?? 'Table of Contents'; const defaultMkdocsContent = `site_name: ${defaultSiteName}\n` + 'docs_dir: docs\n' + @@ -193,7 +193,7 @@ export const generateMkdocsYml = async ( */ export const getMkdocsYml = async ( inputDir: string, - siteName?: string, + siteOptions?: { name?: string }, ): Promise<{ path: string; content: string }> => { let mkdocsYmlPath: string; let mkdocsYmlFileString: string; @@ -217,7 +217,7 @@ export const getMkdocsYml = async ( } // No mkdocs file, generate it - await generateMkdocsYml(inputDir, siteName); + await generateMkdocsYml(inputDir, siteOptions); mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); } catch (error) { throw new ForwardedError( diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index 82857e9f73..b71148060e 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -96,13 +96,13 @@ export class TechdocsGenerator implements GeneratorBase { etag, logger: childLogger, logStream, - siteName, + siteOptions, } = options; // Do some updates to mkdocs.yml before generating docs e.g. adding repo_url const { path: mkdocsYmlPath, content } = await getMkdocsYml( inputDir, - siteName, + siteOptions, ); // validate the docs_dir first diff --git a/plugins/techdocs-node/src/stages/generate/types.ts b/plugins/techdocs-node/src/stages/generate/types.ts index 86f8f96d44..4c1f074797 100644 --- a/plugins/techdocs-node/src/stages/generate/types.ts +++ b/plugins/techdocs-node/src/stages/generate/types.ts @@ -62,7 +62,7 @@ export type GeneratorRunOptions = { etag?: string; logger: Logger; logStream?: Writable; - siteName?: string; + siteOptions?: { name?: string }; }; /** From 591dc81ff8ae46956b25e38859b6c89e5b02980d Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Tue, 10 Jan 2023 13:57:19 -0600 Subject: [PATCH 314/423] Update API Report Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- plugins/techdocs-node/api-report.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index 68a7b80152..12c918a047 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -54,7 +54,9 @@ export type GeneratorRunOptions = { etag?: string; logger: Logger; logStream?: Writable; - siteName?: string; + siteOptions?: { + name?: string; + }; }; // @public @@ -89,7 +91,9 @@ export const getLocationForEntity: ( // @public export const getMkdocsYml: ( inputDir: string, - siteName?: string, + siteOptions?: { + name?: string; + }, ) => Promise<{ path: string; content: string; From c9758fe81ecc0be18d6802d1a35c757eccd0f952 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Tue, 10 Jan 2023 14:16:53 -0600 Subject: [PATCH 315/423] Updated default name and params Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- packages/techdocs-cli/src/commands/index.ts | 6 +++--- .../techdocs-node/src/stages/generate/helpers.ts | 13 ++++++------- plugins/techdocs-node/src/stages/generate/types.ts | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/techdocs-cli/src/commands/index.ts b/packages/techdocs-cli/src/commands/index.ts index 0ff52eee36..102e6d87de 100644 --- a/packages/techdocs-cli/src/commands/index.ts +++ b/packages/techdocs-cli/src/commands/index.ts @@ -57,7 +57,7 @@ export function registerCommands(program: Command) { .option( '--site-name', 'Name for site when using default MkDocs config', - 'Table of Contents', + 'Documentation Site', ) .option('-v --verbose', 'Enable verbose output.', false) .option( @@ -232,7 +232,7 @@ export function registerCommands(program: Command) { .option( '--site-name', 'Name for site when using default MkDocs config', - 'Table of Contents', + 'Documentation Site', ) .option('-p, --port ', 'Port to serve documentation locally', '8000') .option('-v --verbose', 'Enable verbose output.', false) @@ -263,7 +263,7 @@ export function registerCommands(program: Command) { .option( '--site-name', 'Name for site when using default MkDocs config', - 'Table of Contents', + 'Documentation Site', ) .option('--mkdocs-port ', 'Port for MkDocs server to use', '8000') .option('-v --verbose', 'Enable verbose output.', false) diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index ee0ba8b6fd..5fc74eafc2 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -154,8 +154,8 @@ export const MKDOCS_SCHEMA = DEFAULT_SCHEMA.extend([ * Generates a mkdocs.yml configuration file * * @param inputDir - base dir to where the mkdocs.yml file will be created - * @param siteName - name of site to be used in mkdocs.yml for the - * required `site_name` property, default value is "Table of Contents" + * @param siteOptions - options for the site: `name` property will be used in mkdocs.yml for the + * required `site_name` property, default value is "Documentation Site" */ export const generateMkdocsYml = async ( inputDir: string, @@ -168,7 +168,7 @@ export const generateMkdocsYml = async ( // minimum mkdocs.yml file const mkdocsYmlPath = path.join(inputDir, 'mkdocs.yml'); - const defaultSiteName = siteOptions?.name ?? 'Table of Contents'; + const defaultSiteName = siteOptions?.name ?? 'Documentation Site'; const defaultMkdocsContent = `site_name: ${defaultSiteName}\n` + 'docs_dir: docs\n' + @@ -186,10 +186,9 @@ export const generateMkdocsYml = async ( * depending on which is present (MkDocs supports both as of v1.2.2). * @public * - * @param inputDir - base dir to be searched for either an mkdocs.yml or - * mkdocs.yaml file. - * @param siteName - name of site to be used in mkdocs.yml for the - * required `site_name` property, default value is "Table of Contents" + * @param inputDir - base dir to be searched for either an mkdocs.yml or mkdocs.yaml file. + * @param siteOptions - options for the site: `name` property will be used in mkdocs.yml for the + * required `site_name` property, default value is "Documentation Site" */ export const getMkdocsYml = async ( inputDir: string, diff --git a/plugins/techdocs-node/src/stages/generate/types.ts b/plugins/techdocs-node/src/stages/generate/types.ts index 4c1f074797..1d0c6bb8f2 100644 --- a/plugins/techdocs-node/src/stages/generate/types.ts +++ b/plugins/techdocs-node/src/stages/generate/types.ts @@ -53,7 +53,7 @@ export type GeneratorConfig = { * @param etag - A unique identifier for the prepared tree e.g. commit SHA. If provided it will be stored in techdocs_metadata.json. * @param logger - A logger that forwards the messages to the caller to be displayed outside of the backend. * @param logStream - A log stream that can send raw log messages to the caller to be displayed outside of the backend. - * @param siteName - Name of the site to be used in mkdocs.yml for the required `site_name` property, default value is "Table of Contents" + * @param siteOptions - Options for the site: The `name` property will be used in mkdocs.yml config for the required `site_name` property, default value is "Documentation Site" */ export type GeneratorRunOptions = { inputDir: string; From 248d1242bd27421621fcaed8cf54c28088bcd9c0 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Tue, 17 Jan 2023 12:44:05 -0600 Subject: [PATCH 316/423] Added property to track if config exists already Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .../generate/__fixtures__/mkdocs_default.yml | 2 +- .../src/stages/generate/helpers.test.ts | 37 +++++++++++++------ .../src/stages/generate/helpers.ts | 5 ++- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml b/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml index c0c5a203df..460e5c0e1d 100644 --- a/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml +++ b/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml @@ -1,4 +1,4 @@ -site_name: Test site name +site_name: Default Test site name docs_dir: docs plugins: - techdocs-core diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index a7fa11f3fd..186a685a90 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -190,6 +190,7 @@ describe('helpers', () => { beforeEach(() => { mockFs({ '/mkdocs.yml': mkdocsYml, + '/mkdocs_default.yml': mkdocsDefaultYml, '/mkdocs_with_repo_url.yml': mkdocsYmlWithRepoUrl, '/mkdocs_with_edit_uri.yml': mkdocsYmlWithEditUri, '/mkdocs_with_extensions.yml': mkdocsYmlWithExtensions, @@ -525,35 +526,47 @@ describe('helpers', () => { it('returns expected contents when .yml file is present', async () => { const key = path.join(inputDir, 'mkdocs.yml'); mockFs({ [key]: mkdocsYml }); - const { path: mkdocsPath, content } = await getMkdocsYml( - inputDir, - siteOptions, - ); + const { + path: mkdocsPath, + content, + configExists, + } = await getMkdocsYml(inputDir, siteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); + expect(configExists).toBe(true); }); it('returns expected contents when .yaml file is present', async () => { const key = path.join(inputDir, 'mkdocs.yaml'); mockFs({ [key]: mkdocsYml }); - const { path: mkdocsPath, content } = await getMkdocsYml( - inputDir, - siteOptions, - ); + const { + path: mkdocsPath, + content, + configExists, + } = await getMkdocsYml(inputDir, siteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); + expect(configExists).toBe(true); }); it('returns expected contents when default file is present', async () => { + const defaultSiteOptions = { + name: 'Default Test site name', + }; const key = path.join(inputDir, 'mkdocs.yml'); + const mockPathExists = jest.spyOn(fs, 'pathExists'); + mockPathExists.mockImplementation(() => Promise.resolve(false)); mockFs({ [key]: mkdocsDefaultYml }); - const { path: mkdocsPath, content } = await getMkdocsYml( - inputDir, - siteOptions, - ); + const { + path: mkdocsPath, + content, + configExists, + } = await getMkdocsYml(inputDir, defaultSiteOptions); + expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsDefaultYml.toString()); + expect(configExists).toBe(false); }); it('throws when neither .yml nor .yaml nor default file is present', async () => { diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index 5fc74eafc2..2f53e125f8 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -193,7 +193,7 @@ export const generateMkdocsYml = async ( export const getMkdocsYml = async ( inputDir: string, siteOptions?: { name?: string }, -): Promise<{ path: string; content: string }> => { +): Promise<{ path: string; content: string; configExists: boolean }> => { let mkdocsYmlPath: string; let mkdocsYmlFileString: string; try { @@ -203,6 +203,7 @@ export const getMkdocsYml = async ( return { path: mkdocsYmlPath, content: mkdocsYmlFileString, + configExists: true, }; } @@ -212,6 +213,7 @@ export const getMkdocsYml = async ( return { path: mkdocsYmlPath, content: mkdocsYmlFileString, + configExists: true, }; } @@ -228,6 +230,7 @@ export const getMkdocsYml = async ( return { path: mkdocsYmlPath, content: mkdocsYmlFileString, + configExists: false, }; }; From 6d612acd95e5fb83ca7163392b54468e016795b7 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Tue, 17 Jan 2023 12:53:54 -0600 Subject: [PATCH 317/423] Updated api report Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- plugins/techdocs-node/api-report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index 12c918a047..2aff8e82bb 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -97,6 +97,7 @@ export const getMkdocsYml: ( ) => Promise<{ path: string; content: string; + configExists: boolean; }>; // @public From 8e11504ce346e9e93ca7d5c721523f9d51845b9a Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Tue, 17 Jan 2023 13:20:45 -0600 Subject: [PATCH 318/423] Use object for YAML file Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .../src/stages/generate/helpers.ts | 17 ++++++++++------- .../techdocs-node/src/stages/generate/types.ts | 6 ++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index 2f53e125f8..c0a82da510 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -26,7 +26,7 @@ import path, { resolve as resolvePath } from 'path'; import { PassThrough, Writable } from 'stream'; import { Logger } from 'winston'; import { ParsedLocationAnnotation } from '../../helpers'; -import { SupportedGeneratorKey } from './types'; +import { DefaultMkdocsContent, SupportedGeneratorKey } from './types'; import { getFileTreeRecursively } from '../publish/helpers'; // TODO: Implement proper support for more generators. @@ -169,13 +169,16 @@ export const generateMkdocsYml = async ( const mkdocsYmlPath = path.join(inputDir, 'mkdocs.yml'); const defaultSiteName = siteOptions?.name ?? 'Documentation Site'; - const defaultMkdocsContent = - `site_name: ${defaultSiteName}\n` + - 'docs_dir: docs\n' + - 'plugins:\n' + - ' - techdocs-core\n'; + const defaultMkdocsContent: DefaultMkdocsContent = { + site_name: defaultSiteName, + docs_dir: 'docs', + plugins: ['techdocs-core'], + }; - await fs.writeFile(mkdocsYmlPath, defaultMkdocsContent); + await fs.writeFile( + mkdocsYmlPath, + yaml.dump(defaultMkdocsContent, { schema: MKDOCS_SCHEMA }), + ); } catch (error) { throw new ForwardedError('Could not generate mkdocs.yml file', error); } diff --git a/plugins/techdocs-node/src/stages/generate/types.ts b/plugins/techdocs-node/src/stages/generate/types.ts index 1d0c6bb8f2..70c332344a 100644 --- a/plugins/techdocs-node/src/stages/generate/types.ts +++ b/plugins/techdocs-node/src/stages/generate/types.ts @@ -91,3 +91,9 @@ export type GeneratorBuilder = { register(protocol: SupportedGeneratorKey, generator: GeneratorBase): void; get(entity: Entity): GeneratorBase; }; + +export type DefaultMkdocsContent = { + site_name: string; + docs_dir: string; + plugins: String[]; +}; From c2bba4affe41c769f3021359236449204f9d41f0 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Wed, 25 Jan 2023 12:58:28 -0600 Subject: [PATCH 319/423] Rename configExists to configIsTemporary Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- plugins/techdocs-node/api-report.md | 2 +- .../src/stages/generate/helpers.test.ts | 12 ++++++------ plugins/techdocs-node/src/stages/generate/helpers.ts | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index 2aff8e82bb..314a46a405 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -97,7 +97,7 @@ export const getMkdocsYml: ( ) => Promise<{ path: string; content: string; - configExists: boolean; + configIsTemporary: boolean; }>; // @public diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index 186a685a90..aad7706ab1 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -529,12 +529,12 @@ describe('helpers', () => { const { path: mkdocsPath, content, - configExists, + configIsTemporary, } = await getMkdocsYml(inputDir, siteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); - expect(configExists).toBe(true); + expect(configIsTemporary).toBe(false); }); it('returns expected contents when .yaml file is present', async () => { @@ -543,11 +543,11 @@ describe('helpers', () => { const { path: mkdocsPath, content, - configExists, + configIsTemporary, } = await getMkdocsYml(inputDir, siteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); - expect(configExists).toBe(true); + expect(configIsTemporary).toBe(false); }); it('returns expected contents when default file is present', async () => { @@ -561,12 +561,12 @@ describe('helpers', () => { const { path: mkdocsPath, content, - configExists, + configIsTemporary, } = await getMkdocsYml(inputDir, defaultSiteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsDefaultYml.toString()); - expect(configExists).toBe(false); + expect(configIsTemporary).toBe(true); }); it('throws when neither .yml nor .yaml nor default file is present', async () => { diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index c0a82da510..e16293f906 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -196,7 +196,7 @@ export const generateMkdocsYml = async ( export const getMkdocsYml = async ( inputDir: string, siteOptions?: { name?: string }, -): Promise<{ path: string; content: string; configExists: boolean }> => { +): Promise<{ path: string; content: string; configIsTemporary: boolean }> => { let mkdocsYmlPath: string; let mkdocsYmlFileString: string; try { @@ -206,7 +206,7 @@ export const getMkdocsYml = async ( return { path: mkdocsYmlPath, content: mkdocsYmlFileString, - configExists: true, + configIsTemporary: false, }; } @@ -216,7 +216,7 @@ export const getMkdocsYml = async ( return { path: mkdocsYmlPath, content: mkdocsYmlFileString, - configExists: true, + configIsTemporary: false, }; } @@ -233,7 +233,7 @@ export const getMkdocsYml = async ( return { path: mkdocsYmlPath, content: mkdocsYmlFileString, - configExists: false, + configIsTemporary: true, }; }; From 37c17ab92c6bfd78e5006206a6b546d042df65c4 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Wed, 25 Jan 2023 14:37:01 -0600 Subject: [PATCH 320/423] Handle deleting temportary mkdocs.yml Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .../techdocs-cli/src/commands/generate/generate.ts | 11 +++++++++++ packages/techdocs-cli/src/commands/serve/mkdocs.ts | 14 ++++++++++++-- packages/techdocs-cli/src/commands/serve/serve.ts | 14 ++++++++++++-- .../src/stages/generate/helpers.test.ts | 12 ++++++------ .../techdocs-node/src/stages/generate/helpers.ts | 2 +- plugins/techdocs-node/src/stages/generate/index.ts | 2 +- .../techdocs-node/src/stages/generate/techdocs.ts | 4 ++-- 7 files changed, 45 insertions(+), 14 deletions(-) diff --git a/packages/techdocs-cli/src/commands/generate/generate.ts b/packages/techdocs-cli/src/commands/generate/generate.ts index 53735d628a..8445dd9ec6 100644 --- a/packages/techdocs-cli/src/commands/generate/generate.ts +++ b/packages/techdocs-cli/src/commands/generate/generate.ts @@ -21,6 +21,7 @@ import Docker from 'dockerode'; import { TechdocsGenerator, ParsedLocationAnnotation, + getMkDocsYml, } from '@backstage/plugin-techdocs-node'; import { ContainerRunner, @@ -54,6 +55,10 @@ export default async function generate(opts: OptionValues) { await fs.ensureDir(outputDir); + const { path: mkDocsYmlPath, configIsTemporary } = await getMkDocsYml( + sourceDir, + ); + const config = new ConfigReader({ techdocs: { generator: { @@ -109,5 +114,11 @@ export default async function generate(opts: OptionValues) { siteOptions: { name: opts.siteName }, }); + if (configIsTemporary) { + process.on('exit', async () => { + fs.rmSync(mkDocsYmlPath, {}); + }); + } + logger.info('Done!'); } diff --git a/packages/techdocs-cli/src/commands/serve/mkdocs.ts b/packages/techdocs-cli/src/commands/serve/mkdocs.ts index 6c84298c2b..1a471cf1a6 100644 --- a/packages/techdocs-cli/src/commands/serve/mkdocs.ts +++ b/packages/techdocs-cli/src/commands/serve/mkdocs.ts @@ -19,7 +19,8 @@ import openBrowser from 'react-dev-utils/openBrowser'; import { createLogger } from '../../lib/utility'; import { runMkdocsServer } from '../../lib/mkdocsServer'; import { LogFunc, waitForSignal } from '../../lib/run'; -import { getMkdocsYml } from '@backstage/plugin-techdocs-node'; +import { getMkDocsYml } from '@backstage/plugin-techdocs-node'; +import fs from 'fs-extra'; export default async function serveMkdocs(opts: OptionValues) { const logger = createLogger({ verbose: opts.verbose }); @@ -28,7 +29,10 @@ export default async function serveMkdocs(opts: OptionValues) { const localAddr = `http://127.0.0.1:${opts.port}`; const expectedDevAddr = opts.docker ? dockerAddr : localAddr; - await getMkdocsYml('./', opts.siteName); + const { path: mkDocsYmlPath, configIsTemporary } = await getMkDocsYml( + './', + opts.siteName, + ); // We want to open browser only once based on a log. let boolOpenBrowserTriggered = false; @@ -74,4 +78,10 @@ export default async function serveMkdocs(opts: OptionValues) { // Keep waiting for user to cancel the process await waitForSignal([childProcess]); + + if (configIsTemporary) { + process.on('exit', async () => { + fs.rmSync(mkDocsYmlPath, {}); + }); + } } diff --git a/packages/techdocs-cli/src/commands/serve/serve.ts b/packages/techdocs-cli/src/commands/serve/serve.ts index 1e835c2c8d..48e48d4f66 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -22,7 +22,8 @@ import HTTPServer from '../../lib/httpServer'; import { runMkdocsServer } from '../../lib/mkdocsServer'; import { LogFunc, waitForSignal } from '../../lib/run'; import { createLogger } from '../../lib/utility'; -import { getMkdocsYml } from '@backstage/plugin-techdocs-node'; +import { getMkDocsYml } from '@backstage/plugin-techdocs-node'; +import fs from 'fs-extra'; function findPreviewBundlePath(): string { try { @@ -65,7 +66,10 @@ export default async function serve(opts: OptionValues) { ? mkdocsDockerAddr : mkdocsLocalAddr; - await getMkdocsYml('./', opts.siteName); + const { path: mkDocsYmlPath, configIsTemporary } = await getMkDocsYml( + './', + opts.siteName, + ); let mkdocsServerHasStarted = false; const mkdocsLogFunc: LogFunc = data => { @@ -143,4 +147,10 @@ export default async function serve(opts: OptionValues) { }); await waitForSignal([mkdocsChildProcess]); + + if (configIsTemporary) { + process.on('exit', async () => { + fs.rmSync(mkDocsYmlPath, {}); + }); + } } diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index aad7706ab1..e635542a7c 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -25,7 +25,7 @@ import { ParsedLocationAnnotation } from '../../helpers'; import { createOrUpdateMetadata, getGeneratorKey, - getMkdocsYml, + getMkDocsYml, getRepoUrlFromLocationAnnotation, patchIndexPreBuild, storeEtagMetadata, @@ -517,7 +517,7 @@ describe('helpers', () => { }); }); - describe('getMkdocsYml', () => { + describe('getMkDocsYml', () => { const inputDir = resolvePath(__filename, '../__fixtures__/'); const siteOptions = { name: mockEntity.metadata.title, @@ -530,7 +530,7 @@ describe('helpers', () => { path: mkdocsPath, content, configIsTemporary, - } = await getMkdocsYml(inputDir, siteOptions); + } = await getMkDocsYml(inputDir, siteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); @@ -544,7 +544,7 @@ describe('helpers', () => { path: mkdocsPath, content, configIsTemporary, - } = await getMkdocsYml(inputDir, siteOptions); + } = await getMkDocsYml(inputDir, siteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); expect(configIsTemporary).toBe(false); @@ -562,7 +562,7 @@ describe('helpers', () => { path: mkdocsPath, content, configIsTemporary, - } = await getMkdocsYml(inputDir, defaultSiteOptions); + } = await getMkDocsYml(inputDir, defaultSiteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsDefaultYml.toString()); @@ -571,7 +571,7 @@ describe('helpers', () => { it('throws when neither .yml nor .yaml nor default file is present', async () => { const invalidInputDir = resolvePath(__filename); - await expect(getMkdocsYml(invalidInputDir, siteOptions)).rejects.toThrow( + await expect(getMkDocsYml(invalidInputDir, siteOptions)).rejects.toThrow( /Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml or default for validation/, ); }); diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index e16293f906..27c24ea66e 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -193,7 +193,7 @@ export const generateMkdocsYml = async ( * @param siteOptions - options for the site: `name` property will be used in mkdocs.yml for the * required `site_name` property, default value is "Documentation Site" */ -export const getMkdocsYml = async ( +export const getMkDocsYml = async ( inputDir: string, siteOptions?: { name?: string }, ): Promise<{ path: string; content: string; configIsTemporary: boolean }> => { diff --git a/plugins/techdocs-node/src/stages/generate/index.ts b/plugins/techdocs-node/src/stages/generate/index.ts index 3bd42643c1..fa36486a0f 100644 --- a/plugins/techdocs-node/src/stages/generate/index.ts +++ b/plugins/techdocs-node/src/stages/generate/index.ts @@ -15,7 +15,7 @@ */ export { TechdocsGenerator } from './techdocs'; export { Generators } from './generators'; -export { getMkdocsYml } from './helpers'; +export { getMkDocsYml } from './helpers'; export type { GeneratorBase, GeneratorOptions, diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index b71148060e..93285b7468 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -24,7 +24,7 @@ import { } from '@backstage/integration'; import { createOrUpdateMetadata, - getMkdocsYml, + getMkDocsYml, patchIndexPreBuild, runCommand, storeEtagMetadata, @@ -100,7 +100,7 @@ export class TechdocsGenerator implements GeneratorBase { } = options; // Do some updates to mkdocs.yml before generating docs e.g. adding repo_url - const { path: mkdocsYmlPath, content } = await getMkdocsYml( + const { path: mkdocsYmlPath, content } = await getMkDocsYml( inputDir, siteOptions, ); From 43d409fed42ef0e2f2ccf5d93111c420e37b6099 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Wed, 25 Jan 2023 14:49:13 -0600 Subject: [PATCH 321/423] Updated API Report Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- plugins/techdocs-node/api-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index 314a46a405..ce5bd1ae09 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -89,7 +89,7 @@ export const getLocationForEntity: ( ) => ParsedLocationAnnotation; // @public -export const getMkdocsYml: ( +export const getMkDocsYml: ( inputDir: string, siteOptions?: { name?: string; From 671c6af70058ba2ec1f9131e63d69d10c0c40699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 8 Feb 2023 16:03:57 +0100 Subject: [PATCH 322/423] do not import deprecated locationspec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/few-meals-buy.md | 5 +++++ plugins/catalog-backend-module-aws/api-report.md | 2 +- .../src/processors/AwsEKSClusterProcessor.test.ts | 5 ++++- .../src/processors/AwsEKSClusterProcessor.ts | 5 +++-- .../src/processors/AwsOrganizationCloudAccountProcessor.ts | 2 +- .../src/processors/AwsS3DiscoveryProcessor.ts | 2 +- .../src/providers/AwsS3EntityProvider.ts | 2 +- 7 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 .changeset/few-meals-buy.md diff --git a/.changeset/few-meals-buy.md b/.changeset/few-meals-buy.md new file mode 100644 index 0000000000..c49eb8c7ac --- /dev/null +++ b/.changeset/few-meals-buy.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-aws': patch +--- + +Update to import `LocationSpec` from the correct package. diff --git a/plugins/catalog-backend-module-aws/api-report.md b/plugins/catalog-backend-module-aws/api-report.md index 63b85f223b..1725692cb1 100644 --- a/plugins/catalog-backend-module-aws/api-report.md +++ b/plugins/catalog-backend-module-aws/api-report.md @@ -11,7 +11,7 @@ import { Config } from '@backstage/config'; import { Credentials } from 'aws-sdk'; import { EntityProvider } from '@backstage/plugin-catalog-backend'; import { EntityProviderConnection } from '@backstage/plugin-catalog-backend'; -import { LocationSpec } from '@backstage/plugin-catalog-backend'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; import { Logger } from 'winston'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; import { TaskRunner } from '@backstage/backend-tasks'; diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.test.ts b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.test.ts index 87b7f2c487..ecf3b1a961 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.test.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.test.ts @@ -20,10 +20,12 @@ import aws from 'aws-sdk'; describe('AwsEKSClusterProcessor', () => { AWSMock.setSDKInstance(aws); + describe('readLocation', () => { const processor = new (AwsEKSClusterProcessor as any)({}); const location = { type: 'aws-eks', target: '957140518395/us-west-2' }; const emit = jest.fn(); + it('generates cluster correctly', async () => { const clusters: aws.EKS.Types.ListClustersResponse = { clusters: ['backstage-test'], @@ -40,11 +42,12 @@ describe('AwsEKSClusterProcessor', () => { }, }, }; - AWSMock.mock('EKS', 'listClusters', clusters); + AWSMock.mock('EKS', 'listClusters', clusters); AWSMock.mock('EKS', 'describeCluster', cluster); await processor.readLocation(location, false, emit); + expect(emit).toHaveBeenCalledWith({ type: 'entity', location, diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts index c34b247f4d..b6418ade03 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts @@ -13,16 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { CatalogProcessor, CatalogProcessorEmit, - LocationSpec, } from '@backstage/plugin-catalog-backend'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; import { ANNOTATION_KUBERNETES_API_SERVER, ANNOTATION_KUBERNETES_API_SERVER_CA, ANNOTATION_KUBERNETES_AUTH_PROVIDER, -} from '@backstage/catalog-model'; +} from '@backstage/plugin-kubernetes-common'; import { Credentials, EKS } from 'aws-sdk'; import { AWSCredentialFactory } from '../types'; diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts b/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts index 1018e49a41..ecc42e69ea 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts @@ -19,9 +19,9 @@ import { Config } from '@backstage/config'; import { CatalogProcessor, CatalogProcessorEmit, - LocationSpec, processingResult, } from '@backstage/plugin-catalog-backend'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; import AWS, { Credentials, Organizations } from 'aws-sdk'; import { Account, ListAccountsResponse } from 'aws-sdk/clients/organizations'; import { Logger } from 'winston'; diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsS3DiscoveryProcessor.ts b/plugins/catalog-backend-module-aws/src/processors/AwsS3DiscoveryProcessor.ts index 84f2289c94..072c3d8384 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsS3DiscoveryProcessor.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsS3DiscoveryProcessor.ts @@ -20,9 +20,9 @@ import { CatalogProcessor, CatalogProcessorEmit, CatalogProcessorParser, - LocationSpec, processingResult, } from '@backstage/plugin-catalog-backend'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; import limiterFactory from 'p-limit'; /** diff --git a/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts b/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts index b92fcfc022..5e24d4dc13 100644 --- a/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts +++ b/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts @@ -20,9 +20,9 @@ import { AwsS3Integration, ScmIntegrations } from '@backstage/integration'; import { EntityProvider, EntityProviderConnection, - LocationSpec, locationSpecToLocationEntity, } from '@backstage/plugin-catalog-backend'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; import { AwsCredentials } from '../credentials/AwsCredentials'; import { readAwsS3Configs } from './config'; import { AwsS3Config } from './types'; From 9fafe6879be0ffe12dc47adc0b07d26fd786f70b Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Wed, 1 Feb 2023 12:46:44 +0530 Subject: [PATCH 323/423] added new plugin: microsoft-calendar Signed-off-by: Abhay-soni-developer --- packages/app/package.json | 1 + packages/app/src/components/home/HomePage.tsx | 4 + plugins/microsoft-calendar/.eslintrc.js | 1 + plugins/microsoft-calendar/README.md | 15 ++ plugins/microsoft-calendar/api-report.md | 39 ++++ plugins/microsoft-calendar/dev/index.tsx | 27 +++ .../docs/microsoft-calendar-plugin.png | Bin 0 -> 1951035 bytes plugins/microsoft-calendar/package.json | 63 +++++++ plugins/microsoft-calendar/src/api/client.ts | 95 ++++++++++ plugins/microsoft-calendar/src/api/index.ts | 17 ++ plugins/microsoft-calendar/src/api/types.ts | 40 +++++ .../src/components/AttendeeChip.tsx | 89 ++++++++++ .../src/components/CalendarCard.tsx | 145 +++++++++++++++ .../src/components/CalendarEvent.tsx | 166 ++++++++++++++++++ .../CalendarEventPopoverContent.tsx | 128 ++++++++++++++ .../src/components/CalendarSelect.tsx | 92 ++++++++++ .../src/components/MicrosoftCalendar.tsx | 29 +++ .../src/components/SignInContent.tsx | 62 +++++++ .../src/components/eventMock.json | 138 +++++++++++++++ .../src/components/index.ts | 16 ++ .../microsoft-calendar/src/components/util.ts | 80 +++++++++ plugins/microsoft-calendar/src/hooks/index.ts | 18 ++ .../src/hooks/useCalendarsQuery.ts | 52 ++++++ .../src/hooks/useEventsQuery.ts | 63 +++++++ .../microsoft-calendar/src/hooks/useSignIn.ts | 39 ++++ .../microsoft-calendar/src/icons/calendar.svg | 56 ++++++ .../microsoft-calendar/src/icons/webcam.svg | 3 + plugins/microsoft-calendar/src/index.ts | 17 ++ plugins/microsoft-calendar/src/plugin.test.ts | 22 +++ plugins/microsoft-calendar/src/plugin.ts | 53 ++++++ plugins/microsoft-calendar/src/routes.ts | 20 +++ plugins/microsoft-calendar/src/setupTests.ts | 17 ++ yarn.lock | 36 +++- 33 files changed, 1642 insertions(+), 1 deletion(-) create mode 100644 plugins/microsoft-calendar/.eslintrc.js create mode 100644 plugins/microsoft-calendar/README.md create mode 100644 plugins/microsoft-calendar/api-report.md create mode 100644 plugins/microsoft-calendar/dev/index.tsx create mode 100644 plugins/microsoft-calendar/docs/microsoft-calendar-plugin.png create mode 100644 plugins/microsoft-calendar/package.json create mode 100644 plugins/microsoft-calendar/src/api/client.ts create mode 100644 plugins/microsoft-calendar/src/api/index.ts create mode 100644 plugins/microsoft-calendar/src/api/types.ts create mode 100644 plugins/microsoft-calendar/src/components/AttendeeChip.tsx create mode 100644 plugins/microsoft-calendar/src/components/CalendarCard.tsx create mode 100644 plugins/microsoft-calendar/src/components/CalendarEvent.tsx create mode 100644 plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx create mode 100644 plugins/microsoft-calendar/src/components/CalendarSelect.tsx create mode 100644 plugins/microsoft-calendar/src/components/MicrosoftCalendar.tsx create mode 100644 plugins/microsoft-calendar/src/components/SignInContent.tsx create mode 100644 plugins/microsoft-calendar/src/components/eventMock.json create mode 100644 plugins/microsoft-calendar/src/components/index.ts create mode 100644 plugins/microsoft-calendar/src/components/util.ts create mode 100644 plugins/microsoft-calendar/src/hooks/index.ts create mode 100644 plugins/microsoft-calendar/src/hooks/useCalendarsQuery.ts create mode 100644 plugins/microsoft-calendar/src/hooks/useEventsQuery.ts create mode 100644 plugins/microsoft-calendar/src/hooks/useSignIn.ts create mode 100644 plugins/microsoft-calendar/src/icons/calendar.svg create mode 100644 plugins/microsoft-calendar/src/icons/webcam.svg create mode 100644 plugins/microsoft-calendar/src/index.ts create mode 100644 plugins/microsoft-calendar/src/plugin.test.ts create mode 100644 plugins/microsoft-calendar/src/plugin.ts create mode 100644 plugins/microsoft-calendar/src/routes.ts create mode 100644 plugins/microsoft-calendar/src/setupTests.ts diff --git a/packages/app/package.json b/packages/app/package.json index 1b3841ceae..80ee11ea15 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -41,6 +41,7 @@ "@backstage/plugin-kafka": "workspace:^", "@backstage/plugin-kubernetes": "workspace:^", "@backstage/plugin-lighthouse": "workspace:^", + "@backstage/plugin-microsoft-calendar": "workspace:^", "@backstage/plugin-newrelic": "workspace:^", "@backstage/plugin-newrelic-dashboard": "workspace:^", "@backstage/plugin-org": "workspace:^", diff --git a/packages/app/src/components/home/HomePage.tsx b/packages/app/src/components/home/HomePage.tsx index e432e1a00e..b0491df93f 100644 --- a/packages/app/src/components/home/HomePage.tsx +++ b/packages/app/src/components/home/HomePage.tsx @@ -27,6 +27,7 @@ import { import { Content, Header, Page } from '@backstage/core-components'; import { HomePageSearchBar } from '@backstage/plugin-search'; import { HomePageCalendar } from '@backstage/plugin-gcalendar'; +import { MicrosoftCalendar } from '@backstage/plugin-microsoft-calendar'; import Grid from '@material-ui/core/Grid'; import React from 'react'; @@ -114,6 +115,9 @@ export const homePage = ( + + + diff --git a/plugins/microsoft-calendar/.eslintrc.js b/plugins/microsoft-calendar/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/microsoft-calendar/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/microsoft-calendar/README.md b/plugins/microsoft-calendar/README.md new file mode 100644 index 0000000000..e170491569 --- /dev/null +++ b/plugins/microsoft-calendar/README.md @@ -0,0 +1,15 @@ +# microsoft-calendar + +Welcome to the microsoft-calendar plugin! + +_This plugin was created through the Backstage CLI_ + +You can use this plugin by import MicrosoftCalendar from "@internal/plugin-microsoft-calendar" + +> import { MicrosoftCalendar } from "@internal/plugin-microsoft-calendar" + +![MicrosoftCalendar plugin screenshot](./docs/microsoft-calendar-plugin.png) + +You can also serve the plugin in isolation by running `yarn start` in the plugin directory. +This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads. +It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory. diff --git a/plugins/microsoft-calendar/api-report.md b/plugins/microsoft-calendar/api-report.md new file mode 100644 index 0000000000..38187b39b2 --- /dev/null +++ b/plugins/microsoft-calendar/api-report.md @@ -0,0 +1,39 @@ +## API Report File for "@backstage/plugin-microsoft-calendar" + +> 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 { Calendar } from '@microsoft/microsoft-graph-types'; +import { Event as Event_2 } from '@microsoft/microsoft-graph-types'; +import { FetchApi } from '@backstage/core-plugin-api'; +import { OAuthApi } from '@backstage/core-plugin-api'; + +// @public (undocumented) +export const MicrosoftCalendar: () => JSX.Element; + +// @public (undocumented) +export class MicrosoftCalendarApiClient { + constructor(options: { authApi: OAuthApi; fetchApi: FetchApi }); + // (undocumented) + getCalendars(params?: any): Promise; + // (undocumented) + getEvents( + calendarId: string, + params: { + startDateTime: string; + endDateTime: string; + }, + headers: { + [key in string]: any; + }, + ): Promise; +} + +// @public (undocumented) +export const microsoftCalendarApiRef: ApiRef; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/microsoft-calendar/dev/index.tsx b/plugins/microsoft-calendar/dev/index.tsx new file mode 100644 index 0000000000..18c5e8c08d --- /dev/null +++ b/plugins/microsoft-calendar/dev/index.tsx @@ -0,0 +1,27 @@ +/* + * Copyright 2023 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 { createDevApp } from '@backstage/dev-utils'; +import { microsoftCalendarPlugin, MicrosoftCalendar } from '../src/plugin'; + +createDevApp() + .registerPlugin(microsoftCalendarPlugin) + .addPage({ + element: , + title: 'Root Page', + path: '/microsoft-calendar', + }) + .render(); diff --git a/plugins/microsoft-calendar/docs/microsoft-calendar-plugin.png b/plugins/microsoft-calendar/docs/microsoft-calendar-plugin.png new file mode 100644 index 0000000000000000000000000000000000000000..376ae737178386a4f7dcdf91dcb7c421195460ba GIT binary patch literal 1951035 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⁢Y!H?kp1+dU_ipz*h+=ZnR@$jE+KY#K!yi#m7 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
    QR#gOEn4KZK7ifM)gTB;QK5OaW{o@ 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

    vjvv1utyh|*PX2cGCAzS@8EosG)=tD=_ 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�Q`sRn(n{iXFKql)gzweG+w&SZz5e5?LLFhpsm~id z?x+U&jku|WpPH6Mq6wLDF04L-G~*;IqmFpML8@NRDlk3|(x5vmDlmS%P{3_XzaA?Kes z$2D0V|95VU0(y(VPR|zWo)72f&tJc)+ z>=04xHX|qEo?Km`^t-T$XMVj8A#w2zvRN~=)@l6li#rXk@P_TsPL=n(z)k~_K_IE;_$}LE^H;GgBO&D*yP|iG* z8qsHswCF7-a~R3}EsF1ZD7N4K7vVNzeOI;zkoYrI6&&@)p^1`FxbGcr#4GZQ&Xjd> zA3Inuv`X*$C+W{x$7B86oAT<`)2o_K*2v&@&e$m(PLt2h2KxR?f`e&nVZ@-zU^D~& zqMDJzt9q{fcdkhW-UZP0-7`AomZyn=K~gmG7%ozF*PIn~1x1q(ta-JcAn5anBtfK@ILf?-6wd&PtHT zJUNyoZ7Dt4c3~;JT?}v%wi4Z9N)@}$`{L%Tq}+V04xmf(e@`H}e2ms)nBzI#=P zsI%gpKs>m4Hid|2Qlf!npi+IJSyl9hz>BpHyKZ4w3d47XO1Q zqhF1qlC9DRM<#E?!Av3&*emCl1=RfSK8LhV~@Kp5WPok|u zmSY8Nh+bR2oSOVGLTscg0z8KVW!QO%XuKc6{pD549ur3V!Y2lFQw_;r_YF?t4^)dC zxrtg@Lt^4{l5|x(9ZMqvTjDYfES0tMzDF2U9my8i6q`jL488aJw^7HS^Ul@#37n!l zCZ87fYrvL{C&7mOuA159m;Hd;hU=@s25$2B5~lwDdl1K32R_( zKF{_|FAsH=P00&nSI^;f8aI9V(0PKh-%|U)-(S+!@R67Sjpd(S4Ct7fZ;7v9lR5_d zh;d{&ZPv&cm^Sjd+N*aMwJh6Z!@X4lOVo&>xpRB}z+k!J^QZS3I

    M~ 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

    K0l#X@X5zJe7n0g3!XnSn#C8(0FobV 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

    ;=5aMaaeD<+SGJV|A)rS9Z3a z;h>r!Yql2+t*ItEBp_cthdWTTsp@y#bolmpa6lc__Hql-P|GxWWfC4Zi6oLCNMHyH zXS%3h!~Jvux_lO$7(DUl*?%ui`bCth-{jqTFk#Civ69%>bs`$Cq&)G@~3-CZsm$*~t&XTfZ730RKly4%c%nsAhf0E5p4HDjdk~Ps%|*rIF*cX<5Ky3y};u zlW*QE(q-1?QBNFoN$5u_5TvGITQ!CgUGZ{`bMNGP&lhXHda}G0&6_`yApG)k6T0xI zLW}m4bOcr37RC7Jf1W3lmrCrH3DM3q~VIOq9tR4gGu}&QoxJ z^w8+g7(8e>X{bz&&litEL6~x5w#r)o-oRsv#|IKplL(8YRKBA0t}DlcD|?>Z%uho4 z*>3!t^U?>9N1KwCb>ow4fnXK`Y-sJg&Uc*w`y9Ng-pw}d%cLRtT}@F6%jn1u_2d^; zpWk%B`@jGGwT~?zy#XEZYh&0(mzy^9vSXrQ3(C5Q#(7ulTD(~TiG@zDFS!4w4Ip#| z+yIZdRbN*fJ9jh{a_r77JBDkVOOB!2Er>6xpEGTw6Z9669TQ9$d^E|H!>{;n9|=NP zaMgF-S#KrcJdug)5XCvRale1sY?$^S2MgN-)Y>lq+^YCk6yNX@hfE&=Mu?ikIG~OM zX(`qc+uX#%La(tEMak%mb4t;<$?G|psmI%Qb*{vH3`J~??Sp;XRQb>6kfZmA^ZMLs zYsdetf&a|fk?RQ}gEQ!ROa~jy7;fnCyhqJ@=!H*1+NZ zXGn@tuq|<@M4?RJH|(dLA!fz9hx~WO?t6`v;i0E_waDMP=k>n`Xv=7~&bi-tHhY~W z{>Jf~HX$|?q!Q~mz||YW9{2Ap`giIYev1oFQL7?Bloy`5(_-Eqv^xE%Tqz z{&!)Gbd2<-#C@yR^LZKYOa5-kzg>F-%83T`z!}fk|35BRNpj-<)kBrshWzh$*6L}Y z1@4f^Yxsw#_fnMgW$VomI?aLGde3jcNkTn~RZkSlkT)+puXRJ;;FAyx`xCx7c<*Ac zv+r_ry5U{CP`tsHLK^<+Ym96Z*rfiKmv+U!?eCWTE5svFl3qR6RK(nwu;$Cx=DhY- z!!P@JbLv}tPv6~-6#n4Bc=U&FlqBN>EpnIsMePDd@vY}P>T>Y)CmRW=12_^s-`cDB<)3|-sv zyY{~ao}lt$;T+^3bao?OHfpn^;sR~~P@I!7Up=0O!~HkEig$N0Like2zhy0BDqOkJ z-%PZcOv}|o_gu9OisKr;%h^To9o#?MP~9I81rf~kwv)c8$_^@A%&ic@{q>da$b*8) z4Xao~&aZ|xi5lxmohb#6adw;WMkk4rO@nxQme%1bfn zJZm2R;&|~nx#e4qAzRlkJvA}1xII2zF}i?Ty~5yCRr7M)M zGwZHewY!oCy$~&=qku8BE|c$CtCX@RpWGfnnPmi%-4ml>+sW?fsr zgd)pq%cW`Ug5{uC8WWnxN7=JG--;XIU{O05+iV+|S#uVr3!w^PyHCG8cZIHM|hr9l}opft6;EAaDs2T+6+RXkp6b`X?X_z{w`s>&G zbyJBh2S^l|Zii7%_2ikc4eH*QCNxT+nR;fU*?|Ac=R5#PAbO$phos*R6Gl~WaW?*> z9+8kPFzvaZuxRB)lf|NuIwRmI?Rd*VQSHmw_1v`?-(@FWQP*aMkfU3CXzHH;;ph)9 zZJEp!rrYkA%bCt1Atj;h=$xRO;O{S%XWe3Ae;73}o7+uS{^;YS08f^=R_#7zFIbz% zGc|cMx`*Bg+DTUM+|{6qvA`Xl?T%)CkF&qv5!xGhSkbz#ZJA! zcu+JpP3`O0$;cp&N7EG+J;pWM!Hqw)C8M%^XC$t5Lqu=jp$Zemd-%PTZYX&#akqoS z8XYqRIng}+$vv71b8V{ZdMml?#0cwH_D;|wWI;#B)6< zSb1TW3tb-A9R_kb@xiuuG!)>;=?}QpI0lw(Dr=r`w6w2f2wj%ONje7Z4~lnlA|s@f zUhXbIBF7C^jJSGed_97kh>^SfP!c8Vlv{vI$LrR*XJ_o67j+#LEK-W>j7AO3y7D6P zlb_2ylZ`m?lcpMi1#QbuVbm{>sJn^j5jG{$z{%)Hrx7$aCSuNK^0|y=;b>&$)ua-# zzk&aGoN5F0byle{mC)&K%pA}`LMg=cZUwQb9VFFaHHIpLR=NT)WxQ|>W6H0^`&#ym z6p%f&#Jv(h0d{OPPI|c}c>~D>tSkPcoeEVh!YOv=uBD~n1YdF84o%>?JyVASX%$|t zZcv0gFA2GKuyI`re^5OX{auF6Eqt$%mnuGhgn*+=_-3n7%@~l`9=|@5cQL=8sgH>W zbEr4Ro*pLFUi|Wc<>KZQ5VT(j>nN0sraVv!iWW%Mn<_l%=goN+PNwz-!hg}iRouV# zbR7Fi-IZWi!_jSuIF+k5z?5v+?tR0>!S&XL5y|G;gDZ=UCEHrbMmv|gM2)QwSCyYcf|=?fOS zS-fOSZejJx6FXPqCaKB#IPj;EE3k#^(wdk3#V@iK?@QLaQocfh&3`JF`fDV(wY)M4 z3I}3x)b~UND>HJ zYB%QGMP4^T!`wBDZBq;)MN=zzSr%FDrNUj)%soAfJ$h5rvHUyuQTS@Q zf865fNJIC?u0(@Gte-$2iRk?o(>^?yR zZhl3H&?xLzGa)G{59p8FW{iifYYFm$(ReWy4>GscO52WRGKw2Um#)&%B=&c|I>Tjt zg$Po3Wzvr^RhV<^ThVfolf981%3;csHezry2!)%cb7+0t+ELh5#t?-NUCQHUXmTUPZ9j<#OYjA=}II=LO&z5{~*}Eey+gVQ=u)} zUAO%I*fc!%OGz_)X7FMSIK#EcKSKUvV%attGLjHZ?{isp$)AlXp^BNOn&+Ri&gFMT zbjQA+^)+R#&H?45aX$=r=3~65FzXtT_Hc)lQDpZN z={Ild_}k=Mh&wT|p(_DKa#Z@W`u^M{r1<)UxS%;lGB%b=f8-YCT5#tJADr0SSYrTT zNOU7`xu>Bl?tCtgdlxvyEJEfY({4Aag{kkB)mzb?va#IU?Wnvlv-V(7=}E#9%z5Jz z_@TTZBUFU|upKNIecMQYp{IB$0aZXh=}+kK{PE-D4l~y_v8{$hvZd;)`voo;&&p_8 zDQ?)~c`O2#bRE zFfU61Ce7^Ucjp*KV|w>ICy=}B;f`#c!^*fg!AKZ+b8=T4`fMQ($fL8EQ@#k}oTl^o z$iz4PDLbcp|H^WTKm*lZ+)7v zm8dIxf%SW~eR8{9Jpt)lPZK|B=T8ZQo|M48W$ku(4X7t_-FQkHs9bDp??cX@WGl|A zlorpnVJN}8`FwASyEk;g;x~L#IO^N6%pm*vTFM)O6i-Zht-kehj;&W2b9wNHSa9AIM4a16_h0)7&f&FfPzKALB$cUh>*nJ zc=2@di_Et0S+nyU_y7C9#K!=yyyJ}>7$~Ikirm3JHKKd9@uTU|)mIqSr>eL{1PLR! zV3U!7)@zOV$?&}0W*B|;y$3w%`1R=_7NS+8^`&2Dsd!y>rc<&>=}pS~{ME(;EM+U0 zx0l9nqwt&BPFRl^{H|vP=g^_w_xZ!OXGt%g1Hb#{GeXrz5To+xN!tCAmnjHyfe&|o z-R!~$OO_(I{#?>Aey(>(%BtUAun!JjwI%k}U718KIG4G!q|O+MJL$ zHnZ4Y3B(J4V(oE8Coy7SeZ|FYR(_^>b?keAuEiDgjT|sLm#e`breKTHr;=yJymnT9 zcn0);D%%u`2^LTl4DENj{@&!AstNs#*K|6v$&c@_ebxU`OI^X?X6=XRDf(`#tY|2H zg_%;~ND_V*c^>HI|7%<9k6Cf1tEPVP7vgV^IEm?usg@ssa&r7ijz^Ar8@RzeD*L_< z_~H-~davzNyl}AU(NmKKo812R42kzekyXUG!j|bl+!Ctlx3}UIpXD@qw;Bc4L+#C4 zPDf7v5g8gPY+{F+E3eQ%%5=DG#8VZ*otT}77Y;PXR^&zJU*D-}preys?UkFwC6Trs zqF$S;U&ATG6K{Q6T6Ng}1Om?GtO(+7@j6G95+sSg(}Uh0al?VV97eZk%&Az-HV_B0 zGXAheH1b$zfYwLI`0xOW5U3}7^Yslbjifvn_G~$IEQ#q({_a0H?{|moN zZuffj{i;uTN?=m*5Xtl~H9LCiL?_0;$b^$8D@}cU4c!fmUSzY-*uCD6gTL{Uf1q6T zcy1uU!i8NOIr-QDos|;p9j2O5$<;K>KX$H>QeaF}BXZZOh-DH~rKd8Es^5Rv7=rr+ zD6wYjNCcg%8L@>yFZgS5kGX~IPL(I9ksD=fc9-0L+~bOJ3&mu5ZVlUoEWZ&i?A8b& z6Dv9=Il1W{we<7*1yA`QLO!>HLD|v4Z`G~#M>Glnkke{`_SmD8u-{^7=C@@97X3y; zEcq;Gb4e#b5Vp|6A=vG9(`qBj;b(1(?VoqMaFBsRLHyTn%QXW-O-y3)JF zg}mQkpmr}K2OlE3iTDp5Lxw6qbJq0K@q#^ecVEXqC8xoDN#`2EB(!OFu4eR%UGRDl za*E9JG8CT|6BEIzY+S4{ZfTUY0+5fPe`c-kvW8G*cm?FlrCzLjrUZ0xQ$XTQ6H*#A zgH_8JB3w=gUhm@-I(4onc0lHT^g|^mCx(4Pxn9)?hHh8}(*{(Zx4nQ{6e6e*K&$7h zJe)B`Fe-Pxq3AU~Puec~*@{IH{aYj>#Je)YyIW-c;8%&qAU`XnW%;e-k3!ufF7qjX z``LGo;>9pB>P^33TH0;y#$l&^FDPNF=0~)`+ZZYV41Di|tNSLVTvRo|KolYH#(BBI zx^tQcla*0_+_Qn}EA@^5K2byTQS#kdnyC`-}IwK9-d6q@G^tf0v9(P{Gne+VJdey(2lt3Z>f*tXgSm)k{S( z_6(@pIGx+RD-1Zp1!dcgQ=OI>-M7%(t=}hRBe`G!*XK?v%%}(Mwk6dNRN_xf$cXOVlUsra7)5Ro8yw#A|LM0U4RAex&IMM zdkY8#F6C9O8D3u^;$V2y_T4?b!K6_xRYUyNS<5%QX-O5l=6>5g11t&;h)8*=9XN4C zQ0I9dSrmLYu19a9KkKt)fl|E`)qyk`e8GkG&)xC2jJ@LJ?^Gju5U)zMt%FW3Y1fv+2^o}& zU9RAzsOY8Gi|DM(2K&o%!^tPLU@w+Mp$d3q4SpUQ8JCEAyxf_8h)CVbW3`$>;X z#j(%)##A7sl`4t^fg0*d8uo#cza1pUuD)DL_q?6^Yzs+1!rym0O~w2Mh|LV}Se<&d zR{yt`A=|ge3Gq^YZIXXo9!MD8=L)$V9q1q%3M6(nF2Z0NgrrmC#9MVuL{O+?zm8;U z7Mur=aTrI#oFoo4pB2qsRj9kKuM7GIz!-A`igJ%c6`5J3ewp&X_YcFGipQ^)@qu6e z$C=~jLJXnh*+BQI)heUAV*46n#CbN(-Gv|<8q51dBTYica*`Oq7N5uSzmgIv8fzA> zGmn-uYIfl+bq)F#-f-muWq}pcreas-eIGk;)_VS|w4S1~Au8{ruUtC0vo4r}_g>bU zuyESmeUBg-?{LT~uXlTs*N%~Hs}ncPAWpNfGglw8U{4? zr|dK$T^^P}G@s=ta*(%w2UQ3gZ!=~F3uri1MCk?Rv&tF(LcuH<@7qXbt}XI>A*;#s zs&E#KcWPa>Y0obh-pMV`*_$wP<=KJn3e)hjoVD&xNO{q>#?}+mL8cQD9qg$5{S@&b zb5(VUpQj_fqeVG+FiqokkPxHH?5k(d-OEL96I3_v(`1Ws^G6V$XbJMLs83kdiHS3* zLCKRO08}VON!8EYE*Ia1dH-;`MDf9PCBrYep${n*PWGGkQQV4j=Xtd~Y3e1#M<;)~ z(GnkTiD=`=o##=|dOk^9gS->7M}{10sUI|3{s|w7Y!5koy<-ABd4L}@v8To|%?jU< zr=CG)`&lG=Xqgp-U~4<#u<1?RrwB7vN-S4q>&-8lOZg#Kz<>Bb_9>Z&eB=C$OZWSbnGLn@b%zsrPq z5P!gnaENWjML|4~Xbm1P5Q<>+gC@!;yHhDEHJmE!&r6 zv2T)(2;wcLyxeK+VWo2w(Rv5l9HDsX1RYF&vm}9ON$u?PF#>*Ma_v&k0HfS+df6-^ zq?PR!a`5t=Egj#eYstWAsgi!2+KQmE0}=%w(kaugbHUtUDCRQr9hmR0gi!Vce&4R&o)5^LMYo+G6ZNL zdAYaMwhcF=U))vcuAg=0-Dv~bL7t_pdwwJBX$HLtHS)vtP-0|98bzUxZi>e~O)KB^ zNpr8>=DdC`b?&fGY}@g-Dfi1WyY&N(i;ePAMlrhuVUH9R?y?{z(I52nQm+ORT7XVE zDm1t20Tkwab8q#1R|36%T0Aos`X7N<#gYz9Rz&mhM#9NnU*+mMosV$k(CtBrzzxK! z>w$jExmq6WJzhVe4y=o6lk@Hz*I`Dx(eh-~jd=ss9H9fK; z)GiIps2ZD>xbUjpiI;h4KZIbm$ilT0#VJ5I-x@X%6dKCEq|4BLXmtDv2T7_xB=wW~ zDm*t1fun{ebnRcdPA_P+SYOCC*j-LHhi&}&4c+Y$m?b*V*B4=Q)p(}y=e)6m#Z-Sv zR3}03t{M0Fg&xM&pFFZtyJJP@1l(U3(?X=LMRDz=$0Hzom1?--<0N5vd_^0Z=Z`3^ zXtz+DnHACxd#3w@D@)K&Gg?+f=!M>`J)5Z@Y}@kCEk1Aet)Xi*&fL)yfy=6PIVCPH zZp1?`SBRFsdVQ1DC*}MAzX>Qdd(c^!Jpnn~H|L8u)jqpgJ_X1SV6MJLU0_iSV1Cam z%H($X^W-EX;7>ZqOmi_VSCdwbaXY%l<4t2vpngSuOsNoS%<{IKKnjD_ zUPjtcxuNAt3{0q@K2m-(pPplmC&gSic6%s%beY&KS5;Qs9k`OK!vWUb*u+9`_WVzP zSAtLabIadRHA#Y%M!<;n6OdtZmwp@8eS5Cs$_g^GQ^_OkM9)l1(wq58eu9RJ*cngI z;42G!I6;591x&^EnTz{O`mjeoEln|95wtN*FT)6qSjrx~7|2*Sjm2D=qkm5kSe};t z+49=X$^mu~D)3t?mTx!0Jf=B;P5L zP7>jLFA9zqt&qf{hIY}>DH7gj2i~b@OS1mnbjG7QGEq2X57Vj5rzvGkO`0w*6XsBEZIk`!iMd!H%yqD>qlz|6j z%PAyel7^|h|px0*GvaoLL1j+Yo(*uSom-L!xWpu z3dbt#HKB7D&#Oh3{mg#dVPp5xw(rAQs+qJ*Y{R1N%|D;r{}j;o-K|;_kqIr6pFCK8 z{i&S5=6sR@apNlV)nzbqtrC0X3BM})ak}}NI%Ha8j0`H$dRCCaZaSym$fuLY=n6Oq z;~5zv=y6vGzm(2Ai(wN~bX9$|*M22qIlxs>bVVlO>|s`GsLw}E$){ZA{u=lr#dArq zURKe#!^sLNw-AjbxW;2*UW~xmQfkVm{>YHy*vT-*1M!g3ZMPr27w%PJnk>a^aEG(p zHez;{58n(FwvGg1B6T3`H{Rl?ITpYjKQBlK!tZBKQipEpBlZpI`s<{lbl+cVzXYo0 z4uIDvQLtK2gmmm4BOTCv9VhpA*hck}3zQG+0B|QbV7{)qtHU;J@a?J{pFv&>Dwf7b zE=+*8CQ)w1C&ZfVz`*Fa*jB8E07m$V((Gd{YQ0J0kng)kt8Y-TFuau#Yxwls%XLQ^ zX=UPW_ZsnpKu~H;uYyp$=>3tO;v4++AB;9`V3kZ`QrvJ`sM&QgH(p@hr~Zutik@ao zhj;wfQ+f%)FE$%C_ytHxWjvWf<0P2AXLvQZiH2WnSL|INTwet=UOdB7S=cRsYFYoP zGd#a%T^)^t&;Nm(#$U4&0XQr~azj)ciU=hz($y^A8HcB8FmfaKGNzfFFR5t1cw;x% z4AkKXQ*G2d!aUuG%<-9H=#P?=M&_FqdPjmBU5bsA-)3}s97L8$6KPrRaO(xnEn+nH zmbpWZ$DgMrm-c(#%TIPSuErY#9*e}D`qF<~_nEgUk?JymDobkT1~Hu;VBtVe-tm-m zqC3bj8Wos!-Xd&8lx_~Bv;IJN&i`UOH@Xtbi7AgsqbNR{MDKN-n-zqu4zNl*wO_th zh(M6!n$E-SQxZ$ z5WIlc>Xs`YrJ9M$YbYof;(Qb?*-cDuAv<7=1FGN@U1;A zT9AJRt{ulglLXH%`q+!bJ`&z_tN*--{Fuj^&o`TTrhekv{M{1m`26g1DP_s07r15V zs-wW;_Gn{zGPAE0KUYR2<&8T%$J&rYz0NbgC}qF1z|Cx>pGu>W3+UZ@d|$k}W3NPJ zr9Xj{#HNmL`O{%#DgNwp z?S#QRyyUKk(UWJi_xPpV?W{=MvK~@5NMN0$^2A-Yi#vaG8TI!Hq%YZ8(FO*OE7f4X znhV8Du4RMMVDRDJX%IU||KuTf$l92Ac2W9=o5u;&XT#O+t@!;|RL~;H0?+ZTc9+bX zJ!B&YdWk<3`!N@v`=6bHSGs`&mxGT}z`FWvmIZN#X)wa+3jZ(9mHpW@6?O3(eEeSn zz&Bz?MOpjqGNUY+dD_|iluE^M=)2OlJULtMKy7e=6oE%u{?D)b|Jzqve)*5l7iB#a z7gtV7LdtX|w29l#Tm-}LExs5CLvE3tw*wcK#py4-Q3@y8D?Z;6)kByJ1K48|SxT>p zaGmD&pEllzmHu)=LbhliFp0^TrZ@ET2fG^AqWuLrOQU~L1`qF_*R?glVhc!t)>$o;d~#IYlGG`%#j*D)%qD`%posN= zmJi)d*oqh3ppW76ysyNhF%?K2-WjC`bb;Gvc|_Z!`K5;WMq`7~EhtdL!=(^WkVast z4#M=}zEy(6csv8ftuoL3cp(V88}Al;XLF1y(EIGy4G)R*?fefsSnz(uo21cQlNb8M ze*2k<7_X9?*RguvPJa@^oY`ZuvnH<4U>?-z)uiN3#E|H$`%J4{Z&?+K%GQ|s;W#`z zBf%Y%_(h*diZWLCh54Y+L`~%}XeD#NGq7AH{jBbh-%>68YHZo4tTZg2txvr9##lTBgF-0JOA7IGVFN!<~ z{GM2$SjuMb`Exxz+~@O$ZT!!^6+P7iYYcrF`KZBiyKXW;*8X;ixHS_Wu~&Ftmw3b3 zyGO5}JWQ|P?R%AO$%^*NCZ#6Ns5da=$!5=VUTfM@Nojyz+DB`OJG=(0O;GW^`OD3a zT+kd3PfrH<&al@i%CeaWy}Wg=?B=2avm} zR2zHC;TIktJ{lyb$W-<%qh`>%DQ`RmB1b5`&AI`4#`GHBvf!5=roRq*Ni%lGO&`=} zq0zn%KdNQbk>jlyEc_iSh5GR9!>7EZi8X)dgRHY|q9Qq#HEJb=h?nNvB^ca*h)|OjZsTm^4tv-4bg1bLIZklE^m$#E~>PT`!3JZo&J-Whc2Uc#Od5;pSRp@t1TDI=TRVmTbZ8KFdm=c)f%oFhKY&tUgQxz56Lq`Jyph zJI!9y?htIRK-{#$F2?FUsG=Z4h{o-q=T?X0CsAS%m*RW(Ln3O!#cU(7ke>7G z?OYr4TkV1jt5{iImt-NCK=BQ7U8gr2-%bmY&G$ zkfc!g7C=$%#d;;=MSnP=Q%oTv5|zLD7#Df{ZBFdWKVy0Nw_1i^30d(X=CcJms4$3c z(yRuv@Yvd&lN69+C?POqy7{j*hfp7XNpnZBzb~a<5@Rwifz$>3TFd! z1tz^7R%*<2u!sD2v`1}_cZ-}(|EI2dECd`>^>=0X(+-v?=7??A50#^?sg~pyT~L3= zbBi(Ixa&RkZbl1j>cGDfbdRGb#OFuOWE@|~XA$Pt#lIAPvq^qb>TN%cI{BGI>p-pZ zJL>ODJ|(hhr5xHXpr2wYHPL^+D5-_|s}q;AtiK2gZji-CKO}`)AS53Ayy1O;_7{%H zI}=Rrv6{r^DullPz5IEB2vlxBNAUgczfb0-{xqefxjvzuPENZ?Ex%GNlbS3tmAt$n z-#+VHu>9oN)v8PKvH#@wRtSlIYr4mK4F+8Y;x5YX^N&DZR;Z3Sj+9x>J-b)WQI5N&EMOG>5;l@orkT|l;?T?K=ptZ| z$aFy1Mna7F-w6|M+dOVqq$*6GUF7X_RTTLW&s$>$iRrMb%S)174ib_{R#ZE&#te!h zgv{zyu&r{=iCdFIlE=?Magkj2QSD`?FUDW~6qk_CCuolG7Zj~r?qZpB5%1!5KF%e+ zQr@n`Mpg(%xRQ=XKYaalN&o2c1CC@)|NBZ@onY-f7vE@mLu!7RA-kWKRWp z?kVtk7{hX5c(FgVHIscZ&3*dD(b`y3ufn%TY;ETsIzkXXLDMP>Y$^U;MnqvnC}9?q zPiPRqn_R6P0`FFtkOwy01OLQsjU)&c4I+PnC+1Q6UbxIJzwNj=8jswclLAa9d_6_5 z97jY_(R!AG#OH&Ha{8_lRB$bocWh@ZQGRV5Z_#-}bmb@!yKOd=p29wEN zwg^0pO8|>U^#se2BZz^*5j~Hnj5k1W3Wy?i$lu1&#ZD4j8&Q2JC-Sksb;KC~Jf5@v zsK+#(s8n;iDjRjx==EP$F@+;no51P}yY9ad)%P4XEr&GF?pB#1zV8><7YI@bXas$} z;_J7U>#oUh4MpI|*8Lon!(7Wyf*gq?IK#m+G7F&Uc zu4uH!zaK2A8%ajh;q11$h12&?X9!6fGzq|F=03P9^rtWeF`4OMpkpQ;qXP=CH=>4pypsX;4Sp7j_}geW&X^^W`%AuB=7y z%keG3O%SFTrsZu>uw9WoDxn~Q8En6ZE&j!I%czkxeEF=4&?XVE?FBc^xN$K{Jh1vdrg zYfaCu`EF46T&ADyNRSLHdcM6Gq@4Ggjm=F73nBf;WUbn?*pyWLP4xKJz_x}&Lfi)G z>>arEtFlL-GJfUmo-VVDd(M`AFxtOZu8(GYX#3_JXQ{lkpyvgprHdw6!+o~2M|ijD zNo&C@t=%KkfLg%Y*tLXZKFc5!k*a^nX~BVkc6+dvSbSBt8c#atrkYOrECq3Q288p3 zd|`NJ!3oqfk+*oU{F(C*xDw)@>$aDDa=;LyjO4(C2X*%|zDEo0T0(X1{Wi@l zkbheAPp+=>0=|bm&G_aA<3x?HV7#f&&ZT&H;pG4Npik9E#LT+Fk8Tw!=>mb&^NM$B zCPSeA?ir}OFUp;4Q^LaMon}y=cu8&e<998@(a%g25C8=qyuyU%jmU!o`PY7L74Xy3 zZ682gPsf1Mm=~}c#A6Kr>1>YtVb9j*t$sm!v#;ZxAGvykGS}e+y!h0QLb$y-O%ALN znXRr!5gMcpfHU5qeo^h+*`x3`^3*{$*jbw`QIV@$fBTRW4)}cta5vp!lTe`XZ95e3 zmI_ndFirDA$(_$VwZ%Ga@YSUF`FpS>)_Q6HbaG(;d*9OG&axDD`(Y!lOc>b#O*-Ek zAdUI1SuEZ0GB-y`v)l)Kd>eznPx~WJQm8-k4n`!wH{8}z~ zpHNf1*oPX`YD2nNo+Y;r`zF8e-!i0s3Mp|l!m%{l3D$TyqgJc(v)(8Fe(V%95J9>s z;9Zv($zRQ?M|uVq)*GDFNha#1F+$t_B?ar?rjQ)m7lD4m+kLbe=s!hvU|KSEi(f}i z^@d^YYUIJf6_>B^FpmO+P*Dm&NhIQaW-s&HdusTb(_u+GKS{C-EM=9`i1}RI@E*xbc?fbpZJ8GW{HRm(AHtYD0m>ldf*oV)uA$pzCVlRJ}6iT_QS|rZD|>IB+F-i)W&c zx!uXgyXF1PGm@vr@=OaSDA>Z!2ZghOHdS0c?L#k~Q0=mi#C^dwHA<$0ePX9f)vb=Z zT-T)3{Z3rgC6d&|1HTGq;}yEC0a972EUy%ar|oxzFk3$oa5G9ED>xS%s%wJ?pzx6K z?)yzvwW9O=n?K5pP3^NH>+^_)uYx@~_>%Xvose1}kcFyZ;fhPA?9|5}_LMR@*&54E zo=?f5^LHJ=jJjII%_v+LfEfo|ZS&wwp@z z=-FVQ;qbo#q{DGE)|KYdjm}*BDX99mK1rGOG@gFPo{F^d$mVYuyFHnE$nUT5(l|fQ zd*7r#ciI`dh!2?~ufsE7qu^D<)hl$hy6TM&{>}O*8BS2?`YPlCutLa$DiIHX4!HOA zHZM(;p8+?qq!fMrma!#O88JFl>s2Ix8oD7IHiBVI7hTW`@u~15C;6DK$14vku`~_+rJb26|7eR$*)|9uafa(3W=)OXmY1Q7H4wF?e2D^fZhSee zC3ErxZ7x8ER%S3W(Oqyc^2B!wNKken43546VA#Vz_{2yJVA-Y#@bqj=M$#Jp17vW5Q_fl72n7BuyAXP zqskvfu?pSD4Obs~*Ry~Ac+jWn)&3`^iIb^+POEGGPKYo%9ydM=Sl^r|6JN9IDx&kh z|A7-=saUg9njDUXtjrqk&eBPmh} zokiLBh!XcHv3I@kj$8=C*34WMe_2)NY{-2y4eNNw$ep-Y9C=A=JmCunO4eFbV*Am# z>?Kpl&M#+n_`8oH7j4UM#wz#mI$Shb*dejcFtWUiG3tG#PT^OtbElVn(HgjgypMkv z^(&db6KHWeCeddmaf$tFAey{!TB?MlgkOV5{lEYKd^-T$){SteJKFjW^(?VKo z)5|T%e^kWw)m-)+ljR$c0N6P@-o1EA0CN=L#aZMpG9}$-_Lz#BahwH$w3c4q=E^B+ z2+noithH?f6DFSFYV_D?<>aE+hVljSj6!={2Gmid+={q>!mne$BOsiOg#VVeM>)d zu|Cz@e`~)r-gow5xmRi%SuQ~9!j`6Rhh-vVqU;vWx2%aH6Yi}KGb_aAS)&=OFp(Li zF5V|eZGde;K8jVFM}27t`e_gnjj_L(;^+gWY^?;Amhn6L$ ztL+Nj$n6$}t3*(_W$@>a!5p(@BfZXyb5ss*6gTL>s>rx$PeRvUpC9375uFs=ACdXx zT+%lcD)7ag4eNksT=*7mE_mVqS1hY%rW7rB&E`nGXWrQ)mw7D^Z)AZvtnDJmG1{JJ zMWy!CP${s}xpG*Mc@x$k{Qp@13?WQ3AN<0?#mY{F$G!yF7Yn=h&el0gSA`@q%U+nt zXgFNNFrboj#Mx5Mzy{Z#3^R}M?-k2oxLE@d_Ktsra9Jl>q*;OsUlaJz6M4yWmS#&i zzv9PB?`2zNI2Wgth?+d>%c}A;F!$Vm-}T$xvRCl%@}wXb7QF=ann9$D67nSU8Vd56 zv|3-G=S#m8JIXFj7se;{I9dg-XuA^a35N!xRt*I;#`kG)mlY&J%cya^6N@hjbC633 z_7@?I3kAPFNKVD>^S(M6CS;59aPu8@rUScd`uv-FcHC=g?DCVx*}8*lygfK1SkgOV9|pQ0{{M z(!6^oCjB`q@=6y==^WuK3gJmT7;x{of5Bjt)|7ch;saNedLHtLA}DioQk4FGy6vB9@ zkk?%(adl#3j|C^nlA|{}MZneok8;R)E*YFCFNSP<$eaY^%WcVAHND7jl^ewsfvP;n ziDN9m#`iWr?ug*8!3W>T2)Id#$zI)kbL9xSIls?=BI^-|1_SxniNE;6qtS2QS~|a& zmEzztsVhN~6@eJWelGIGc986mr@E6iGnzo&!OlFC4UL#vO?G^_+X$z=?@5F_n3P26 zJq6zUBepuWg3(8bg83#_T=mJ7c3vtKbyD6&`>7~eosD;zk;ErgX4iurOm2}67FR^K zA-6-!WbvP#fYG0t*SiC<-N|+`Nhm#%UUm}2t`f2=0*jWaG|ljGb-iH)J-akqsT~hA zlI&@X;RwL-#5|dGJ;8XK`6nYt$$4sO!S`Q$12axuX6$+F-SK4@Ms-2-Uu~F&TR1 zcki84XOq(=p+{w33v=dZKOrEi*G;=f0;)fcarbZ)Of=f-Tmhb|?!y6(u00no`CmFY8}shA=fqXEykONN-TrP5 z1qO}cIUrZwDM~RD776BOu}$o)W?2?8glWaef%Q@6?Ylhg+B7*3%|4X+?od{? zuw8g{RCM5+jKD2ahmK(%ATXm@C}tkb3T7Y6;B)*J8nynn`t|&$uFK&hQ1|WnxEaB& z^OiBMMrWO?Ws@Iy z>l;6<2~Iu&7?4Il+tKf%TXxZYAsJ{C6_l?d)rJxuFFMFa=2>jyB3k$fAhZL<00H`| zz_{T~k0G9X8_Cw!`+(MD2;W3K5oZ&*)ioG~2*-JBJW;1|%xBU~du&s+mSf^_yl5RR z6?#Y}xKI&h0>+=aS-d)=OhG5BV9(^sTy%TOgH|_LTkFLdpE6BbXIyZeSu=HCmyJq39q!!Qj?O#8iK$;>E{v{<<>Ck>Oz`1|#Wyx=#C>za{avgZrS z<_mXHo*TcOfD2Em$4yg0vH`bgV#dVRKB-=EVj3DBXGN9}pWC%I&`qv@;QJNFv+iPY z=riYl2_5&579@ky&^mAf4#5+eN7)#BzsIzz7YdZdFnj#SCfWL&^vnXMoi3No#7Q)WVW@YqRXhe-K=8gm`+8iFBQK8eU!4Q}m3Zp0OL6dn$A@bWAIAfjXuB zl?S||u(Q@o8;(xiQ%?e^42y~o(uT0MU#;iZx4vpgXUOU}EF?PRsqcS>K0J{p*`!?E zVCw@Yt8adRkH2-_iH9+%BlB88-jnTzsfh@rlQHL+T+0+Aj@48;WXi0~#T<`yBVLAP zYb%B&T8#D*1kubE8a!zjW`4&EjI|Pln4V7GtrN4&1q|Oyajeu|flS4n?vt1Y(5+NH zLZ3#EbI~7VR*jj-ck-uHLwp1Mc`Oop1Mn|Aa%)cK-wMeQB zL}|^uia+bt_Yma~p8}^iOu-nQkJ^W{(fC<~mpkS!*)?pvjS^#v7{fHe2B;LDmV1%+mA z=1PId)G|d++M%glbj-3J77{g*lwBMVH8_tZGvT)=6bW(U(_ifJr57)LAvw1oQMoli z^Z9`;oU_>dkU#L#g~DPjTR@*Po(7}uDt?#^+6NenQUqie?-|HGv|(lh;$kwpe|rnS zU;e#pIW3?3phH<+Z^J~ez|t{?7Up5XK_^awYk%w(7)X4rx`~E;g+CZ`1q_CR9PqIY zlIwV`!C%&fu1}`fi|mfSh(g4b1K9X0@?wbpjmsnrp6gxVU>)c@HIZ#NSXU(j_4mk@56kGf?|2!WWl5ldhqrR`P-)BZ3<8Y*C zf^y>$Y2?8Egmxw@V-$F6EO*tSQkLRl5*fp)a475?e5!K`%rp7vrK5t$osfWd2}W`h zE=_7r%UkMFo$Y<#iX`m-JwC-;0lJYK!sxS!G>oNZ0v3XMX2$VK-7Qg6M8=qtU&o85 zYr`4VtEOuQ)}Oc&oM5h(P=G10wDQ9(3|(MV>2Do%-`8S=3r`?WCGT28o3}{${>=+p zsKB;~7^3k4RYP=2Ew(&2dM&~g(u#08K%`nalIzkuioCErc5Ou*`Ck7n0F=BZ@9!Bb zP6?%vCwwCqc}ck>Ltv^}JoB4Ae_KT}m9}dlU4P8b?_X9(^;3E0Ju}d{0@V zdMPlc>qqYCMI5V9ls+reG-DV2j8J* zN7Z$qZjw>w_#$@IwHn!&Y-CS2;+6^w4>1zrW<2|ZzmbOJ9@GsIUxeR)hLw1p0?+u; zE{41P{ym#Hyt}(dOp2H(HC;{FL`;g9Ui`%@x@JaSMLf z%`6oef6Yw?=w_3zw~q)^EFM(VEz_si7ynyKoJ%0T9{ShxA!9gO#n|jQ7qLax(?3Q1 zs(09*XYC7-wDwVFRzxclRn2zG35RxsTvs0l(~-B~m{e1&wf%L}tUo{o%kF5+pIp(E z&F5BoV8bkWc#njE462MF?MC|RBqsNFs)exoD}p98b)6q>@lPAduiIFFFn4`w0^@6# z@|V!P)2Qw-(JY;^8;P_Qg8^o{9k=y}21ToonV)9Fb%zwhyKs>s)BL%<{zGFp%sRcIUY|;Jnef)h5o}Ri;TEBch%NEkf=o_8rm$Z~6 z|I9`S(_?n4SG6UV^uM1&&}971S(|R=S6RO;3e9Yd|=HmJVyFHMIf@Q&4}vvH@Y_Xx` z#aX8YX2K+&VQ(`$!m-f<9E$9jVORAJyjU^1uuU7KGQ~Fpj2Bf8>6F~3Ml@NyoIi3s zc%yfze&bea+1Z7mrA>qHU5CSo;+$Zgt^`bhjW>4!AqXS%$IXZRjG}{w7%Z8c?|&it zg)+1EPVpVyvPfMD=6GxE)a+C+NaorY*Tv7HG!O8*VvJFOz6Ky4dMSxsQ{uw?(z_^jF*(3`!yx_yKj@GuQw>nF8)N*zrs z9j=LE{3R#)C;^j(;;Jl@%#FY^*-8$s8lDsiSX9NGgOpD;9v~`?JLiwWvVeJ^7OIj^r2P-;h7vAsN*PPmU4*We-!7Buua1 zMc!{)EoTM7#e7-|p{}s|h6*V$3rQ7Iw}g_spMM2aNC)Vs-_;eId%-k>_At^%&*33F z4mALl{%$o@XW_XWnd1&)>wt{hRRH`tRmrA9*-a9vu9SGcF6p7y=73SHVl}s*Rh|0d z(@NIMtO)USuT*djk;BvHx>n+O^xyj0lGqq~aI(hTkf&22&-1<*yabGEr5MG~0^)1i zVEF^ihkCdUdVqybQ6S<$()ydip@#KQC0PcxL!VWZ!%oFVK~VX>-%xE~w-HujB!h@k z=!F@&q#m0AI|~vuROPiw?IEYUTP7`*1kGC@T617w&?PtbkshY=6Am%G?Z4kw+G;&0 z)=p&G3ysrTGr)mK!Q2cHeeCb5@g@WSEsNF?ec$rX)W-u4ZWf8noC+Zs`SYY_h;1k36Ngx91Qi`FhlrCpx4T=$oGZna!( zuE=La^Z=VFS<)Dd%nP^C4lHEHP_xt0yHHw7BJ=T3)yBZz;Ou3dGEmvT;ew!y2S3af}c0teh*zCHY z&D(npk9_$f`xa|n$T(GxuZ3m?oBp?yuiQe=)s6TbibO<>SPdCI-7|7H`yLh{*@SZ@ zg{n*Y2J_Rc>2C*VEffA49>yT*1zF5nju2ediB$%l#f^4)pRkygH_D!29qe~w61xXg zfR&ytl?kK+fsJF#y)|e|hY|@i0yzgIwd#kHY;8DKhQF@`whZOPd z+?OLO0zMk6iiL9?IzE*OL5rzEh-!9!o`urCx5RzkTXjhR75EUu52FjG(A_{6{TZUd zk}xWZKqSF+9L-Dk$|NS8X<~2ij3Wefph=$G8weJ+288R$9Vxfl;t#0b?h`)cfLDK2 zSOKLkagBHFpf6UfcWqG%e+bWKg=>yVEV8d)B#0epY~x+^_)0z~|KpK#k;-52GU<>l z96bGvUT5hMtURWb*POX+NTke}^+@tV@22SicgXfCxs+YB;J*e5$O-OFXuqs6nMwDR z|JVP0z`Uj4OH-hv)H~=QX$^>~sFI`GdNBWkGG6q#X%vz``B#Jn1NUPX-SmPX2@sKp zH5WDd=fiNvgKfidb>Ne*f598)rRstBAz%@_wZg>4ne0p5*yYxzzY+0)9tIN%-A~^iHwrV0(BMp#Ich4>ZUx z-R%#3wVVY2%H6K&L|bQ33n72^6Vy;gF62N2BGbcyCyqp`BN37K5P8%N87mn{Jr% zNrDGzq2kVW^y!s+&6F-QJp)r^2@YR0k;L75 zNR=?mFEoT<95ZGrL|buuC)8x%qWfvw`BG6Y5ET~})+-u>`+nhIMv*+zO5D3l+8RzX z&BjP>nl5l#QH$T^zr~M|N6mqa51bJb+HI(ZU|hSn7%jM}wpB=(P2RE@uP5^jH)R3V z=C^df@MC1h$osEO`oj;8svw|IboE;in@zT76zwDpUZy{HtTFO5Jk_2BkCS>pfa-QI@Q@{{ zTY1B23Pd*UgDJ8o;sGcN#iU#bV&_JcIp`nf#+870@Otck9OqFJ4$yH@-9h{p#`SJ_ z*ZF7;4;wb__p)8INVU~8Xgra57C(NU4ncGzw|;{fmT-)%py*5zot(_bx7?5zlG8~M z2L?{%FI!}(a{dSUnB4>rAl~Hf)(jl_w#u9&CaJL}RZE9bz|EY#=e+q*-cP@|sh3*0 zS#8C#zJX3V-8fn!lDf(c?ItZ>FdPZc4F#@q<+a~Lk$%s>BzqYJ1Jq4l*lh)#jg5bj zK0ibWzGUcbG&FnugcxO$xrzr&XO>iuO0@2NWlULqZiwEjoTzEwklIhaYW!s(mhgM& zf4@roQ8x(el1~!NS()J+6cp1xx){;4j+Ux9hbHihk(ElJ1q|)W!>_kv%?KxtNfq@) zu1KO(Fk1m{=7qA8`wLKp3EEZjkIYvOv<3E!zHBZdNWuKv?^Fi+PkiFP+m?J*Qp{?U zEP`)DXODJ1gwp1qMAw{I9l#n&iWXnwl2a6^CJM!g{ZMOCelUB@DIWKL2*#ffDDYi> zaHp43eUr4?g;P5cge)LL-=2XaX*P8|8Aj09Lr_=TxQx{e!P1!vzjQyhj6b13pnO}F{Sh=?OAzs}Z@JSy*6t3SR|5%&K=jWq&j(1vQBzw& z1qMV%Y3N}ua~lp)mG`m&ygvmyBobTauxRa-<6Kv45~FvOc~s5Hvt*RR!J-w|niY+t z0_5nAgtFeuf-TMq+C897-x!<#8CqwkjJnV(w3+O?J<~me)m?5Sr)(l7i-RVH9TFXL za@0lk-Qxt=eEbE3eExAlcrtIlP+Vk9o$bQ7sc>L7qqSr@+EG!D@x|<6RGLYPW3C>% z%GWrXoPb@nZO8g{EHIEugu8x8zu`M@Idk^y=7mL|jY3Xp@`YR4NU9N;#3&PLwSHRvja7{RiNLE`(T zqx!%w_&U7J%`D1B9XIEHThM>1jHMXj1cPacFkk7Y@?%`&8-qqQ6B7BXv`G+f9cFsT zjdh@*hzYkFJa@+0^2dvI6BRw@+}Z`i)xc6#cIWa&Znb=@9S?_nBA>>(%v zotw4?iEHJezfwxrS87-2icEEm$o%r@Jk`h@W)5VeZ5wCL)QaXzGTA@=TYuJ^#^8CS zC9b4E5M=^AoB0WgeyS})LLx}BP;(hH&##AHd1bM0Z17&yb^iNGi}8nptOQWu!t}sw z*AraKfl$MPaBhGY6b4|O5P1Q3a^bCRYgvX`s`LG3#GP_6`wF z^eVJahO}hpowq@=JJ;umxLg)jUyM>u^p#y6C$`3FW9z(PRuQH{YJF z6rW^&e`8fwrC;$V_W22X=tnXoRyl&Oz(L z!c&CSeOZVx#i@i&mY<=_2FLuU9J=3qf<(b3X)~W4y~4lnFSf>ujL)v*t%>z8`zq$j zhjqA$S!D<+Fzz~_{NrS^@ux=s`yjoCYA+(&d?a<{lax_CU4!_Q4=ja#5cE0`33g zE~($&V%amRu&&&b{%a9YaK+;P)~WXnTzCP0uS-LJAQ=<&Bl7;+N5DUr!Ja;Q=xg)K z$W#_9ACYV5Zx}B{9P9v1hqs3>JIAZ4?`zyUFBJe3Xq~V`KBR{!kCE}8j7^tJP>FPOP~_&%-RDseeDgR-T|jv3M-9d#c}3b~jR?-zj9AGKbp}a( zZzc+_&MV0PX-0HqrW+vTITY`ZhO2c&Gs%t3{>JZpSl!ObY*+i1c}^tI{7- z!F?O5^xNv1LFOyBWOY6B>BY*$HAV1^kh^?{b@y#(22r=xMwyz;)s*y=*5RpoZU@;( z{1uL#A;*_|%g5b!kb(#|DKPqK-ue%R3O`_b2|6VDBsSor^?i)XC z$Pb(qJLrdHp#|e8c5r)*8ggY4m?-gxt3v;?mhl(Uc<$TDGq`r%p6~Jn@_sYJq32c@AbO3&n8X;=pc2PbIR3?l4~n}bto6PIzAd!}qxyYs z@oubPjq5*ymBu!849u_2l}O`pD0+acjw{+&M>p`)2PJX)DMnA477=!UDF24q>FRbk zhW>?w=6yt>UWV4zyfYi>)Uj%~I9}F~63O&)OFXhWS!{S7s^&aRg|q9oNb&NG4Y8tA zf8?K&04^S(p0WFiQxP))bFbW7CVrV`sB6-AC2A9Xj~fiD3)DWBQG@ zpfW)#cHLm~admz7*EGe1>3rJ+e)Grj2UJXJ+DsbJ8tIdhg4F9KP_7mk=6nFS^|E@t z<8eqQU6Xo57DfEjkZxV{AiP4odK3D^F;jTjsN(q{%F(Gk%^Z2wc_ugUREnNb5VObZ zP*m?8TLaL_6^p1EIYy5##SOM<9en;AK``;&Pzh63jO1C*L4Q0^Eotny9><3G@Y_R}!DrGMN@)}$ zQjyW+JSC!xbZ8gNgg;i=lpAi|6u>7k$M{JuhFdc!%9quQA7kVI_=T`|h<@7zJ8@M& z{$6rhT%)CY@zS{+oA+ba!yW^MKSuxkDy*y&HNU`3xBo$vc$-RM{=s*&oL1>=!1Hb8 z3DXe`zM*4!;8_DwpRnEPM@PE4zz2<5pn>j~B%dxjLLn+YQ)fdm$_t>-%@|0`o z#^p}N4^ChK$bCple1rW@3Du)~D~Ul%G_+~0okz>>7|ERWi4tIpg&uG%df4`PWm)&v znzT4#J&aWx`*$`J6>k#G?0XmGygkQd)w z@H=y;;DhK|y#hXVd)jsQvnZjnE-1e~NI{nIXi2g+ZO}Mr^W3sf?qW~YsCBVm07^n{V@dL2zE^@#s~q(zlxC5Tt>j_6E_>h~Xyf{D#qdDCbFsXAl}gey8mWu~7YGw( z(l4Wd&~mD7MNl+TqOX%6#LMx%n+x)7?{R(mlyn(uQM$|nA?2jVC zKSHIqSjK?Wd|2UZgQ%(_aq79B_>LU&0+ZC#6X@v4zWXT|J(z&r==7_jn?i%GNFU!Y zhaz)V{8P+jA!Aa96QbPcdo2LDe#7~9Y3W|4;ROS7>3+ZH+^n}r@L_Rr@yzlL5}7Fr zY}|M44ReBPX~j9gZ+Mc;qs01d>_@+YZ2^fG*X?#hTh=^O{cwT03D7>w-lhjAb`6WO zSL5|1M)*}Uf8pTu-jc2g!oJJjDR_>YzX9=J9dwX#v1cTUh0vD7ocQt%h$Uf>mWpnp z5bkuZj&uc!wkzbhe%o+zx%30}PS)Wjv#s8p*YxO8P!|6`DRNBI6Pmelljgth3L7%y zTGl*WGqBC&quvG-Uddf5&u3A~!{*H9+r{bvm42vI(pi?L9g5j%A)>6*!;J z9iS8%^2crKHTAk~N1Qi#*t|r2wrpV1c}8HDQb#6B7{I@Bci?X(+rm)`#7M$A6;D9^j!>nVjc=guSTYDaplF9Pd zGs#Dk(M&2yFD7ji?umyA1!%9E;NV|{>B4H!(HDYU?l2bQhy<5&c7i6hU7I>}Z8=Vx z{qT310c&;3n$N!x=F>L>O`Nw?Edp_+Rs~Jk5#dr($!o7pnO95=yUu!^*3Uh@*MuJ+ zL*VtPo^J^4^`h+1sruGX1FgRQ>HbqJ;fe>&@)sKtR-MnL)gp;b|L4G~E>`nLs6M`J;5K$U0=)fkAEPkJOInGA#J`g9KP;lr`nVl8FpALv&6*zy2VeJkoxdtAyZ|tuzI1$^ zr6!K5w}SK7rWJws3oaZic zo&AZ2{&?BB+z@Wb_R4^R0$#-5swniU#EX`|wPRTb&#ispxNcPaHF;!rgp?$<%TLa}B^P1Mm#T!@*9#?EmZKt;@ii`ie z!4$Pn9q(uha9(`6xqT{}iL1N%R#!o{u3cF-GgK>*DC{4bhWO;fh ze#=GIw=wJ4GkgaC=*>EEs(aH6&)0(g+9=HS2^1AKjS}QmYr=;1UXmH~Y~ggiexAOo z0|_al!Sa~qOfQfPR8YFW^GD{rcCM%jon-m_BDew)xl4|+Wk_02WN@@m@!@|OOKUKo zxYh~7pE4|>F1Yf5Y=#M%E(-k((TVc+OaKr-bV6|gdXQ7WaAHn*fsqWm`}iFz$R)30 z<`0;saG@|NJk;UP`q}@ThOpaaZ{BrP$Id%Q!`TM*Uc)epc(YGRHT;D*qey_#fGjzE zA!N}phZ9*JO?IzDs)WY!ORqhRENS`$Qc`8m1B*te`dN8;w#eZ#Pv*#=!^hiGXKlbK z(c!!qG?~7$1AQpKBC2B=y?;&JyZp8+WXvQHE<3~FVNDv}TzkJ@hL8T( zFk|thE@UfeUn_1>W5*dF4)e?Er+EBWP=KR##hb~nuq5nzl9;5)uxMK>9{|8U3{Q;v$#Uz=eBalz_EVu^+t%S4`VCL-*Jx`E!fa4& z4VULbucLahzu6o#Y6$43+_ND;gXOqit}VI)5uUo&qLOOg9n;>O%#0b z`4i1zz0Fqul*ekFK4e9z>b_=Qza)z0^D`nj^W3^nZe`OKvJV5d0*^bC4iojby2Vw2 zM9r-mo`uSk&(%j??m8mHErC%z)!b*?5jZ45HVx}tVt3xN#EuFptkCyR^76R8;tRDyB1TQ0JMjcl z+XnY_9Flweng44$YLXFk*KX0~f1u6g?HF&i3UBA)D5PYKR++%^L*dq^(2?De!V}<- zv6Q(SLW4neZhNfWw)vFwU9ezjVF9vWe5U-eY4oZvhq~<*zB5}cb*9!-cnKA07&Mx5 zXwC8g-h_Y;$I8`uyKC*1+w?G;Kc6Eo6RWTrG~@rTu+RxXqS_w;2$zYc%zaad>BfE1 z_HVMl)H9IOo5mY)Q()7Lcu@8J#K^p*F-zl}D^b+RQ^b{m1$#+0oBJAeO2hU$CyD#? zg!`?b_at}r0N@)gtPQm}0}ECRwtF%3&jbV>CQZ^E0=66Y=kcy-fDi;zFw*JZffD?U ztDylW(0MhUyn3i4tN`OW$#7>4VB@VTY0)$na5k!q zwUdrv<~OV_f1LdTz-Tp; zwpdL3C2br2xzB|Beo%Sx*08O!jWIekAmJzaM!s_Djg9=SHm(|JEA2CXJg+;DzECZ3 zb>9!sIFFS@TiK{ZW-xWR-hY>3@=;sz!C;nj`KNdpvT7G5d=jsx1{sc*>swkGCi?>< z9n0MNhE`RShjAsw`}UGT@gU&lDC+7b`ApB=WUfM%&kqPKqut=WG|Shbf*f0H1XvO` z!?3x7^&FTLWc9-C7qJ5xCWjo|7S!{m85iYX#$8qVvb3p z9;EXM9Ury#n-3UuB8qH&+ll_1H^^Oj8&P8SAuRO)1bX;gvzqs z$y>}W{l(q&@+;ze>y1XONMeVg4SM>6!+u1Y^T(g1+xK9J2ro8x3exI{ui^={3?5i& zL9dq+ocgaN1vN?sT79jENkWX6&FptCK07aF-90gR7cYVtsn=1-4);o zG1UVa5KZu84@8U-u#H!n+kASKD8YVw!4ix(&i;=4(Es%7{aB>@Iiee7EgiAT47?!Q z8cMN!Rjw>=)YZz08wCkPdqjHM+p@~9- zbgg=2#`do-rtv~WUi@FBBIJrvB5MIlkB)_8m#drX5y@mSs)(=q;F3WN!83V*76hK& zQ?JMMZnj;uO`++rKf>LUDAvCK*y!7sv~QUw_vxx*OHKbjzgNqb7ULdkNvwlf-B@VW zCu3ggTrxyO?>p6phQC^DksY2fHpXVQmj+pyWf|Bay8u;G?jdsS(7HWmQ*LHO9}_MT zR5TELzJ-hG;yst5&_Oguqrp#%1j*ix(H`N` z25$A=HH0nAz^<=6vNU8MG6ceD@2IJitfUDfO^B~OjXktgPp?!LYHdQIAWWjl8@^|7 z$gA*>Z)0za9bRwR;<*a=-I+H%i%hWy+X(uf*`BeWeUV#?Il@`or3L1WpD&a^-@5f8Hp@EQunkIsGIG2`tI8$&jmjgVNcu zu*q`D#m=SKNewR$n zoyeQak?7m)H-+0aF?i9;`hS<` zCPCNk7S~ou5i>8GX1c|E>+q%#%|Vj<`BV`@arRi27eAc4_{DxmsQ5zZy3Z{1tE@Q) zZ#4x%@i(aV(mvEqbTXDg&=4r0>0_z4W7A3Qr@a&)3@;YWcg!iQlGRQ0cLy~W=3L#yMLj5+ZYA3Owv9H)4pYw0Va0U zsoLMi?YxiYUxO#JIbQzsKW}l}4Gy;0o{v$pVs2z2q#Ogwz?->Ey72g^CPhu5&ovw2 zU1ST*ulbw!vIIVvg=)~zng?+=Q{U6P&24XeX9R>vSoDV7#6;grtof?soMmUzBRBSh znP`tJ_N^G0cy@*gas1iJjzZ?-&zd#Yn9cF5mRlBl2IwVl{0ZN9B8dIwb@emn-e!lz zW*Jq80W(z)@i%m7#Vz|y@CN*3b>kgiV2zD6vl)5l)5I)zvm_%Jcd5qjwZnZ}!C?() zJdi#pC?Zoum-CC)K|s`BHx<8w@S`Q$moJtDLPJBc0EQAD?0CNqX@?0vBJmJF0(Vuqfe_OPbE zT)1I=cRklhtMtL1u!UpXm4Hn)I+eSDx8W^?z65(*KTovG^!-!4CF_iG**ohOHs7dz zrr3N@*|>NKMFOnhYRNlX9AY~*-|$qGxZUQF#z^}!Ko;}T)vy4z87~a;onaCz#7Qeo zdB*?UM;#F;$R2ws;{qV-cUksl$bk3zR0>95g*_D96z=qt4^7Va-7fxc)m|+FGH)2JRJ5K2E6s3JOYy-ihR|*lmvB?U~Ac1vZI8Yi< zM@D?T$b-Ssx>DSHxDult2hlkp^^sf0cldwoy=Pby(bgtPk|>h11U%Jdn*2 zg+6MEnT^j%c<~upJNL=Z-C=^6E7&=F6esfHK{#931Bv5W3{(ec1pIzBv(oTFI~MbR zp7^fc@jcA~*TpEF?~uYN$N*S1+e=!uz;*4r&rP`PFVRXoe-%T<*$8iAzV0cAnhLkTx0#Nf5{oY&S^-Oou@iDh7^VN=@b zAqsJo=v<%$6NOk|W{=MtZfeDHxPA}N-mfhcck$DEE#KPcf|;eiE1XbYkTS!}_>%vl zw9#ZeEyFqT1_$f>rR(=eX0G4#l$nJlu$&hJ+`Ib^hJM#C?}AI49*5^RjCqUVQ!b5O znG)?C{9~@$Ws^%QteUKRYeg-OXA>4k>>OcnE)UoL;Nvg2TR)|=*Yw(QY`P~&x6P&+ z#Y^e*vrjgg@cEv-GB&D(4xcKIL_r4=v2}n_G1U1 z*O%+rO7m=r+ODkv-0x!EmT(Y_TjYdvMJoAz<~9Dn;r6T8{$8E=@ zPIK_Aj+m&oE=C$d)t5`>_$&;%Cx#XV8+`-lAD2>arN^(2q0jOpGsnjXMF0&Ds0M7L z%DWXs{qpj3=rN8y={+$dq7QfEYnW-PXcX1MTEMPkaJt#?KfYr*D#qeM(DM0B8 zGi!Ri_l-UaR*SlFP5`K19=#oQT=L@Tp%@ibAIMlv*nEg(60M#>pWAaD#s*S?_J20V zQkCEx(oNgvBuptX{{V}r4;>z>PlbBPi3{q#PJ7SWlH20GIPv_Q&bQ!;!#TU(&H7`{ zq*m{)9TZofx`QsotBM1%oa+UJnSsp4?^RhS(~@t|(4-Vn&PD@?hG7Z2fcOy$7-`@WOzNWGTx%tIB{srFfhquo%VkiTLqS-Nh5=+-iCW zuf33@K_mgt{tQA6{}Lp9~%{h z3mgg?dl9)9nOitnz4uP>Sl*O_gOw}_e0i}Cw*<$2J&H6Ils5hPT^KGBJ6FfK<(lG) zit+unS-FN@KiE2k-eZo#z`% z8SJy@-`G9M>2%$fq-G|T-WU^mw){3#GV`iFVU*KI({8*k{QGl9NE|-u4ZHfsRt~3+ zZL66FdqkEP`IZxt`FO)~K6l=iw(gD^Cv zZSLEu8Ht}i_^Oxa@m-ISmES4hdw>Zv%|n?sDOor8+m~vNOV>D*7|q>NLq1qIyFZI} z9$}+wv%e$VbmF2kY89ip9qS{I@bj|7E)4mm;{1o$+4hZ%#KRx#c ztK$}Tq?pv=EB8N{CdVi$6tRdkXsqywu4E7okQWIQzlU~la(%h*Yl}iqcdFbc#$RLa zj`y~)Jyx+FBT>`DY{n?`_83ZxI%hy2T?5cPM75MY`5UCa_Uwy9Gx=Vmv0dD-h06odk2SlU0{X@&K$wub(+|I}7YljhHIK_PVi1eMN}Hz~LAv~CnHSFhqpJj?C$ z$AR;K0q&=sb(+ztCkwcVxN=EbTU>4NRO~2j%fl_UE~4ElU<3V~tmYe4j&nl?HP$Uy z-XeS8Wr%%G_fv~~YZz7RL!L3n>e}n%h0wkzR?LvYOzEd5yV(6{I+JDVQsu>1dCNK(pWf-EZ1S!zP zKo&zE723${VNrD587(z$K5Xr=z8c7w0MB~x&$G5cc%fClqS_tUfrF#Z(3qj|QX>T;>Kp0rqm}wkKEGLG8SR)tMHZ|pF}{CO2k-)n12Hqi1V!@Q zi%5fCoxAt;Ad;n)ah8-0D!_>@UB`>PN!jFb<;#Y5^WnuOcS+6U|)vC5E z%EuvZr-&g#l9FF&RyknE0CRTbp4_e?Pwda{GY>mcvVmMYOhg)Idy8#^%-+==F=n8| zR+-g*(E>O^S>A0MP`D@wUsI6K30F>@O)o0KQRqwHjrt{g{5=|DlY0i;CR0NtJ_YC6 zYoVN~e8xaP@f58cJ$vO{aGGc4nHx$y(U5isE`FxWC(~*-k_HKYbpH9Rw@9Yn%1dk?8U zN@+x2QO#3#F{iAaWn{?AiJT`uP|pjwsP|z9fR4k8bSEOI;wS;p)Y%Kcvkw=_*UZ>4aC#W1@vHH<6sx&`8|C0{cHV{pyVM6~{()>c93zny{mHW(_T& z`DaD9@h!eh{r498O)e!Gc~Uf`JPiA=F2DqK4fZn){3J*l$8A0qANA*&OHH#6Cs&54 zkiCc`a7$LR3$WRT%=NjTj6ZCO=@VurC$4p6CFCSXS3JE0Mf_fM?%p)B?m&cM@0@NP*29D2Mu`!#B7L-yX!p|8;D}p zTG=V4WXa$ZE>7+!hCPlI!H2dxq`B5RlvH7$v@7K#-_7m_+=;Eo2$4#^5_zNvyrB>8 zT8xx*W_vpb`1l?Q@&5g#YF_Kr9f^uI6a3P65iarIhS6^?H^!w_v4|(yp8z~=@6ql` zuJclNRiUF87<|P(2i62m2FK2)%A^xp+e(`lp4e(nlzgNd%C;*B?iBMru07{oZv)U% zTB6uki!-O%R`RTh6Uk|>zEzdD7&V!`%Ruq6J4)GO@a_T_8`m{|iwjD0I zovuxN$2QV39$odCw{+O&-9V zb0trZKSM<06r{t?jt+J`W4c9%a?+f9+rYYDkYYfl^ z(P;~l*hwp(e2FTq%vP~l&n+77e$Go)69>w7hknZh&(|Ejy3}TbGdt;3WigtJv0(P5 zkbTHO@*IW{(PTq?a~UZHN|kX5G3N%NNz_cH2!~Tgb*t4%<1 znDP}rPD<@2S;?G}Jkj`#p_2C{NlEkjV+bLg{^#ZVoYo)2U$%&)K+H@OM)!9RSP%91 zQXZHbIsWm)+Ki5x51xQOqHy~>#^Uk`*$fl$BX=)r>*YP^mt}PJDUfmPLvt}tkA55{ zYNziXn-nJpqiaWny9Jc)#xEQ|!zSlD74b(lpMD4-95s9xf0F@G5E-j9Tn%K#AZpj^=#QSwJ8oXqOHhp z3U5eDR;g)}ub;N-+z^v)DdFGQ)m3P{Ugf1pH8R;$7&yzs^8(pb@h#eW>a;@{pG`dY zg}7fPUgV#-9?KWv1{xT>EDZo_{f$R|r0ngn^k$0uvg7pQ9dE=;qpbLTB8I$&Ro@8{ zk;zHnYx#7gf)eAl4i)@eF*a#Y6*l8+ZsXql3+o%Y($QU0g-trxJs$HU7^?+#e-jcG z1{8-95}%XaUAyy)aFV71L%w|H5bod*{liKsb|313Vx4+MU&9`{Tyw{YSyxjhs*#S2HKAAvsQCwMV)r&13a8sH8#tLr=FT++V*3k{NR&KHaFMREO z^M}L)W)>~AFp7YPE`8~BL4NYIQIACq;XV-`JLOQv-zOM66;sMSSv_Snh1rOV(8d!} z4m0@&q_Ia`L|Of{eyDg$SrYx9e^QCd>THYf;JdOoluB#;K8QjCgIC%{jQ7rhSD|v+ zI+PAI! zvTB5SyZJnB$85$!tKFG}l5zBS0S1<-e8?#ky`5ui!Fy5^bddG(9-_N3Th8lRWTqY? zL0?NOKa5G#V(Zcu8l`tAg#G(kLGq5Vg%8LFf9GU{@ zc@uEeef8QLqe3TACCvN`PxZ;`yq#D@2HC{wIPVcrYbFe4zxYx?N&RteG(m6g;r8 zVaq`6|T?=JTkIY@CUH>HmJw7DLIYbg~bLS*g(lFz4?!; zMrfQ6MzaVC<3+Qazyi#d1wv~hjgdGx3A1q1g zPmwGon^ER3iT*4kHF?nTbsPFuzQq0g&ZL#gpOLS<@e%gza*cYEmBcS$2S-t+Ev~Gg z=rz%aY|O%J%y{CmNw4bYA`_|(XniP}HC6mffoZY59}O<)OfrDp(ptoux?rl!oxYGwr=h>z-P*7UG`nfM-czcb({00 z&@TdI*Bj`o;+lUD~pMCpd7uH_w^@K(T)F9!>L zDBB|Ttn{0Vj|PI{(fC%~&L@!{Pae5cHpSmPAWko#fu_;EeRK;S#$Ajgk+V=srY8=c z5-ulfThU8Misc&5OK9_CV%scZo}G+kS1DH6CyBI}$i(^v5yFFo_oIblG$n$RNL#4{ zo_b&lOJu(!pafyF9>mWZ;v8pN;^_!$G3#u#vLk!ePsk_wKju6_c$@n(<)IBN(qWCc z;jf&C=O}nv6vrg>|72FWU)6RN+oUEuO9j6DVii^mK3|KqYt7nNFrwKfzf%#gXKS{9 zJP=Re`SX{;nSvxM>^4~mm8H&EdSeeYO8EGvjHv!H@VP<<8g_FBXV>{h#_#s1y`@lW zMD90s^?X^+kIj^QJw9I>o_spAqi38Oc^TF82+dtcBaK_K)&!CPlb1cdfUtY-=xidM zt}%2eJMq1y!_ts}_nh`|7>yV=6iM)laTwtg{Nhrs_U68`?_)ThzXm3PUcyOH5mq2< zjzw0c;>ee4Am_y783lG4;+DNg-Y{vukHx_=aBItOtbMdcl;3k6%&?mrm26yZi^Uv5 zu9nVNcJE;#Ufw%|p^~LQF6E4(`({8U<=_2Y2Uij!DgueAX5*PYIZUps*i?E)|FBFS zQ^mId-GLWd#)>QDOKN|L0~n+nlXkdTxO!h5V?NVql>7XKGzHSJ=i zKpky;^cZbtm_jjRZjEIZl)u!fhir`=^Kn5R0@XJOLca|(i?i43UgUn)3R@vdAm!|J zDrw*gQN~2b`ai}k*t|APc@@uqt^+`AXTAX2|wdk^VR1p6{Hg zXwsrnP6jd`)Z}5+;UJIxMY)=r(`>~Zt){f3KgaTb1_Y2!`|0?bbamud_^5k?8J^y# zu3~wxH42Nk{BvqjeF0RUR$Ga1cA4pfk8MEREUgUDL53qMhWXIek7Irrr(1OfCk`fq z#qe43M)_FYltk)Dd8yHi+5cU zve{0c;*axaHp2D6ccI3ATXZoNTO52aS1h#}EcX6@&njb-&OiP#_8hyeptpMd`dXV+ zJ&sqW=OkP0X_d;LTi|(dD8lh< z^7`+IHF5OGjl?R~glcT2P8cB8UmNz&-mH&c)_uW0(Fik1)G4j6eR;!u{oz|Y>7N6IcuZROwx_7sq8LLA z2~O4_D)@WDrR17P07nczYc41}sE?R=g6_RN&Idwopv|KbTPiG{Y-;M4?rMu~k+c=} z$!fA}qQ4C@=ecTTOJ?#JM1}3%OBrF_fC%dZcR9Q%72z9p-1?f?^k@yINu&1!04tJ7 z9t*y-c&C&j^}h7>Y8u+?y49}TkOdKT_xCHS7QnHadcc-!Nqdj5B6LtLaV_w&6 z5_obs+-Zvs|Ff_-^p}!SN1779;9@D+R*xw&pMKo$OdaV2$YgS?rQp6v_^<9bL}pZG(`oy|lR-552MwETY}o8^)|RtaEvkG#B1$K8p> zu#o+_{pLa1PcgLphVVaQI{fDu_ap^Z5HMZ@|9Pvv(k^g?n;G2n;p70tzdj1|-&TQ0 zwRai#Q#8B@$5i-J8}CK8n}f;L^065QqE`ciUTg>ToH5(AFL$DknL~gqFI|hCGwvG& ztQm7jbM~)x28v9#5fGm@+fSwpjUPL}X%f`b12A2wi@avj zeBN%Ph#e~j5bCBp+@|$jJZxWE3=~ToKQ=_}uXM*6d2!yGd{e1x5dvn1aXA9r6mB>K zXuq>@k|!!g+BXz+->ruxD68?+I)uy`+bLXrt>cgK%H-Rw;Vym>0_cSm?Z_fSndEFl z#HZSQ0@j)Kig7Gab2UbUDd#nRRPTp-+&82#4`#)=;4V#eNfvcirqj~Ef2wi#=Ch+B zCSna-6RE{v$V*IdU&Fvq4v}yqKQ+cgj86G&YV3C524*aFf1)ZOc@qqjaD7sG^F;u^ z9;A3y3sm5pen9c>u zNVCkV;w~(|LNe{m?Br>xHWpTK2;cY*DVl%@cc~d^ZFTbpheQW!%&%s2bv`$nkmpOd z+uk;gM;cxG;|ZR)Ig=YZYuMAro-$ z#h^-nNe5g0&Ta=_AX^M>5rJ6a8$ROC*Hsa@^EWNCOg5p>jUm~ij^A!*9tk%E5HuZ) z8C>nJP98KWFMV&Shur(1hY`w!w-m^5I|*PGV`AMTR8k{#xj9>o8I(5 zn3}3C{Yv=OL#u4L(1hNc*F7(P4mdRVux|6Km&hjOXD^A@ zQInKfui=QB>{Nx~j_5K_Xu!1u%9G}lk?#rOKZiwn-&mA5k6wbUVwgc(&CI7TU$1+61K?spf zBZ8nY5qFBE`r`=)&9uq|)z4e%5{nB83mW2*M>?Jx8bX!vzxh902`cvf=Kd^1uNYaf zK9v6QDa8*%n`6_kh#%TvX5wMEj|P*uJ94<*HH@sZW8A3)#>6I-rhV*<-H*C%wH)r$ zq~0e?#xtH#!JmTqoNzwyi&YFmtGJ|mm2I)pEgliI$0RgZeLFxN@%aCdb-6wgPv0tl zui)>ih2?-UUQ_D4i0iZh?A7gN(1-@xp|d;xojdD5>NL-iJz!D|3&p_MU9JLe=&bYq zw!IkRlLH2EL;{1hm*}(S&^O)gpm7jP-)|W7I8;(an^t+%|KD)(|0+X8;`0kDz}>1b zSKov-(yD0llRe-K3ch=Db_<7p+=!E{EDI^ZG?zpZWG^Gz_2#SpSl-uc7fkp^hcio> z_x&9(@+JbTaXA0gF!*0(;s5sW`u`jH-+4~{2O_`@EaA93jkILPPfzrv__nRJxwuf6 zN1O}&du8<6CHZMM#qyOQYldk13LBa&J=N_Yboi!bYc)zltlZ$<~1l~ zm>9-+aygw=jo-u0Pj&4RV|U&8YG3JQl)8}#^@i@DQ$_$CeWmhEalTt8*(|N|qud$a z5miI{#PSfAhde!l8iK4COpYanD}{LBOQ7gSbSI@~q0FlXW}UwAFA6zZz36v;qTQA) z;wk8NGyTq09T=&bz8stJe^v@J!g@idMpUYplEi2)NZA<7>5tNJD1jdu z#Dm;5;&Tnmz!pbgqtl8s)`{z33yqKT8B_jvY3Wran1Np*hY3v&h^$p_r#D!q=8b#p z1kWyDQbtwx#q5$M+eU?K$H8LHLbuEf-KT_v8u;4ah^S2)t?Omr&IJOA7gokLaE6nRNCZ17} zQ4dSRuh;vr3q;~0?c=kix#1s^$c*m`iIXTRqh@OKZNI!TYtC|#7f8&e)jgw9M*LFP(`yaHc>Xc>eAS*=ubVu?SC`OtoAnwQ>KBvxR`KHpA z<{pG-OO(#ktRLLC%XWs<7QK6$uF7LX)I`2ba^HH4UrP~uT|OuQ6z3$AT&gJywm$YJtU-g;R6@9QdGCo+j0cHaAd8)}C= ze=__JfkUymZy4pTn=MOfGS920$_i_>$X#q*3fHBq)DN@DFu~{@R+Y)|4-&|?I**x% z&)Y)F-wNfD4~9I({_Q+_zen{;YEBG?e%VJ7M@7_qABitzo9a)M(|C24V#P~($Vb;q zGmvqPj~{R*+`h)0nS5lJF7PCDK%C=WP4GAUk2Vqatki%uPe8!5?XKig`%%oq;U8g$ z5?L~ahQG}ERXDHW>XKtgI}fH+S;~K0PdkH7P4M5Z7mGt-nV7~bN~}?-;>r9y41qab z+t5jmbxxx3^?p^jc@f>I4L+%vh?&a2EY_yk*Z-HrRvS>I4HTLBOxAHjx(Ub->G9S} z<uXb<%syk|KvEF zaSXf1BXQ`9IObGqvo`onH(@;O2K@w^UiBp*SWJja!aVU*rDJgaX&@ z09m)Pj>cz{$fDaH27_c zC(hO@?npQ#M4jxC{fj5*D88IXEG?OLAEujuNagynl_NUezgp_i?xA0{&m%0Xp%X+ zY-e&%By^$8+5UYLm!}C;YscFMk2htFtmTfunogR+-8O51OOM6NeGdHZ)s-KGYhoKd z21TPFcZkp92;LEi%e*J6qt+i`>T3ZN!L1Uh1z5HPoJwyf4J`Ae9Nn@)0M`ReqhBeZ zd#;-7?ySGBx`j7drnMwOZq2zp*AsBTVpbI>L2VaDT;dd*T?q;a6YU7xz;%6{;=b1R z+X?G;cH^ht;(@QzZW|VQ?D$h}VJyLuh&bFp{Cd+k4h_$@>dBJJZ?eParxYP>NPk1M zP2y-=#G+fbs!X+Icg%Lmr=z&A_to8&oY@AJ#uHHlsmjC_v>exBWbhJ@y?k^O#x{?XHYZTmOx3;@3|UAn#F%_oct^1blXh*Cu`FjNZWaC z$fp0x=x3hN#QjfUi#z^5hT8u-P3*Mm@fx+$R6HH@&x<mPOjPeFCf ztgk9|s@}4L9~=~@S)A!ZWE_1&&}QUvgB%8wiB%>>=liAPf12=nv!BqKsX_hs=a`4d z{XLHypN5{0Y#U z!a~lVBlhRLxMR@=H#@OqcL_$Rh;c>DAP2h|=)h{6U;)KxafA_WQy^N|(qJ{YT6)GWrK{-*OO=5;y;FAjY%l-Dwa{nh&ET`iVT# z2lXs`ZKpEXnEu_za8^>ae^59hn_h!F2R@tqR5QBu+Snl$qorr6KKq1y2Ts!`S{Q%qu;pj~wLK6H-1Gv{Q3`3+YB z2FeA03JAYgb(Y4P{0kvHpW!R=ka;3N$6$JmR`NcSm{Y30d3N6K6eckF(CspY%Z@OT z88>--fodI3qLqV?^>O#C+@H_1Vtz;ab}L;0pb!&m0PXfnzeLjcD9=94(c>IZYzz37(H?-hnyve zjYrd%IoM4UI12S#Te0?07keTcN%M}0d=}9wAthfx2Db-ys|%}1L;A*XutQ7H`8kKi z(Ov!?vreBAc}_Yq*_s~!$O6U)rBa0nC#OZRS@Ae>WJDEV@I??}5%4?{sJ1A5%TXHX zLrz4hxTiX(rr)crsK`OktMrDAksLpq<1x+a=Xysye=DQ;t=z&tEtz?BXwE-7Iy^Wy z7&|&R>H?1P+udO^8D z=7dd27^1e-l*2i!qwY0mNEr4lC_iwlaQzGW8_R8Btez z^0^w?cOMyjYWAsqQ>g0?R)BBbEhH7lN`XP_e9oyhhK8VJdW1uFjX?$+Ezu2{rYd4( z15#Mgo_Pp}7jfRpC$GOnCsG(LA;rWQ$XI-5S9ykqw zU#uV5DKbs>VTm6Kz*dEil9}ImXj$bOb8AsgqczgG*3?n+RBfokdO!f^mj}Fn9khGH z?PN=~xq0Um^NQ4UaeGIFKTx})#f{#4t|}8P5T*avr$pU+?+6EH1cjm@MW1l1;+KY| zWtIKd$}I4dh_;ewjUE7?GWjx*zPX1!G?+kG^qhL<2ApJ6GZx}vB3Br`2%^y4 zo9l_opx$|3iYK&JV|%BUbbWE?J)UcC__VVU&;0K4Eq8EG zjY0K(|17}RjjAg2jR^v!c5S3#!Jo80g4&uH@>I&~?DucR8UFs>OFwv-6~2V#Bd#$J z7jmj+|G6rM{(#C{Ww>8P`~C*Kv2&KRH+|A7RHV2{Jehv|!uoyMOt`u0r)q&^xNV+T z1L7w2x1Z;Jam581oeeDjf<9kgzDb9}+2h>VlGg6Sn`6OdL$=$L??VRj9!?{qz3oKG7 zgTv;`_un2FUdydl=DV5XJduIn&{4>R7u`D_PM|8qM$tIm-<4+&OxuAjj=}XKvE^lz zv`V0J#flAuAG>}77js~&qew6U8bY`DJxYcN&KGiU9K;xsTOTvQT*c7zFM>x#5V0$z ziE`-E>rpu5yIh>FGO>yZWw?^>Qxz6+?P5!XcHXM!sYoVRlHvpk-ev+cN_u)yIBm}9 zwC*88DE{V9yAARaT^>Ms7)>7+$AcApkQ1l)<|A80 zMgV&2W{zxo)kiw|{GgX6xm*A7PUpl2wck-+J?kD^w4xyFszSP`gn{%ZE72huHED4965akQDsgN$@2B4K0eJR-A)#B=8 zZk?=lo&XPmMM9$*yfwofXv^%Ww0|37V9mXNip}$p1|Vb4=1H=i!Xzgn_(gCoAL!$Uv?7CloFSM@-+g>MTw>qHZ!CUwLo#gXJqzg* z`;+qH&IitYVb2o#WsZ{au2%LRhnp~^cx9HKb7$QcU$SHEf~|&1S}`;jo!+}I;G39e zjTmaPyc}3#lKw)?wf0@>R67D2#Ue9hdJ`-{%ZFU@PG6dD+Np0mOf|DuOr3pl2EjoU zFRu2S3I8=teCpn1Y+^fYU9dGUD2j6hS!wcz&D=t}y5C@uudA#-f|(}a;H)32NQ%b2 zarr`!&9%8vO={T~ckjHqFCzM^8@oH$ZTbOkzt!L!UQ(gcBEwvPa`{($%08G?@H7Tq zXrfjZP9Nv!RS2}UHtjw3qgluW)zCLDarDtAKtak9>3`GmI}8(hsmCJ>%E;X)?uUfO zXw!qWp{E-kzH)0G$NltbE_~zCYbF#DtPE#mB^4TXg-?)7vi@<5y@VvL0u9{=!Xb;o zVDeWLnTE6PB-rm=9EBYgr)meIH;RD_$-4HHK({}?dR0xCP3Be*lc(9*w>z=g!;FBX zKTTPm(dY(LTxUu{c79a=ZaoIjO+!7GZJQ}lSPS<(KCoSm_!|y%-qFo}5BqJ>h+cQ+ zkcpjd@uBt~nLUx;r+Q*~1W-JpQ?D+y;3)qNvf+%Uj_q zNR{92upIjAdh!h3F{E8zG-ZEF6Ux4MD-08Q5!2Vrr9U6K3%D!q(|F?t?)`R>v8!9SNc<89XAJkyGlq5vt$-^`;m5!Dv9qC}9k+X` zG+(YwD{lFY-ouxoFFX#3wxWAd?n~2q0iy-G7FVmF`$k>isLKy?y=dmMNajxLd(tfD z_uu0BP0CX&$C0rwEd`vF12=txGzvg~a{A{bz^)FjmD1;XF9LG$(po2{eS{jHrW<&k z$4kab&a_9lA-~PtI2d(Nd;U0VVm(U%!^wfs48PY_TJGee^ zpW~!>I8TFri41v6AB2AHQL>Y219N)sv%rwp5VPda=nnpGN*s3boq*>Ryf^8;RQgW^q93DoN3M}) z>8kea%U+tXuCSne$f*13N%2MTg)p_|A#*(qv8Zw!zN9TM^GEd-k9sr_p z7b>l}eA{uoM#fVTWeWo$mGOT!;&bzzHs=#H{e0+M33;K5P>~&ys_=1rFg-=ziLa)( z>+%FPN;qLho5JMsU|NR(JjOB_i(4o80gaNQEHoO-A=~QZ5+iOcO|-y?nyCB$M(Y6P z*P@nqF?6~CNL}n_e8Uc-Q>r3ZO7{AHgLC!{v<+fKQD-SaJsA1Sj^0U`rWZeW_mG59 z8C(G87Z#q>JahBEnO5>>!Ag?|~!_yhe%(@ef|zb2uuNv*8#Gd)2OYyAbx;R|Az zhmu9p00LyZN(-(Sm7NlP+4y-pFZmTYiETnc%4e^)fYog-Ut6gpRP?VQq-^=Wc{aeL zJINCII%0QP+9mecmPV1OOH;Hd40W+Zw{|wE?d9HeQhE1I3S89smrckosg`eClJ%fJ zWn6A6Vg{Y^B*{SE|Cj!F_x2pvvoF|l`*_s(5%>;=!P>uY<^LLtS3LsJtiHlM_&YWM z+s8}h(D`Yz;4hq&DK2@tdC6-t5vLyU4)-knzK0w>9r+q{ve? z+VDDf%(zeJl9;os-V&@MoWN$s;yw8MgAMmqrW1YXd*bzrIdVILM%(P54|PSX>-Q zC+DC)QgtvmqW+>BQKw(ckU!SWHZR#$?1;MIRekP$um_qf^&p=#h0e-cA=WQna!BidiOND!ORm%;#<{ zoHW0%*>04VyzXcntJdyl*2R3Q`|EUo8}<7w=(drjrKqiwh9Q0<50R-k(`CoA>2kfl z2PoTkh`6-~Zc%7hzAq*x< zHOFQ&DEI60zwtERy9tNcPA+_f(WF9lw0qm7KjIO7RS==X~U58=i)s(697 zA3SA@bv8PmMjdTw z@2k61jpx5!HiGxUmC2{C*;&@8YAo%kH?kx7>}`uC6llGlUdLDc(p1Cn`AV6<%h74@ zhx8|zHJoO;^Pn4~c{jcDD|Hu4Ts1lp`lxN!1~gcU7sZpm+uhi@YIG_EfQQO8qQO~T z{7F7Y6Ui#)&#>2}*2;VS&np-M|Ffsvu6>8sr3apSnEAhBE6A0#E*!XsFQ}s}!qRb< zK$CoqSLioMu+7_tSCU<$WbuNSJ6&qI9duOQ^YjO; z<@|)E8POEn|1|c~dMf;cL z(dk@Nr{FWd<2nliPaCow;-B{9(I|jd;uvMxXv?e1%E?4Fbn1XncKTnV+5Vl2@X+2mC<37b3(DA?ZoJISi&z|h|L9wo;I+9kuK3F|EDQg@^y=oUPH ziroDM-1nI}=?K;N(t)Bmr7jmaZ?5~wh|}~7nQ3vmLW>Swdw@Vfvd{K?e`nl#$2ezDS>YV4xfXs=iF=5d>P0m_k_EAZ>XI%KTIAy0J{UzhGZ3lSJ- zFFIR?B8$gqDb`en$IUNk2YNlI1wj4!nHe8~Z5aHK+h%X&%n$2=9sKd;DjqlW8w}+4 zYVVBJs)?-}F{#-w-`G#W3r9hq30W2^CG1?UI088H`YRwh%0wwRNY1h}wo3A_{(P z!sN9#=xFeLAIRmPLV-QNy&gw zWZ`OOT6gJS-aTjbtatE$YqKU#k2>hP8a+hU9&@+{GIPgffs<;6hVjrVoxvsV8`Ep8 zKi8lyr@GAzf70u)aKfH)DR%l=IrKmOvD63gBpVV56}7E`gki-g=T_PO(T!)zIt z$4OP!?%?V7klheDGf8<@m6{JJKb@);qybpPe%AXg(|XJmzk?z^n3i6In2RJch6Xk8K9T z&MzO{(2mL8O}#^+s~p5XG0%0#7f<$bz6iL1FAff|}Zi&bjB#3P-Dsq?;Xc(4GQLAVvL~G}_ZFmK6WBDqZ7F6lDqj;drkbY+Y3joLd4k*;kEd{ zgm>y=a4?(8NIbR$E(xSQ96vAnwS=kdC3B8uOXVQny}S;!SbNf(Lv$l6D-gWcdq0@E zL39aweHaYGP5AReV%SfAx-A~We;Q6w%vq^G+~r>DZ>Go#8z2>KqoK3XJh$IeY$F)5 z+fZRq>j^`^+MuxmIT0^v2MD`uo^B1M@85suvN}DGsx;HV!bgvXnvJN+_JI3Wty1uJ zS9Bwqd2oF06Jcl(6lVvx>=!Qfp}`V#rv^t*MUEkJ{;;jfPU6;jk!nmO^%ekk^ zj;|Z6mI}0$wbhrGXF4a2kGae=_(|Y`JII|Pbl}Qd=E-M>_4vNDA6m*RV;a-E^ zA0B}pVTV{pa-vP*uW>E`;SZ*(IQ}6kn7)m8&L6r1=M^iiNy;~!zf4*)jZ~gR{*TYEfkOBjs7L8qV(>9@WPyvL4cpkZ8jg18v*9{RGnva1@R7Bc0gtP1$ zn-Kl{tWo&kO5CUTmXKtD0kNi1cLce&m5aX-#ib(ui$PUiN6W&u|6IHk^Hht?B!^13 zE%PgA5Z#gmtwG+KYR_M!F}(Oc*K+@d4v7EP|CWm#wMGiAKiUm13!G%$_81rjEIWz) z32%UtdWHOo(MZb`$$p?VjPa0^&n((PWAs9RN47J&?RS?{YddeCAvWopcw^|b*QzE# z^s=POpJUw>w;VIA^*ggEh$+vhyUAk@H0j~XoTsV1X_B_kk;^}pruvVa(;(@xRk>C` z#_G-L;#F*mz*8&qvFpxstAX46sa^RWUEwwO6x6KeGOi@C?yD7V^bwR=U;t-`hS>m1 zt0>oS`7>t02@-WBt2{&b=p@8ZDd>WW^{?WZS5_}ZUB=+6JJsgA7MrbpJ}sJ{+k-r? zx+u>ELSov2-Ehq|R9Vs0c0?=_g9)+yG|ucT3;s?&RAvCX$v^A0pEcnD#_NH7pCG6N zX@taH&J=0ZQE08l?@YgbQIQ6(f}Ov3cj{=pSuDUeefF0if8aH=Z)iNr9uaoGZkWnw zeqBx0qTnX%vpVPUdAC?9|Ly*R^nyI!Ux=#>e}gq~+u`H1#_Dq5Jz`UEL8ZfQyU<(gUuk60}keAJn@w!t2Bw zo5WdGAh35W{Mt6|)c4Jai>|XjW)a$_iTwv9jzr!%n`z(jAw?-`@Eml@@V=QrY~?AG zw6kwF{kc}9{sT*W+|e!$5-xqFD&^4ZXBxvX)U8iAT~IDr-?GWFC6v4OP$W|nhD1yi zZgd|P3K81<_?4dDmPwIrJGZ*eahT%q{@Dz8EZYvh%2w`Bfwqz_A@&|io#~0=E;Iee z>%`t?ce;f^$n+4+Wf&tjC(>)B2e8Vm8U_xzyfr`B@WBSJ7}Y(A%@`rWD-mr3d%jIE z8J|6SmQmHWVxoG?$wEil+5?$a+)r^#k_lswm;PZ!Vd7bSdlV`X%o0o|s@5eJzV8CL z4gUm0@4W7LdyrE7Ll)Y8C;s59`#Af~ZHsq)9mi4_!~t>aZ1N`+c9*H%TZDjtNPvhu zZbxo8ukA2lmA*a6q~0G+ez{W8@|TW!GH^n-tA4+nH2AHE|1WOD@%ZPj#I+1Mk)KTu z@I$n>iIE<1BJzh`Y6=t^&t#5fR(~HtlPP|OJgZ<*oZ*)!BipRA{3`F7y% zMxT}r7T-wH6XfM(v;JhEx=05F@Qk4AyPu5@Hx6pHyb=b8V8Zi$0q<%LPV(Xr`;_=d zq9u};9dCU`sx-ktCLQ|BlXLZ$+9Rmw*&F>pr(s-L%G~2E->qLH6e!H`YOLrB}8_QpZ!}q>Z^EOx%9ufK!EwY3aAyj;d?^Ks}pC0CMxNqZDm(px>=ck*R_@B-6S zb=5*uUgKkk;r%p6m`@Hp&4kOwv>LbK$yri&=88OEz}}An;rV2t`O~4MQ+jY;E&`+# z*UvcWari{665xN?72rps$Pxji*Y4bj1DFUzXe9(ktr2{}#Y;|RK4iIYF_n`wwBzq_ zDg2CJta3tZEOa?q3sZ`(adA0Ib2O0lOIFW}#lweZqfrQcCCadudJ;tYgjy1aTFT6I ztq0SHy`7(Lj4G_FbV=HyW=p~?xt!Be8TDHUwe%xnP3feJp(H+6N%oM)2{(OI@UqD_ zr{WvpKuw_LIWRf&>HafU#TmY=wGzeW??p>ccQ zv8D#046ziPK0RPtLFbb1d|1mt(_PdIB=wryBf@#Gb3%(iDQ&AQ_Za4l#E=pOLF`b7@!Z>8abykufZ z-rs@<{gy9_BbA>0LRei3M;{j>MB@>|hRL^yl2`Dg;kaXZipTonmZ zR9>HXOtYFSeKtnorbprooy9cbpWYs?lw}fE&%i&CChv%T$4riwEWDsTM2g#2sTu>Y zxt>_GeRZEfO_j^&&hjW6Ay?T~v+1$&!S>;4pwm!*irMLauV%2Xe6MhGI#CWG(KDQBagbIP;HXS6QZZw(tcc9h$3fRpw`yE>&JhZi)crUDe)jI69qGh ztpr>DV*}fNZQy?9{y+WUK;(YAQv6AIL4iSSl}w#OPxE(~;rEQ$15prS`0{lcK6xx{ z|HlO^ll)=M0YF78aU;E~?31bI+|bl^=WfmxXXgHtA?J@|5hVZCMd1}eO)g)>+NBq3 zNqH+x<4rdu>9ZbBLwU?u6sW1nz*$C@DaLjhb#vHn78-nzq=6KjI>x=t&#v8TLY)L9 ztTFqq{++4&X($r%AGqz7>8&HYuWJ9FY>0t0YY;!z9{ zQwWE;j=nYz@hJzMgdJ)eI4?lR%zfxmfhS0rH|*<^z?5Aj^5NDVpF{5Jv1|QNgu8|$ z!Y+EZ4?RbYL%lNG-!Nh8N~H*c#xr+U0S|}Hy0_uSSSSva@uw;?*;|^yp_)91 z++^u2-wrISj75iyOh+rY`=qOkSLyB7gA?tepH^6+KtI|BQ9|^iw%|1D0ZY!~b_&$T z3Z!+u2?#gcpj=eaNZC~&h?Trth^whG^f&HMOjLlXgI^+b_nxQ??ma2xAd9#oVoZ?Q z*>SYvX3Pt|-hp8VJ9JLYUaZxX8xmwb>X*}P824@Km^MvkjzCWp8MHW(S~=!@#jH(~ z{hY_`ny2k*cQ*bgc?5Pe2a9fYXmk4e3J$Bi`F5RgP=tHU@kr-YHK?TBTrazAx~vz0 zK4sUh65FXQB#cU-soFifo|ke*moEqpf4Sf&o@+rt8|z1W2&#S05OFh*$<67a_s!Ft ze{KCP!*v+c{Yb7cIj`aSMJ$ z5YAHRj}yk=_TFRmpM2~>MJt>^Z57zK#28u2-R>+PPM2Ukrr($3xl?V&ZCLZ30PMn~ zYX3MYAjjwqStu(r&wf5>2%vX3S_8X*IM>ZZ9Fvdd%(vzV27lntVUZEM`j#E^k-33Y*=h z5WBn>&-(sUYs>~D7WI>^yqWNUv%k7sE~z?fJq6=zy?O0o*FmaMVasEemji`2ncK;8 z)mu(Uup9i#lvh=BR1{pOl}FKne7QHtA3foW`Oo0g`TCmKglJAwqLBH(nnEGg@+~E& zj5VO@@|Ejd6qN2~A$MOoy#`(c5e?V^pCS#@nw&+76aV`lR8AuQwu-X&+hlGAbKHNL zEbl%^*gtQ0e!i6#p!&?#tGRDUFs1lmLd=CO;CSphw~uZ&(@to ziu;(6#(`v7hW^hgeE)gIe^^WIlPwtCM4?W<*@uD7JCsk%?93GGzfOK2rVp3a0WZr* z3x;%3&)5e;co6jaM@{h(&7EHw(zNsm-Qu_R6vG}{U6<6YLuwoP+sMD~%;~&OD;YuK zqe`fnRlcIDW0ciPVoGS2H89npX(f&seQ8O9-eH3pMISxNyhi2E7bZKzz%Bhk;)d>d zBz^q#ZwIU|v!W7zY*FKy=*4RI!eyK4C0%kMPg34rjd^J_OxlL-tGN!|h^s1x;s*s4 zEwyvLUm{CY`%GrfEc4rlj!7_}Ez?FVtBx{eoj?2L6knM10xh^c)*2H$=a{1r#LerK z2VKIKj$W8?4s{(zYd7rr00az00v@2-!X9r;3}ZE$I@+&I78A8Vr3%20X2+F=+d(0f z*i?IE5ux;zAmPZ|6ZUZDa=DViy$r|e68xY+yPW^Ar+O+er$P-6)^=aDt3G0n2f`PA zCx-tz`WAgfpXMc3=d1VIe@Jahuw>bZ?c(;GjshoHN{a*juW0aYk_&4hGx z4h+*UEBpP5k=fH8?Q6?7RI!q=i9c*U4NzP8F$@1ct$D5FOcnskCy0g1WnoX6_wEk& zZgyM)BQ035el+KBs)X_)CwaMOp<&TcwCq)N2)~f*ar% zv2z&CM*9;jz5ZN=ONPPkwMqX+JwfKG+UX5o@T zKW9Pk~atFVDpi;f8U$4-O^w zG2n^z?b2QOp}>_+rl*hU715Mei-mgBw{cfoc3w*lN(6D0QQFln>#}kvaa91n2F(}Q zY~~q0bo?zzGGiPrM;&x%xRdDA7xKq&iM^UFOsHYFx2oMY?%6(`$ zq1y@MD!{1?1J?QFSr1PM7+34U@{fXVSCdf({ts8%q3p>@m3|aNO@|b7+OsD}&Km*( z+5jBb7`u9vbPuSpF8owVQtq&I$a99bUOi0uG+i-eCw!DfLg0chwP@0EVe%_Apu715 z%g|cRKtS{Lqo+wJe$&9V5s=pgm)-9hM>_-bs)w(fwh`%A*r`MygY7yo=<%nzW$?@# zAmXb{3$3)g|8PS7rH%;S{9}rCh)>8#`_`qGrZ<P}uSXjM!oe0fXCf=Ei=_>RrdBz}^iu0R_BE_1$qVSUs0LRG(nCUI7u z`w70B9{!xR{3xmt^Rf2f@`(0y;sdA8z$C`4_x2kNki9~Ur#KBpt;MuQJwGd?ou8MjmM9?p1b(z}juOu^Vl z2uXTLgZ{7X?k1Yz5cpyNNOy2v&CPtDFoha}UtPw9U;RNIN8|Y5D*cGrh!L+Nxxz^7 zA`r7Kty4@hsx||jj!v{*30QGSU7CG0=|*I;H=z8`x%x?bY|*wabIPxjU;buT=lfIi$Ue{TBDdCSpHYMlDMVO(GxHX+oH>o^61@*@B3PB z5siK%V_yH=C)iZB&1Y9GxI|VYA1W_|GZ?i*DspqL`OWPUCU?diQn3LiZ4y^^PH*{z ze^!b!u**MsVgqD!MorsR&IX=57}U|PKqJr%J6olF zVR#g>Ul-y!U0iY}tD#?Z^O+61J@XMP=&*LTChsv|3~p28Q;Z=lAAr+-VN$?3jOIbg zdr_Mfkm-8!pp)wUSFXW2!!R2CaQS2VD|~+;3BD&`w2Lh`pyS(nDk9O=xBtOWZvJMD1Ka6km@y$u^hv=0J@ zaoHiomcj%vDWBPece@tjR@>;{C%VHpNVQZW&y#FsuT10E2cpW#dx32E0t(Nc_Rwoa zT-^I1dPRO1!*+?xeemQ~Ut6Fb4Fm69)CTR3I1vyl{hLPij@E+STe)os)0AswnPjE6~CsND(_Gcw%LHFUY8i=p8IkW#Y_ zG!U;MPez*P2>Y?y1`a>lk#-5Tl`L;qSg5SrTTE`o8-{fW%*N4`ef2HEoDx|FfaM{&;BM2Y2nDWH$ zb8K3W4bP|#0pFHcK{SPQ6>;Xc14H;z$bD_(3zuIQed{DDPIcAttkRUgm4Jvsp|(B( zXFNs-a9D=mDmu?lQuYN?&f3xgN(>$G+!qUnzy54Pi_K-a~+D;@ufj zx3VB&Cm!y21c6Jg$k1i?6I@vB$n=EEk56IT>1PjU9|~zornDY0A%MQ*R1p{b_!>d2OMwpyF zqPWbvT}w<^FTzv=F_6-@ zvlONA^lH)N(~^_Ow)Tzourf~7{69A9?1@jIod$P4{t}s;EFsb?947T|mxR6yajC}H zBb?ClN|!0Kf_58%2pg}^tiuv!b-Wr!L&aIZ6A-79(kM2+0_!REyU6nV5DIzx_9P1R zS+S4dY7LU>!GfR@B+n`RG4i+mPHDg&T!U*g;vD-S)clycJtzbumsKSMhAcm{Xyrn@ zj^W{G9f#3wVM(;yy@sjpaUy12t!}?K|CF~mRHIvj5GJK_C4va4)Mso}& zJ9UI#`7QQX{!HPsHc>J0vVV(zfUGE`#`T(sD@zrEUk)_C=tw*&mF>#7V9}vZb4v`# z5Xbvp7ys)v$WAj>eU_=9m~V;r%teQ}+WOI{^f?aDwzCF6ywmGg}nIW-L; zkWOJ>9B|XOlEq3v_)tMQY}n5$Kiub{#*lRlhoKwUgv(B+0FSGj1E;6y3qww>wEw|C zp<1Fl#Qf%wZr0TYy)?`r#r_thp_nYR)!V0EZaOU>^s@)A2H);fA!>qET#;e?;-=ZM zkQnlL>c4GqQ5{iw^vwoA+%F0Y6vkV`#I*^vhe^L<@FQbz-&9!6ES}d=j*kW}LK|22 z1LkJ-Wj`lP7uqAF_GdlM%YHF>*5w;Oj^sZv4Sw!OE_VdAIoXl+BYjcMsgu-rpu6~+ zlbnL{VAQWm-MBe3_^#0Z78m5w#`p_$W#cn0e%h+$4expiogI;%!L&}%xG9ZN6mUBS z@YAiXBjv8*X@L!n!FZo<`gb5fclRkhy#DBQp9F#ip-0+1S9G_ual5E_(^NreR^|nG zQT1OJ|0_0NuFFFEm$Ra+rt{VDZ{mK%)P-l<**QmYMam&qX*@QR<33KWEv9ur@lQSW zZTG65@^vdnvycASH!w3|`Tgw7k0Q=D@@<~y{u6%kRJkRT+ku+h-px;5R1QbBLsbv9 znN)-)nF4&_Lv&NF^4x2vPki13k-OoUfsU(3aS9tkD&iQ4O=d9j?2gyc)I6mwA z8%J{#us_hGWq9)a`~ko`Twb4BLg^?YwVWtsftk?r0+tKVT@;}K(%b3;1TFX4ldr$& z4j;)cg0e)BDl(RVc5=!G%hyE?SPecUNbOQQa3sZ>Cp&^b=ugj0q*UV=E)q?>ah{mx zbu}uaaE!uQgR?^I-CKE^MQ9}yhu{JFo`2dl-n*}|m}w7)BDzYkg%1vvGnko2o3Ce( zp{5hj*Fcco&rl|km3d_R#x+Ip?nt%NgI2A;y7SRXw6i9U?~uQizo;_|ka3jhe~H{N zdQA27fYSahn9ueLA$V&O^PPH)4;d!ibm7G}eZNR@f2nvdYb`qF&g+Ih0h(Utgg*$s zcnu8ruC)pZ__K5@GFf#U7g{(Ct1FzYPorep-qJvXD|1JNEHgmBAQg1B+uW*FOA z?fjv=$S7=!0+@AM7#2^!UBjt1al=y!YRv2gZ!^ z%g$M6PL!H+Fb1fWO6&R&TrnDnLp1)5E0*rD<>6%<9d>44-2>8*Gl!LwbPVxJ-ys;WA#G&;^b8S$FTI zgg;Ag32T<^61Me|y%z=Jp~Y52euXp89yP}DvY?G!fU?SKSs4D!+iYX~K=?MU@6V6U zarT17gdQ+mlKuJjwh8yq*t@iO3Tk10dqxgS+4o8E-S#;7_JkYF-Ob#|uha1IZ^uRd z({aqEH=Yr?QJ>k?pfDN_$_5cfF~c9KjiZw9gkMDRfyRHt)FUcAz!X$pbN7-ux%vx} z$h}KHTRQ%ZtgBi;&c~b(y4;R@h2>)LURY2ycg2e<5is)t>f9K0p zbsha~#N$+~L7EB;hkvNusYsAiyB%WC#KQVd-xxh-Z5u7<=*t!{?I`@`-EaP0*AqAb zRWRx-dhTgCr>qv%Tq9G^&qo}dq6<39K5~{)pAq}bpPu!0+>4agUU;=hINU})%NNRF zv3Vc9|LXr{ktW$940FJRvmVe&h-(IE^FNr2I z@QdXB_vatfzdxmW#LTCDW#GSV1Si4&SLRV;U5aPbNErjWyF?uE>tkdgC(T4~mF_J( zU{!C00wi6DrIMp?hZNxQ=nJJ_PO%1O~Nv2c)cm?#1XHnOVnh+pMb|KZNyx#)?|6)+JD-CWJJuJMe!;4lACA zpZ}(D8$P1NYX3eHd$7ziDi}~XS5el)DO@=@uBE3ZRO&Se{6au^a-V?W999xdV%5@7 zd54)2dAjL3BmdwPAoU7eKB~AK{DuJ;@=DJ*Gao4$5D;_sZz@X(@ios@c%lL(J$nl> zDAZyPdMh6EQ}$Azb)tcP6V--;G>?lPtY73sI55wX;=J;$Z^CrJ-7B6x*LWNvLvIkk zww5r92oQeuqIfj9Po;V9m8oXA>0&!F$cY5kPDrRGL8xhtX1-!0y9U0WT^iLh9c_zE zYploi)$Wv{h$4m-->HUV60ZR?UO6A8*z*wuXp)C3{))LOjB(mQ$#u-Y^|bi%XSmyZ zz|N;r$eeFjsvS-)u(sN1wHiHdoyY_|i10i~ePRMQrX%l16EUBdzN;sl3Q;Mn?@07Ecz#Tq>tM z@?-(&)hEyoaKhx6SH+7H_M$^203SzKgaCp;eRccz&CBN411!dc_#NV zmylaLSYoEs^L-cAuJ@k&LYVAk~~aSizvl_MV9~PRQ#@stBt7>2x!b+}6!! zbM)6-K3vm))fMfFv<*Q?B&H|v{ZPQa%)EBH!m&AUd*{Bw!+Wy$HNG7PP}MI-E?0MW z&~2A=H0s1PFMRoLU~B4f&AS)XoKk^o3qRC#gal~lw~J}6u5mfQ*LHX6UDKk=M!Kxn z8@_fQ%N>mje;4SVd)pcc92pS=gs_Do`$NTfI8Wd z>nkvE3ri!>UoQu1?mS>W;s6`xOM2hGD( z5$=*tMD0`UEDaZEZP%14sbP8dt!SpW`mJBZAM*a0>L1qof%SPxydB7U4C-^;7`cKL zn>QxYTY2*nUFa8wIow4|zuuopQcpZo?`l4<`ZXOqQDOA^XJB$9pyEzk9#fO{1O?!l zKk)?JozH8lVmfLqMR2{e=9GZFM~Zs0R9s}&&CM)CEN>YL4>vuHSvDu2w$YQAjVoyt zSzRRl#J-$RLl3kM~B23X#nf6d#4{!X5N{aa}=J9C1NIzUd_mC9+K1C4sM!@ z6#P9z&a@bjzDKPfmm6^5Y)mHV*}K%$8zPhZ6lx*f{?k9N4GqU7Ub1I89ea!Iz6QCZ zU>aLRZ1^^**Fya{_!E;1C9PPd=p^EBu)RvuaYN(9{Y-%u&RdrZMxj!6;c_c_l@6K? zWi*Xz;-GTaW_NlY+s)}kyQ*V6I}RAI4Xj~#f)qRiR6*VeO&F>IsCC})N3Qjnq`OBU zr5rbLhD>aF-*(AFGba=XjRpy9ATD5ATG)ZKft=OB$3)R0ow+KUiCO|*0bDydR%E3u1! zd1?;l*FW{!R`4rJJW8M#95QXXwxoJ7C&GB2zsy~$NF`2>Q{f-f3Z(&g*uNm6h80cY zO`+1i*gkab-!6hC$-g&Ky=bnMjPO8*-wN@)RiNT1!f@?hpE0=3W)`UI80#!ZScK89 z-v*^RWQ@7UXdZ6g<#DZi^?glP@cGRrzSWu635H<28lo$k6!jWO>1gBcRFOv`Av5o* zF;PNXCXUT~oax=Z-;=mjaKq+Ne=1AJ^Yp?`PDk+$J_1v=6;q=#he6QK=WjR3w7ZCSh@JR#XX=0-wWK(^?ulcQ<{4Ip}o_T$TqG zM(V6VnJip7gsAsr8Uax3zyXheB!?!t?_#0k&;e>fGY8CPAB(EphE~_to^=UN!*16p zSlAGRP`KD(4JbqZbH;-M#TeFRe)Nrql6YCmk|`qAGnlwJRtdqc@bEp!+4HBvdyf1} zpE-=nN)7*6G;g_1_=&kr{ydv90Ok=K?@IE}3xb+8`I#vESkk9} z(_gXGL`HM|a7ftg&>o6rP38M4IpoZrui-pS?ZA4gg<#p8*wa~%v%{QOL zT;3;vr%(dBMheq~XqXA@$9&q@=lbjD94ph)_dgU_UIULf?!Ig4h!6~8UDA`KvrWEe zGk7DGIs#N9g5_;}x@ztieXV;z%@XU?8T;1Q@*J4f1Cnr1eLVl8C1|%<9x!Zte-T_| zhp57^#KYb-jI+qMgAVJ}K2>eo}ET8GAs(Fx!&k zwb1$JAXBC{rvDA$*hP^^YLujJSKm7mIBaXA*R>7zM&2uCkz*$gPJ~*dlElEOg}7Y= zpx;$;>g87IgPJYwZ-afGv#ZYWfkJ@d74ELG4-BIl~jh*b99ul znn7f@d~&}W{&y_^Cx@#6N+jGg4OX7nK&)^v9BJ9VkNQ{G4|IoF&x2g{U3rToY~KO; z&VaSD{BCAw#F#HqLnhz^Tyk@Ht#|dCn`n7h7QPVd`S+G|UYW9BeT$$cr+Z;sO&5|! zqhGvO5J6`Fr6h5yrnzq{FFgmZUv%>ASQN7q{g+jFG}<_I-dOx%wDjNPpX@RqVi)~g z`jo_l(0_T(O3{d&8FGw)48!*ml0YHIZ}nMy3(Ebelmg#w9;2@hI@ zu$*A;)%e|82hD7qNi7p75-FG6AbU|!@%b*b*B2|n$tqx*E;%uwK_{mo=^Bbq$i>J# z2S(dz9mj2Vh(K;0VkIfI+?|Rj9NG8OA-Nr*q+bruKz*Z*3K2pCczXL+M;ad0pw-DD z>C?aRkhS}5o0)Uft4XU3_!u#Y+sa?I^3ymNRW0++x$9gFZqIW#v~tsm&326Pv3R2KEi*WVhlUx0%P^{ zltGhE9MXvT_VqVvCO?GsPTM0qlk~lh{zM&Qu!I7{MmGJU!%sLdG`!I{yg(CnB z5c|E)79l}NdULvd!*@>)-^#7qfGn^bu7Ulie)&%__fql=ra{@su(b^~bZr20rV{3no$~9WOu)E3U4Gk+_v9a4w$7PV6pJGi+ysdK_vqH!$<3s6Sm7Sp!Trca>Zk49TDR?jd9eH zUp?Ran}Me4y~CF}Rsn{>uQCUlR5q(U@e(uO`BRW_p$ss%0|7o4(%OVM8co4?)N4rI zJ_pzn87f#xp%Usa<`mYzDV=rlp?^IabzAIRG0}R_6a?0SQ_H05+nj9XQaRZm6_PyE{#16@i&yXEKd34k<9oJ|YecxM0p!q=@ul9TT9Noz|0X z9NVA$QWl7wcFcab@_A7lI>>P%MTrfR^8FdSmDJu;)edpItdSO!UwBH~WzaTxKBrRm()C`$?|CIWkqZ%Z|2k&u z&xqcmkf{cu>FI}DUc)zAUodn@d$m6`xRsc#gBov2;m?rX=T*cy@lQrVF-)OY^v`zw z1=-wHi5t_hCt5d9z1Tfjo%d_ZBRTsdu}Ua=>{ru5Km<~Mb1~R)6ydZ5<6b4}ScJ}4 ztK4uWNqGR>$Kl4UJ(sC&^!=q>ot@n{duhM5qt!qhpIE})iQ^;?x3d#8WFmwG9sknr zT&7P~(W9+#$YR~5*%(=E|Ipg2n~CS95qU>Y^Dqcz`{<00@le`NUYGBg(_=T&4P_nm^y~x_qf!Jbw6DH`i~!o#u_~4a?_s*M1-T z+P2J2S~2w8E;sA6|3y?2Z6IE(5ow3VG6ih zpH8wwy|D+5NNLUWkM7_1i$Ug}CkzLBjrwsVPp>UOAjf@eV@gZv*CpQtq6aPwwy z*y31?8P?hWuhYsX1Gts!ozN||#s`a$b <~LrvlrVfL&T38J{cJS@HTZz8GnY8# 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�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≀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

      FYzzq4}2Ta!gS+QWd#{|A)r>?uG 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

      GowiTYx!@G>^1aa z5uUe`?gmGoQISsGDzLGnJ{lPgOUHmn!uf`1RPkkhycgt!Oz%_;SniSKM}}`7RMDp> zeb&+G&5Gswo%$b2&9H{yZVY_))CN{F2FB4^PZ7alIXY>C%|kSjHj+fHjA{MTeQ&NP z%P3ljiF0ihcCdSX%rg)rT#g&tm2+OgOYJaS-E-cQK}Ivll)PwYNQ4k8LxqrldZD(~ zUr~2dLTnpIjOWgHY9#K3MuPB@V8MLHBXGqdQ`yFLHc-rDZ$DDJ|l8V(uo1Vyqb7I!t;!sAb zt0Em~*J=%qKK)p;IDhJ`PWMetL(D6?zbN%`GE5UxZ_lxgj=4lUTGkRhI?ILHmWPrS z4-i?GIi`m?w2g(=;(AB1R<(W@+e==hXLRVL3oG@2Z@rlKDv#QytPlQsw}oZ3(MW}x ziuIzV_4*-}Q6;x}o7=R{NS9jh;pmdU#CrUmj#BQ*$l%l5*2_$yuN|Xh*vpLS0bVz# z{+iLF&ux?x1;^**z-xlP{;f*e6I>+%v}M3*C43MFT;jgh-Nf4o!FXKA!-J_&)>tfi z$gV?D|Au+s*)meSxJv>RTFP@iu(;EiM`tF32~+2NxTvfJ_dma6rA&kO%oIBfhn15= zFEXh_eU%~aG{W&_0$_BZV=XCZ=uH*PZ}qWgd8-aI9T;O7R~c*q2+%zTyeg-&3vY|! zDAju;y??_L+PLutJ2bPOzRn_y@O&c$TeF^VB&TG5C7kHc`SM`6t_GtD#CpS2_9!X? zVl_a&gU8?WQ_)yT^!xEnT`iJ)Zb(`h6qNUJ*)6IM6$w441UpzEe6h7rtU426x^75@ zlLph7+PLaGhM-`qXa-*Kd9|`5FClqPA?nPI?_SSpTs6W$JzpbwLt4}wi;D&}rvqiw zxz4Zzuh=Rdvj2DiRHy!qI94ZQ#F);PVp@;wWs0w!hI!tmUiKL5r`h&nmh1e(S;o&o zS&G*V>gA5!H9S|7f=I1`A1j5SBe<>5`Kih$Uvo{Oe|nFd&&8?jcmZI_*0?uA!els(HFT_mX&gK|I9TOtKp@6RehUuJDtx1}*Px^4#}R&26Ucf-16Ts;pR>w`GUZ={_4Tu^9Nn(@Y@t-#{D zC&@mx$H=^U>)oK5ANxl-94#-rSonI)OnS)K(OZr$+I62&+~$UD2-q^7QAkP`mu`mw zKl-xhuI1x|s5-K`*Zc;*p~}Jro2)72x^YaY|JgG3>R{w^Zl(a7|HFY7#w}mVF-S}E zkA5^>nq4y1F|9VM2hHnQSS~XmBC1LyU`!C33-^Atj4koQZ7hhv zv6=j|_pBD6k0nvuk=%JY-rrPfP}b}>2!Y_o!@w+u(L)hbgc}Q8s@H41A0`)h4ZTJ@ zPw;-?b_$3>ACdqw&pQflTj}~Oq97bIR_jL zAYpND5Rv$sDyknQCWTrtopDeKQav#{VEo%``*>(%T#wb%y;+UJCMAEezS~i6Oo9`^M3nc$z=sZc7g)%UeNsg3>~)& z)uAGG&;K0N{bKZn!;lExf?_tF=KwIz9*-IK8MQ)h)H_(lo*xoH{tEhU%)EkB!ibPDFsoLX6M!fWUQ0j z{9$@*>ZN@Q|C0%x7|#yT81tp(B9SvYPZY47Oa3(d7@nbCZz+oKvH?f4$r zjjyH&56ammmtyK29xF_Jqluued~F`WZZ~uR$;UR(tRH7MilebOt<3?~ zI4%2Ht==WF?JYDt|Bs}q6+NM5rLyIyn4|F+6T588Q5Knz0m6)N`kudp0m6-Ns(Uo2 zKQex66DKGEEPe;v&FkNPQT5XJ^F+&?n=OJ2T{-;C0atC(iq_=W;GIL|ebmjGBQ& z$$5iC!->eWRqVst37xGfm1+T#Ujz;kf=1|#Oo=`mO1*tNWd@>mPR_P@jfl9 z^qRXx5>uQt&!A-4Q_irh@4&(M-#7hPW(d|*Nc@8Nwrb&3sm?dP?+yzYJW$LaFo%na z>+yrb?&Q{4F=MD~n2rRG&N)lwsS35BJY=Bt$c=O}=gJfEw+esG@N2D_`VP-woITL= zk2j-94P5Uby;MYLOOZg|^LAlPzlZ5Hcf?ccbEt%TX(faO@zeWwd%TITm+5@*{_a20 ze;oSIIoJ`{=nUvamkcxjVcTi1y=&y;H~E)r(x;G9@WU;~%&I?MbJ^Vh5Vb#oerxM} zJaP?2gr3~d=5J*0b>Bt8kJ>kRFkaSS|Eznfb^A-;^w{gCer|osg%jWqGb!%Vj)T@a zj8FWW`>W)((pN=Eo~ysVG3fQYb8h|oh1~kx`MBSFHcw8c(FpY0TWvZo8zF!CFU4u4 zk5Hq$R^Mtw3pq-ASpoXyj@*pDrUF7x=RJ;K#ZWDmYrlH9`LDe>N7fKesXMZhsK}7q zTUOg{HKE&N0MeLGSkEhs%4K})peTnnEJg9{E*RT9|1|e=Ux*;3}Er zZyIuvEqij`Jcm^t47~DO?Ca=4k1E#Trqqnlfs3m6?|KyVQRAMkQ6|$d|^qE0$L`Ae54GpVqTq9lPe zk@+EAUnH)|lKlsBvB6jZ+d;)Nqj(zgTFME9A^ij0W3w82n8 zSE~lj-J{os%Z9xcaAIP8&l%A-Pf!=|&}#Mc{TU+!d@Z=koVzaj;63uOLx&tDE-v?W zLw_U%kZD8XH0gXCWp7=>C3O3Y2xtP|$Y?sWHT*A=z5kFiYmKdsI6137oax&<`Tm9A zUlEEdylw7x(P>h#-Rz4m;$F(2n*o1dabH2uZ!+HWUIuM2ZQ)QhMK#tF;SiWt$@`SW zCN9YSi+G`_e+?eo$`J|99;~_X#+?J3ciaRYS-J#>!q!71I(Rn(c;;xTo8xrviCW+N z-m>=vRQ4iN0Gq+(@ildCpOr`c1<`jNB@6P4WXi zI(QTXj#W~#sgwn9SJCgLFDV@JR<@xN1xP$y4O$Ep#8~6C(_k2j&QCG>3Q)8lkq=lv z#~e)|*Wl51BWcMD`3dm$r8i^vZ^h#T0_^=5OQC4TWv||HLaZ-w5iy+!(|NyIjyrW~GVDjS#(ukyxUDt?FN2s^btb2O;f0ZK3 zAf>?g07wtLw~XezeVOeqE+2t6^K+&NuHo1C#zs>ln>7eLkmdmX|8OAolbEIGSO(0Y zjHGwz(d{OZFaJgFl#1qis5ky+W|1S7#3tI`Bs+6(slkLc9A6d&$G`hb@aee6_rC4# zy?0MZ0-c}VxCiDFbJIC+P>f&cCw-^$WNP)PFZVQ@nV{v>u`kds$CY)yE&A90QwkXbIR0ioPAuQzU_OFo$EsQ;GqR zka5C6p~!FWG-k;a1hGwDLBYdhI^M^U5!YL>$s-R}MeCf`3y&>sv zClk!DXU9=YvrAFwUWkM`1i84}illM{=Zz#@(Lm8l&4jSHW>WBm`57z$aHh`!03l#R zP_*MEWM?ck%_*H|LDe^uvOE&7){GI{uv$v3r0;`StY)Wj6Ruu>)WyUzF5Y`n!a|pb zKoXt6EG2p@tpizu%P`^$oG&;}e5VhGT~Hm9@M zM}VAKNEJA0`Chva2avP1vMv45QmxIVMtd@k=y8byX{HNp1j+z-Rz(XxC#fMYJ?wFW zOM&aDixHRTek_-G%}U^jW0q2$WsK?lUWoOd-XbL88Ad4c5Z7LSb1D}Z?vqcCnBgk~ zc^A=?(d0)#ufa5loMNtl-nK<5qJh7Ck!!&q5>i9F(tR47(jhHEG6Fi3F}tv8QgDuW z>EX)BEN4RzOYfk_Q0d&S6#&ibLhGaGKQTokAnu0w>jx!P;a$P2)j1lk0@+h4)CF)N zhuuxlkbA}>Mtu9A(!;E5ItB4U3p5-kays&6Zh2b0-R*MV#W@Abq(Hwp`4CX<1#KZN zdTnc9{#vGn-vD8nXy=$N{2*X( zuroG=Vz?n)7r8#Vw{q&+UDgUyx@r*G^a`GS%wm?%3RP`&5NSw(B@1h|ta3bGMBwTy zdLv>4ddt><**k+KWH5^dU~C+`=76M9O*2_z7Mp2T;7r8S1hNvLH&c`vah!^oqZ8pi zca<(Mu8)2NPLLr=juyBu!ihm^dXX_A4NhZmKhQzcBFOAd01k>`vJL;LB$^N&(gCi{ zl$`&{DVZtRxHS8J@d|57d}Z(w*GGGNwH4j+oyEO2m@xK~%zHbiEi`vbvQ#3#9j{Z| zipe3xM^uKEDqosNex!5TYtw=#1mFB#(Z{45{XVxT@hPlgbz?bFaoCYPh*hc)T&#bv ztnRgFQ0_@QU2F)3p2O)$DuX%vo{of+k~IGSmmoG@FUGmz)6LuJcw%3ax>Y>cHZ^ei z-fpnQH>?hRX%N>ZR*)@bmAs&`C9mTw5Qkw;QV`G?jRWrrr-OJp(+SJ+-q+f&vC_tO zg4kxAHza*OR)A*32IQg@#vQNYA>+8&DV6jb|4G7p>3cBw<@yJL-{4@^`?I{-lSF`U zMAp6&9eSO0LqRFLGd{oBC{>re!{03ybk5!M7YP)~^(MWHkTmSYcv<*PywJ!cW|sus0S63ofTAi~P1Yg?68)BJYD);B!tK~5-kIlPN-9K<*o%p+TIk0Y zQSmw>{^VBC<{R(D(=u65uUCLq8Eq__5B?!&{2>}*jeo=&(i^N>Kd+(PCl??z9m%b6 zu$>@s4Ifu3*wA&WZU>BC6#IT9Dif3lwp^iMB|#>f99{=F_LTqfW;AxqbtzAQnn2M? zjoJsAwF{hu^yh2r2xTwjV~R`O12TG~kS>h{8?=$JAI$l+8mD?4hp-Ny))!g0(2=-7 z^J}M~{{bgCDeYe(kfXLee*yAMX1}Mj$HuLB1g@Av$$V8vfpVjt4&Y#U4$6+81>GfV)=fGH!EZ+H>sDRk;>`# z{$;?61=EzM!I2>Sr=5RJe98O5x?ax1?1OHj13$RvzQAD_pW-vItmmlW!2&Fkh*Lyv zPsSxhNvPfFmAhFe!(LVd7a6P5{(hqX&`?+dXo-hd1k1X54To%`)J_O_rK01q11G=C z`;;#?)RB8DMiYgW!Ci{Spp(}JT^>{c9O{BJ<*>*H>`H+MyZ-SiZY;xJqXvF(==S97~(Adj^fY=%uBXo<7`Z0D)d>DveM4 zq&F~s{ydbFJmnQN2&N2^5J`$S*?ZpA$&0aP(5q#DhEyXh78*icIIie~y4E*_lFxHhRv;f@4V3-%ZeWFI+c}PXr*`7 z7@otXzV4iiw@4{+?0wb^-lr#I3h{LDQ9$mU*tLJI6O}{M2zHn4JkI`m^dda`{Do+*^;3 zi(b&Fhm_4W(-$M|rjNVKNf}FAP#JR3J>^Zi9T@n&eNG|{^!K0 zZ&;qG$VB(fqhE?iygi{)XBpj_Fur|}EE`qdA65Di7}SHK)3GpJUGv5=p|JuIr>ngN z4y?c2aN-OVMMu+drNWT!6Q9KfM5?pbhpYJHm zYjeB(m-^iLjDV-nrgXxrrd-nF@7xn`)!AVFgoV->J;b{{3FU3Q9}*ItVU50%I#qZ#qHi4IJB zq>y90;3@95eR)S4evju&W4GyQ1Z-|Xc3~roN6}4KIxCGApS*WK{xVMUcy${c`y7H^ zv2P&y9IPkVaU7x(p3^Z8YOXhc+HLb~`{3wfyH3L*biB+u2`m2LS3m}QnZzJEl4-=z zoFgFn1v@L`fYgyS_Y3$iNC>B6C%0*kApO|frB|rSs;wuYaX0}a%Si^V2CZ8?_~_}Nh>1G?G;33WH(#F7dfcl6rA_MIP(eS46VJZb zYjxS%i)EH~)Sp^u>K|#11h?nvcygoKHdNcCfjl>L&#dXFl>&7*?#T5IUPFQ6DK%Jm z8ve#r&D>F+up6T@?0vTg>rmW8OdC$ad_**qoO?8q$GC$=tJI3qI2G7+8@fw?@J zG2LUJLrSj`9k6UNYYZqj#7IlCLkjY;y3B4rsu#tL`wUHf$=;;<{e|lU2vPL6@@)*q zyu6-MwHZHH0Zh`QyE5U~u2~!c*w4O$m|?>&^S86G0?W>*d?Tg6<|?l7J9c9v)QxDr z12#H4{+QQssn-bd3qMJSZwwLKKG$GQMY9xAg0-4s=jl!h{;|Mx z&wPC*YFT$De?6v36CI;D=Nvivfr}5urjhZ;m`E0R2wxTD`id5h>cMJ7bKT~D0zLQ+ zdHgYDSTapsJatd>-w1qz=k_{p*~B+qRT0TOd?|YDR1E3R-m%v62G1_<3=S?aH_!z) zocbPZ>`&@M(EhIs<9moivWIy{Ati?aIWv~9`U*ZuDUO|=Oam@Z5|?W0UAY5-zII5<>1%||r35Ln~Jsra*d&siOr8Z|riC1GEQ&%T@A3zN-GmN|bwoHROhW$0?MkuJ$3dnP=%%e86A|QE_#!f{#y;{@T%V3z za$3eE6LSvjSq9&tY$6j7kaV6wl>qIR8rn*70OkAKMN0mT%_fciGv3^h*&? z5U;=@`eePzfk3^ny`*TuYkMd(MtaAO;B>clq{~kR+owlqae#D|Tt|9VJXB%Eam}Ht zBEnj~MH;3NrJ0BN>rhiFJaPM%kS@uNfBbtQV)#AZyd%YG+XX=!ZYgai)%JZ){%@+t z)Ws)EFVUUk1=4T7NgZz+`P{rR&c`IsX@y2wChskFCIp47s4o|!sfO0$ zZ#>Lk;l`GmyZDCWwNU2TI47h*Nz=rPfc^-=kMC#IOmC+njEW-NOX)($8;4cM#zp|! zALYGtNB!&cad?v?t!;(RyXFLOU+fpi?gUx0SUH3eXVDh=s357W?TYAbN>mD zzq=7Mf>tz85kql;Dd9L(C`DL%+4)rGl~?C#H$4)6-1X~LZ$Y&#%S&s9`DIIR<9Yo{ z$NesCTU)H;Gbuk>pBpVDb;{aEnd&%0zeNeL=G$Ctv!6u0fpXDXWwIXUpotb>N+@-b z&pTOULot7ibRu|r0hnqN)!WT#USVqjWnxgZ+GnO-oG4k8QgKRiRj`@j4z+QN*w(z{ z`)Y(|FJ0IWC8iwAcCOjaFf=`b3PmSHBLo57nNV6QS)k##y}mY06Wf3n@jS#TMtJC< z+cgH)=gS&I+Q}YCi7l~IC}TWla@5}+?1oNSPJe>&y;St^<72Oro;HCD)Zy04gP_RC zex%qW&2V~Z6JCFB7&}Q?d5L?`fw_67ODB{9yIv z@1)1Pb57*Z^VTxHTWlb_KGTo&gXBIxbIeTQ_>;ORTg~MUnF}TMM(RH{CZ5oxN6#I_ z3k|3;sQ9|Q{)>6Xu?RsGA!+sw(_cLi3@ryy=YEPRQQ;+*aJ^$|okQl)!3O ziM|m*05Z_E2%_=ojffq@K9z%07xZ69%bUvp#kD7g7TRTS&EKu;^BDGbJjcW6;Nd^l zlFnUb{C@Omtuaof!tvrti2e7Elk#CG@j=Yo`!KioLjys7QggmVM*C6-N1d8((qQGa zVcgJ9yh+Ma5jJ_kzue!hV&$*)^`y`{^gGia)I(^d(=Z!d4JPs;grN0^Db zU;C8uGQQ$~Q^|c@$x9apiyjyv0AA6$C3@Q=3A+WXA#3&g6z{kyZgv)VnT>6v86Iuh zLGPv2+LNU(*ehBFMzS?7#!^h;m zf|EVB_JG0kpI$SME3;tnsuG&A)0gKUm%D+R2RDsq9ix-&X%TWftxA6`eS4_9I4;AaQ%Xf z#7o@oGuLbv-^Bp@gY2=WYr7!ZddjubJNjjgZX?&)tK#+Hh*Hk&8jPWf78kD}_Sy{_ z(sJB?!ly4Y+%|14i&tgrYy@xd@br(y@zr2!oAaj1DEiI~oAPT6o;R3VKn3%k5i{@M#+9g%%Z?2_vw!ee9951C9zS0wYEBv_ zNGt%xTu$A4x?fk@9`!cly7(z}FM_WQYf|Tp%!-|odWq2Sapw=H{Q*%warIE(AdWoB zj-DUxT1HRJ8zc}VjN|5Ex3rUDU0iz*pGDgGpT9wscr=|*Sk}lf*&4v zba|7j?4BJnGU_u!UvsaWupdkv+Istyj`>Bs4X2v;PpKSnyv8^1-*5SU^IG0|9JNRN zbrecHMfi4T%;>v~PY;*NO?|3OwevYiMrAfbhm?SQIeuK%l-1YwFue}3gRIl{Kinx< zw%h$$B&krRbk}#8;F4ESo84dSaer{V@AK|Lr%Mku9&OsIkS?`;&t0D6q+LayH#v#F zGFumM{F(mjGi|+oooU;Utj{`wnN%8Vpj@(cwsM5?#iE#zlh&t`%a!_%sq_*&aA>|P zi*iZ&o~J)A_w)-7hzbhh1`j@MlXB>k;`e>EWxwJB{vz+JJx`CH-;`@VU~ZoSR}19Z zNRlB@Tm`1cF`?3$fAZI-*wxYQjhQ}#bE#B;lO>PO!|5O&DzF0_`=&#yvuFoQ0 zX>@ItSQ`ae!fe!wD>A#AFtyP$0kfmGn1%Ai+Jn_E8beQbb?cX=Pn5=_@cy}Bk^8yS zWAXSdPO#T;%Jh^48|4m0||(y@7P$IGI6< zqFYAC-{gvPg(xpv3BUL%OLCA;TFjs?eD-vr=cls=n>^#QUdL`bG+*bw&#?U0`<-{c z{P&;nAFJ^Sad5Y%x2(-gw@YQw>7U0XTuTyI(LhtFG9bMb<r&iG5@jB?me0A|Nc7XyPO~W$JUoW{>ST``D#4-@1N+;Byj!5mN{n^aPdDrp~c?x^WV4O@l$gqr~ZAD ztv-|&zK=S7ICF7m zlS8;F7e7zA`A&&N7dz^6GrZ%LqE%^;33Hh92+fAihF@v?8W3K|ndX&sgORs-q zQz-A!q~$u7ApcHqo%VzOe(nF&x@5a$Jt=Q*w)L$XJaw`I?4HA7D&SLSbgy+p$ZLfG zclF!Hx#o&9TIK4VAN|0`YFoZ9au!-a8^hS6-MSl|`%kE32Ii1L>8L|gAi1yg* z9<>Nrzdb)lq0O_r!e&Br0y8FCO8I%tCw8>92I*>+M>R8OCQCuF{Qn$T$wfBn3Q#mc* z7qJrUwQ*L!i_X$5!$-=!cJHbP?4U6iw|Xu1hoA zM!B0uulT>!4tAe2=d98D>WnKWP1u+9uO%GE|L+nW`P~2oEMZOt`r7usa8I^TNi9|s zKVpJ<2~pe*mtHQ<-2XzL1SXB^zuEDi6tGNLWHgqb^+MX+?+XTcon~59Sc7G$=1XF- zNSFQ(d+!|;Rn+VYDyWDkAPA@kNKOKhB{o4M2gx~zsLF47g%tjao|%Nt1tCNp4!$?p07Z) z<&Rs*cE?DQbg1|o64BYKSVw??5JEjKlF{403+9XtG$+Wt(Fb*zrJSyq0xEqV>|$t( z<~PyS??Mi7=%a%Z@le4-M)O$-t`r2|hdkI{qj4)ajvpM1w34QZYA79ISP(J2O_7205~?|4RyZoM?zVunnWF*{vJ-3kRpj z#l2nh-sa}veiR%y+CL_$P>FScYZ$T1Q`C(&4BH6~W9cx5q&KgY$JJ~wbKT0T*( z!g$0j)==YOCB1{6(XSahwXw9kja^)U=6SecQS)n%Re}UR>@b4H4>O7AGzQKtOnlyp zy{_Lrfu{>yjM(^L-~Cpv`v*}+1%q&%x42VKEM_lw(6z*sE@j;!GutD5a+bGUq;${0 zI#)L{%LcdrPb}nZQjSR#uotor(Ci9%dCUvNbosbCbH?DD_wE-+awcyC@ntURYe!Qs zj+9b9Q}zwvt@t$QCiR@8X~hHO0c;&iB4uMUnH7I4;0&ge=FZI^b-rx-9}Tv*%WT>} z_yM`FS^K(0Y<Fd;$PIQ0lMdo;Y7AM3vHRHV5{W*)nsl@*o|_#r1_Iaf;UJNxy%UFbYuze7j$ z?a1UI>;1>w@n+5%v|VG2H!3?#qTtj}|IjHUbIvV>Pp^B*z84U`-XsZ}Mk1V#2G5|V zl)2=6m)U#YC^}RuG(H*M9~l%mKrWh>K##>vi8^lUL3B%?{MZOzmclKVT}iVwy={36F+Q_ z=#SR{*CeH{w<`x_#8N!`{E0xG?Ixe5+MMQ1Hm}Tpknhpi?OF$EV#6Yi<=GqFknnh^GA9mQi>7C} zOied)g1>{M-FK5XP|Nq1f`@bpJkmP_OZx0%c38-NM&GMhGG^NkNuGS~=4&HuV(Ec0 zfNo$XS71k~h(*~iP~+Yk-r|SoJeRr8Wvv_$GM$#S9`M5IRqH&k3skee)S7Ns zy*sH?DN)pJ4`aW9B&Ih#Xk48c&I&C#azZRFvH<>IwlVffWKh4(gF~s5oiTd$HE6+y7WPDvS0%{j9!XyS9qeqVhc|3lc&wDIVHAlOR zB%@~%N@I?7>U|>^o~@Y}iET_ROMjn(9D|JgNt>?B*mR-AQw4SufD^QKd5<7W9WLH#ut3pg!0gv<6=POOB3MTGmTt z8d8}undoPS(|PEO`q2W#}O1`dd3!6zW-(K=++E z@A%fNfi@LUDV!CHl3Dod;vfXmC^gBvCA-US_tAhfD*6YD9w@OfFx28_(xV?!x6A)t z|DGB;f>XyY44|722L%^>T|7_G$$nE_-fV)N(W+7>R)Qx4?NJzHuiu18J^pp5x8Mak zvf@Al)DxIPi-%k6pS=ZXC8GdpAQi|a`o&j!1njW`b~t_0Ws876;DZ_7BI?B#;99dPUjNCb{xcl5m${N($buCn?nb;sNnJD6&W-_< zz_};^b@TG_JTsn|%Mw7P2Yi$I2UEF zf_xcRzF@IF6v=V6xYGfFKx#4B0z4M3Gqt$ksdz;XSC@()2C*Bxhe=kj(OZ;5ULOn? z&rl>P(l&AD<*F|loh5kPeQjWl&^>~Q)+$mrU{rhkAP>LQM;bxX|1C|?!BuV;IT?I& zBq-v69i#7u@2OB@c%4KrPknWvK)ySFjPTmVymXa=)=MLrI$-+D{RP$8ggQcW`qXi6 zVi-9XS#$YN8{ontOUl0hI*e_C^MehW1h9^2Nn)-S)h z$`SO3#EMTVMVj669HBc~8^ai``sa>eW6yC1=xuwu5|bS+=p+OzzDBK0HFXNTw6jcU z&i|_Xpfl#(oX=NW&bNAHcY+jN30NrM1o%X`$WbQ?PJNVOIi5Xy5ZppQH=?@s~T0V$gdmvtpsqF&rzgD>iVob{6W$F-j4Ur2Ifu5vT6#8Qz>D zP*<&F!e=aC@rVO|bz$Yv8=73qVzVDTr8K&AfOJ{{mLla^{#`UJ8K&&|m#SP$Z-_aU-mwH#aTOn|z<3ufc$tfnnh)m8miUnG!ERhZ*M`)$>RK3JA4;K^AfjzaN@W2h&!du+2hruH?$xhx|gK3tTc`HNJ0u;a(c5?y7wdCi&rThxaF#^U--m9;Y z{lliU170=9Br!7>`6GY-G?XrX6Y+GL=|{}U)^$Oj7vC*BJNHiauzB)XohAsH*9xjX zQlT_1*t+kY9R0qXNZHQ3W+8YBnz=T$RvGP$cag$gSG0VRGZ%mjZY|P*HKxQLPTAb? zjW#Z~MVfw2CJBswtV7&rrSlN{soK^tu+!>e+hc|{@OTq7iRCz zOf{jle}Yq6Iai73NzmY@mXkPxUn)q~kDH*c(8)vJfFr5$Igxi-he?%TPruf-P93p0 z0Kb$t3)BmZF%3bD(RYsX>bakblg3Bwsi++Diuy+8d9{+u(LH~q)AZ$?1vP3q9hi5< zxE0wk;(NK2cxaE^Ij+}^ji7}c6CQWDM!!9S8Ox4M})L`PlSO5K>&QpQlyO6bE60Cc|ZA0>z=7i zb?QXHv2|Nm0?hStgQm1>L5m8vk%YN;`BK)VzRCCt415nogYfivbk#gt^7MR^JijEM z=B;WiG#xlbsy?LsaLwz-BPwO?5!?B~wN^Lm9_at)9jW#Zf4C-O=86@1D=>eAXKXC zbKp7Y!3lwt;DtvPjpxF7ZnVeVNO0!w%B zv+L8;+L7Z2JD6SYXilzhF~_kEsxfx0zGu$@)tw0@!%0*DL7am~PlIN=9HVECoCe`? zv22Rplr~>e{HC0~e`vTzet2Bq@D)mzf;eeanJ0#koiGc~*kJ;#3Q3|aZqqkA-U9t> z_L<+rdhFe)WYD4NSl{XIozP45dtZ`mi{+ME1%eG%=S4d74Cw)WT$m?3V$e9gD4H~B z!h&4{<*x%f2otB(qMcZ(~8TuB1qFAW-1LXE(`jKgu>k$C;s_^LFaV zNN!s~jbdo_H%w=+na^bUarn+eDKk>PdqO^i>mlM3nbWeO1hnHPyNaLqMg8-eXeTI8 zl5lY{i`o&(T?BT)H-kk$oM{gULx9@28xgbioHbQY<gQfSPny}^VJzPf6)bw;a$e0y7)DXKqqQK`z_Lf`Wg(z1ztHszS z{xr&^LfMM7*=Mnw^q4NJWfX2Vt%$!v^}mo7KM+b;UjAtbmKI$9$_Ot#ymFN8pUnb$ z{2P+Y$6vWI58+b~eT!Y}n51zlZwLaPhb>A}UH@4H>*^X<5gIAy?YqwD@?bb{O#qrG zo`o_@t;1dU5oaeLJs4vaRyaO#FuXZTGORt1oxrK?E%UPEbxo>!O?K6^jzeEe&62WI zYdx)h$mn;h*0pzQHJ=``RNk3na~-q<2kmCV`SI4^`JMRbk9K7BR{y&3+l?Ok*6LgH zl@IEB4J$&gl+BU9#I>kd(hu65zCCZjsV8$q*D)+VfM@niiPV|>$6cPJV!A6&YGuYG zk{!NlXZi?8dn7Ar-@TGJOJ|$WCtz4KB$krd(8pMG^GdJ7UH<>nWMzA3`*L0)l}Df$ zbtmxF>pag(tw=k_TBR2oyFiGiLpCWQ-10v95912|0USe-C^k=SE(_^N7R*JOkyu=(cOwRYJB-kR8_}%PK za?3G=Z<|_t?5{i1#lwrl=^Gr_M4GEUbCx-bTGm3(AP+b%v3OmTbu{YpQIumwZU44_ z-$t(2s!4yhc#fBE>Y$1%O~d@7)jR|wb#IlcA1cgWYT44z27T+}FnFXO7_@%lVk-(% z6qu#8UKl3Bv*O{0sJrl~b%uSU4iT6S7=02#zJ7x}Zt#5y=jyA;)-XvE;29yVO2$eS z%nd}B*#ie&gc22LCOYSuD_LKv%6R`wBU#i7#9|usNyIj}7+A~d^sl9m$TDKMyss_3 zjsCr_BrpUKOSp4vRsY~Q2pbg`q+_Kw22iIO2ju5H_VU|^xgrIJ+?+ZS$D5%JLn(RTybfk5Ho;w&AS{eOg zL^5vZ7s@41j=n`K#%ttodt)VWly|-v$2sAIf zH`<1ssv;prFYC=3Z%1Tai!f_5)5#Psk6K}n4VVXpe2GSZZ_W*1)a?We)sQ|g3law0 zu{$SuX(ga7wYBG5@nyh*DwhX|exy@jn-1t}jMZs_g^>n;#U85lbTJ<@xNR}&_X$BK zbB%FK8jDkqKy_qKr!HX1iDuk_0eDxg06?@|zQsSAqi;9)lrhh0QBNSa>HGS0??#CP zx>~)_Yh(^#gErQ&hIkNAF#P1zPiNRW0(5TCwK5wXQFljJE8C6apr~o{nf{+RD1BN@uK&3 zQ-jW4ll$H-X12)m;`ht{a%G;+jS z-tEp$aCAGYz@%4MxW1v-209K^8L4|{m6@5D4?RSwsHs&|sUc~*knc{Nd#F`r7ekR? z_iZ+ppu8^u$@1h?JQZEM`G?LrszUv2euq_ z?OGHOAse=kJr*MBNN8#qdwm?x1n9X1bns!~<3RIE)FK8GxN({)G8!>Y<;4d!&savb zMULT8G3zxNL9u7{U}MR?>c{7vJIIytF~#uo$S8|qhLzmbR_O=qV&&zr6VvUXTl~5$ zeGCL_SS@rB*nQQ6?m7*=*Ks~}FJcC0Z!i5<@6mC`W+CHY|R5FLg*-@3Q=eN}alwfot|`o_|++ybkZ=Y9s4%3yH^WE?oM ztlfofV)HIPWQA{h{4jyaT**I3uex*I+MtA|oalKrd&QDTPwleQ=w(SF5?6Y%!==i=IvuVv}hW ztWTVPU#9gg223Bju3hY;rrO9-yDuZDs40!l&hZj9zpZeEPada7CaC0PWeISvVgvc; zmig%-g!?Y+NQOn$9TGH*vV+1mT%;@|d%nJZL9Mh`Luj3P?N&r5HRY%da*3Hv{YY~m zg=vdQB*Tw{g^$|D9_&#mJr2)jex7}-rZ)Pz$sDgr1t+M(JgQ_f9htdl@*lMFCbl>! z$N6U7d3y-oLX7%*B&-k~^t z7>`(jheFg^>Im)wX0xM8*No+2n->_Q9n$t8eu!MM#!y$_#{9%TS#N&fdc&WSHRl0J z{Ls|9)=gsNFMB^X_Ygtu#(c>;T==t7JAZeI9Y~=m#L9@#(&Yrd|MG_|ZhzUL1@sYV z0pHSyV@9MUmE%q#sfL8{?>&qXt0{#34labgRQ)8kk(rU(?cMoL4jYU^{*9HyFo$g_@DN+S2mx}qY@!jOo;RU!39NE3U46)}e<_AO zYIbOkF={gHKYq`S4W(Zvb(^SymN6IIle%RbP_O7Q_!1@3Qr@+QucH+&Pa8#3Juda8 z?0erce#bD;por7gv_#xP!tt7Y@7JOu4`tGRzVL~?Ws_{&1H|SIr0bZsB<-sr7un=Z z4%QRAC`pvZp(Pqc;;$lH0-1DIS?#Ns3EZ@A_W*0qgDZ9_SF{@|Hw`L=Z+}+I5|a;l zs>+>zkvEWm=mC}^ebZameiOc$f3U5on)Sj*{UmDFIXyIECf&Q$Xyu)Xt!q5j;XQ$w zIG3%(t4u?S_53>v-)W23URlT#lfOs!-xm>s3<9qCAGqAi8W~8XBVS*?=&Z-V^e#W) zTfnw$kcG}y@?-N)bq-`xT5T!K%$@&9;KGySwY3F^T;Uv7C5vUQXpmn^yf%u)k0q_( z0>*D$9qD=!7Oti`^twl5%376tD*<%5IuFC z=sSLYFMd^jCCunRMV@f~=Ol3A1u(D=Ee27xd%2hSHjVk(owW|6Ga;JtMsu2$2AhzS0cgp>W$|my!jpfAox=_g7)>1QcYp+YpL6Se2l6&Xp=Uh-( zS=rGnSqF>uUGj!fxRJ!Q&+a=P*QJPJ2yHE-DXgnB`jt|zX<@G-7 zxhn4up-A{Hq|Q|x+S zsK;t>N5f8V2M_DDv+2)d!&p1`tI4fbdr(hLiU)w9E830CJX_;I(UNQj^I>&q>q^!} z$devdAfQAdD)a?W%mAB71^!lDLT^0FAT2>A@yy}Wf0=}67OOPfu_(l3Aw8K(k z$3*nKvq$K?B5~o~!sV!Q=ihA%`Ct={+T}f4dwC9v@!aLXeM#a}ZUXWJL*WzvjKb_{;sO?CjzA1lyBWDdE*KwLcy^ z+*Z-P_e`ttMI3FiEgzNAuK;J#=>qgaAC#uJ!wcM6GBwbYE5gdmUOr2BW_P(`X%6zw z?FKwMu!yAv>8(_9R60}N&LFDNom(F{p*y$^e1lr56jNePk{nlz7BhY;d&6iBnEaWQ6r<6J!5Bezk>; zV+%1_sIZLaq5IEYEGQ#F>)Il4KfV0BRmR2VmC!OScJ_suajDmbjZY-FAht;f>lm}8 zlL#mpNsklmxKE``7OkI+YaS+gpMD9sRDe$Hx^_1_sSF2`#jKi(*Ie=HvN+OZ`Nn45 zgWBuO&!7BeloSK*S`{0Pzag#vMc$Lv#NKA0uJ63F>DHBC zQ+ky(r_?UbJLU`+{mGDG2`GcfW-RO>{0aMz4^yoBc!5j1;kTSK5$<{w03p3c;Aog& zf`y?VHp}cB7WQrQdl9z(m{AJ_L!}pjY@%af;JXnM<1t$Iiqm=J$}7!3{jJg`A=pQK z9SS1eIu+IQogHVwBgQauvwH50*KA$HjeGy_B>#)S)broJ5sXbueu$> zuU_b!BEg081U`6l`hJ{HHh@pvp*mVS(Ng`-q0stc*`HPKKu>9Q<(WV7VYZ1b}LYRXfsY&qkT#XFu2^3aX{hmR0c2}oLZsZbw^LnS(a(QJRzDx>GoYVdXH{( zgGt78z(zN=N=Fd;li@-GsX)OrXr9oXC(L~fBGBw4JN0vwn1lb*#ChJuVm(kMptk}I zA$9|%*;;Yrua23L{P-JQEomS#%at_A=k6K7hJ))VcdF_;I+o8v%J3N=Nc+ z4GW`=eq72rI-Rd3&3(ATUsWPsw-cKYMwRJ*Qo6O&s=^oF>uB7}&~`N^f{m1sv*mU3 zgV)B{tVzc4->=0XEu+0+at*y-E|VzzPLcdA^X2V^Oo-ysWTzX+6gE9M6#pe}cz__4 zcI@g2y~rSqlioICj_p|gc)r;I5jc;N;@n5y1uH77E}AFbd+YsHR4jpp65@6Ix}J-4 zy&-~G{!4rli!(mcQUBv3I_0|KZ*7d9`ve2~!uZxk!bp-#c@}T;aE-((aw!G zYLwI9{4ab1A@w$m5}2;>#oa=^i_qUR9Ol~nO#a;zZJ>boD`VIwDvvZgYIU)@9If0r zx}>2OkIz2Ts}td6?Om3nNJ`1x-~-x9@61y7GL z0rc{QTN<=hyICb8SoK*|Ws>QI$W_CE@I<44YE#C_* zCL9c-F6c{7tFA$PPC~!DN~xwTlBsd3F8pf~lR*WyL38+&?}x6E8N@B-d=_U^3LSHU zRhHCm*$YGSRv6}+%nx&sRe3GdRZx8Y@VHEDyX~4cHv8d&^0F(Dh6(-AmNgc=xrW3A zFV^HYh9ncXB6}t&{0a8*DT3$UyGv$=Xr{#zQhDmp793V`-9QjDWEc@A02_s?kAey3 zQfT##-_+lpt_Y!cz6Kn^wMsRG9tr1PFppKN4zGHomLr*YsJ%;I}m%6a4+6ioP zk@6dc>d_;mTF{?LX=o5&y;d~T8`tWfhkgtJ8X^w{(MVOhGJ+MZs>Y3DUFIQkxAseP z%Iom8HxldDL|B+e^=kQ$++p&BfNs1%l$A<2|CB4T5Sw?AZhg0jt1&{TD^dCTWA%uh zxRK02Tj+AWEz~bHY-TBeGvNBp`~1yxPYF!y*Oej3YKXH&H3;$y(|Ma@{}?r`F{CJX zp&ZvFjW>>MdkM2Z%_cdIP^E+=TzZswuRY~lws=V&~`PG4VvFBKl^g%DWZXdxhA_se_YxHrq+FjgvktRe*MGPWbicwcc^qv& z-3D?k|B`F_b5a$$QtUSw3JPTo+-~3rO3G-?uQo*6V;NbY?f`atnvL&KR=O zEz%fSq8UloO=7v@8*jutdh`B%w%LZSeb+r7qhoo6z^T_uS6ps|Ot#*Tnd>KjPDAZ|?VZ6{G6OsogF72vp5);-#^DNNu1raD~()ArPW~QNDBO4#fF74}~F#}o= zQ2XtwV|2MugQhrB(0aNOv5>e>19?C?V-O2*pW{nxR4QdU zs)|oR92oRDAz^sEcfX|p<45rON13^0Y0(ve$$w`D3a|)UR63>x2cxVPKpi&Vy7IbFIc!%(1qGf3U7{_Z(boKpA|0~%hL(^3( zDX4VZjUO*#(uA=3%$-HFe3BgAb-tJ?#Py!^W8M@J%%z-Ex-BFcOSTSbNI&Gk*YH<~s45hS%FT8XVZTTj+3PSf-yF1?wH&WX6$rfp zduYfsA=5_Ie$e|Of9$^X;rZ6Lm2{VMXwFX+3!a-y!C!BR35h31u6A|^Xx9%~=LYLu z4rrU>P}0w8qf4eoC^@0m)4MHJ{jLzI1r%b-PgdQ3moUtvggtt?l#`!F{uj4^2&7N& z#Cx(AoOWUtjF#U;HrzWI!(qcVa<2@wv|wEonS#JqPH1)IUv?_!s;IrcQwq36L5uIP z-fW2=BTP{KY$y(o@qHT(bEE1_s(<|z#Cag=+8Is{p3)4eRm__9PHSSI<`Y0=p^OpW z-rsw)R+G0a&qVYd}T6+ZFwnx(iY`8aPDTnB?I;K7b^V6NqLVjNyDTz!YnB?Hob z$wcD>n41|6X17%7YZA>v^TrP}R4enb$|{u)U6Rir6S8vEqE_g@i?iarbWor8NKQ8!dz|>is(>}c z=+8zb&EEc^e~C1aL33z-0c0l-A0O1nfv)NYYB^{Yy_d-oEM3rv)9gs=%4b(;_j8LW zCQQ0}@X=w+Wcj+vnj|w*&{V66f!5u2J*O`{lfD_c>(CS5loINFUn?)Bx|?sjm4aws z`LMR^9xgx!qsZ}5&88YYjRD&Vg?tImX6<0=Vq2xVtBJk?(*iUwPV-P**D~E0x*M4z zo6thwK^oj)3fP6)5{bB7zbFCWdgft8sy2ogJ8Iww1dza_N5S`T&5sk9WqGuP+uNee z_4E#6ii^8wC@TYWQF=3jPoAq?x|WT0MX0EHARk2(_LZDnqm4lmg!bG3XMPai1GF#Q z&#*cYgCf9797SWKbr9)WU}vSnG^n^e8bT}O)iUq}cz264V7J;6aHSJ0{~jgQBEkp; zNMlMR0PA|L6$baE-)4_AB0!Q0F10ebOA+{`mjA{UyLyylepLtfx=hgl4Jv|MEa;dd zt}{)!i;*rL6}7J~2K6%!2e$2u&dbZg6JB5U_RC{{a1XdqIsD=Q`#S8uZ9m$Z=t;sq zuE1%sHxdl4;o!=A`l~f${b~z~Ls{pxpXMs^Bd7G&$E_0DUUw*N;+!L^!(ygzN!K+1tNE9q5V~j;!sWT~av<<&Z@Uu5Bnr|ke*r4BF1k zrGjpstaq&@#?1YmsA5l_9n+z&bbmW>1QA-i(*fBhDZC>%1~CxJPLhryTjzcwnh0}C z?Q*&2Te5}UJP}k*!mD2EBU60NMZIq9q6MC_#bTq%lg$1*Cybib0f&?Pe4_(x_nxfk z{FUORS{Au8Chh5^@PUM^WteByMf!TM!J4Uu;^s;A#iE|5-$xV?=+3*K2C96rN(xy> zrJriIz%^2*0!pbEFM`yHcl0_L-!`E!u$!y8x+&9rG42lNz#^}hGu3k`3Ki15I1r+G ziOoFV{R$mxcm@%3tjJbG>@l;v7zaivd4-E$sn@BLX5wGV_X5lJ?cVT0wJ|Udr^^dt zOHQs%Dn9mK{k=0@@IFQndv3jpYg4oJRqB?{6&)wmBTnq5Vn0ArGkUn;yxTBMzvxI(Ec zFoc;li*%UwgVOMW&y+-U3vtVg$v20HBuwi%t~L~h6#5?B6g70&i4NMeEQnP6iP7Y77m}+Qdbh9#Cs2uFVjG_zDIP z3f|>a=zmhqfWsdAPIHrgIvN(!Lw--sm5nT%J@2*9;Ct6x%4@ik!QV5wzWsp{Rl(C< zXO#bV$Fg4XY1tQb3xd!mh5s}Ku7y9MP+t$xjSUJs`0?V)bs6%%wWblsPmp^3u2h53 z{&~tn`$27jmS6ajcn+s%u%;k!5+z`0i4J47&g-1&Z6gNslZqt(38tYuT;|_P=z|}_Dsn!4T4iN#*N_bQS+8Mp)0Z2UIL28MRO~`9f$sU%p(Nt-;|=Ldv6`{ zsPIH7_7$B$POwGFtGyWYQu!ae^N;WADwkGVE(}uys#`ck5fIiqo)bm&WM+5!HNMre~#jbgH#=N#%uAFL{~}8gU+wZ zs8A3))C6WbzidK_fD&x26Dh?y)S;R<`957ykSPwPMs%vxMYQ?X_kn}Kxs^6N`Ig#^2gEpxzaz!vU(PnmZ4JJrsgf*A$I-RO*3@h`1prsy8LP2wQ+hZm7O92(D)`6O%chjqE2_ z18$me*pDC4*ig9v-80eoG7-e!q?YB63(uWY4*V{`^b;(%)GakJ-~fw|0MS83P$GIL zoCk3G+lQYi2y9zlB|pIvC#A*GcD&#E$gIpx|3Fd)0yvhSOB&8VJN0(9Yl4^9GodRb z`xSA&Y8mnT>p6mbZ1I9tCYmYexTilZkaRVhiO41ts;C;1Jf_9cb6i9mt2v)MB*nw^OtJd=p_(XN|jn$WzJ{r>Y<2Q7-a(@2_fg7@4X*% zPzdHI3VJks?E=MRms}C2%rl{$5JJ`V1d<(j2z$aol>g?q!X_~hW=a1o*Cr=f#i0nj zN_F&Ucig$cz}K3VGZFPzMT!j|s#YpW+O2YLN!J339fNedqdp7lfUjW|T_k-aDZ3Q% zp>Uy(84i5LflAN6WEWsfnqD^tn9TIYwloIgH)1n9z>*<{&y?Fg8S-BhZMbm*OB_xyk%peV-if?}PTTS1~)gcaCDl=3>}OfG^xu zxiZWuX7W@omeb)AJ60RCX7-A0B-9RI%O(*}TXdYTVgNr@1G>H=GiM`_Xm@L2CW1sc z$>V7ODoQm4MU;Av4h%d9?&okS-Ha&@(R_$rzn@?gcLqrUV^qf&(gk|6j*f$2ZbzK$ zqKG`VZU;bFjAB<+E*Q8u#mJHdffBX@8hqh{Yulg85batw9LF49) zfO3x+6DD2XIc~%fK?oJ`pTL-K%x$}^%7Lxk&N*MveNix~h-|%fA*)K=T^LHlXW|Zf zCcr_e`QV-ZmVM^?D}HsSop+>~W2pI55HXk!?U3E1F>P*aXuE>v0C`{QNT^* zBDwxDe0gbPvtipxh~L}K15e!e!zxNuH$K-Pm5eZh1jE3iZS(4AKJM3egV-_>vD|@K zt?C23)1M|w=d$Va3TgUUd>*XkYsjqIajwN5U}kBLdUZEGfdEJX*^ZpX(S#C*Rd9aI zICd$Bz#&yt#4^n{*F6t>d9DG+vFJh&CdwXLs^Zos+M=|h0=qzzzMCz?_OlO$W*2Et z@v1)6Xc#TR*0KKrvmlOoD(N;hH9PxA`^I*U3!%HWzL#t+HXats)eDbvA6?_E7QsZk z1i%wx5U}8H-N*rAHgX|xZJyX9ugg3nB816TFi_(2B3XpaoB^pm`GIUbDz8&@wWx!u zmTbKUJIKBl`e9PjXyS4({%a>_GL^CeOrN9+O=K*md}nxKYXeFCU+ph1oqvkRyyBdB z0r6atGN5?-k9Fx_Ty%aoXaT zXq%Rno8NA{vTZjZ$g_T8hZ$t&37~EUYd{lMB&6Pj#*774^2p_T@q}l2ry14*(wr}w zOY>Po#cPGSaR>8)PwV=V)?88)*XXOAVplZ@znxUky=Z=B*A^4~Ma=EjyYiePL6w}T zWH-gQxcZ<6TFB{9S4||ur@ipDA1>j2gK_x8kX#=}g`g9Ey2WH2cm=ALKO(a5G^y#8 z*2m_nc;O{8G?d1tgrerYaghr5O-a3~;fAB@AZjipB@!)+u{zVJS2%@~&RDb|K{fC}1;2)77l z$hj#Nb1*VIDhg-e4k$rzxPM5{YldxgTjiy3`w7Szy4_q5xK^5 z1cP6ko635|j}B=C)0@F}1d1@}mKlr&T%YLFKK_nDL1KmO}HzV_Y^h>x+I@=(F1cl1AQ7r+NS|zYeZ_qlDf_#%A|! z1s!3ai&_%(?SJH1=|8B7bS2BFll|8nm#K1vSR0EW;SsI)-_*41%TJ%-xoxzVUgq6- z25c_21c2}v7`~c|P9U>5L=!R%t+=FI3~tJcurhz|1DOg&%LxVv_Jf^Cn1ZLGB4%|9 zHq(tj4NwxP?>f>X32V5<{;F^==bz+JuwbikoB0a1AetVYWuOfwt1aTXs1=`Y`EOHS zCX#`PIRDo)feBCvl3Q{*FTePFDE`#?>(N*aUf|BdEt=*rHv>>IvP1Z4xMTft2;!uk z?p%$ty!Y$=aS(~6Fkej9HZkgtiv4x`J@Zrb0Y&cK`l^@SN3i9Lc%n>l8IGS)My=uT z)aRueRf<1HY z3lyqvUb4Cw?X*yMF=-nyPB`yD#>h7QKWvRH@c(89d{j2mIeQpP_!s7zGA|STK&Xi1 zk#$bIKzhm6XP>FS$h9NCK_w4(LU~bAc@LY&YY2=TW`Zihn1z+DwDk%Y z|KQGfpp9G(-Y+)-&&RWz{wH@9pZgVE;1PX*6k{&W(o;C(>1O|!j|{vYoT?L?KB$<*}p$UEn_`)a~b8oSN~0U zC4(k?`_M(F)_3PJd=56;q9K(A5kuvSq?3CGqD1BokCpH18LpgLEdZHHn);3}#l3~Y z6P^Z8U%KnwXkBgXcp6Ij@n!836RxESr#2xs;N_W#`khUzOH=Zb>eQR;Zh+C*BKU#X z`zI;$&`FH!JhbWQnTc)ywx+nyQ<^EreuF5&WA#+;;dj&Kq`nA4SsrV^su4(DgxVFx zN9-p(f*u5Sc&59CbGcE`C`VC?rBQe3L^PEA?S;gpgzk0_bY!gB;5Sf1p=m zFbf<9bN~|!^aLQGFTFtSwKPY7)cgBTK={DS-Z6fkJcfQ1si7bQ#N;iyRl>^RW^D`T z$up)(!1SuJ`tc&@ihFIy^_kvawJL9wn-kv{SAOEw_9>E5@XfticG>_vX0k6Sh3Ma} z8E0%-On%MrNA?28;q`6qTEIo<`+AKXRRh&a`&bb(D4l%oRja~qMV(wkxeBG3ML2vS zi5n}mh5Y%*fYiEq1Z)4x5v${~vwl4!bw0Yv@PoCB47oI#BEaAB=sDBJuW65F3quKt zf>sa7=(nan;`Xf#-hOjsXN-b(NW*YK&UgpSKPmG!QHW~>S`AOeyL7e3o6XB{3$U^e z`zoxSzr;9wh?8L+zhu8$d$euYg+$p!x*m{K6f{@QJKtDd6en3$zbrsqyu#(gfi+w^ z$79s3K}5lydKohZo04D(!V@ARK_Kl+h#I< z6J7Vkn>o>$R^#v69UTRhvV?(6XttRge?B(Pjd%E&{wHFD^|tQq$1@a9>==Z;P}Is~ zT^gC$uP&45>Bmilo@;_>C1EPB%iX_D1M9brYxmZ{{9~#Iur9G`^n`B3$laK#I&x1@ ztc1;p!wyEZa%iQcp|8jj$cFGFHg0!zfRX7K-*H{0p)H*VJM=6kW(@|{CahDh=U_^* zi|}5Xgil+lW4QpkdA(u@{q{tD^$@kD?;H>Rgwe>dmR08g1%6$^yXr!k<@q2cci=Y7 z`z`;xcfqP%ejLa*XTz#osK_@@xJfrpRC5#!?p5I*>j$W#uU1*QVNoI|PsgL#2 zfRYI46Cg|s+D0m?r}I%mx7jvGDBK@kqh1rI>n2W;vzzRXZ{fS<&$wD&W`~8IJZNO#g0d%{ao% z4km~HzUY4r3+C1X!s8sfuX%^Zxv$A~=z39umQQRqt+$hJ2j)yG{1T=3*>m(c6#Djw zPm3&%iZ=tK(C-aof%PQMv-}8#f*z6j$!?BklQJ+#&YXVhcqyk~o|l{P#Z^sEz=ky2 zfy?$$P&S{t?X5z2JU8<=f&aefe(7KW0d?!= zo#Y`2S&B!4Tq4*R?~NRvikqT5G17gN^Ff_I)tO_nl#+G$sjg_GrUgqbg*?tyP1zLM zQqfAJQ+nU|9K~jWzM2#dtW1(GM-~17eKgTc17HF)wRVQdCpbyua8PEiK6ps;q{@1k++xw&c-9VM<(x(5q*5;nzf0;=U)_{a~ zt=HB>mCs5?6+J1U*5kE>%x!&pme#AI)!|Uza7J14U=|-ysNsF+lI)p42z8vaO0F~& zyI4#JZR@S$G#wnPuaLLxzt>P9DPK`u;p8o@|0KrHMO;FE2?N z>2XGa-m>z-0Jh?0>c2$Drm$xtXDlA~lO zC1)f_=7>lJ$w?$h28ohWsbo;Hprn!{Ip<2J5BlByzV4anSv~8{ot|FzSFKfbYM;H| zo!|F;p2tx1ox>xg-8YvW)Abkh{_|OF+IrbXAOVg-~VSp z9=RrwU;p{6)wBN%UOIz>GR-oLg?QuvOGhd>{@BNUbJ!Elc3|{G$&LH;y->H3BIJ$M z%UKbNu$dV<7=#VJS^I0qbdNtB_m4T%ta)4EU*=Rz6`}n<=gHc`ChC8gfBj!*i~nU# zkuGch%lzXZHO~2$f^H|N#Q)2){C`Kw|L!l1PTrnrcZw3;T5w8;PMmtLDw4T<29ejC zu*0yI`==07pu4P#X){rl^EJU>j!U&8U7DKy*O(F4* z;$*RHJ5IxhCilK*VNFK?jUC|a<4Xe1XiNm}n{JwxeQLV1Ym(ccw_N5j0GiR%DnI_V z>Odi`T`u)8(}6}Tb(5Q*OApEp$Q}=|2j-|tv4)mU^H-b9?3;hI=mohy`=v!L;dmbD zeQa8Mx~P`B5UUU>;~RJLeunFg5#b=`-G13>1ZG)mW|CPacP}tEuu()!EDVETiX)r!6WUl zuDLprccj6$S;Ga*a7C627!44GE<#{)DO5GA9!4`i>o?l}LhqKixAGQ5a=_l7rZgbj zQ8w+rGRJm)2I%ln^|ZF0F~B>{S}MJRXs_htk9882hoNd1SG~Lf`Ls&`ZMssdkIt_xHKcEE zraEz&ER>Alve|!Csql3#tNxSLb@Wc%2|&jH%&Sp$D;vD)gMfSYpe$C~=1RWdMSsYp zU3o0%nLC9L4LO)XFc@txoJ3Q4g0aI3bB~?hlTjO=M>DnQcyZo3#ithWLGkZbd`s5M z&kY0aw!O!R{F^8Iy4yVl3M4omTd5nQIOr~xG(Ab5eatM4Iv zjHPzCMh;!(iL~vM zIX%y=C^M3-ZMkW`S|6{w!d&jD^xFk?})L=7gv% zC&K`is3CNRdW5rgVHi;i_{D4)a)y1mrbd?qQ=aG6FAP=fQS6Z*5{G=;tZNrh#I!f2 z_Uxo4qF0(u;^j4Xx-}{+CA9Uqy#=O`NT21@B5+wBa7B&JgI*P&tBG&iGE-GVzT4_I|PzRPy0!pSF-d=~aBwMmzwi_jAi0g9__lO{`Q|DRI zB+0mGm` zFU3Gxe%PI^{5T!e{K;^^I)m+~N+(?KmG%#SxC)Q zOc+6~CYh6yY+^KezwR~!<^>(s72vN8FNrU~& zRDI^v@9m9d=(G9-FYeyNYxPdAU&?>I9`G?e;`YxQ6hGbcv=X?X(Sy)^Qwogm zww8+x-x{CNv^PGFJ3>cL-E)s>s&DfFiuK~HT9xS!;>TMqDiROVR(S!(+)a>!L1(3q zNnn;N1qD~l37d_OTC06RLs7&PyVvxMI1t0FKPF)8-h;Q1Uouz)IIe|MOz5P#$ z-N&o(JHU{GvLkFN|D9``(Ufq$)!&e3DOTu;ckR=c&mT}o)ZM+}yGZyZg+Fy%&FRZvlbKXIDoCBPmI@cR> zh%=`ch}-t?6;)DH)(h|bqarij;Ee!h=>Gqi%=e7ontP^qfZ8G}Qw)Xk)V1;$gnAWs z*o+6W1$*0vhn4V+gzC{?;uEZi@ao_=1MyFfYhww4T%H#HEd5g(swF!O*F(|jh58;F zkS`4+d+Z~(Vbk0?*`%MjN=KQ5x0UVfQnL|Cyzfi~6mPdse~$$aOYS>rz&bPh?ksR% zQz|9BQ-d$0y1vsLXMy;s02x{4diz|DhF`O;uv^a)z>`M0hN1929#VPrK<{ zF?JmC1(|&gPmoYxJ0HSZ=fqlR73yHM^;>mn;_=_?W1OS_)MuUl;BosOYMB4g1p5C+ zMev}U$gSyyLdIt9L`<*29M?1UwkvUtbQYZI&bEC{WOZk!#9<-jl2XrV(>RW*ryib3 z1kKgNOA~p!9gBROuIE1tp|24efosZD3Vz$|CNsV%rt(21c3kVm;hmTH%*9m_^D@&V zdN2Owo79rkrrQJ8#i0|MYVoNbl-U8rn0Jh~fjdI-d^c`&=4nWdu<)G#5SpGSnc7naDBt*ZZV1& zsPol@@C@09I&?^*w)l&YmQdE`!jKVp%@n04(b0#*e`GQ)%%@^Srbq5}B7?E|MaHNq zom-)sj(z=+X%Az%g!At&!uItdv>1PBj(U{%cV4g!kc5!I>3eip;^uC>eI*e7s#_(j zh7!Bj6I+ND)*H2`?Km>OTa_1M5n7Qbt+=@i27or z!rsuz}XqtD0JX-CEYcB=Jv7 zX&kGFv>jY}FTj&9d*A`)QmrmKn2NqwF6)N&{^&#xTx)c?cgLaBSA?-2IIfn{!@*!& z)SH)bvH6w-hLYwL>v~mmOVWD2&qWdA1lz`URn96~q_wGzc0)(Bm3PAlPll2 zICDe!$LDP=TBz&{vRMO;S+=Xu5$(>oV7&QKcizz>%GYo-PUF_=ULmG|$jH;p-yi!vO(Qj9hNJ@K~q+5EEtll6#7SgrT1HAZbB%t{Vsx^jLX0rFcq-8 zUfgxSayA>UVHp?eBMmh>9RwQegg z*ccAF^=)Ru5X7N~!OArNeFSel-UCDz8kbH_jFGs(HMn<=eiX81a;}2|AB&6I)Oz_>MuM&JdMBDhsthnYr6uW_VL0z`fjrGcQ@g=L@`aD-&vE#VS=8s z?Oji3yey+%zkpJg(iv*jFku7HK!O}0`|>`9l$mQyzxj@O0+dD>Hg=BR`SM2DQ;8{MSX)P1>w9wVnH<+8B z<4!!I0nF>S#0Dt?M^_zjX!|p-ow+*kgWYJ%S|!!E1hK;<%a0@3SNh@v28Wq>Z>?+6 z*^zz*YcQe| zmrMHuE%)?M#%FjJ>mI@NFhXk2{vu;cKqG=~1-Ty51K%Tkcsr0L><0;vRQ(LN)_M&! zJU+|fsVJWz4)2hS2e4rW3WhZzv^I*%IAj|Q!nh(- z{p!h~i)da$68yOttrb%i$Dh9mfU$GhfuDU0lU%(MdTVW_hwCx0|Gps6P>|xv(z6u- zzaJ5OHw+A~1t&8{$4;ej4vGz*M+ENT*13jPSQ&fzBYkISZ=V-$BWF4F(aF}YZW2Ub z&^uXy^BoAb^y!aeZFwn~GGG)tvve8gDO<|LD|zOUIyE?R?8_as3>-}df`>MUeTs(o zSmQ~opb72vu0yf{WE}#i`HS7lfUAPNz!UIS?0?hvwy9H_CcU$Om@9C>+!5n`L6cVg ze($UzyP^6B-MqSe(uj}Ti@gzl+qaJVpEiq%h=h7`fZtSCX{4}UpklWYJ?mP30^1@BDPCzYVYQhZ~&M4s* z1jNv==#DAFMespXPfl9YAM}&>`+tx#r9mZ%RzQ@@5LZ{7f>xCoB%f>{`ur)>3p0)D z*^TcZ@+(?}&%O$M|15l^9>?6;EEpv`3js>4KGbpo21%E}eN4kZD;V)nk`ef$hP)NpFKIvMNgP@f0{>}$M zPZFJh2`3uQ{FJH{H|x#xgb+Dm@t|M##lIHctjm|S5w`ze^O*Ju^U}pvlS_B<-i#+4 zzw0Y5**|)rHxtw^m?1e3)E9ubH5B2Ok#!J#QTLqO?ubHK_Z)Y1ouQ3atQSwmqHr?# z0oCUgjcIprt#iV+bFfU7`f-z5x-7y10;Io>lz1S2Eb#k=^XdhqaLvKeuy6xZbxbyB z`W)jKS)D-bn?E zrlHODtf_kLV;&BEatbBUOtAg@a=M{wSyXhKeB1vgJ^X$k#sC_iguckE%Dq^Y6k<~1 zz*?e-rD1JFU$aOF@Z2)+{8L7!nW+~Dn-;F}V+xAHxn7oY;yx(Vx(h+g#w5{;xA@hT zGQRNKnk|tqm!;ESFJ&)FeC(SF+1N_YzQ>n$-s~1JRsb15`#d_VZcn4N;o*jeU|!(* z25;r7l_cO~TSePz@u|}kBEMTB+jDqXyl!mmgES{ey_{`V5p8Z*SZk-au$e>qJO|p6 zTU_^Sfvd3!;=zHis;vI68Q&{(v7TslA=OaXZDAB$!2-YEyXAgct6?n{6fWN^-{!Gx zF`>(qPF4q0ruj!BuProEj(kJGgkH`C8cp6gUEbdd{z!%CTR%WGsi~6qV8o<1myQ%8 zY6|v~NBqmh5Tfafg&w9v_Tt;VQAhi*#uE=zL0Hci9O_dmEKGPR0f%IYEB^H2UB(g6 zTdnq6i8yr!w%zXYb`Fix&(B%jciG-ng`agb6v42HJL+(Bfw_NoO61kDqXYe-_BXi7 z{bl83u&#-1rgdTq$_D)ob@A$C0q1!>OE6jnng4J#K$A*r!I!-}3MR3&SA#>cmA&qjZ+N**!}dwR+c9J>VigUmxt7WGZpK}%Mxc}t?xZQ z3A+ebQ7N3IQM*Ncr}1CD(=i!s z^-QJT+c|<@h7f({3zLr>@%`Z+<5IQGK0Ox^P-tBgW_uE#F5&MW{*2y^K!DM)E_$3V zfcInRKir4~bO&U@ly{*^4|gc+upaN)_lNGRN_@EYg4J1;a}dMJ*5{xatIE$d`<}^s ztKjZqEp~$>!DL!}5~_7AWk;LT*t5B2qf56!n5I`mvZ2HbG%4Tk%Desabg7-ZLmcMw zo~vz+W4SkfF@xnE@yVM)-~@qY-a7e~w}n~WoE*wtZot8vjJK>gQ)?!sVX?DUF7*VX zuOxvJLlT*RI6Bt)kHMkFGWL9+A`X+P3P)Qt%u>~QOmP{~jD5A8^P|M86*lyi)~wf? z;c`9VzU6XnM>^tyQ98dec~UveiIRzQWFO-j?+GtyK;8{r@cP-`94plWANA`XeDCi=aSa4e`AuHNPny zugMgZ!L`zEn2b<%$YVo?6Yw-wXij$_tUK*7s0+xx46;c+AiiwN# z?1M04zCo_HNq_oFBVuq5goB@u8G*k=ao567Z=Y{r46~NsxCb2Xtyp0YdboyGZ01H2>b_djDh`%GB? z{RYa@DazbpX1=-A%S6)JGds779V$FQ+QcC4WWedHN0kntm2 z@Q=~&-qifh$^O6P%2u={tC!Q@rECzu0-S26w(2Lijvm|tot-dsA(s!2%luo%KT+Rp zy-MZPAH{_oPkX$j8@;|}G4Z?p#+@G}S0i437bXAkEJXk3IIYBek)KtS`&~}-PtPe1 z&jF~x&kgrZ?ymuNg3P!+cC46U6jVdWfYtty?4K-Dbb~t}ztuL#A^A)ox#Uf#zr9KZ3H;}?ZK^t;+k$peAtP+G+gn;je0zJB#jZNVE)LeE< z=j3!5`ow|kCop1krFsK&c8y_%t^!egH@tsDO!I9n4edk`@&)@@d^QNu;$+TCIM+Q1Abpwn1UqE%vo>fh*$<;z-Ya9%t+}+@P5;2QJdP zou!=yAuJefK5O;x{sFOQHzK#!HXk1ySIo}viad}cf0mRwBPl*UeC|0NEA1!oNjW_z z(FkyBW`nKvOtL@}L%}1x0e?MmF34N0u43LPrxpS4ET0U)cySX@&=tDc_?p!H@O}Zh z-+&lwnmrW}_R&5Er=R!g+Xd|phB-ysfyVVc=$>KN4VMTqyZgmwAuuXB(1DEalerP| zltPx7jRA80)9Va+x9g3CwXfehT}W0T4o%7GOVWeT(j~Wwd9H^*_hZJtfnJBUo})up zJ3e+8bex}OCsGh#_hBvE>wB~8_J>cs>JOj#-b*S1Y3S<2P9=ARBGw9DS}!LxEORym zWBG=vJeY_IS)le6A}u#!FkDhX?;{prn8qZY&~+8bB!N9SSSC^6V8$+8ICy+Ryg*JU z;bXanOV|1@@nm2p`)%P#J1BRsAGQ&@?=m-&Id`CsljXaSz1cMc9{`xK@a4t*0*9hI zdnG83=Md$(C-&$G@FGI8(glKF|4Lip4vFwWke`#WpOdZh5rmp>wxV>=W6gL#Bfxae zaADSkAT8bU!TG%~J8;Vdu794&opzO-Lc;4Pf{VqY9_?kv9(978x|;2TNxc41#Bm$} zL07&K$NvbAU=!9$K%aKVLDvA7$Z-T)lK{n5)+W?avzB9UeFryj$l8i7!o2%7R^sov zVZ+3t=7RpwGp?|K>$#vvkoBuRL&O-Vpm^s>o%p#)0!ztkuU4o>S7pvB)Aw1wOuF z9rzA84)5cV)FJZ7P{}Y_Mz$kkBI0b?6IS%T+@j>E_T=DpZQI9ks)zNK>}~CXTib}l zjeM3|>CZaFx{K)SCDoCP*vW3##}n4KWwXEv8c@%f^ip<10EdT~dN}|@-L0OgO2Kox zFctKz1s5R}b?KcmAMxu^h{aQa#cU)<2p0>OYxC=~TC=3SHK$%Njo1m;$!5WB@AO&? zYpF^e6i<5XwBHN(Oc$sn4H$b^obr^a3b(!lkIeHqUbw0k1?vOusBB=ps4$EIp3btp zrGelXx{1pMPgplf3$hQyv+uSY9n49zZIx$>&iZXk7rLNAUDDd;8QZmPv*CO6Z!+}9 zK1B`+SuxVAq6QKDHa32BIN)@5{&2mlvYS)BXf6wAU1Wxfv@HwNtQ%Fxy9G{s?3S|QKv`~Zr$8dVLyz7?#10ies3oX5?$XP+ph;vD!>=PvPQ6Hve_A#ppfo7 zm$s|0SYD6c_GoU!7H7KtRSIWu&fK+g`GI>}gw5)mrSdT5R?eR(@T(U4S?Vtn1DVz3 zPA^m%+<5t%K4YzW8gI$&x{u4EUDrFkw|I^JKsfz@pF^JSk0;OJXqm0=`Cx}!S2fsi z|3Oj6E}IcB5&ut!Dj`X*f6!yFs!K$?Y^05kXhqTY*??R%>I2bYzHgIn_Q4My0~okCKndjS&lX&8>mU4pYe+mBo^Wpzjt>HvaU-Mp-EdKK0w4`K>(WUMU zH`d#h#~2M^NcO_^B5dQ7n9FlykB*2CrO~4d(O_sn`xh953`5&Vih-Efdn@nz*aaL{ z5l~P6?(gl_TKaq#hv9;OV`GBAW=G1}m(v3^aOpX!-3y#;0*}O|PIYz-hu}l3K>zo| z8lhXGY*d5rScO3qiWXK#JY6&p>v5W%UG0lS9JL#T8{0~z2bq$DALvUY#| zhOFZu9J>E2+jX~#{!wrEhr9p;ACiN<-)D-sPR=?CIB&dEO86rMVS$3~_veqtN~O&? zF%OIV(GUB5%e*tcT{&g&r=SfG1EE74?LpKV;PCW5`UNQHZHEbIVD|<*BLzMCkUBm^hmfCFI?k0+M6!%b zcZPJlm%qBFaG7tPNvblg_`#IIA90PZm?3Nvv}I)g2Ss)73if*R1D09e;nv}3hb=LF zQR@e9Nt}o8Ay5tok$`Ddw8dEbDM7*>ma1Z21Gl814nL~!GL%rWwyW;xUesV|9X%L2 zGwOEP+y{7B;q9^y=o5}flCxNFC;p0+PXx7sp z*0exOPoQpAeE3S|4FrgF!IfpFwXbEg^GH6SEHL>adT}2FkSBpVhY0ZN(7iST(_h#F zdf;9k!x4DAH9ZFN1<_lwqpthmN*NE>U9U(5LdqKl|4`nLK}YaB{wBP0lcEr;fE~<^ z4Yi?d3Sv~aLL7oY^Uz~(4t^T4R*-6DuOL5VBLFG_n>~fBNvKaJ;7<^C*a4G*EC()X z%S(`k=<5gei!1j%^fdgta38{D)C+IiA87r@^pg3<^s3zN(2&pnUDEn@mZJYwtBv-R3kk)jfvO6=Mf48*A{*I5vZ)Rg+S zJZ@WDOD@=e;~JFP)^F+wiQ2yUqXnXUlzlGK@$1W;2IUh>?h5TXB}R_;geDfE#I#_B z`061E64%m(MRmC**PeJR}TCmsD9B9^+07d9uGHp>PtAMdA<8QQ{T#qh_))+%Gg6GMVRU-0HSh@B@n0nv z)4+`iuFij8UYv$u;@74F*Mi+XxZ-@@tgB@4sTW=0UQxZ zi-=mZ!6Pp}l7L0Zg=%{4wPjZ^aA#Vlt zQbaFjQdR|)Y(zjj#ewM3>XrDnL>iynVzAusKT0blaVcBMXRNqY#X=aW94Qg7pO~$> ze6pAgo)QDkQB=aNQ=$SJP-^Fa22k|jImn_?uZe2_`&_bd`xH2#UW)t|^WrSfpu`CehrgH0MJ1f;HT|Xeb4a}XipBTPlL1hbw?^R;o zR@PN0OVu1YF1H{yS_%>9kFe>MhRjJnB-$)PwsPt@&kubwAF+VLo2+(D#Fs4{mJtV; z@CtZXA7M+`MNAq-lNeT9b&vh=)=n6(8U{Hv8tQ`YQz89ssnz^ZR-vs(r_bL{_19g_ zUUoTAKX8I%aa{h$;(RTJ=D`rrNSWtrwXfuZ_ObWub$dUTLBUSr{U;Va`c(qeSKynG zUdrar=T9e*U{4!ke}dC0P|JM755n!Nl$=OfJKGHk!u4_x4xF_aoQo+^1DF14t^p`R- zyBuQukd$4yy8&>F7SEtr@m7gb7h??_WTp&jtdwbg3=@d;h=#9~I*z z%0D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∈YUnTULYF$Qu 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�~6{kbNy;!B(0)9OCM>?Rj9Ch)UzQs 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 y{J9R)+Nr3ELb-7T_=uPYEt+a;Ujs11b#1?$c} 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�w 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

  • ~~tmFIDF^w9y z$|QFdU&q`QAAUTX;rVbw1C?ELmQ80tyH0^i$cRrndITIkx)a-d8O}0S6ev}yZtNQ4 z@*?)~Pw;j5eVfM=Ca*200gb(Rz-|My+%s6juoigiy*T`X^P-kjn}RH2(PrH7;FW6O z_?u#@=#b)?;1v23QO$#3{;IVT!yDcoS@Uwe*yNiiXA7#=rc$)XtHzs8ID-SJ7zp{v z<>apaIeaj9d0E11bGnTN;VQQjah4Phx8rpxEsAw)CiG9Q5QY2);VzR;6XXygD7zGK z{f!peH~t5f1Lhx4bzX55yB|RC=~k+s%%LgRA!xYyXBlQ-=RBi{YEe#=*jQVd9XF(kmrUxEHf37frAu z{FUCJed##M^y~$xUcH=9%u)U#H~8*ne5olCYp8L%60`Bmpb@h>cCr`y0aJPRIhv1{ zulz|#XB6T0jnshtbedGZZ1&0f(-z<(#!?mOXVWu^5+#M)r9iA~g z&W6%Kt9?O1S?raXgk^Y1>M0rG^KVs2(1k<>-62o)&7;(`qin1o89}v+&r(8 zx6Zg`k1&?9yMX^5Z2R|{BKQ|z6sSZ%OXkz%6jdj+kKhWVCZ{;?L85zWP^9&1Ty_}a zrYAS+ll%8E{XR?yW0@a0`DnYwvhs0et9UU= zU_ZuouIgZN6_$k0@x=aCoa8L3H~8DQ#GADu_+;^`d~~H!Cc`;Z|KCMjyDuX$%0ez;A)v{+MIrYy3tRL-&vwB6YP2mBH^NHv%$x+sUs97 zWQya#a)*xX6MDLxhU43*HYCy#*l}Vc30m2)cZ;9BBwk#rLeTdcTAUq_qD_H5&Gpm( zDe8ONE1v95t?>B>%*EDs!qA#Wlmp$UE$LzRcg3)qiovbf?$7!Vv-O}ADiO1H^U`CJ z@G?6V97wmmFWf(RgBvW%yFfAJZ8vz7(=r)*&e0q;^*zGKaeumOMfqms^pay=3Q<3P zd-xrLNS#3x_iQ_v00rq}r-LHur|?-uupruzSVu$9f4!H%Md9?oCT9~WW!DPe!lGK8 ziNS*{#2_H~9eGNt#$%Uv?~A^e1^WBtb%X7NJHObJl#!+HS18sqA5Unl)2QXzns4ja zB7Vczop8`OHxq+#MK%3fHwmqHJmMKGa>0#rJ#E!uhR_jeNq6?EUoFEk=&@#v!OVnh z2GN8j#Q=)@uS=Z>=vhtmCpdGPrle-K!${qjz3uKK&-F~#E35WV(*`0Br<(VYhBw8U zK{RpGT!t-_k}8`YD(i{c^n{XFpRapw8Cm%RpqUfqMqPUzLK z!yMQ}>|~mbMoZYv%wR%vB%M~K&h~t|e619aNx}C-qkFqV0Q;?Qo4hXwk*NwHYNyZC z!Dj&n{9B)JNvmc#Xh&@sxUH7(`&P!ID`*J^5kmWtohfJyDL*Mfq0#g@F?`0y1o6`u zH{#uNyfYuY^;qP?tW%q3u=AKCNIoNqTFJY*FWV1_GQYrc!l-G*WDWzZkHT|qs(%?9 zU0pcX8mx9qv#g;r0I)hAB^qP0-^3?zNJ(ej9To5@dmk_f&vQogV{2Y;5W6J@*IFN0 zBp1|*iCS%ZD@WxU;Gk9*;J=U|xWq|{q?!e*utk!=d=D|H0KZ|ZR)?H^wx+aca+wO- zbmf%6cUhLQi(9bh#}AHA>olwqPul8)cw7GhF?%uw|5&I|k4s zYOW@;G`_X(5U7?07HhVQTOHfGSP1N&UtBEL!kVZCepdA&$8=uN_#+qM4++5gcW&n4 z9+Dyf%cIg0`vDW2*Gdx)1)ps7w&${M&$c+-;t@2AdQ}vH>@jl5YrYm8v7JFo zy3gb1E&a@;9A!%Lod!z3D9KtxCOBpBRKC~%DwQ3iK>#&5nQf0TOHN>;(}S%XbiMMw z9%-(aG>nlyK+XL*odZxIDTC0|3N~2*U3Ap~P0JSnJu;TLL4qj7^W&pI_GZeq zuvy52|FxUmyK2SEB%%$B7#PMI_7LFyW;B7}CvaDyot*&#@}q(}u|nB=R76~G&`TZG z^X;GewFP3wF8AEu70Bpx>Wl#Mm#Jx@6&SrOB!n&j^xkE};-dd7nl3AM9$ebjFye{f z{P9I_WRyF!byiKzdq_W{#im97qB=zk%Q}zCsWJgNI}6Ukf9%l!909&r2KrV79{%9N z%%0mX8|nE@(Vmz1{puZX!%UyTbyCwO;#}{)JsRX1Lsh!$2qlZd;r(Bi8w7{e*0@e> zyf;UwrJYM%KOjKu65Z%KTX@Kz4;1bsrA8YgutD(sou=QH3Uzj(An|7VubCRrGkBf9 zb4gS}O~W4I9`OBZ4rl@VXPIj_yD-uNW{{?OsWqVWC87qjy9B0NO5DLLignVKc9cwn zMzc09eiRL#q1<$FYPL>F0a;{}_~}xR=k4yF&_+Z2hV4T)t7ZPLpYWb2le|G0Fs*0( zTfpov)<=6KdVp3@?OWjqShH5O`N*WeI73-ZbbwhFHp!3BtyJAq#Z8tzLUHnsYLz?Q7h4|kEo%;Th(dz}@GWY=?em*W+@ z^XE;bK`G#cUY_fNDKEJV9u1D%-5nS-!0kHtKJbi^tJ;RtApuDzFsYR|{+8HxGgQ-Q zQB7#38xwG<)9@u=#^88cacA>Irk+s_wy?^uH~i1f$LDp25eRQanW?*|n^5@!W^lXo0p5$pbF54+Qv6Q=vEt}(I!6e2`UO0HD5OL!VY-K87 z`wnJ=+w;e%4Mg9DAshCAUlEuUn?k>UFe&nRp$7Mg1-JJ&RhG zGnkgqd-YSN=`Hnrv?d{$$KC@&M1;-^0++Bc69va%g|3dDQ3loWEJMBAX1n^yMS18E zTH5s^%&gpdO?e`>b=aZ+hUdY#o_aA~gS)-3(!$rv(kYKAG1W^Fa7ti-tu;{fkMo8P z{M|xZM8r{JoQm?>7m56DhX{{7KK!C<6bjI{7CtBKIol+?@ttX*aN)e6(_$S=m-j%@ z+<7b8tPL$L8?c)^m%U6~vH=DjxXl08>lr%UbMKzvr8}XF4!Ny_yGvH{b#t6W$_nW! z%7aeij{9;<%v>lt{D0mS3!o&x0Q`J`MZgW2)FV5jJu-a9 zuo8YcI)Wc8{`geCb_YI#VN3jMi(~Mb_U!ngL35Bwu?Pw&$5dY=0=q^>;k4^$JfukY z%=+)_2mUGyHB|B!10`&gx7rRAV)Ts}#r*Z5g%MNT{Y%C`mu+SOj| zTOO`+*M|>&5rzt!sMN2C*iOiT^Cf|!rfXl z>LvAjfVU*)jivL^DT;r_n>}7*6)4NHk5FGh+IzN#s9SAoKdp%5W0#pBdk}zn=B4>0 z;n)22yFUEoM*&>&GNX);fj8(dQiN;AFJI-#e**L)vT`F~c%Ny$F4*`d?~}`{1BGA6 zU9-N26Qzk-pweO6xl^M_>ui&B)kUcmi=+dJ=@cQSb!cDM4yVfyW7xL_0+g?q`w{)# z5zP3|Y2Ve5I@!(a^82fud6R)7^^KpmZAQ1?RT*&5JjEDz8#r<^%MrIpF^~yu&rIzl zGw{Lu@)A~65@bAwmR+{5ccQZtm1j``8wN3$V+38w$CWbar}q6)$ewpHY)+CFZ7IBA z=Pd+!rI#|&v&80Zd5)rBsKz##Y_LTFAp7+)BFuJq;W+%g3Wbo=U5UUGKl8F0pkN9G z<251dRz&I;$5xloEU1mID^AvWlwt6HDHnNkVRqVH^%(2{nReut^s;q!-H2OV5z@cK zOOGh4jY2>CWZi=#)5tKfO(fj?yIlIiPb~m?RIFV&eDF-(b-r#uj4ws``KBML-1UBq zM{!S2mBVOG)uc(XI2X?7NMMeJgY4=22G|Kl7H%Ml;b*pJ>q}VweWoLO-k$yl+ar}k zz_ZEr$UYI6MG5cBmnS}wwH!5CybM<^GDJ>EVGaHW__T)#^){Ny!-^MT?XATw!HsQER+_&!c@L3bsVg&UYT(rF|=#Kbq6 znsGhnXZdpJ%L+!eh2w?o(k}=;P(xiR5#T1E9GOV9Mnl}g8jL)l9op`a^kE zd$JSul{t!Lowg`b^C5jr9yMvSq(DX|ypTSday-g;6wnH{eqfYHr6C4~>H zx^SICIwdDbqVNZ)=xI1BsGTy(@?8Z$r0$&~u57=zDgHRGou!A2l4>zG5k)`&Tg&Ob zWpVr6PFlb3Zx7UOPi|>Iey_eZRFgLkSD7MsZD;}7z^{|E);__9HT0LvY0Uo85u7b@ zq02DyVCHL>qE+@m0&IbP`)I}0^CY@;hmQ^cZ`VwA`0fb^X7VrToPL^BCha0mAQ)#StZeZ76*Z~G+tL*eGlo9B~A{`v_28rJPV^z179 zy14Jm^|0&vJdZ=)sbCyXzM*BB(<^5V-Zy(n@SHq+2*7LnBl6~+2sKw>32uy!)Y+bp zLtyG`N7!{VC=y`#?}dTagXF|*jyDh|Eprpul4gvaTvXUjDbilrA3+5s7g2((( zO4aY(n{~eGe?4kX7XXm^$6W^liwK|vj7&wDAy2`0EnvU{NNUDN2#J_(rIWMFunqz_20a4MKK%Kc^mBy&Q} z1JF!Rb@9C)v3v$@Ipd(Al+ZWPaPBqNh4g7Jjq3K$WL?d-EJIwnwj{@u?;k0kQK>?s zJK)r}aVN3;T*@ z@=glC7U>^N4b^>|RPZ7!t){cz{FmXI=V^vb;8s%B*U`%bjWCWf;l9Jk)3y4;3xw0Y zBO*+KB%})Y=S2}$Vs0F1(NRMNCNxQAJYl80~lb3g%>aURsw-aMBGUnVcGO0xI zKru*MQ7?7T%I~GhiY?mjHjq0wt6$CBghEf|BxsfV zM{AW(fQF73-#)9Ws)>r$Shwm?nUH3VJbsCZYW8QN~8Jb%tt$zy8TGb9Mc-U5;#z? zX<<7o>VDN`(vgHkIYH0ZYuO)H<9gI@^5?%h9Zo|A(?oZQW2NM$7lbvi>|JVi-s=R& z4#%|AxVZff!RVsXkT%|0J>WY48Y`8?=W7ma*gG^9pI~~0tFNa}Y`3A?UfxRNvsZTg z>D@fXc5Uld$M)1bYB!DK|=u!C)oX;|JLy}b0yufS`=Z7~YaRHTMrIg*3bUbxjl`Gmm z_GG}YF@=K2k({9aV^cwuJpL{fX9K$dD}j4(42Q5#(_$#qTp<$dgQHB5o7#w(NYIbV z)7ZURivE_8*0#@Qfp&qWQp2Xs-l;!tO~Grvk;=&GV?7o04o|v=9;y097_ZH!;98RU zd8!N2I+Nts^xU+c`FR`h-w~Zk2vW5K;?}hrl68=i20PWT7Ju`eC0NnNVj}r-%LBSZ zkw*j5SEG9S_x=k+C~RL-qdiCyuq+&5y<3Z|n`>Pxz(h3frOk3_KO8D7Y^mr0vzW{s#1c0nKUKo*S&Y-n+MaMdnDV{_n_vTdPo8f3 zGyMb88!PZWqdPV1Y<+001b6%KahZa4*j~VUL_A(KgWGHx+R5`IN_58On-HujE z1Y|5!QW<7Ymq*1{>HH0w>35juX0L|ylNTE^ngnANm}%dq4ER+aX!%L?MnCC%on+Wb z@1^0C`?PssG@XD*9^ee1qWvuB;CVxtaWqMML2Yo`O0?yc5V6w>a;7AQ{=2notW#~D zGZn)HbVnrSdSW7fprx=}RpX;5nvymySS*q3wJE~Os9=ivLV|!l*Vh3)csc8u<%}K4 zu>fr8YnUmi$2}kE%)1D?7Q;=y z3Yv$sZVUAI*OT#W@(fzvEuRBBCdTl&2nJWYb3)qh&Jn$txTCxmtMqAEd7Kj-w%7{) zlO4<^?M&pQ=0jaz3b!Cqn{XR$4ns_0i^KDut5w~69xF4+ju;-lhQZrZ$L(`KrE4F3 zZ_dit2>m?i57&5eu|cqHb%QPqXW3ki4k*9_R6c--DaSt^Z1=o}?0qryAo_tvv>akJ zl+Ld3&v$=wErIy}tZGy%;$08g$V^&$s)B6TL7;%~*83qis(9h%Bv}Yr0>;Cc4mdIb z>rkFemws*Qkn}>mYv$|Df;FK+J^zUU=(#QhK>fLoMbGAJnv6b|$`szzDaaSm!X7_l z+gr`Xa1&a)-jQ|qYIFwEE9Yf92~i`(x@(``b(I74>c+&mVs@2er>)JMR$aE@OX)&y z!@z3qL@%mDm&DRiLotf1wnzDL&-JxoS#;*^?Ze*~vwCAS9^9wjFRBcCD!OFVLpHLa zz`y_sp`@ zV{o#}Hw)%Ff~0^f-n>+_`*uKfl%W3+swa)L`{dP4i@^aKAJ!?u=T9amI&bsVehZ-L z4O1eNkII)Q+rY6aJCU7qXzktluMw3Ll8!(lGBNm3Z|jJ|p5FGvfKletea>0~la&HZ zA@7gI330;E+{;9FG|W14gV#(b$3WdIM=y||I4tPw^Wmq>6C)iKSrs*69|DMa=gipT-4B1cBN{}3T=s*IW`?cTMO8hLa zggEbx7)L>Oi1YuT?!BU#>iT}sM^OqGmz8*fxZR|=d zs^$gbUp>vT*lRjbDe<1)`UpT@B{5c2Dj^YKX3~j1(sVR%gH#&|57u)>%h!7WR+kllP1`c2zibdy#k2H2U#N5mf(y zHKa6od4H5 zt|Mg?kk=JF`;vwr-n(_fhi!d)U;k?vT`M~LAInIG6!PkSTrl)?LF4~eMl49v(f?jX zuaxfm;YJDU@u7Ia|NHyuaENz}!7wSShC~WOHKM+J>aOgS>BWA@yr=jwPUP=uKH#|j zKUedk|L9&zIRBWk?_wM~WN$9zZs1X~yHM!)x>gc~;ep{y@7 z12!bjYX7HtwCk4}@E1)#7Evd`k&oiB|Euk+|IJ#h!Nq|Y8*`gQD$b$n>s#*TTZuyy zf$hlSq~FXV#~@0psCw*kdGOWQ=Qf&OhH~l;Nx*L!#&caPxqN5=cYnUeUDtmv@8NPn0M7d@Z72?I}~`lJSY9}J4G^$%VVwjfI=f3)QYZ=FfM6mk?r)RKXj znEmmM#5bUxJiHm)X*32+kX@F(HM2;HLasS@J+s>6CFHC*^dFuE zmf#Gk0HvXB)3H}5ztvNTK}sYT3pzBg%-2(!j6^wo8R;776!_*WFDHR@IQ}a9<3$%p zg*@B?I$l5Y{ND292DOA+FpY5}ieilrRCzg-sSv{<v}727rsr35zC~*<(x%HIYgET$6J9-M;G(JPr!R)>XZE_X$FAMe;XeN({^5I)WljL*Q`GmV^fp`m zs^>l0AI|XHe@x+_c8tFShY^pN8j~#g{6!^qHkgB!MWZy8&=O$Za!7gF7L&q3v2{y z*nIt2;CS}M>olAST9Hy#aw1o{Wl;;5q+(jJq-Beax}*Ca(M9yp6VAu?9+wq|rl#m9 z$BliWaGQljSyuOM7*!ro+OThSz>CXd^g&Gy9|!1{{Y29>5XZ6tNH>*FYI%jVM#eRK za7xpDI$y4TK55k0S!M4c_GkXh$~(m`-}U^x1&+X{?A%*si4>$FA`$ML%4s`3;d!)% zIDdKVZ`Y~bfY{2%=GTyQH$F}ee}FnGPB2O6(_c?kv#x`pA%69cG#$Q5uR8g$Z~3bH z^AJikVtq}A?0_8nT$X+<_*p^RmSRzEeaz_23UmuFKvUikh)81A4h&Qa(2NSzEac~G zaA|=Snh)q5x)}z76+50}uTn`%8`~o~Y6~Mo4)-{UtD^~%!+}D`<1ntvVG_E&yD(#X zuTB=N{Ng{hy@_*Z@w-7z^&8X%b|;ndMPIzPRdZtWGgeeQ;S7rjJ0c#z`=8&nv-Ak) zsR+GwHh;*+^O&;XKCme>TGz+EJ{r1)tVt%XRhkURsmT;0hArC}ZW*iQ-BT%kc9~5y z9fSVportfQMjE{00C2UK!aJ4MolNkqdd_bPB~99c#3?hU(L&U}pDV%Ch~unN$*+e0 z=K@LPhr_wtkLKN60Qd+=k+my5Zn_nJzhinFFcVYrdeL zjb&H>6oO&IHDLGuJY*LIR8y+SLvr2#l4l4xODWhv&QNS6c90CRi@*7e z??RT+I_Tr(8#?F>+uxZf%{wb3%%As?Q}I0b;7~&H1M%K;IeT@!=-msuB|6%5F>eQ2 z2o=FcZx3}v(MvU)>h>@`eF4JxqdK9frG`5HGM)^@;0MJ`_UpyqA3BtZ{+)K*5Cj_c z(LFySSzDq{6gT)s0W2-^LE(ei0WR)B?0S{?B-HW9>ve~y=}m^#!u5Q=jzpNG#E6{a zY~oQx>K%3a8NtxJS1H%N($ptA;1Sh}D^&cZeP1Vl(vT_avt#jAE+)0D=g2t~o(X?l zJ~y|bfGXk8p_eu4*33P!lBezeyMvm9C$G>v+C?|R3hV*>)V~?7Ybha zrdgdb@hZt_S|iHhkriMAn9D|?6T=D@7?ykIa-Oem-(_FbJqwZCL4_FVK_=F2z85)j zKPGiF(C29K;hA}^!T=W7VdLG0Ct{)%)va1jW8Bi!4rp%^K5G=D6`Z&VfqgZ$(DLGG z(puI>g6DRr8R1ZtZqi6pPx5Mw&6w7c6^SO*b%U`<(j&zp7=arbK`QpFx+=?NLD>c` zF<#_N(f6yN!Khv-y6{72Sa`HuPiKQIk;MA(1ML0-tzpv+5HZP`8hEt_rb)(~LCgUU zE8jo8zMOYTjcEiH9n`wXphHw+Bs_+xPse$K&;|08}UPY?@!1>eAWx}>2UJ*1ag zlPqB`o^FpTWM=9P+}Z`~gr9v8h|H|6>B8u)j=l&@ptNXIgMoa%Wsw0B2{qv49^qb0X(;sGVL$}) zaah^kd;R(bKkh2-4#Owmd3rJolMVe_-JNYF`9SUuQ^afHZi5G5loe?~fNh8}str-W zYOVWvTE=&^T&#W~MU+(F{k+4P@ar4u6LeUvXS-jBPxc(PhG?n9Yok?@#BbC5mI>we|?I}kU{FiT=R?7iqWzzt|W*I`SBj3rV$iY)Ax!Z zo19H=E+9uah)`Ge>(vyjc|Ty2^1N9#&Q1-H;_fBAD+x&xX)34;O$3Hez?-d_hhlug z)+!!><3`L!SB2Llx`X`c>xQ9?E%(awK!M>Kvi&%;?~b7X|ojr zH5eYjwO5NDn?bb>K3Apv-1A&p(4XZjp+QO*_IN~pMVEvbqnj>|Dz^duq9I{LQ8q9Z^Y2X&&6*5>B zmmsNVjmzJAvSam&h8G>^WrRREX&5K`tK@=82=wam(}5&X?fwH(G$FQzzOg*WkF_`0 zig>}v2zOzVplqMBOkb?bHx~VDNv=rNIliXu!86a)Sp-{qnPmpHHe|p$U($oEr&#xl zW@nS}b+u2*jA2hre9jai*<;UbCL@K!<&z1j4s%J%Z+FgX3W8V9oKVtpG{{bWxUL+Br}YB6I7$*eI4?c z#VB*>*;Je3NEN;K;P}IPzhAOK7(>IGKBhJKx19O#YFzury9Ag?bug56xa%KD|MOBZ z0T(9is>-@hUmc&!ytpiXAG8bZ#*m6EE1z7pB3rO5g}NkgVw`TX!m6Idx(a0YYW?my z@8v%fwJQ1jYluu1yXms6FSmYYn;BQb=p3KZLbtu6@c( zr!}0!Gv=JeLNkZ!p_pP0<$R%m>g24_CN^SnZW*~>HQ_MbiT~+#U0cN&*M$FQLg+Qz2sM@-v zayLsXQEUMCK^reY8D&+892C&j2S?TnW0A8vdzmGAKaX`wfBPNILhEhBNB((Fx%Y6b zaFUJ9{PRgJL7X7mb^giKOKI>8mblliuu)wrXDbedT;iBVxANZ%v(2B`{QLTA%>o+Q zHIYP$9{fW?k!BXItC@ifr0aZ5?%{+9=Z0Oe&P_I%tI6o;aZ$wdTbq4F)3)_k7ydc)RmuVzM*m!@j6CDe(FGW#||_x;LWC6@9sXkwY|h zgMoiopxj?I7xlQlo4x%?g+kF_uXe%cA0;Zrr>M=}b7HCSi<&#)F;0%Cl8Lb`qGKnJ z8DSqUezkMRAjgsQ<91_z2^;;iJ~Ny!CyMbtXd1)bgC z^`f?GUGrU$=6$g)3>GPBHm||}oT$j%8iOFO|P%9TDa)P~uT`kAm3a~~V z=#*vx97wRQrG&T^K(x{35$7>aRk>oq!IYpZD4!alC8M&yX6NkQd!q@9(>a9 zC>omyB1;;1>^vbne1Au7@eC26oU#vfg_F`W9O5^u>n&7ThaDPrs$D7Y6o=y$ITkPS zU=1>ba$*JaoPvB7pJG-;z%DZf$T`jpx3f*IpOUGV#m?gt1-N2_=3p`}Y1RR1#}@JF zv<4=8=}vFz5lT*Qlw-6hOUIH65Q5@6kOW!myvOerXq}^5jp` zXnCk`1)~sK8&l`ONx(njBMKaT`+)^0b%$pDdBp6(TE0eGsA~Z zM|$?FHVGMbu_tW>CE|F8#)B6PC1?kYxuZ)>k9s^c;8-4QTVw+59>OvughtaSWFL4FXrWIyFu{$iS)VbQu} zm1Ao%L9)^ZLMk(wTU2xIhHUWQf6wWWCW{P`)~4yO_;a3g=CWST+y>YVp>-M{>f=%t zl;y|z&>T;P3#SbO&Ord7&~DO3R^A3*DrWiTWO09l2*Um*+sz&9{5VnXtU8F(NTMW> zs}4dh%#fB{K9WfX&HJQ+0lKe7V`rZANn z*ok9+hX`{?W1MYqCIxf!R#Y^e`=fMCU{2sm+%lV`!|U9O0#Esp#cBxp)vfGh-E0q*>uNsJcp0L<{TxdSi?%u2t9Oo?9EZKkjQL&!+0l_>DqH zPR!+Q@c8#Dw!=Fuul?e9d#%Eo#3i#nG}eV$QK$QcQ>9X|kh448I;+gIhDhjqLJzYw zq3ZhS_=OJ%(Utn&6=`@whsyj8e1m0VzsGHiTAVGNg7x1JW~_8lkxgOi<(xVu3+1#nQJ<3~<0N(E(IV>g=`8<(BXbiW z;D_dQcFg&wY4qV+&vE5;3PYSHP8p#H&R2qbw+Is17ODHk&c(ZiAxCtiNEGMtxb5TN z8D2@R0I+tEd`6`BC8=Me9P=;!edkl$S&G#EF-Y^hG)HPf6JCP2_DzGHmo*-lIVgB% zIS?Ih&xR*&jDQ2=JMKU8!v;{AfZ#=X3Ci#}xU(usgYdQbTSQdfGp`7$P{^E?RUedGf?$AO#@iwN9aS)%q80!MaFpf(3#ALhD;V&Dn1(sVQFf(h?U&>&nC5ztop}@3{Kd=7P zdwk~QQ8yyVjNaFdfut(sx}!li=WwH$XwaDHL+7cR($QqQ@n#2SXWN;|gWbwWV{e%@ z6=)kF(=&SJ_pi}=E1(YT1pkhSN6#2TekXtj|A0t~N+DJ2t#YVo2cPIfIhm%DAwZUl z{bg`F#*dh%t`_0Dy?mu>V?*NzNT&v`Q;TV{-3U)A(kXf{zoQ=YpVyCzs4cUkknRB$ z-qcTK(s+#ekdP|o^JU?OydOR_Z7>1`gt>Jv{M}l_Xn-f}z$0Z6D{|$Ybg-{m{YD#W zcEif4eMhjyqggMED)iU!v;l9XzO_o6k)Iy*W5U|@w$ksXMKSmxm|qmodRgS9#Jp?8 z+fSH2V;hFiIM~7WTl3$5Wv-K2tih;~9l)~na~mVA7~o5B0TP=(;aTquYDur9Ggi5q zXzqCq!Eav45rJV;Q7xgI`X4-7`Gujvp{L`N^tQ4tP!c3=nOJ+3g!XO;c76loS)`~a zgPH`J7O(UO-M4)n7;)d9XCV)f`kn#*)Hd*V7DU`o-dR4U6Qr3%U2l%kn=no2fm8d# zbFfcJxu!Zk>oORS{80i`=hzu8`{kK(jkmC2d@5cB8O`-h-gSQ_?csgo;T{wM+%bA2 zyrf`FS8kiU3_F=dAZX=2ygC!;5}UjZrj$h_702CjdF_?xcYcYw1><)kGt+|mL5A|K zo+IClEh@{$FhqjMawdovUv==e$wVED$6zuT{T@WnJCOvyKo6j9%R9w;P}e5Xf^Xyw9AlOHqxrQ1z37V zrJD=-M1Y@;T|+RR!u^Sw=5fa^Xybg0o=Th-iE&HPT?a9CG?QOgPV6R0d?cRw@P5yB zwLYA6yj37P`3_Mr0eH?mCdTo9_-VHc$jbmutt7@`qdeabu@*EjyzjMo)@>y=%6M?>dxH7VrS=~j^!35SQ)vG5C z(^B30@b&D%1VX_HJd+UjD;tW!4LJdt8~PbZeL|LG2P3&0fCKoCL!gj$1!U1>DW#|4>M1ilZ!S#`KQ;2d~}fWs``&z!Ea zsK~kl1YRqKsx!PU5bsWm&%88Pdt~ig1M}MpbUjq_P!V#?urJUc$l@nAv)8>5+Q5uE zAlNtJhmcvL{Ab#&BA2?DT@vG5E|>3zF4y8;=iP}oAu}6)I(`3hLA1+cMu5{%%K8?9 zi4$d|zMp2``@D^B^4u$Dl}5pLzR^&JH>=S?^_?ANoQ3AVQ(uqNkcipm^FXK4KWk91 z&|G|vJc;>J{9E`U17YKrdoPndbL>OftVPDuqxLg~ZrZQ{0^8WeMSU9}N+&B!!99LXY*|6DAAx3b)#+mU`a4oNVNPH_$2_6bTyt=p+F3laSl zPJLt-wVep=WFD}JAXVO@AGypd#G3{)9accGKC-hV9X+5a_SK5SC_X!0r=V zbe{GG(=)%r7hPIkCsK9=adHEhfFf|UR5akt3$dDiMu%xfyu!a3>wI|+?C0S`a2H#M zaQEp`%~o$sOO34QprtSQi6NAM_p4U}%^OqXOU`1u;urWrqv@%%s7S-cU@Lef6zp@S zUAIEkamM_j%8HLa|1*nrF*erlyDw^*OyWQDt%3RUfRGnWoHt>6wwknFqS|ZE!Q~k_ zu)LSjkH#JALjR7xTZuO|&Jpm^Pu#*eGfr>!zmPp*@%{ZNQ?p&rgGOrlz#qx2H?pWP zd6OAe&SL!PSCHvM-CtD23YfKq^>a)y9V^brpRKHv=}S5io4v9W`Mxx+RbTo(+uUAuy&sv=Hw%6U1(ZiCs$AFSoT@0TG2^qH%A+P5X$BW0M<|UN zuawp+Sdt%_n+EGI#ag^#GftW1qJ#%BXx|!PndJ&S_mt_8clS&7-Ouh1ITiZ@7S{Ms z$(Y_XUbcVEHnFDd5a8jkvL>ud{y>)KFL^(l$}c zyQC8?ZZ{WyqffL36*7}~C0|U}=;1S;&elr}tq*#BK5Ufs=(z`fi6-x|`~g3ZBfO1J z8S8_6H`{kpoes2tgvmqY$A>3RcalP6{WHw`G#&%Lk6+Chp5ly!Z2 zFOr&OD;cm(fo4Gesm1+*XVW`#$)83Bj{fQRjv8?GNAk#swgKtDWZNi+)B>`|&T++C zLL)VsIX61CHq3uzufv^QM6ERKHQgp-5fVwHKCZ(^Y#WG*18#6(h7}n`zW%A{k@5gO03r-4VY@uRndJm$^>&O_yBaOVYkAg4!v~M7bx3wAHxa7W; zV6~Yw))BH5cgJ-E78}WPvWkI%Po$>U0J&pbK0@eBD7AC=2l!Y-<%+)ZyIzp}+lkO!?7qyR}Q zZWu$_;+TG)v5taFAa@gOEi5%IZd_8ueZL?wLdzjvqt+8Z$;XyOG|-R(q%oA@hDlyO zx+Q;FE^7YtPSxa$ZcSYjfiSgp50Jp6zh@<8H=e*2$(S44Mz`g+Y~4Q$10*9Bg{2nx?B|J>(@XBAP0Q&UvNlAW zK~J-VC)VpEhh46I-u?au4<=6O0%4+pE^M3V`d3qn6>AQAWcA^r_{4@2O2I+Nli`1D z5a0oS3UUBuN0Bh-z6>=0dd)^AVCb#*XQh{u9?eh?JHQMj&d6dGSZCL8p&9c1MA;dF zS%Bt#pgH#7u9w2*hpe@0h|0T2Yi3V{yURA}*5|QiB0`d9XJ~@YmVV2wcHs6E_$L_o z#~~8WuAa>S(|LnXVa{6gK&t^7=lcYH>AH?l-56kYYFn?mzRD*PY$d)+`LY3%Ry#Ba zrde;ldZ~t$Im2Wvu!YamHr>p)wY=KY@ICb1$A2by@P^7gQT~JTPdqrb;5IkMMM*nZ z*16pYG@+qt(MfLkf4qo2PQx`UjtUv;T{vVP;?W9odYTSG8RKzCOW}ji@=vJ@-*6#x zdM0Y3QlCe<|M3~56JEH(_Y$1{9VH^t=TyGd@)&|m7Poi1fKpyLDSHuV(5ydE3fd#hMqtEOvehe1-T zI0BYCOXIb!?5!pudCh|IusU?_@$&%pKd-rp#Pqa=AhTMxPC4{WSHTbliKaVI>9r`F z;LIh3fMb18wP(CnnMA-(n=4>0wHIQ`u1e-J-ulQ)SrB)4aL7Xq*`l*_8y1CGQp#=& zU)+#}p`r<{&+KZTY>P_g7&cp<(sGL+O@8+fr`~SB-*e00PLm?9%XztLH-s60t?)%n z`-3|f+>-u0*Ov!Q%M5fJz0WDKv|mhMqEF2&jd`#v9%(7gJjwn9ujse@ROvj5cPA_T z?3v(7);47}LLeO9Fnz-B^@WI^4FSN<9cFsrO3p&1lIpi|&TVj%%}kVTH+cYgbb+6*wLIuh_) z^tq}>?4#8uHbRa_XmZ8-x`yw6PU zOsEnAt=F2n!O=qj$MVCEgYfs12&b0BS4Qq?)$#@{f>Qkj^!ljEWNRbyTG5G^wV_T> zSzMd=M%3{;g8oFPH)j7E-;?UqTT_ZfPu=Q6E!ag;*lBV2=9XibpRhSnsNbD2?B?Uu zf_FtR=G|sg!~Nvfk8l%cx{AloE7!Ext}ph;)8e}hSWCyAq)It>pE*+q6e{4v7ztvJ z^LIB7PJCI3Z;?7?B7Z;};O@W|hrtl|Ar28;NL-Au@ zM4n;bCN^?+-Z^I#do=Kq9uLL-WJRq<1=AHh-q(R0 z#90Run8`z^l1sAGQ)vuN?3 z*9l*?i>U79u?rxfxGi&kRgtE#4|KNd1~XsjKNmt-eC$F?!BJ9QBFa%JM($ zYY$$`4($~&N*Uu4br7Be-OxpbeNfel76%H~<^CS|Z8x&f77E!bMc#sv6Aus!Bx~9w z6{$s-Vf9t_Dh1@}5$%wtz4SB4=DFlkFoFOj6DCQ1&svfCI8fwPpbLgoSPfc>y_^v> z${ot}Gc}Vy+^vDHN>PUjK&-%k0VMF4lKdG)b?;1*dEKNil%YZJP^wefB=tFqUk=x! z{%T4lK-9bEUK}(21nmG@W)wL~_S-#l`A)Jz;0dw0z6BIZ2Lo?Cg&-J+nZw7e1?h)?r#CQfI`?htlEFI{=Rw+3vth!Iv&vS-dkE;e(Zdo zP2bm@759~GuWqFAj7KSAK{( z4xo z^uV1eFj1FYH`WDKdTb>|)+A;5l{1BsaA_VXDU~@l=s(ZfotRY5*>qInElVloT+45m z29ZtQ@|VS2lq&A3Wq%9(IX7*({JdK4XoQNW)DwEsFyc`JLq+rsBT>sE(JK#) z8dCZb51UtXn168Cgo@gfUUu_u>B7)RP+9{Lty_DW23DeGKXSFty{JTLf7%b_@}+Z% zJ`;bI$`d{ilMi{bJ(RL-oxHrSanWxIhDEM&=P1Y&l79vMat&2`1^DFN2@{~A(jP7_ z>xLUnU2TkHC)>S6ew=djs5gL>5VpcHE{sEf53Q!fjQTJ4e|aSy4kMAl*9;FsNDFZr zLGCZ?6t7*xoL*;;VnJ@#y1G0x z0kRzU5#T}hNIT7eKK--Oqux92pTMlO?eb!$KO(Jfto+P?(dqFqnU4!f5(F zQoptS#z9t5jlN~jIWCaTd3hP}8)CCoY40YUcIew38s<=A`J9F2fuV9dXz<*`8^@eE zDfzv1U5M{|%4qYCi0c(%O=gSDds}AaXL|fvC0*k_4+p3S^xirC>{opI!NE}&cvfAN zVT?wI5^{tr$=16&?3KQZbk2sn8_QdAsRA8A{eFgj9J;l2kwu0~Bs@s#@epn>c49?vWBpB|kbYmfX9Uf`9DBFAiv(s`%jwplWb@7wjSaWX2Yb zt)EP>#H1Zl7=3QfJ2oXJjCWp#NOGs#={n@gJouLmZDI85?(Kmed=?umcQ$i>q1{e* z0(0p>Uurvf%iFU=SV7Czb;Fi|oz0M6HP;Z^D}=bF?bUL+&7{wx^b&^f52{#zO41f! zrV-%TeVXkqwkEY&0z3c-?`g^qg1_zB`md7=O|IY!l~(qPm~7=MRn=K*kLWC`u)w z?^)T;C`vB+)8>dl4+N4zO>Dx))&+H-ic~;74J>!dyO7%ds9Sc2yb7ft^Q*??+r8Vi z(7Bp}Cy%9_@Vzh}CBzZhrrLKgfEJ+)CLnc3ULV@F=cxN0?x7@*c%f)w>Alb`*AvzU z^CcZUC#*(T?qziv=+Wk6Z-6hj%0(arwgAtbUA0gz0FghWi~%yqV|(JyXwoWQAzwQ- zC-+aH^Pn~O$#cDS;{x~=UqA%uN8}yNSHGScJ;h)a)0C*M zSHWF$V;)of27cu;Y5ctRmXR$R5g2&GlF57AZ_xDZXeWB(w83s*2D|Fu*ELc8iLyyB zTL8%dqh72;5iEEP5Gx@F&c00p%f9(T+_Pkq7jzQv#k2}Db!S5o3TW>ct@=frxVUA{ zgMkuMm(P)8zrWSS-0ih>xMh=Yn9$ey7VGieSnH)fO4K|6*@C@L;;Gnj0!|%mx>J0Q zcLsxYRat7jCHh{Dvv!9S^ijX)8@^9S6cRQ_Z0jh_JK!i@d{qSvmUHk-2pc|8I<(y`wKhG7O zG#cRX^i75GZMPYAr%d>?PO!T-gHW>l;neQ^x=T#o7XOnYHFIivq%Lu=HfB;S=;D+F zTYkC~UIc#Ns*)lkS(jJ>9(8^Kym_v0;+9Kn#g-s!I;;@_oJdNG;#hx$(pS5E2`dJd z4M&8w%cYU;@BM7%6uY725LCGUs(uy*cHDYj>;UW)jQ zBb+~ZCS+NN0oxs@*;IAiZDYP%MotwWTcmaIR+`wTtkOeXUeAwHf%YBgFmQ{JPmsg| z8R*ElWSiIPoUp`L`|#<(jLK*VtJ}yp$cH)UrM7_}Xy=jV%F4a+?oPV359c^b_@&*; zOCj3pEwT(thZD}#l(TIRx%CwnCeihePuQfQz?8HuI&3xF6}s1;U03y_dqEq$>{tA9 zcmh5I$1jb2B&d!)Y5$OE=8<)u`|eHc9>#a)@@w1JKmGYN`@%OlCkp+c=P85qqDy^2 z)5-{?WCDqdRA_d*%jCS~Kp6Rc8T@p?9I~UFdU0(4r;@MJYL*+3&KTo$ zR_^H9bJ3l^pem+mYcVqe{o^~t#g;3Cn#u<~r-{PjAs44^#L6gpKX=#L=3zW2W7K@k zL~esSM=Kn!kIUtpAFgr6(8bmYV?dkUw=Hoj9F;Nr2*Rr38B4WmvF1Q-C&W9(uW$&9 z7a|BAUhX>0o#Q+xz%veVQzL+SDcf!IOzSiu^#K0K*HR#a;Zy9c+_vZj>fHVf7+9xg7D_RD%lX61wW4COHX40`j6|5>#jK|v4bHVh5UFB0@< z!s!$t4z?NNKi*+ZSGl9I!j^x1!>#%tRxqi!3MSrgdfJ?F3DSv4)_^ShcQ_@91g;=(#Y`vJMOOAdl)2Hr&gaR9jw1E=8O zg)=@W&g4#sR3Su~XD~no^H#CbFpavK*x$5Vk;b@u9d_Z2Nm3aIQh_A9CnGhbU-4SO zeabmESQMJx@D8I3H5YrxgzKr1eyRu?gKpPhw9EoUe1~RrtdQb?Fyn;tY%B+v6T2Ijk;KK_y43JTVjsjKqI$^L3N>Yfc!M(1pH)ypG+tL3(Kw6q;9Iw${YcM z9?j7d2yeX$P!vHZ9XQo*j7ti;kpf7*Njzsu9HgX$38K6W+ z|H;LM!cL(L&jj*B`-bHHD!{^~V@{AazuYppdRNdcH}w~Jr(wv?oj~Fa<;*zCSU{DX zuH<^wL(0LslAIfe(HGNr88ijb0AxjKj>3*4U}CpC+XHc?EwY*3>N|V$dww-3qYOi= z?{BUAy8O(Mh@=j9YWtjo-ZBGhf5{r{dr}pBG89X~f|nNyC!62#*6f*AT`AkDa-C)s zR)-_8E;d_Q(jWQ52_mA61+Je-%HU(sXm;%;T#|AN8-gB7e%5Qv#JEf}I;&D0cr6 zfYXuHOW{u{4{E%RVLDr5_<|B6eqTmvy=Ot2+((Od!OJIT{V(xf`Y4JlxzX#^6ChO` zSw7?A#q8bZdxpDlTSNMgH0VS1lYr~1cx1bquU@OjhT_fs^a>!BppEFb>~_|-Sv|3> znU|U%M233;Rw;a02Lwj@b{>+_X|p3>DO7M%Vu2Fmum6o~8PHGRLxHT%BkLP4bjN)Q zzC8+yM&gjuSE^C$)Bw^jdTe=8Dl+~siPG0TzFqP+1oZE`D|z4gZ!FvFux+3M>3cH( zrV=63o43DGUY92?J6)7mZtO3#?|=P4F>lw2lTFE&nsm_}QyYfmP=ihV)UyhwT6~ZO zHzub3lc+;YvY9LfC(o><8&~O8VBPj0y1=I_VY+&pI^%_e>Du(qs;uwVMDFAVnu{>p zGQj=xsz@2Deh%Sod!w1re>ju-CFpoRljP(d;J)*6S+_ZZs4us2El7FE9M9@%;ndPVFfacOqeQ`B-8+LP z<=o>fObljIVBZLaNRa19jg%4HuBYQ+7w1HqQO+(8lc>u5=#Xpp*_H#~MhON#wartFJ^CcSJLKnNe4WX(m_s;g2 z-kKEFHaDn;W-~LkM4i+&{}NC+_p431*eJiV+7+q7&-IyS&&gLvJLaNbsGDJfR+t^e zFIGeLobtjlK|i05iF)B$_q?04qhx{XPZz6ks@dDf#Wo3_XvyALLQhFkDWpzO&ig7P zr$+Ai!V_XMw}B&DIiDIBXlQB+W4?B(l9T>CTNWt0|1hUAYg%$SPES{UIxavWy+3)H zlo(-VV`+%U-+J@r5_8C6H?7tBP!&VKYAIyvzwU20Al5YO2N~^31WXHLijBTSv#??; zI=<3*q$xxBhE4_wHzC<;LjrAF*%Qbjpx-Jd?}Iz?-8SqaVCo(AS}s0!#+B^gy*M@5 zQ!I{Ip2K+*t1^yub&4L1&o!REb&ewl{B8NMt=}zEREQeY3E=eDT{oL{j}JG(X$;-6 zA?v41G-#QiT~TUZqp6O!I3%gxwKUm{N8zjH;~}Ya&aJChU>gNdLwd~}C{cmeesE5S zFAiMPTSA^G$+nVR#;9Z(GTzdGm>{3?mO}GB=UMO$g9mPHVB{g;Nc?+n0Hsn>U9IaD zOm^{`hRWX0Biy{Sc8bsm%y)?$!_By)wZ{-jUIzgO2A5V?Nxa8p%EH)Y*b)!3~&*0C>L^mBU=Q3Dzg$&!oP^~wsaPqblDh_$bQZ+~O zXn*NAa3u(~@$(*LBa}0NIs%!*Luk50i8tx+Oo#TqvY*YH=?Yb>nvMlMws&=UIKS(w zP;652fvE2y)fCuoKVr^gF6D!E=qWz|mUoy}=}4_epqfCUHIfxXXg@(BS%Ib-d$9{? zP<}SWtP@i@Wc}|F5d}Q0^Kak_=Y9fkLu4Y9IUfx1lYd=z(8-}~C6MCPYn=~E)~FZ- z11K;;1cpb40ZgN4)6iS*I^hP7bZ>eP-mDiuiHX@KF@ZASyB-cxkqfwRk9g8PY{wQF zcRUh$e)%+X)P}5x4}apZan38uO5oM)jorFXKch7D_IyS+4$p`!TSp!S!BBd9gsE7e z#upsF+lMFX+>p@m)69SzSm8pLoJPm*JEAtv-#z+wtKAIxLepoe2BhO4*Q=@p=XLb{ zU+&EC#x7iy*4sO!oD)tv8Zkb21GHMryk97H2SwyYaO2}I8rYP$(mjD8q}JEb1T=W~ zW~tAlybplf-rs(Xb||m<+IN-n?|tVz(kO^dR~?`F#n2k~nOpMk$-2LrwoLa-)fTpl zAL+F@1gDCJzDxZLdP0V@yO{4reWLu}>Y9gna!6CKGea%_3Qsz%DHCGw zN{Dp*95>JJBARA$L(DN=zSd6Xpd>#@U==eDN6DCwkzpg)MTW|$4^4T!^Wd$+>3gD)U5{31u822 zvohp*CBwZo`cZg|pV#TyfTWv?8SZ^StG)sYXWCB8$JO`5Ei0G!`%)cr3yC~=|A>F$ z($rjjLAcY6tl1AOIe6dJ0;S6+A;?xTtY6HH7ZY>ET{R3n`v7cOw9m>qh~_LAXGnJ6 zK8N3a^JAI5@tL2+BZSLHQkY`1S+u$%fkkT0+CbE|5PUY=!XB1!uZvz^=#uldht{!y zw4Z*``zl;g%Z=((hs4YNmhiOBq>!@Q`85W*L1-%|1j8MtzOf zyXLj_ap?PH&b?KIvtWv$hQoK6a8=OSw6fZj?~kNXmd6n$;Xb3ppbsO!@wK3duV6x_ zz0qznrH!%yBX0adnfhrKS7%E@coa|g!75y=`S>=W4q4C0c=y)v&vo#ON>UqTM~A+@ zMR}*iy)eE~)wt$N>Tf51UIu&=$8Jn0NtbKcAMBB=_;ytN7l^D3XnKF|e8hm|Sp8IO zit5DXBbzzOZ+xJ`@(e$=Ro#U>=$B5{HifmntNDq(X{zv6FerVOY_%M5;vcj6X84YX z!ZJDxnFC|*w68=m!aYlqkB%$js$Eu-rPJ}38mc@M%-;kKP9kN23W_VuOZL9WV>o@% z+0ILCrXh>VjE{bl{xCe)w{ZJ+jc~yBLiI;9`bFv})3a%3tHq|KZ-hPgW$YG13k}7$sRk=)b=!_gMB)qttMslhu3O|l1w3~5`ZzCD{+FeNY zZ3~((n61b?+xIo9vi`9+ji9(m^P6AnESdKA zkL|+t@QCZvNop8l>qql-_9@h;%KoT_`7rCVFKocX#8>Q?wJ;BA=y8);zPC4pybTaO z5+VT7x37bi3x*KZy%n9#ndVnS;R-MYaFil7pLU1{m%}y`K`LOX4NwTMNVy3F@yZ&< zbe;fKtFj~zlp?V-NX7H6Z@?*)2&v0Yg=-g^Fl$LG?ZVVRIsvQQWhr{O&nG|w(5^0m z&=&c$ba_<)gm94gU!=WdSX5uw{|kZwf*=CY3?U979nu3LU1HE72qGn^G=rpsbk`u= zNH;@Br*uhoGvqML>@)tJ=lrj8UY!@`)m+zpvG7gWh(%Bh3cvSoY>({YAl7@B!Xm6UPpM(&=Asb|q+yTFhQ|zP;&qr#t9m z5IM8A(Yhh)5IK{#NRfl)6WdDjSj>HMv^t7e_Em@wFrEWl;ilEj{E)z=Z)i>SA8R?Y zdff7vwi$sdD@5Z7AlDtczbUj_x87T#OdCFF#d&r3-wk@KyhI6~CpzDL#&@eV5kk&e zKOfk1aZGI5pgyt$e1xYyM4LuIGmV2tYPQ#a{$ngC@ZF3l46}xJtgCv(caywx z=-?x17|Re*;OGF-_WjtfPRJ7p&sVg3qpEQMYOvb|0Xj*Qw*a$9kq1{B_&}Gzw#`FGfChNf4jQ3FQukAozH%Jq5yBhTa>H{Ps$V7uwDwFhg4;{Qhd^y*G z&%cp*w{L9wUfMf&rA^+A3`vC#=lQiZKlrvWFH*883pH5_IU2K3raN4bh!!$0RHm6w!M@y?xtx~y(**0*$wrRNSth5deT3Uu8r z98}QTuD^zJtRIKWl&b3PZXgd0p>}xtXHnC8!}Q3Y8I{A(#;9@hkI#13ub}0=8GV~p zpDV7G>B6fxFDcr9OSx^7gU^ur#v{oeOA*JuAEEy-3>(i5#Untem%o-rnDUXUzzSvcCu-u zdQ^M0Fjqss?dWW|4j@#s{YROazp3V)0l8$=6B&DM^+ediHDoXEg%@lr%Ho~UTL}Xb1==>c6jdLDM6iTj>?A7jpGJOdpxquc>BNOLC7J zs2!(>D-zM?_lkL*36xIQQ?0zC3D+lkb3jn-WnEQLrD!AGY5dK-UVf3+0F@O+>ihF;OWduMHF74}<_otTocwPru%l5LoE zYL|wzBAx_BsoL1L>)T^tb-rwTjXdxz#!OL43KDpx=l>SisGs=o&h2r5c$Z)lSt- z@g-&FL5Nv8(GFkbjfls!Kj4U2=qJ(;(fNLrs}7L5Oi$l4VVN4ST8N z#j2EN5NGWWYKK3-Pw3wKbvJ$NWvBYD;j}Mz&>zLeuuHBk=HlMEmBj!CV!%%HkhRJ} z5bEc*>L5s;ke=V(&Cl_DYyzJ$*t6zlLRSfsC8^@%%G3$ zt-kH#mi-~1cE%>ay71PZ(K!Jt0i|!PJ|<0dZx7<@#t0(%lUj&}+5 z>jy%$Zta`a!nh;ODX?V2^IY)iiE&UE7Bq5EbUy6h{ddDNf?-EX25HTk26!cR!B$&)_uza+aWp|>Bz$CLn=#}@a7vTxSUKs@QML3n85 z4cVwie@;@n>&B0N%l1=;{+Kkxr(cQ@j&F88UCR}LA zNWAINKSbvep;Ff{#KFY)=~K5?h_9cgi%$QUgC?S&h;>)=MaiU6{ikO;IS89u=~W^v zWi4MsT#h-U{CfFz0+vs_gxc*p_7r?G(Qq6FAieUSzQ_+RMz$QL&^-s|KH_80^ADisU$L|TEl+GHN^MO7H7Se8Xtpa&^S-0nFIsoSWzuh~s+L%=6%YaG30<60P9`=MD2lAVuW! z2sK`0nrpWk-0C*ThDrP+D*)@!^u%~I`Od9Q!_d!Kul$KMe2<2fPDy8${k}jX#}4V{ zM#Q&yNB1&Sv2Gh4>(yBbY&~Iz9tK8BSAyTDbm`~*uki$<=-z%3#xy%)qDBOmG=K#W zKp0g)(jEJ*En-2=96#?~%_+ROcX?{2R2d6}<#LPNhc=58?EJJq z`s!m@`82fW?kGF;&@$U$rK6U(&pvfx15wqD=f`9iAU5#_11;3dhTQb!HENKf*G94a zDfs&(DW7NkLY}+huB^r>GSMy{QKm&?Kd8^tjHTA=x2MN;AkZFPPr12Spb68>cJ`%3 z8$CJ+96%eQoJ61Cf0L^KGOCQRo)%~dLE`wq==P{6COK!3RVq^4c3~fjG?@RF_mQT0 zMq{(@umG(=>n=cT-12g9|S#OD3Te7*P~GB`PAMma0PUhGkmGxVl?sjGRG-{a88N_w;Fp%$j|Ca`*28n zmO#)%W4eUse$C-OK}U_LW^&hpD@8EIpJyboGiZ9+c2n^hPxj#k-{!kRx=)i_e(cht z2`lF+U)*B^2`qPMwh=rMdEVhtMMJxuufaORBLTilBrfBOP>HC8-B6AjC0_O!y%xLty;?AD>uH_xQljmBT(o(RMj_3MPMH~gZ=c@_^ zHUSccJpw~m+oq(jAQWj9`eV>6a!SlPGl&7M+5Qv$ zEGc@OK8KO*!aj@k6h=%2CgI(yOx_$Q3vT&t{DkSdo|vi8nraO6k-LcGe)to~L4A|^rT@~QCO{@g zR5LJuBKahuV(+IGh;Pn!IMfte_JTx;^?ILgBLswY$dOZV=j1}5+;xZ*@bn!`7P19e zo#HSX-e0%6-MqZ4%P|KwU*$*kUjh@oEYK*3xAlS;Qenz&k%L&pV;*xJI~l^@ZEM-~M@~7)QklbKbD&uH|KbVRRr3o;PfQG+11NN+ z#Fzc0<>Q&Z)dGI+gnUZ&(%)>q&5)>F^cpP#?fk{m0yaWG9M0SOpP^H?WVG!MHR-z6 z2fFda$K|Rnp%G3EO)}~m4-eK;L-gRXfq^=o-oCOGSEZL`@Kg z=vviT6IyrvcuWWQ)Pl#jEvwMB4j7n$+TsuRYqtR(r7L+JfiANvfZQ3#U+#|SUu1Ls zQ9pFcj1u|_ND=QvCK5LFt+>eO3y3hWq?#_EcA~Av#X2-y#m`PllY+uV-Y`ijQ0e}A zxJKy1qo%VF$6@Mo*c&&V8|4cH!#wp9V6_ln?0;yExb!MuVT4T}0>L zwnyMGw#6XCjM3dTWj@8fbHSec$fWGs4;)%Z2l0!^lVXZhKe9=z6ARSlGVvo8NR8va z=X;t|>Mk$y?Ep&L69)!-ci2Fyfvm{wpGS7`(lm!WW6Rf(+WiHspa%EQ4F^v;kfxD$ z%tqWG2ZFQ5v zUe!I6BrA8*!}0`?Fv*pWAiU;U=I)Msnf6FC9XGy4s)EF%E!H5fDpoPQoQjMO_UTP$ zsE}W5;&wvEpziCEw>snBCu;xaPGU~?UX3GK1l^IUHVFf&bWTk={|#*-@W}s8JX4jj z*ZL}KnloV`Nm@0WtG{VwRR+%nRyMhd-f?kT|K2q?Jwb$uvZssTaaenp(6)H9*Q#2w z{}40gW-^h%PGJfw9Cn^j?tr908sscN1cq z-1x^lTbhnJ#aNX_rRgz>dtK{I*eFj8`#kAcMD!8YS=0mm8FFX$C}f-zKw3uYty#0o z2=^Fh(0mv8rf-_Z@xFd7*ZgzVG_HlMLpd)m)V9XGkkGIh_iLIe?I&-A87X3o(@yF< z4oGnd(ofo9d?SG`_>E7Gd zXgshT3gdr4x4yh7^jP)yRNFvGnaxI>aU--e{YQ-AGlGp-Uhz}9qH^cJdtDi>TOaAQ zwPGY7Q=<&cbCfP8_q4<;cb}4t?kJyG6gxf zN?cwlwPbwNM8_#oy+mnHbCgI_Pe1OPTL7go4!-pH=E1wXH$uixi1YYqCb^}6*-ezP zf|MMHaJr}bNw{~BLuQ}4p<@V-b}Y>|&p!mjV{r^~yBxe$Cr#ef?DI-?_2+?zQm`qn zfcb+$Q?a3#3M_LoFIwJsQBj#qYNv&?eB8aHxUT4QCF?Q^*abNh?5Mqs9i2EaZqqD^ zIxLWW<%{Vc#C@G-^UC-WAi+cQCC9!pSSQhEq)mZh1J=bmAEeY4uxw2J zpq^O_9S_6j5=C#)R$n4+wVrS$@8L zv9fn3FPgHIDEUz(c9^_GQH(T_zuTBNn5r*-ysIX`mc3(I+^&$CHJq$USl-DryKK2# zI<|Y}@^O?%y7l@!p>5_c?L(>=P)aeaI{~s#)uiI1bb{Oah<$C*KJ)6Y*0)qh1z^t6 z&;C!#rx&;G;gN`Sy}+j{{R3ajj0AMm%2#uPPR-G)!Wl0JP!n%6znin-a*C9%((w(k z5iXmdaZ|aUnu?wHejjYUWYVMe+7TYTAU!czO%A~y+tC{82SIC_>IWsYvCpGtV$OPq z&!^9hU(OrK?4SO80iUT3Vr>suQ2VQx4yXnBKh?WTqmCyE2x#@WBUr^5x?B zJY(~}9S^J@mgMibC`@o0Hw$XIts3k?lP&V~hk$(DugjLP1x13YFD1Hf6C9b~S4&n_{N}IIkc7mN~LWsPDtua`M9ap!GqETX6Nr%>yyCQZGWe3%Mds?M-Nj zBYTzZG9qqJ!6yeoD zJ329rGV>{1)Yj(l?He7Y3MiVrVP7lvzx$>jU(B{|xgy)k7DoUja4XneXW!-L8k7V- zuv~?suYg2l-nQ@Hu?p%)iR>=;eqn|;mE8o8CYs7tE0oVB12JH(kUVN&TXZ@88|$>g z5^_(%vw)c;&a5l=$0}AnXm~p;2oIlFA;T?uo67Y_%@VFw&fvmYB!#*XhuSZso${3z;g&BNrnJzO7 zH~rc`;TmW5XRUj+z;|E(db_3-_<$aE$6nXHi{4iz-FaZ&V1ulji3Ena-Dd52xbq3l zFEQ`%JA{JT)K#17toNGGY^lW~bb28cr&8vk1#ka>+b3?a_f<%E*^dUl-%sw$Z!yxW zd&bXiJ+qgIo-DQ*VI|jK=VN;<&Syk@FsAzb3_ridbYQ2DP1lLl@h?kVxscz9Cgr;4 z+neR7IM@5Kl@M#TqNnUeDgvK77yi4~d1)=&*5P`_#s=|JICT{L0J`hc6%4)*fKjdB zSl}uu*Lz@e4&f>Rkmw6@NP~O-BQ)2N`oXaXxIGkub1U&?(7j-V=Jx_O2-~g=uNbrl z;1G<5wmS$qTzTyExT|8KWs6oSE1V~c}zZ$c0?%L6o4 zC_cVjpLlKkN9e(#&dgZ}zORI8f-gJ=Fjs<#pDkZ~?K#tmF+DdusEB~T7QBx*&Z36% zush$=Vtz{N`gMM`e^cw`$UzR928@ zam`MuwmO;$O^w|jD~2G+55*SdYlq-oO&Ai=@)+K<{iw%0Wp=5FjDI^Y5ve}r&3dM^ z9jRsm7i0mcn{@jyry7y?{fhKheGv8>@VBH`5DA&X18&`N3v2zr>)({!Ti+s?jhaJ6 z_gNBg8b~XB9nG_OMz=25Qr^(kwy<%m4p6G^LQxn@0BnFq3EEO{|W(--U-k80ca!?+V3pfwl z6{fdnT8$a5t1kCfLRxHoAy8Eop?2F_D<>h}ur6pT#st0u@3o-g2MJDimqB>1?(M$C zd(wio30tuP9hCg>Eh$OJ^}g51Aqx~*wO=4`M{=b)LOgn0T_+U%Ue7Vr=-1(c!E+QB zz4u>JZ-l-lJzi1qBZ?9`!5Ly`&mx{rttWEy*}=V2mnMa*l&=OjVbId&g%P>~+7frP z8(gb3?1-I9!*+?m1>?=p&de}AdycW2Zia@pWS7L&uSPCl*M9Veu#1h5d%yHY&r0jQV=$hHmyAc&~pqQK_dFg?*o5_ptII;h5GQ?S(MwUi3Scf~5;e^(C_(9O@9)SQ<-N|pOCW$ZLw;gLY= zzRqL1EYAQ1m_8JDhpMv&btLfP`K?TZ|mNCChNjw-9%w@Cg;MNuPdB{Za z*+FWo+MS~+2|^zEUf*L_XZjty&9_P8P?i01;5@!+P9gcR>%H0Vo6+Cq`qk2*)2AFG zHS%0{?3P#dO--gb)7zZ0p7%aHf=oH?JgJ3AY?ug4Kw@l62$01}cJM*L9(^F^nZB)W zqVQ3Wx~hfkA#O|^OT(=6J(+1gq4Pu@L)Sa4Vfl(W>}QwFJkF*YSDb8Yf4<2ils%$K z;(BMs^IsnfWdYCE-~I^)MipqDZ-~?SZVo$;LN4}nt#p!3!>Jn3mkV83pUq}2;Ffth z;enl;?KZw=#-6Wq>QtMi;h2kxpyOqPkL&O=Z+9W$Dw*W;^e=a$(`V*nC0Z7U&P^V* zd>jMpQn1YwAohEwEA~KQyC3!YuT$^gs+uV#cH?RkM!j@}xe95VeZ#N(h_}n}1Xu>4 z^yX)PQ;;c6s`$hJ9JvK0TE=WUSl*+9>@aW2{P_zJHe)cOEJ!gL6HQq_K^Ex*pv{3Nf;e!}F2) z=F6fPJ<7Pl&7&DS>U~*lc9>JstCGPCsLqN646NgO3L3_1W>u&*VIbiYJD@MvlO%g0ONk`Bb^>wrbar%BC5}RJ4+gXzB(&|D>PyZmv#M9b+ujoN65Dq_ATNSCOjH3CB zq24)$wXq}7W6RBXkjyo$Bf?KWg03;uQ5OMd!|kLaB=D;3N_yI%&!Ok`0_zTjPuybr z1t5zIvfQn(*uc0 zUF7nB=b`kP@yr&;Oyn$_`Ec`ToeZw93!%2(I-xGmZus zBlkEL{+RtE4s~>b**K@v=d6UX|1-@k5X0YmBc13D?4f9V>Eq&80+p-T0eRe(}oQu(Iam&N=bEr6pwgJRHEqt z?4EWHGzA#AJtj7)6-~T|TF)*8^kfDxy&+1T82N=0W5q?C*Eko%-vOz7iBJ;It+De&78-vcQwnuxUR!;lfNrKL*&J$l>twLPpuGhX1jb2g-X9=usy!V=QoiUx zIlhNejeUkH8-DMhnSrF0=Ia5h+!dEY({NQ8q>KF&(Yd1-P48&2!`%IXhghK9blB8~ zqK{(|`^tqpNm>O&rto(oyXh)I$Btb2EM-)&-xIRZRm9#L{r>HE)T|6!Y|1fv{KM}eos7R;w)&c5ZVxIXoBDHtLZie3r~q3 zOv!jJ0m(@pg_g219wR4OcwtR_n{k%BrZ-udPyAYb0okOjF&kv!FZW}2VNdKJhf!Y~ z_F(VV(|i_X1>*&JKVQOjao@*HD7JYD?m>0PY-TJ+&Nk$>Jv__jLLP1SW7@4z#k_~1 zmjO3X9hte1x_4A;Wm5{j?Z7*&=t{5b50d-VXonlC=CM5^fU>atQkjj}d@A`lBQpGP z5+A+dUnI7A%Z~Cqlv;B&kK(6m$l8*xlm8XdD;1f27V8H{VUi;_XJ)~|gd)dsZ_R~u z9`OayAya-Yx;~x8+ToTO1w*L3K-w{^hJ}7dF9)@)hVXr!Spr_fMYvF&*$UTi-*SvqC7+G_!iubkR+Okm+wERaRk@#t#eHJs)ZZ=_m)Oan3_#A{FNtOy$2= z%!hpndQ$!_yANuz4`XDkr~RX!iMn&}V?{-a!1G$DtBC1?6?g_zE=A~6E}Dk_@(ha4 zT4L5y%E!;Kf`S;*3}yC@22@a!Y7Y@(YA`NkR|@x91fD$9!#nuVAj7IaaKp6XDZoUO z^F~@L*Qyjv%@u5M-y&w4f>rA!@*1-Vrff*AK{#W%Ok7x0%HTS?2!IpSYxr?V zHiM^0RxP@H(@T|mqd)H|f*1{~LcdFfPWnFW3-6eSphwucKdK^=ynvrk$n$4orvB(y zFR*pwx66Ccdlz*?xzv-8b$#>Ads(UZW*9nuEGu&bx#6II=XaTo)2G^v3}x5#x@> z9Uqb;BgF2>?0QrQu&b=ud;SqML3GYhje~ZR(NqBcd5hM%T{gOWzS;qTaHtSeh>5ja z9b7fdJ}XzFH)@r*o!W-*4L%{)+ACfNMvbTbkfgZer@yobQ#hGipgZ4|-eI8XSLit=g25fHqA|>5o z074i&_1v$HTMR92lSC2Xq%z1NI3fM?I;CgeU1F@{J|EY)s>HygsHE6c25AtvC4}3o ztOJZ<;uwx}=3}#kOZ!y{5b$!gjS>FxE(VX7ptB#GK|+A+a(vkC=)TfR7I=(CUCBm% zH9KfqyVeb?NAE3^itQXXZXY>PG3@AzW-yPc%ZDU&;`(Mtw!^;KxNnAHtIt0lFx4RN z3{)U^b{~2Y0`-g4F7lt>6oUQ4!{nqwHGPN&CU7BPjfW5iVkj^LkD4?VGsYyWazubf zLdhVvjt%=G%~&~C&M7bM76k>+^AnXgFo)Z2@K3mV7-RuD&|eVvE~IRn2n}gCBv=gr zkn*n#P|HsD&fP2~K^rb*s4*p(QmZE$SDn;tgddO`f1#~61tuENFG>^{u$5wUFQN7* zc-bRKu3D-;_xsO}`m=$5D}2IfK|&`u=-J3q@=Tf0i{2|!gK*c?dvllYwCDDuX`&}H z8u&#G=A6616W+^mN+Cy>gLSwVaDqG*OWy(4Nz*FA+WBT)@v0S|pHB~TtJO?vvBR!3 zAj5BVR+Y6Lmz8iKKe7xs)MLVm`*TyYN)5=%qF)-Z%L-53)FZ92C7_eQV`np3`f9fy za$JjMlRNjy@@|z*)TGWTF;|zXGDKI&zTYF})tp@oeF65!z-mVgfSl0X7>MD$gq~r* zQyizlbww^=x7h%#H1O=QKu*8MGzH2}IsW0PCfs1t4$X5`!6$r)i4(s|Ahd4X^G}r3 z(uaOr0q6)c^q~VccyBoN$)-vFvLXGefEiPN_m#iUoG)s!M(kVu4E}6+V(q1h@a74UwP9J_rU@g zy8)d_B=0?$X9ba`zZc#HyA~irC^^F3BX(Wwop)Ls$jG0>9kfT;O<|raBTB_lX^q#~!RWlWfgJDYfUhi3pguvS_o@9?7=l3q)STkIBf!-_97+7>i+qKE zNbrFiaqd)5<^9xhB5If47C7m!241iyN2-s)qa#2MG(E97p}%yYMc~-xx}&%_WzQ#Y z{>b0svi_YsVydfeLeA_p)Nw3a!2Z4hE8|_E;lwIIj!>x!hZ_q?a&tgPT%{S`MDzSp z>0XFnqc`FlV>LCa;{e~m$;lM^kyiG)sb3fJM^UaF3!fd8(0(4TwN179Wd4)>12mU{ ze4A#_4+-a9xA9Pl)!0a#ocqOA@fD|?qOqVt8l$#)7=HzUwUNw1f88%Y-vKe^-lHUw zBbMM~fl_uKU6$hM5e1?fv44BH8bx+eHK5Yw{$~3&hk-T0EY*_-5sraLUn&vYG`eif zjRs#`uAE~#$B{&vL^nSri>Eixa(IWWPhEoUE5-38S;I%NdMLuxpvP}}-4w5Yvs&($ zB*N0-KsfW=kXj57mj%5PuD^fX_F&&XLx!){L;d$Uh2H3O0aTFCsDaB#%kKrh@_a6) zFMyb8mFYWwl~@G@`JifQ8Dx<(CX!tQU{hGALxPA*0XADx=&1&+uGJ6mqrIKN#UCN) zTi*(TeXFSS9r6_xW>{G!fPs`}t^3jWJ)YzUQmcu`TC{OQsx4c%LQ4j-&Dk;+B{(qn?oC*2aj(#iT!kU-ll2qZSK;Mx zm?C-!W`|jPf{&C^_Y3;4%HVPC8msA3dWH{|$889=)ey*y)*nPyFInc5T>3K!(<_4+ zgvE&=wB4X~3cz*D@;nVUrECLy(n}*xQsYc0e0QmH@T9Lzop;$+D|?5&Va_KsiNTrJ z;1aZHdi{sk2_Y_%_0o7$>g;)^n#s9&UTa;;@%7kUkSb#If@0^-7QMp_maBiW|0InR zW0md^Jll=vvSv zd6i!Sf8M(L!|^e+%%#lS0f$-L952EdM3$Dh^rRhOIoKt>otbmq4T5vnE!L3RAKV9b zuA?-vvm=j_R1vn)*|^ZVtOACMw(S0Jcm< zf?xs|&;>TYfrm?%L+gHhCn9g~tto{t?R2(@t|?kUOtMoZ{}a&vtM++o=uJ2yO^JK= zrfwjLsX^<)73n(u9~^1k;m!x#H(@)RQD$!2u)azrapWtk0iUOEu?{{qTSV(km^2PDK;1RNw4E9sUB2WCcw>B{D9d zQ<$#i+Igr5YB{-EvHlPm*gN2v?YaAyiSQXG-)6Py!p`Z^HS2#*Thh)f( zCNS_3oqgdN9zGx-Oq!tRb98*VZHr>leoR;%!1X=PUF6GL4o1@aZ(+q{dsL8Ds5JeV9J|aumg^yF`E#-Un?CLg>=JMs{5g zrU)>sa~4D=l!z&)gWQFRgBEmljN0ra?9X;1T5J+Wo%P49-9)wm%#Ze-uB>#{ssGZD zii`K~)MK0c?RbXA*pDlI1lefFxy<7Jr8Wr~*nK(C2h%iKd`lskfZ1&!hCdpM9`GO3 zHO|2-^t;VH>mK*LQ#_ax@NVtyeK*C&nHLne&c7fo?)f&QBXwt%9>NlJurt4T&0coQ zI_VtV7rF~DCi^|y>u=w}x!TgT!*|XDt=kW%juA}<0;OH{0S)Vl=X2R6uAWyA@!Q@I zmRu|JP$hlBcSNi7IOm{5lslb}mO}wou28&Nqw}qm*VxxRQ;$3q3;zBOUfOP_RKNwep_W@aw5{fNl^;+;QEj|@Nr;N8O?+9ch z+%h6~Q=<*Xej}WPH@<_yjP`BfOevaf6~_bhM~b}I{#JpIG?^w9F{e}-ioO$=@S&@P ztVK&d()zMPY>Ok)yXix3(u7{TN#l@ zjjWJ4p{cE6ZMt>1B_Q{bEjg0DJz0dILIGfK9anmb*xY7d*cwV>)XF;UP}AjAOiz+6 z5O`4Qw4~HDEpYfw+NIE~s#m{Xf@9FKKf?Pec4TlpLX9zgv&urT%}Zr_)2Szqbii3( zkZrj&_Y5Jn{+htD@mWgDvB|iHN4ir{K$TJAP~V%_Pi5T7W5{G%?DxM^J$poNj8&>_ zU%yM#PoJ zR|w2X(|XFy2KW#v=8OMf8&1%RihMrksij>}(Eq%GYfk!6wkQaVXH3?wrQ_*+zgJE{YxKqH&^g`!@=O&=c zrNAhL4_UVXx}}8w5Hej+N7vfdmk=Mru8mya4pyBjJz9-b!+tD+FS96iqIx+`hEKH9 z{osrR5fhjZiG6jkjjnH*ETYcfr(wi0x8OvAYX>s zzs7z&m=8F_^tqD0;rAPbKIVxeJ?B}Jzb3&Nv-iPcFgmShg1^#^?eM)l+vwEa zM3)Z;Zi_vNq~r?n5VW|lQamtw_dQO@iA2RV2P7E<#hMqmS`O|w`UIB@Q zudT?-gVG1q*V7t4H(P{jb#k7oIo?M{1k^9Am%jght^^xZw4~>D++>1d9Xu_67J|0< zY=fs)0s@df3+l;0COKrk_)fOrb%{zBjYdmJN8KopXqTPY3<^@5l?Px6b`wLGmm7Cu z)v-q`2fNw87FwwiN_r!R5rM=b`RMM{Xm3Gbbiy)=!gjxydqrXu-%Nuh0`5iE#PN#v zjsF+#p^-2$!MPB!sw&{wnS(ym`_m_xi=RK$Lr~c59m`(%-K6x=j-tW={Z49qbwbcm zfxM}5!&Y_eABn2Q~PRJax6%MC88mw7~%x-><=I z?lUr_yDw6pZq{g828Q@~JI%R-3$5;&S&?24qmFw|{=$aqK1f^x3^S2!ahtTBbljt1 z#CppN>x199X3e}XxPbF?^G;1uxnv25$M=fN&zQOl;Yl;vQx;c|zgK6-@KgRSoTJqr z&;JN)soqQZVpBbc@=WTGULYf@wjRfT!92qoW2G~d6`3L@zvCTLFj<_SIsWl}FKpZ? ztff1I`PPFX^{}2`@!cs(p*g_AR=Ey_a%@ z?~lAU++B)AWpXWFnXbx7rKRuDZBAfb8>TRm&mVuOx}ky0;|7#Y#10rXYe1GTB=$ac zvE0c3f_)AhC$t8FDA4;l>1Xy|PofTL!Yx^cn>^V8-MkbzN9439hE>*;^<7$#<*VP9 zhD6QdNcwWm+RKvVF<AH2#ORHDcuswN>Bg@w>Cb5v{j zM%)$Lom?$5-z@f}7qdX&DVTw(;5Hw|>j*ZI9koxenb_v=lBHP%I5FOrzk_NAwy zQdhDiVlafc+WJK2yg4DA%X(Qb?WEYE?kGR+u#c-Y0osdgi(X&Sk9Op-Md9mjZX*bW?LLhWKT#^ zVmY-pM5emcB=Ak;>z$EG*Ys_JgUE9u z-NwYRe388MPV}AOwC0BL?}hr!sUHk#N({*4>M)MwNk;tB65qb0BJ^RQdPNP326Fr? zpwlpG!S^O!6nW+u=I9;S<$(K_YYvacO-v6VY(B5QCMa`?bd)e!_S&%xa29Yfk4MO` z^K|$|$C867^|tmw+sU4NoZSChIoQMtpX8hk%4{FSeM}N!{t)V1-sr9R3X+@LiXH!X z3nmH|HSaQ7D625_Qu9487qKCrXs}nFnV2J}$vJO>@P}IURG`o-)958uJnn7n=U@mS zaP;?3dzDj_m}jB-q*eD}$p7Odw;h7?yqcL#%!;oNBNthAYw%{D<+1#7CM-yv5F%G2f43&yJly}Of}tJ zRgiv~c({B*c^(p_wSzxe<$6%xC{|#{25MRks~l*w#*3uZ?Ll zo_ylolZgM`KC5-Lf6bJmPEdMPU&VQPQD5Baclj0A&d7%DgvnQpD@z|1m#(D?zF6=J zB$txU$M#$!Rc_zt7wz4@Z|r|zs})(Hmw~ZV$Kx*f@@P@ia{r0gbYzS@o1RcZ>g?w# zhh1&QEU36M)w92M{L-{LFwrO55X#u7sM9j7z?cw+#J`?*8_Ic%o%pNTfJnyJL%6Bu z@8Wg{#p^H01yWB(r49v)8y?g>P(J^kcl4yhU!4akB=a^+$cyyoG#gL)*hz7>ZcG?D z;Z%1Ev`m3)I(ABd4&J<(ULHXKRR9Ny?1)*+)N=)`^%r0@uR=lOg!?fY2apw6IOS;P zp(XQzCi~oIaS!VK-}}rD9_%SDUIaHZah|+=8B2!Q>7g)9pzHKxd89It{S2$rAnmgM zDR=+;o5wOP%0f&`TA*4l8-g20ckHSZ@|k$Vi_9k z-+V24FZu6mSG%E2)2AC2P|&@uy%#AYr6v7VLzK3=dTXaYi7}OEB9jeyf$|*HfJQ7+ z7uFPTmkKR!&p=!@&lWK@G!nf)g=!`NkBz2Df`@|H^q;3MoKLLsyN~e60CTe`ZW>xE(wfw8@#CB56S$;q&-Z^B zoHop~fT(;VeAY$z0S5HF*y&Sq&Fuu3yhoM50Mh|={Kp6>ZWXb(Lp@tMeYH=?|Sz;{5=dCB3W8J{avL?b9*ckIgfAhX% zBuq_JN5lH93@<`_H+D~NYI(&dD#nS@C{ih;?;Cx7@j#=iNwJ|S5NwBtMUM9enU z_J}KFejU(3^5$g!`nsJbeONhB_dnNI0i-bCS)t>!wCyp^sR|@v_)w5T7XBymQPF~c zv&O)eb?Yb}QR^Qr*e;C!H?6c%ps8o0@V{RPd@FW3v1r7?~#b4 zXA;aOlsBGzz22E$i>;Qgm;EVrtO_W0nl-@QU%$7Vv^LiN{^0On{ipjKACP9&wloh6 zx={Ub=f|jlY?t%n`F)sJTsKC^llll6Q8D!ux(KC0=70OTUU3es1OzdIx4K(UQ}%(I zUXh=TK=#*x8wUf9f7%K+%5)@72E1`)I;&+ZuU*C=Q=N$3Zi51owcbd z!go*3%ihx$LGl0Ay;)pL5;EzmE3*t@8yuY5C!Gnkr#hc6H2Lzdw_K&D0y-Tt(H{bi zX39MZlqb~E2hn3mj98y{qfJ78>XuF2xSWjbJta1APusm8XBF;S`;TzNHSwEWPsb%V zmxlC4Mt!rzS0{#n>J4j!%1O?vhl?C3zC=O=?-6qL-DEEp?Oey;A5ssW+pntX%wfPu zqXg?ZOXWJ?x<^0nIdj$le|jI{^s|8Os6WQx7|7ItRubaA-#~b<#SDUjoa$`%tlmjb z5u|+wOK)nE${ubsW6CtQUcN--yrE;bl_MYtFO2Tig^1OvY3{~Y6~pF&2C1d5Pd7Z) zRSAR$AA7}_eG$yGgUp!L!MEkqjfz!Y*v;6-)p7E*61m zxRGxzet~N8l>GenL)>@MfH|3`zaG~NbP4nQt)yhFX{3jRobP#RgaG4CFSw_RRBSZr zfQAU}(H|$9qNtJouD@B>Ob}}&n~E(Z@?)K^TW%WqB>bkQN8HFHS>--A!y!l^c`N9a zs=G!v{sgP6K|ym^cUh_5*{vP+?2CG&QCdtp-h~LmFZNLa`04VIGTSn3xR=HJ?!qkm zp?JFA?~bs;HIW2G)?vt6%%IBKgcf|&P~&*J|BJo%ifZ!f-bGOqM4HkOFbL9nkq!Y7 zP^w6;p@{Te1StVQkS-$92_hY&S1F+=AT1Q>z4u;|ki0wmzHk5c_upgen|;o?I~Uw! zjO1O+x#oJ;ob!2}xmqMjq15`Oxv;yCUg?EeQ!eyt)fw$5oA9i_A_KR?;EF4wAKun8 z0ZJAj8kQj5ksp|j$5vT?yKS-@E2mlyl-^Wf-TADdFWny`UU_+NT=2yR0ewZrR1J6t z@2?=u&xU}-y(=;j{tG-L%FcUBxs@U7SavQ^B4j>ev(d*SFqTU~gP}B>S#deF0{jC} zSfKk|Uv;lnr}Z3E>|L6gqpMb8XG)7hM``NscB;tD&e+F&CToL60p}_Ni<22QFa; zW$lqy!|?dY+|OS)&+8c;JfBv~iGd4aYkq%XQtEs8r8M`t#2G@`ruz9s?k|^qId3tY z0r159p{u)FTJt*g?VPn^XWSlZF}`!d+o|DUzbwhG3LpRY1)5p@x!M;jsON`DyYwq} zJvD?U!Sx@^#)Ed%bLlYO4O;vn93sy zO10J7V-=bd`QaN*Qhyej*X(fxBtd++`YzIW^(^qltBF$jyC+BAZa}vp5Zm76VNDNb zxr?5lQP}R>Y-N|bQGA`}w8)`*RP9*Ti!0eV;HAwlHf<&TXRW`3LG{*zC$G^d?5}Na zIDhoNE>h{zy;nNx3su<3r_(Ng{fx{^Wzt!)8s`Na(>!!SoMATb3r59R?M>?S4J*E- z5ojYi?epWY#OIHbjFXYN7+RHC%zQKXC;i39F<2ier7CpTo17KKMTd9$6EkC;hk2NH z$hc~{rHKN=2@WIzt;8AnSTa;cBNf_v)l@$LYj1zVD_ck5PCD|C+Htgh9rU&0%$dgL z(%%L%>M_X;bL1jB2s;thycwa`JxQ1G)a@>*mfq_<=O?kOU3lZA4cPpGz)}xu%vh+I z3~BD@XF}U0zq?Dv`&0qGo2$y{Nr$=1Vmt5&LoH@)Ps#cB@a;CSW3g|TE0qYgvD-<* zf0BDXRTV+U$1XtA;kn_=_h(#5Ka#Kp6=Msqp2*xah%}NV1`U$L$=gZ#>Kzw794*Xi z#^~16FZ8)#({ayxfbck%&l*WTJ{!j4k@}4#zS%=`!%HYHqlz6Srid)Y_gxw#odO|u z4Dcs?r2d8ys!fh(Fb;zPkZmbAXa<+=;2W9uW=~(XOS}Ud=UIfjy z`#j`bjZu;l{oDoHY6#*(LD}~Xjy(<9{DR`J@BEkK<01Qtx*d{# zl~HjkoE1}|>ChCaoLEdZ#hF|=P85&;KiHf5Sc7A49G1&uFt3$@l|(q8x|{o2Ms6{R zZVG}4$bI;KUnP1<+rFlw+)H!3GohKaI|vF{x)C|OW*1vVLT1ztXm{2qU9Fv$Z)kaa zR=Jq$_LB(A0%g8;WAu1|2*ksOnYcf$Y>wrOOL!idGI(wZzx9~Wt0nhW!byv{0oC}6 z)3zIV@pxb4_1ErjjQZ?ou`s)%vvVZx2G7w$O@XsKJnF@eJwlPtl!uIK?$SubcwEx^ zrA1bD$V^<0^P~UEz{}u3Jf5Dm4yJQ(hxn?=4a-uk_U;QXLDGYnQsCG0)z<^yEQF)D ziW1^_Nc*wNBG@FNK1`3tK*@*iho=w?z6MhC0d|@eOu+a%A{awlO}QB|xL4i}Pt}wy z!i~ETn^|RFzuRkh=0$uPuSo=ZadD-yic{AC z0={BY#H?hBE*r&x`Rkky(HUA)F3D!mmvIiCjV=rH;yZ^qW!Jh69)Ev&pde5^6}s2} zm^b?Br^Lc8Jeuw+SOYDVzAUAnuE3k`hb@7DmV?7YOLXVL8Ovu}xi7SHw{>cIXX6-y z0UU8+MInT|qRI$ujO$c0+v(tbCx!_J9*Pe|GB~Ghog_bE?EMQ4hHNi;y2=3i%a+2c zOX4J?m}+v_kFUuOpub$e^SHa#=0FZq-LS%O@?9Ucd=mWkl`NEN1>TQK#KcLzoRPod z+yNfS0{?WiIMD*Lf08g0atqLokcT*O>)>F0V{>%)v0rC*#Ch7M=U;A*oa75a1q{A5 z+H@h5Pu9$SvZ+vfWS@96gU0n{aSL-IQYvqt>}lmwMGEv$466O8@Huj4!vLruR~WSCtecrm0PG)Dy!eS z+X1o!x-$2++Re@6Cj7F-3lj%2Nw=n2$-dQ@*A6w9#;h$qHs#f*q2nI@`W)OUo_=LYA|ALMy^9uL)-8PAqOf z-RzVlzgBhuzO4DI)g8O}UrIC%XCu^IYQzUJKq@Bj>q<6vVii#a#g8iqKvoeq<@%fo ziIBvMrcFAVaof5L3jEY3THM64DP=djv8r)$ zpJLwZj;otk9wK34e2oNgGmME^9G66rouLFfTs!MK0Ix*HXmcRBLWI4pfu6O@Ach>f z7vo>x@@s!_;rlzya5=n5f}{K8hD2jMj{On@`ZWYT!L{8xEDri#W2A4@!IdH3JzK}u zx6Yxz>JJ@RVes*>_(W=dw<;DWQz#jGv7(wRPRlv;$8j6VXByZJm6vJAXe;+Vvc8Ko zo)Cooh`vx283Oxx0*E$L^8>U@?5rKC&Xv%n2l#R?o(3$1RS zOPuKp1L|E+mu0?FN#U(0T+@Dm{v=|-yGO~Ee>`6$p zEH!$D2VGu;{dy*@F(7x~J8Ow;Bp*Dvkd+AA1D~(C!yWDuhaaBi7j$;T?u=sJ>H`Xv z`}YeT3uO$fpZP>6(o}xgf*4R;ph2=0c0Ew9mBETYl4pkCP~le`CZ zv{FOlr{s%rk%-nkWc|MVH{uDPtQGi1Q=~zjdFpzJ@dtjVp-$c&0Qs1t^J>D9qlDc* z5o(N3BsyXQaKY46oS$e_LLIVkH#@-V7~Xj+bR+$mhKnoq_o8;t)m6Y^T4ZD8F5HP& z?;Li7WgrN#wG@r^K_8Uas4dA0G*u?s)jf$VUpJ(Q`tm*M@}9ZS3g$7aT1YUbFRCio zF@d1%uq%C{_bDsy`xp@sd(P-wAj8H$24ljlKgo1S4!sx zSi62mh`QzN1W5R7$R6V;u)q}Hdn0ug^gp!#Zpvn+s<_{5ksKI|@PCd}5M+{?e4 z6d={Ps^&Qu9arhmrqIr4epIPTTz13mwchgzl7tMm5IwVkG3Z!MOzhD*L4^%q>0RqM z7IgOnD{jk@SZ=b*bpg&?6Hgi|1?>zu!7YZ~=49qzHmMwyoAZU2qZvV;ca_n4gr+^2 zPnOD=1U1krk!6B%Q!q)L(D(1})42oP?}oE{JDM~XmbP+zBjwpWd|6_j`eP{B%qs)^ z-$2dboPD>tOWIenj1BTurF+(NXmS6m!`nevtQ-4tv8o)ZQc@Pe#sHe0C96+n#%`qY ztRyr27f$GeZ9>e^<;6=EM5S65)SJsRjq7klR!igZJ{&FsWmF zwJiCCXsP1C!pD8zx9i{vU*12#jRkW{5Z(OPqu}oVmW(VSYT`IF-_{q z<3o9(ae{=NES-36%MFVODOtnuj+n-t29LQv<+0kQRHTq#ZeK({26s!x6{+ ziv!TcKsv44X4bHsmL^s#*&Tq>6(C?<%R*;LqRT&MUpOmxd=`utkKT_*9&8PycV}EI#*0V8`@y7bwLS?JVYhZyDkTnuCi zx_SWW#YXGvoWpE@ACft<(6F*Ki4gPAeB}=snPaaX6pRqWt$!E3|HGc%UT(8}Dv{2D z@r{_$$)E`_SL8CWU`uwCroSAWv#xOw%K}ZkgnI3#Db27np;&Dl?LX>VX8#Z>afjRF zmC-un$J5bLuwrPa;n!vE+@zs(Lz5*ZS%)%>3@4Lyh(N6a8lC0*_q=iZG(-!WPn zr%LUcv@2GPGE7I#^5*$m3zFP#&|~Wls8ZQGWncx?jbh9jmYk-;Z|dMQQCIe70u0~u zUVgYD6nOY100wN?H;AT zb6N_S`zTg?9z95pZ|1|(#w$9Fcl$FiLm*ly-6T~C@bX8^C4(6_R9m+62tOo)3&%G_xgHb!GG9T4!Tp%5;R;lZnU5Oof;vCeeN zDVh{G1JUG}w3?D{v?Wj#A#RKEprEHsJTi6eqB5w}=Z2VH=Z8N`vhJp9#}`dQH$yx- zhy=_F)3mXaTJawa=2{|EQ(s|)RCwAJ-CtWKS2_Kj;Pxk z#fqbakRr~|c_4H5pvn^$;BVv1r_b9YYYD-a0Woc*fE$jW26yuhamNM?5drQBI|?16Gbw`MwoYsZ-F}iKN?O1cjbRSzKn_ z9o%BXL0w0EVCB|#m7j0;a2kk?H?zAC0H+b^wpi>x?(uUKVE*6{i>1BJVp_A9Y&978(%y^{2 z4L`K0%k-T11-Mnru)OGr3x&DSX8Mm6xg^XV9JmD$&)L=S^+%`Wm?~~&ZgXk%D~%_}<{*UuC)U zNJ>U@y!SX+J&z2k=Uz|<4MJska((M$?u5JwBaj6>a(OM3v66iHoq6BJXR-B-9llH3 zGT9UieB&Nj2AGF&NK57Dg^XwFot=oitUjN~NwiBKw-W?2_ZUvgQ4R9g{5B103OKf0 z#QG2Cgd9#&#>GBS$;2VR5MKvOo-XXl1v2+{LVV7UeM3X6mw9DKkL-<;1DAP0tCo$8 z@x6Wcn`11;0hCh@6{{+?hU>XwBQRQbvxJ-L=fTuSTrUoH%~5gWT+vD-d-81&0r__Y z>C0LDF1Qz4vJ0-{wnDq2Z<{>w29jE!TxjUr;?oyn4`+N*zIJQqkg7PR$=%@K564sj zo5ppFWT(C_a&=mD8Cu<~W8K;Z1fZ(^6ar%IM-DShwD0AGqc11#&M^uP9JiT-l~5@L zFZn_Wgu_M~a1ej!WcZYJC73~zQ5?ryKo<1F(H3!uTVFs54&Gjt6{}=2vJE9)5ftp26`smNk#mou4^ww4WZuy;zv5lK0DodZ}s6+ricZ+7019norL#71QCPXdft^RJPD-Y6b?cp ziQK0BX!o=OKTP0PWmDrR6^&`8Uw?Pe$t_JEsq&thcT7_NVTqR zz~FLOW2b`_d*AuZUJd&Pw=raQIJMfk;qTzat#i^PL|M>t;bL6(iR1nndH)tEaG(_* zU%P!b8FFFQKmlEz$;a@+tn@JISZp1iyqQE#R^E+!z@Xt4rbD``!foB3T z8(T8vI-Bxbyh=evT)-Z@u1c(PY3$=sZWgQZ@+csrK2VyA4^$QTiBBC4M zF9cLyl^8m-xMH;8a8xs15?;D{fn`Pc7`B#3Ve{NqriFmmH?D=}#%BUz@>0o$eKgOb zKeB+hxo}~;!CD~qwD*z+4X*;uDu)eiYI-(DX6Y}vjmBYJQKm36r>%e3F}6Rk=IBgl zt`0fq<3l$Fp+*5Jepawg*$(FYo-lwCY}RF>lXa26B{Q5 zOF}fOfj6y9bFTQ_Vlw}*(k&g*GHNHfUQqB_p8OI3b{%7f%5OCVMA#fvJ7eaWZ9G$C zaaaK*|HEO?(~4*WWPDN1UT!}T^$w|Kb~JITT^RwVR|Fw36YBH8ZZC#>@9DOF7zujn z4Dt_58YhF4C_@r5+G&0SFV2F0xjq(bFvCMte)%{yETDZ3p}RL5une7oe!&SxzXpbD zou)im&Hk!Ao%{0L(#!Z|aHaq32eX70!(}>)D1lQ+iU#*(=lUe=goeg`qQ7uJ6phMW1!v{_FhuRvEfIwXo2%H^*a*H(6C6@OH6W8?=j$y_R?%K5r4M!6Qz+S@ z#B^kW>6p`#zfoHL-us!W8zc@j&mMoPIbvBD*q_RQ8n>)NCSjW7Dxjs*bZ^~s3`}$S z+atH=9_39qFMeAumg1LRh#=dGlshS@QWcD$QGbOA5aoQEk866gil6uPKbc5duX&oO z)g~s|jVIq-O@wPiwR$oRp0HZJ?tU(z!!cyyHww0W`SllWehE~24|C?4e+(tmT!p_o z_9zL6D5?G9b@Z#N@^D^lzr)`Ado3FF-QbK+YDju7*~OHQ5T!Cx2YldJk08fQvvj+o z83%j8j8K_4xC4K?HD^hwNwLD&cL1Lc)|p2@(f6&^jt}T(9}Hr4Tiyk0at!-iKyBfE zdJ<=~eXnr*e69Hhv-;sJlUvvW8=fV32-?oV>{3SVfd$4CFo5AohpoBf6%JQ{hs5Mz zCj0f2$6OgTUmUjn41wzf0`|1xb+VHC7GcgsMO{` zSWjIxuKnMP6wS#|f_6glGmE(t+APsvH94!nrvV`il()M%Hsuku(FJiU zs{udkvu`jlacw>pAbcmG>t!8tzSzm#f%z4nDL1QA|3D%{&q9_?-bI1BdOGj1P$ct+ z#{DthH}r2cQ(XXX;t~AKow!GsRO^qLM;k9rz2=0z6?K73Z4tdwxj7OIpk%`lA;{O*gz&^evRXdg4sw6_&vb4Z4cr-xrG`|7+#fMC}VJt zaZJ_Urtwm2758^Ng_fME0-4j0Rh1uXw`)hOnDlo>jq^3TO^JV=LY=Ru(a~Z$yXD@8 zUcrC6booY&vu~Sq;lMUiD9AOn{5d|_9*gNZ^U79nLw-EL91L}mTamY?v#Og;I+8P< zj0gS%=HG1?I3AOOmp`Tj=!+}>aHMSxe#-7K^kZ$LkxOwVw4EYU8_NFW4mF{y>fIp3oQJ-c^z4u`)+2|l7(%h{t4mG;Jtg+T|FlZDeH9QLQyPak%B;!5#Z(Q;C8tF-(@-HwFBnDp& z*f0n03-@9>Y1Gy4BQXVh1vgb~`+?kj_|LEWCixR)@4gp`rwcw*2uN38da5*>?;Dkz zDP{Ll?>@b;5~bSa?fjRoBX3Bl5vclf#f1M%Bq+JbOD^G#YqdOO@+45$hcWlGJX~>4-4g)tLumJrqQU_7`~JVq_+m` z?lQwqP%8XM0hxs#Wimf4E>S9XcexcWyGeMB_0}C5N!{*^2n{GWo6rJ(eb~&$ZTjb} z;3H+*Sw7G=ja&n~!xx;7%1(o&9(B9l9+1?x&lkp+3=TCsDCj{9`exb{ma%mbG$a}RIGGN(ve&p6B?<(Q2)_nMNf|p#4wu6XKl;ncMne+f%;@^2m zN8R~TJv@0u^jxbibv7lCh+_y!Ms~{mxfZyj^EVZD(%^~XZ%6*WN;w)BAm&(A@6q23~*9zN+EZ7PFv_w zB*b|bSxy!Xy~HLmzxETfxB+R9cP2Z%^ld9<3|hZ3vGoE}6keZHC0*Jrwp`jVZv)XN zJB!#=KLB#lZryqOyV}uvg$N6*th_B`V%9tk#O!rf+Cy+SVf`O3aAL}0rbmdYq|hGr z-i!05fX=E+#6xt`@+`F_nPxUj#9xdt@+fgZ0;wK%Vi)~;6QWNq;9)JEtNaccAK` zmtKGgn1(B}1_x>$ObZu?ceMz*Vvlb!ZTS^T2SF7^?`wGx5_RA5e)>H_~1AQ{1VKhwS>xMNZi0cg>!NQD0E6h=%PusjIh% z;zZBw6Gpaf;)WOlYx40Zt$IMq+uMXjK31jID;GC2fS`ikGU&ZEQKs6YMIrO>C(-qx zH@R&$x2IOnpz^N>z+9wj;HV(}_K^D(o)w3bNApo-C3jv_9SkT%DEvMaoF+P)41tUo zRk(#1C_1m^WnP7y-uifM0F>OtwW{IkBN7sc)b;hy*tg=0zd3Eg_Y+KfDxr2clEC9N z-+v$jy_cO5Tqp4wMDD`Bca8Sp+$DuO;gZ{tOB{}v#`AEfVtUJ7?720(W&M%Vkcowi zTmM#rz7$J1>wtX?(DlJ(mY|b5;PmQty4PIwVNR?7mtk6aVg3Bk#n;C~n{g6XAAijh zTBp*rG!77*BJwZ?>jNgZHh|M?v@+qlt7#ernbGS?)_B;B3>`+Ef|fA8^)xWpxGDx28&g3ka@`$W`xK2e#&(FS)PGDb5@4D9;3(*C_kvy*~FV z>kefgL?Na$JjktkZ(8JanU zDR(&%x+w{26zgZvhi?=HNOBkv{|)m>yqkh+f2=6;hi~YhTQr&|a4Ka8$rnuV$WYHa zd!bNDw`@@NpK@ts7 z@1!MB-c8oJ+Sgv1WJTHR%=oB>y#;=oS@LPVtA9zI0&bEH*p^lKz^dPWmb0Xo48DiO zlxf&wCvZ?Lb_4kja9>KzY(PaKF|?`gAUt#(0$}?(i}S|*oIrqi%B7L=9|WWq?;~X? zBq9UNwJtY}1QJAAtXl&{t(QEP9k(se(4}9#H(Qe9I}<@SGQ5W~Emy{cn%GLhe@td# zcp^U3XVmEKaRhS=8GLhqa$w*j1^dvuAX14Lfxrlkp_RXwUF^X&c`FNVD1M8)=AB0q z!RN#aLAvLEO##B|x9r+ooD5K-^pL^W=ULe;==>+2d8qz-san|K)+!`uzuodYL(-Bz zNUXV@R={jYssD*lT#?r+C7x!?{JdFYiE$2<2+0dX_*kv7-Rou_JcC=KxejZomYl~L z;d7A%#?D< z%}T_%Wb&z$5X5`+#p(JbIQs0i+Owau@_#8Fk9_MFeEhU?+n7~U*jzf8=Y7#DCs0yk z%C|af6*DW2TNY_KYZ zzH99=6FKrE2eX}?f?k^h)bTh9Rx@2J{8jA4rlAjxmI^xRB3x7vpf>~CUEgFQigNon zh-sT%4|lkY5Ov=uFPdlduIG*mryp%x9AXew#6256C+F*(rbx0P^-$3pCd#M{3%#M3^; z0(Sfzi8uYstfV?lK5hzQ)xm$&QUN9;Vx*#>NRoH*3Kxtfks8FNIU1%jS z7dqZ{4@-=jhjTNqIeut&K;zMb4?`E;eR_ksy9Hz5S8S?lO4ilc&LlmtWWfPbG)qS9 z0U#Xv0-O{V7_W!BYsFi0*2fBCb3chD=%P4J$k$^f5W>sfgN1=Q2$X=3u;eTvOHkX@ zMZc;zwG4Xh#jH8q^=JzeuiZd@8sv_R(IBAE>EQrL;UDQLNqwlvDt@l{qkZ)|Z=d&P zatXh_Z-q&>iNAlYd32@n3pFU(5J0mY8X9NA)1g29FTj-T+NFrCh;FPW{)R+9>y`M8 z0uiYpSI`t02Wr@DyX< z2FP+QpJ|DScD}5p9w6o5CELJE6I;!FP)%lVF#+*kEi39JTA^RK4W=9X!KD;HKeGPW z!@u{a=)6~7-SThfaTq~)B zU|xe^eMn;qZm@{NN@xjA{F72vk$+)^yfa{Y8l;sCBi%qso~*a6ACBnZhE4JezX4CB z?QMWv;SZ!j)wUmUmS4Zu+O=oIbi+rYvf8oHzv(NUj1enluE(9yU6e`;2WI%|-(S3G zMP{4187C{Cl|2!;FYEPeBXU2SBX(OFANhKq?cL!Aw(zFyrxCtVJsW5Uui|Hf;f)WQ ziwIQZ{N)iDPoJ!i+XG4F^*@)V1#R)q+HgRX^%GXSwm&M(J>pfTAJ2p)vGh=sAWc;N z%z^hw%1I2>L}@eSGYt8#Q0@ZLW|KFnHRGva)(=q|qtGe0TaMr(omuFoxGj9?%g9|6m@Q+A`96Pp4qI4*h z8aIt@Q63@hZ{G@q2Fw{_SUw*>Hy*mHZtg==RcRtW@Y*}vPB!z!Cb+tFXEjLg`tI@{ zK90YKS|23h(PuQJWzlZ42H>l~Kk);{ejqZD3ye5rAz3KtCvmnrc3@!OHGrVpM58w% z=5bzrWgspmwOC%X6wW0}E0XV1E2sQUU=BzbraSlxAQmwO3FLD+M?zJ42dPZ}A1Xdd z0F_KngI*yq>4J1$0E`?N<-MrHb!R)p_VG8I9Q)AXGYB1rV$4S2|wS)_YBROYTp5hlPz%35RQRFnTljmlJ4G|Ug5DU{~H zmv9ok?d4le2?BF3NR@!$w*KB6`<~zw{&U)~73(N>dZ;~_P;J|*-Ya~)&0(DM%m8OU zyDvwWq|cL#r%s{vJMsM=6pL1_9Dkl7Ibg{dEj-2n?L+1nIN=vm4OW3nL)7F_>W{72 z7D;s?S+NASP60RBitg{ElFyT0o)hyiQ}qN_*}t>vDM)-c!=v)xJ55WHH$hy*q~F*# zp$W~PSi!H#x^th#??eThs^G47I2w!fYfc80m(o;SnglK-t%eVVAI8Ha%H6Qfp&n@& zpC~csOfwxlJ!CjlMZLbY?=j};zfo0Xntv+*#^0hY5f=2ZT}pM4ghys#IvZ;mcbH30 zsE!Tz(kZd$_}%O_^RhKhGCa3rKTm7QG3}LyiAZR1ylHSebGtlDx?r_=k|%;>8&1ur z5D2n$zPze`NDUsjKMRdDJr|T36iMe96P)`348o)(GS0#k zdz8auxPWfQ`hs&@t>I)oC~WCl_6%q`D)Ef)6#!lIy!ZeFxOuWY-UfEXK{T3ydsT*m zn%S-#kXz2D&{NA3>-5+Ufuh0WHz#unuOVtJ(g3)@$3(*S&#quSxt6Cw$GcWQ;K11) z41RElf@OW$_Lj`pDDTnArX?W3X?nB$<>xz2MqO3H%n}MrJa25aVZ0nM2@6*I_s9wQOs4DSo5v zR?Mv2E(_$AM5|8S$WcejlYk9vgYg+FOiq-xQUR8~gokl+%Rr$UI(Sx^v(0O+PZ*`` zma;*ucn?_>_i;KAkL#HUZ*-l23iesPyxd~QxnJrZF*NXOpNPBs5%dnO4UPca3A{`q z;SL^TL$wu5sc5%~k{H#!di&K?*78_t4yfSn`ug`u7g21`-m;v%B1NeZP*Y(PS=vdxUJ z8yWj|KfYt0*cv^^F!1FZvP-U5bB)w-W3I`R@4cGQ7LosQ77=d!?FaJ9SwSgSkR(N+ z2~(h%y--n92YjbTR!r9f1y0uZQNCfHkwkQCop|MF-THI-vUm<_64rRtGuNY+hK6Vc ze%G3%R0hFKs+rdW4Bg}nn_s)X!&0d!M?Pvk{iugh!=tFV<#F?-cGG!u0Jsc}ORoYU z5YWB`GC?qNK?CtKKFT?g&(5CyhEzx^6gRZ^>O&R(;UeZypBf|}6|@G2!? zVRj_PTKnr^n}^gHF<#K$b%7=dj$YQM0XZ*e_>Zdz?<(P#a@S=kt+Xe7S54&Ou=a0b zhHs0{%8e1*Cj!YF{4de(FguSSWK1$j1kqefQeEs_o#T8a9mRSjr4F?veEqF5BICw9 z>+T5y;}BO$5UJjA?6;G`HO9@#N7W^d828*+3U5@YfAyM{;#|jlNLes>FYde{ByNf% zoh`GDEJ~8_-R>_gv9Ry5F4@*%oo`+g{0Oxg40$N+9!0uj7tgSnGEjjN{MgA(@yzbl z%&=0Fm|h`}dL!cW|H@A?TkW1IIh-U)X1RBR$qEjHB+6prV#1s+rFTYme(^p&pqW26Y-AHliVF!3Q_tFW|h{7F9IHlIVJN_3g zck5*kKHh?ZNVc zH!N@-;5wCc)2zj*8NJ%U}Hss?oC4Psy)pV13^}m_q-Kz0^*)KU{&7oO&y;ty=s_Dhl zq@0_Hh$>OAUKs zyWc)ayZO_feN9wL<@DjCmpCICZYb)JsP|#%Rkh@Uif|mHwz`+%*NvwefxT8Ay6y@6 zk!;Vhd=yUEJVLjU0ri9ZkvjhMj@OJE(cx8WYhh+s-s&O|$0}wEZ3|hH_zf7##!8o$ z#{T}u`xnoMU9FDITT^r6pB?=(NA~J@X})Ngc&T90`*TmAd?*}3mV=MMW8Cx~x-=T< z$x@y6l*P5vg3sSO}Souw0ci_b!5Hr!!29u zLe=lP$G7|Z*kYk`A;Hy5!5AjDY)FMg+w|g^Y+bL7!F4D+dx`%#_5Z?*{~vhf|NqJV z!!Az=peR5<59*|)_n{FH5uJ%zGBg(lb=CXe^&gR#`B|uIE2hN#K=VA&a;qw|bGFfQ zMgJjnnad#V+&vXoj3{nyQkBNWL`>2>Wy>fgq7^ zfhW;8xkW4J*__M2DbsS0>n7-w@puNbLdu;;B$=t}aYdW1F>spAyIdNaw3ODB-J?p^ z7E&kw0J`|%6@2E$pM@72eiF^QINlnY z`N)O6)a&&fTAupcSxxxEEnIAjKIi;XCcq*hRmhUp@|9EWw2 zruvOPm!hn*O8dkOdzE!4K|A@J;e~C7zB=WrHJx6{hvKi-jaVbYK1zstxQu}NSp&AJ zJU4I>nBAQ{=l5}SdD#r4ee>bU>eCI$f!K`KhGd$)O*jaVZn!A0jJ4+I-O!=2-?gEo z;AZ}4>;gB}d@gu;F0X`EVq?@#=dz$I!w@%1yxC*#W0K zDD$}a#P;xHvQo&_%u9vtorlUER&78*&!-mSDshzE8}d*UIj6ONzkzH$EU<0u`4w`s zCca2@;o3WFyjOeW=SB?noae*A&#=Qhe%o?#4?e~g<8<%PKpI$zofmS8 z@LdlkzDfK8aoMH&s*~jUBk zP&2Ih444wvg}A`ARo${+BIE+jw(Ypg7dFf_runumxt!5tzp(f`(%t3kRT6)A`LWm? zkLf6uYsZ*3Cy4#0V_bUrtN)v08rzho|I;xIk3zZAcuk& ziEn(x`{nj5Us3w_3hxUd`f&C6xd!2>dB&XuQvYs&dBV$D0N8CI%!Vi>f#n4J>~n_| zKZRw5y`-vmUslG*Sdb-VRUDa}$hVk0PZ`9_4Cqw|R|*6D}T380$j3t>L=g zaxAp6CH3-3N~2_+R=+`n6QU9}3m$EMR|s7)N)YFpKkQLy>5H>``S-PPo{}0%4yqAY zLT$9Gt`uW8R2ffl0=&d;#%|hQ#gQYu%4>Mlo!(^=CLQ(SF;jrg!QEsen+9dZMEEG7 z*NlC+pF7r)$1~XTRXKWY#CwL5PF_1}T~tU#eaJw z?(h)3-lP9>O}HIb@t=>xZAq=`E%{$-@(lTZW(K??Yhv0DJ8x!-t!rWNse2)Zoo-j1 z7dVaN)Qz$B{SOcQFj;Um723)joK$g|%E6tIhf4zd(~&8l^8+Dwtz6&L?%Dw)`lBK_ zne?8Z*c`?4=e(AJ<*5O=Ug$;6c%EgNp8v22vpFtFq7!qX+dnvDRGweaz{d~73Omy5 zCo0F2D7wLZ#mD$9Y{DPg#kyNomKT!eh>c*h;F$8eR7m%~3VQ)$FHa%YlDjsTcDlvR z&P$oTha6L$9jEGdrt01;Prm`G^TKvyi&)%wE$^tLeX7F#101x$k-7xNe|up0&F@#`me{$D@wK4SYwQ5%o>dOcASDxkJNtTAzU7B9GOB-yb_v zUzL2ar9otU zoO8th`8jg`MP`L)@X!WgLw9mG2#IoVl+62jbw8xBrBrDnb*^}1Jw&7!9Ntp5R)Y7>=OmuWv3FD);|pgFVsu)H@GG= z=YvltxnFyK)gnI~wNNjU3f--8Tn{6L61eWVe+=B!K!1QsrkJlf%Le_1V~8HQP2IY; zaRSAkhN_>+AJj_kHA{EMk_(W+-u2}kzAsvD3?k)KS->Jq@Mj*SHncJjoR)vP5%>lA zH&rkjLXI3$!FN&#CPYatvG|T5(7*`!Lo0&Q9{AGW?Ip#91_AY~3bRY$n9aRB8^|RR z1R{rF=JECUdO#x0(pQTs5o!F|E+_#|$AYN?8J9hsyQAR(Rx9)5@!7!>dk!cH9w&~E zTIxKiUJz7enjNq`acDAc&S|OHcMe+AcP%QA@rgW>SiAeYD5eMJfaS&h8PM3y7iHWy zKhl}zeA63TNePm1LW&9H3INp*c)~f0)uuG=ERZxNeruqG&{qFsn+)H3)$uahzsXL5 z{2-u0Fb<3`4GN5d-JC@=mCmcLFj>U#lDyD^9M&P*7BK8uXhT4;|iU~ zC)!2QT_|{>eCJ9)`={5}gDmO@lHV$Fx>+(jBgC>LDaqg23-7yzdWxH#U^~;FbASKn ztS{77i&LdwLcn#YKkl2&@UWtuG#D&*cZp_S7(e**%3R?WBZs>1x?%SHKrO>sD{ndx z8iG@!1QM#iZJs9|WsDWMS()>MpLPqq@%6yC$`qG)9+YEVw@*nkph@eb+^G6t zy)IA}{zUE9+76sOd#`Y~7VB@NV0-S%FGs0XC%<$aGSvB9?`UpTPe$u-Vcax|PQ%Im zlY!Tr_lQckz!{U za_>5}1NgNXxG=VE_9Xs#%{(VKQZ3)vRc$Hw-{RkOk!QBEWhfwcgD$m)HGz1pRSrNUM-D87&FMD_v< ze%K#ttx;e26d}7x#2)0L8q~O^>LnADTcKq>vinGlhztxHF!Y2f)NuV0{$bAZvWf zoR2{VAxG0`V~*FAo(^u`Z0IOb&}BWho9>eks9Pz3ctQqnm@|H~Pf#BV*iM8@ZV<-{mQrcmY$wTr59CY(=^7E6}BTz>O zrE(_&`o=4&5)b4P&(05EKh8Zc1PX*$mb+j2Ifbdv{vdO`ghKE4N2{^a^i5i3e}8+f zj9xKiJ?fyAUD`KN8@-Z7O*MsiVl7=)BCd20aFJPJe3bj)Q|OTq;fHU6vu{$|f#t)H z^0~y*%l#Ghj^H5E&(Oa{&|B0q{qXRB#WWPyO{>oDZm$SAi1fvh`KTCxV_XR% z+@(oW_(?VojOnm@Ip|*-F_h;d-5|^P1FkI$q=jepc;a{P&yLOeii;uG)b~Y+TZeMc z7sArc>ga*v8ui0rTxzml`FuCPLri6@K=s(Ut&Pcwo^X znk9}v&UQOxeRrcVCEKab>jIT1GCAbsrxgm+RAaCBmg&9k@T%gYhFMkq;LDP#<-!}3 zBL!~R=iL!E;8d8@m zeqK%a^I_mnB=_NK#DbbD#>H9q?J)Z4A*I{;2KP4fXNmmuwx}OWwsWR|-5<=l2!qJBxtitWy6M~E2s+XP0065mDmq|=N$JeA>?-f?aFt| zK=LsKSzB9;PFKh-dmyw+E`Yk|&TDzK(Cs{6zT-1bd!Q7OH}S$;=3*P|IhDeku6p8$11w9HMN)dRTw6;1#Z;)V_p3+Q8h>AE--lnKsi0@Ee0taKD`N@I`7KR|*O7_b z`r!$qS=QEyK5=cu4HdRuemr_KUk=F|AQf<_OrH+IZes3+J4Lx>quHx60|#ooNhqn#()o%{s|CG@~1BK4#06zlrs`)L7l0 zIm#GB57kL^EmA($L4nNMOvE?!PI|ZogHflj2#dwx7N1W1cE+)Q&fHPlCBs5@E!eh~ z!$oTk?+(CnGX#aWCKsySC;9OyN1wWvLRUnAZrlsa5_w| z?ToZ>AopUMdXYaHtZQSKtQL%PPYD(Y-pn3B`dFWXZ8j3w>~G3H+Pi?)kJf~Gq14B+ zU=~Q=&iqI$qoHDNvEd{?`xDKZPYlz1gZR&mfGzAgsxrCmd$Pf^$24OVFUb+#m1J*< zcAgNg8*l^_Pg)IEZ_dTz?yEMfxvbw;jIH%Z* z#@DiY{SxAa5ohN~M-cC&b>&CF-${*+h`wrBCK}~XlLcxDZK?wC_4Crm?iew2u^7i);!NZ}0wgd84uOUPdEN;~SM% z_P@I=qHR=_z}>BQoaFzuym7E^-Jb=9NzvB zxUQW6<2tCfOR3=t-Xsq6)zxGtewo6gHKg%{V9I{sar(rjf4Y6f1NL3H=geOotKEm@ zoXUY@`f~+-7K@bNoYTz?%Z#qaQm#}LB6cNKS9qo2t1fRgy5n6g;AH%{3`-COJ>^oe zwdcYYuwU@y44ucsfpJexQ$ADf{!cA{NbJycsjbqFQX8z*+v}3my*KsPO-eLJRfmP`K)?~HQc}v~Bsa9b53Rc%1hez|5Mvp+X_jisQ0gaT* zZ`-6A>cX*D^cc}qhNY6*XW`q%leP1>sHU#ovw+W;b#Xt8^iS$gp;hMm2!lF$7wsrs zpOsI&Rp}GSaU6LDK^lA1#6$hD~^REiBG@4aNnMy zs@qqN6SQUW+t*vuQ~(`Ji~1JK&)H+HSw2A50W~Js%a_bk*nut^NU}jyGT+S7{gBTau7@ge>Ol!4itx195=$}*#ob$F7>`PRRYf5*P?B+vC1IRlOtO> z&8w9GKF#Z-YUKpgQ$v(19o*H`h1ip8N!$l^>>$m$lt?bMDDeG)b7 zc|W>%=56(xAVYx)?G4IrI%=7>sD<41vOC+$Q$PK7qT22Dd+Bzjpbeg`Wxjuo?hRK4 z-YLpv6g~=%|AxlHE$(n<)2Nnb-TO?gG6;~&j_2Zv>~q{>cEo>DWkF#6bq0lan#?d=m|7|%ppKC2Nx=<&{D>29YqTt6VA41VSo+x3HL^5hx5PtJH<~2 zc{Z#bwuRV9eqU9yRd*o3s-SAFnQf%aYunQ|<#)KMMnarvnp8xQA^5cLv*>$YRW zD>L%;Afn2_t{6Efn?;WTz6PGOEe>B?nO3MM?l6&+~ z7eUzg-o%g^>@}guw1xf8eK3w5*wT^DUQTNR2#|lrH16Zb89}cyz>b9H(&8uAc~o#2 zV){ve35;6MXYd){6#SxL=AW%6XWA!0aB)MXM>0gMgthf+)Qr!#{tr%0E2i^Frvecu~ zrbFkY3wlEKA_YF_XP4toiVKM{-wc=jEMeLkDrqES%DFYf9wP1rUNB-Dt9@kh_1pF1 z>=@23gUS<)TF(~q4ZyR&nqBq_3H@3DV~oO4Htl+{9ySBl$IRJ` zM(b@K>p$`l>~@CV=GNa(S70f~Q5ejVryS`OeWrXo4WtKso?7qt$RDh-4W1lZ*!Bbdg{}L_Ec%#7Jq{-@k^VG~nobh`2 z_23IMYVAquXfn&2xM^Pnpy2;=5`^^d)c~eW;$>Q@wT-u@FgI^I;*iXUkknt z1SuP~{3LSFO+SbnmtQ%XusfWcz;aN|vF}SxZw!T)vu$hNT?bOSeTw~X#Wyq#XFZqG z{B@V;BcjgdHJ&1hDmW06yGjZUq+;9V3Y%$j7hCo9dn!Ga@WNEv+YFT@=^=~@pnWv_ z*)uBmlrt#cjc+y%9{uIsoe|ju{pI22$QKIu-fSGFtMZ#G8WLOgHbM>?s+?`yt~>iE zUZ3)Xo}eGY2$!Fa0lQ4*qVDL|P$GZ-ERaB;A;Vu8Mdfp2#%k8^QG-C)=UBh{?yjG9#Nic zlP?!X2^xMKr^r2Ao|KrYSIB-c!^$S%jKRAT{xMUqzBl)gRmFv19;fsE1gi4zq2Og2 zbGA6^iEuV3?CThJaAQ=jRr>8fv2ujG{nDw+t`z8NF;xAfOm5uZHciT{@vY*}VQ}th zX4G0y%?{`7jk|3b?Qgr7;|Lx<7~@wYJU7mrmH4!uY`BIrfbz%B+_C7tp**FmsQK4`$5>+npmV;YmRl}H1RGBQzHQX*sK-D~d7dcxEjBC~ zJXu;=p{HzKBGTCP?gO!UNdKwsKQH^N*K{et*a^tKWDxxhe@nQIjd`_B>qhV-=)oyc%`8{>RKc2I zZ1OIs@fAu${@Bq6*kn2h$Y{%n$wh}Q0pj3DqlrvdEwz#?)LWO}-fxQNPOtKJ`}TeJ za1p{_%OagTg&B#>#e9hr01?}q4HW48)6+7!1PwFX#3HpXaZVzT@G%PmeOs@(`tc3my{ z)2ioF1-DhNlMkYG%yoj$9#HgSZZZkI3V-@xi13z((z_73%>rK{mL$ao|$B(f| z-^>X1(tzoX(ltR}y>zOX?H~O~VScu5e9QAt=?2=zE+g<8SU4+{a_VGb?t9Y&;~hi8 z76P7b`g^w`4o1!^jpdQHZ7xI(YqPw&Stze{Gscc4%imLAzY`8R{UI_tNow zlhO}&sQo5LBK?-eAR zvUjpxGL~@t%4} zy^K+0{57~)%4`fqy_M6oL7DMhqNw<2rZ@Z&_$L>{;>te!#JbC_g-*$0_^-UBxN}G2%PSzfW6L$D84d6Bs%$buSd>& zu1P@0brV4=J0j6+sVbArvFqdK7h3}&nrDR_tBVZ=Aj-s=iyYwm$c@}CmP9-M>knP0&nVr_@HJU765-&oj+ z9pxVsOfZ{Lo^6{?6yKklwoB+Zv@84w{DdrV2tkGQz500!n0bSx$3XXyKZsB}2JmW( zgcGd_(~X+~YI&1V7dV&)Qz2dDG&xY6i;MiDB1dPYlTFLy6MWW+GKHD$(Z&ZfE%;-3 z`Yn!@&k}Rri&H=9cz;u<`nx*onWMa(AoW%eiv|I4)nBXwjYk}%-bUe_o$~0@_qr4Y zKR)!oPZL)6WILu*;quEoGF!NFbaq`tg3#}h2}zv^SN)R5N@NJ`yd1wLs^3a3jFYk_v#F~^daPt? zhXwcC^_6%^0K5XP0Rlp?wdl7`Jcf5 z;qRz_x%QSHzktminz?^C_<#*MA4j5;=3n8gTAH?%L?vg<}s)lfxi@0r+p$$s#yOaxaaeh@@HFuJw>yXd=eL)<=O((YkjpM4c) z9c9p?t(B;rr}*3mS6KaIFBc14+Pgt3U8&|OuS!smZzE4GEL)TFu~Vc4h}T{~0uycM zND!d6F(aaN?sfzT#H_NcTQCA+_%riOOYf)bRln|#2Vv!9{hq8>MuFRhdbXe4#L9#} z`^Q2a!s5iraBhKlTB9KESsW6u(9w)`|HQSHb z@im^(gvoP%{A{oxyb>!Nkg951B3NM(i>Ad{W3fQNq-As2?tc=&WCrGV3MiLs%#x1Z zjm^iJ=yQkzY-Df(mV-wSCH=2 zdT_xAe`FgvJ=}2f+dxMz?j2$5Pd;rXT_!?+|JEEYPQAq~sGFrtvHv_P7VruUq zB*#8U&1G$c@SXfy^^~Z_hE!}j#yQ{q!(&jta!?WQs~)$nBT38u63iiMCpa#Yma=mm zT&8VnJ^M4>M`r&Mo3H-u4IrGk{1>I7H2ZAt4X0!1^QAhBrUx@G$Yu_#EkZN_OXeK>laSd$5UHaqx7$IIO03T2JSnrU*hW;JnhXz#huHIG?$b25iC{<`#Z zu^75w>f6?`b|K+aWsJGVDcY!e1dxa^zg(tpF{Z7ln z7t*oMVVQ$Nz9WKP2{<3{-D>L6fi*10hxuyK+H$;Q(rQiO2hmMTmKhzFi8JAj4J0?? z80*&sqxtI)rH%MX*f)jV6P~1vYMq~fG);7y2`rHNDYe0vBLq;-5ZK1I-PzZxmc-MI z6W^|SWT*F}m-n#~xR2~9b*c1qnR)$f!t+b+CtsBAFeH5NVkC~k%S2S${Lx{Qc-Ms0 zA*c1YeR?}YYE^a1kIiJl7H%lUo`yvmb}Lxw@k%O?{uwc!Pi{@iT||)0B}Gv4{Hz@6$D&#tz@}*@JEh zsl&TPi%4cJ?bFYv|G{_LDB;s=lJyZt+(RT57pBLKyB%KG5lfFzvJz6B`%-ixI&tT% z&1IR9)yB5A)ypfbfXv~5$4lKWJ25+11k;pL&~R^5pFhEy8CbBkj=v4@>1@q^I_qKN zTFh{!__Px&?B62}Uau2sZ)J@#zfqXFb2Sr#0OfiN)&OttH__F<;938D_FCRsynmVH zvF_c|&eTXo7~(9PAp9c!_V+m6w(6lG+Tj}S+#%DX^1EIE8s<%m`RoacFHw(%?&?u| zcvl_1p_v*eC%(5|>v(F!8UaraaBVuPXnm7*_5*A-4=cZdH~>i*kbflLG*3(xa^;iZ zT<&OdwiAH=?Ew4>DTOy45$vf0I#H3WVF86T87QXGVjm| ziR;oYG+aB#a|Yp?kz!;pQ-D(~UdeUS2>dmqk&!{_;}@KT`%ZBnW2#WOsOmRV-(aq5 z32AiW$rzhHPH#jo*K;~nw>;Fegk^VRo@3CMbMMwGw4K*`Z`*6ZL$>Ha|>kWDVuCNJia;>En|yk&rqkN%kXusc@Upc(7%{dv&G;^WUo zVx_dVwzGgK*{`;o3Iz}+TA>qYAcp`F6%xuKhzSVjDfAdn`nDXgZE^APUcIAH&1gHj z@qlDcQe13IRf|?%*jwQ0vctW+k*mzGS+LB!`C%Kf&2Kxa7imF$q0ayU6(UjGcqeO9 z>RVMiSr|qO65CXq)a!Io`%zd_YSgFO>qiPelbi2Ot+$|b1sD2e1c%JB?XktL!FwrH zivTL~;OmN2XMg|LRD`Lo=JliuX$~jD*pY~&`c3jv2dtU*$Y1wW&5@8Lk}&rr2cn2i zmu!qkFI*M1T|^o^`zr7GhM?#5ANaBade7-f)QO$vpdg3EQtS>zZ?$HCgOI zdN4_kEuT>ZUoLQ$h=(P!wy23CKvx>qHrxUDGJ65O4(D?454>4V)n+c-*tSo`<)-!; zAwqnC7{qyt#ZDICdFz3F=9ycE3O?v3PI(>3FLNCpAYBU3N?~ZfsWo57F|Po2V1ZB6 zagcWJKIBhoSM9e(38++kmePy})?NP6wi%Q#s5KA44mzLomyuDs@oV0NE6?#RpfJ!c*x zoe7%Y*{V~CeS5ga(L{EH&j<39a6XG&&*J#_!sE^prVMR<(se9{xv2$}xL6R{i6=*k zo@|}ygtA$>bj&dL?pqeVmDk@O=Pj;1w_d${oMlS=tRZRk#aS%k5ij$8ED9S*QbRt7 z_`#}B;&WS?Yxtv8{}W$*7Qx@r+^5oqcAoX1kD`Atl-!+6n>pqRQMpf+;Q+3k7iU>S zw(VCL78^bOw^z^@@q(Qtj^)!-YTNA9WrSX-e)za`@5Y)QsATM8^!oRT>c=`8D}da_ zLP&{#JA1u&;RST^EniK7Zfw9pinLWfumu z1+%dEZBRdTnekZfx;|O&UWI~UVu$zfVH&4;oyMFrd-f2gTt~7u-V{?$kL5QulcCL? zTj3CNpIF#Qt2}gX4EF*k)E#uS$h&4i#^RT=Uz0=cYb)M!K)h{|f?4!o6f?|Z)(PI;9ZIAR5^k6T_uzoVIQJn7*F-Em zuOU@$jq9;;z=}LkxZVD**4?ozH0l^{({>E!>+=u{l2yV@N>Ff38yp<81-$jo2FcQ0`7JgfY6Dp6(@=viBC$E{ zZ-%@0yrLtnu!p``zi*WO2JRrmj-E!5zoH$vlNw@KKrBQF343lJ@brvIO_}Z-bOh1T z0(xkh4{kuh@r=!M$b#DcjRf*9j#y+o-=}-KU@ZaBWqN|(lX~$(c@SBf4r`3L0vi|C z3^c1AL3*Q^RkZJ>D&}8{NAXQt)_q@2K}O$yUm_I2E>k+H`X@Hsm)SvV{<7-%SHjA2 zCG5$uGz5LZm7R3m0vpGA!ZGSidxxzP8mAweVJ$D(t6eT}uk;QbwmS`CfEwUtf`KQ` zF0Ji~_sf)eVP?9H(pX5y-{CYS^!Bs=V4*Kejcl~Yib#+ZbI(BPS`kZ4CqzdXPL^~v zWXkNc^S;?|i8$DVua=XjaQUf2p32fdclqEf#mEGOo>#P%juuf}f|02i^4Kt9?5o4O z7|FqxKM3`Ob?YynNopu4(YSC+frgRY6NQ#dA$z}U6(gp1C$WpaS5Sq8TA9}NpXb7} zbT?IhvpIi?Xj50?>2eGu`dhe0=>L3IzWrjn3MBbcRPogdrk%Z2@jV5q{$c%qASMvY>&5F5@E3 ziI9)3NONY!adlevgkHPj)%P#C-N{QXY}<45Ll7KAFKav{y>lMy7aO-aWT&q8j z1@-7hYHTj)48!ZR%Oi1r`|DmJ3X)vq6e}hP%nlpFSS}0xWTki@!hLJ+iclrNbGJ^a zyPfj6-Y+vU&1N;K)>n%k)^sH=Ewa zdLt7%*L*Gqu={0mDYXMeh45V0r@DGcS4g#$@Lx}}>VCVt1jIHY6T}Fli6*e2{aL}i z*MlK!y`i6oy5*>bCsA;b_`Q2J2zDn3#Gb2G9OlidcVTsBbLwM;2S@Ig%MZMB9(v=F z1@Xr6_gunumEL&&oANWKXSX|w$qZD>v(t^;+g}d4{*-a?2!5?}OFVJ)S@FH^I;0i! zs&lXF3ZIWw7T>*9C}{e){^NVc&Wndn(-4nG$$Q(%@P=gq>KpE+o2|-c5?)9Tyh-;rXpMsJ};U0&r`XD$U-mcqE?F;m}skWdV7Tq-(s1=UI95vCl8lk5H&LwVIiz z#??QaXjm@^QQPTEzvlH?%`LSDc`xdX`!fYyOW({y%$$iMzbNn5^;FK_La~7ztOqd|H?pA2e(J zr|-4Cu@7iQo>t?yhp4 z6Wp%y!oL0?{J8D%H;gh@+123QSL1b=1(6w3=HRmhi#==aa#$+X54h^$uwXF1tVyp_a#!&}jfD9zKy4Puk|BO9^t%m#5-!NXhWgYJn_B!k6wW+LlC|6o=B zU*D|bn3s?%X>2#MOoIl8($o%mh-N66cP7W#0^58j3^C#@y0Rs7?6&M+{ zXvRui!N_U#OBa!qW;lr=KfC+?sfaAM{3G93{+Y_Oy!mdH#_h0&@iBs!z(KFe6aOg} z*kE=5wAnPyVJ!*Mclf>u;`{~E7)f{@Xr;)(xlrdm6#nD5Ct($>FS+Dv@_av}pIJol?Bry|YVXj*Nl=Fd_+!MHu>BU`=zXFhak z2GnlUfaH_dO@C%1z(KAOI`H@B`Pf7s_)2l@+76f4$s9OJH&p}xwed)7pIP-HuQ(Ob zjDMSxHCh5?FSp#vMA@I*Icr5}y_=Z-jqXA84c|iO>xKk$lLN=Y*Y7&MPRl85|JYP* znxK1=SpDo4^=9ESB{?WXM^wP(4vRpPp7^1CREBhTt(le^9h&Hik$OBRr2?bFkwfz!YT6u;QSE@CHCWo7bTki`fUG0*?hA*U7xv}7H6 zSkc#-gj>Qq-vpy5^{BWX^Sp`fKozC(&wd7@4hb3K{8&Pe{DMV$1}ciZmN z9pBzzj&&A;&M6sSOmVygTim+D_ApMxM)X{>`{`^FV*q34iSyli@<14_nyi2?;Rb_P zT7rlT!Bi1~fAn7_P!yA5Xz)mMg89z(*O!BBZcPYcbee)QLh_4+rZruZ&3>X~MQPd$ z;kK5rdCiN7yRZrHO{Y{ugq?0)1);L&%O~WaBGR>~L~Xk?0}G08s=vDZLM9um5A@GS zM?M=1R7@MFq+ded@EC4`G7_Ak9U0eap-;~ST}lQv46Z;E^fxRS{cMxhvDJfb3irGK z>hNA=N?q(VD-;UgnEO^?(itYjAagNr;EjQ2H|>zViGmg%79{KJeqERxMd>Cz-{$#d zYLQ|bA>+gyb&u$e~S z@TeR|V40;&!S~98wp+s*I!zali=)UB#?-O1c+QR7%pzgzewm%5--D#DUSATqlpV(Y91q*E4N1A&%%ZZU(jDT&*KI7lM^4oV zuitl;uRbOH{1B2h1%`ecrRPtAmbYDcvcY}JR+yAiAPumE6kLe-euq#t&l!W5d&msz znF4zFQ=x6hz7IDKuq9o_8PpzOA&-Kc9oP_l%8a)aP_CJJ$Dl&33`msFb$q>nexNDE zSxC{UbmdpEP4qevYWMK+PU*NgskD$lC4dA6OesH$-Y-QJvmc!61GVL7@ZV$T@p=|o5pkrNz!jcgDd)z% zo3%L3&J${0pb2ocWyA4~>R0P@G!yXJiECcy`an*j8@O?ho@C%^q{UrfxwSbY5)NS_ z8@M7n-}bvXXe0^_kq>eed;d-xvv|}?M7%Y=ya4kb*>%U(oppb_qxlkmvZ2bV;Jw4r@6Kmfx2VZBqZAqLBLl}#blhjUl9y*Txmcj$B9wt|Lx92ek>RQy)qkYA67@gbSuSihd3 zu1H|3XGM{f<8;8-iTliWK@;iMznOfdqMQA}(O8hb)z(i5(26*>T8GKbq~OT@W?abO z$aPZ3nwneIVq^@R+fWBuLR`3qcek}T_dAlmX{xhvQ*yh%oykOPHA#zqSq zmyLiA*(E#HsxRiN-j6&>w=h^w%sB_itjY2?qs9?OV>b8bJvcQX9UNDJ5Het35`1zHik6* zMr*QdGv8PgURX@>jrLqHLjtKHQ>8mFl}{~t`*~uBR&Yv2wFUHq=jU?Z&XVsHbCOo1 z&~keJxJmP0;3t}Vl>^*~UcC|z2m7@(k}7qcg7M;T^!H7|zk+K8oobquWIWr=&6MV- zK)?oLzoHIrvpv@kZNPR;$?k^r&cFLAd^Q{QBxylhCeu@5bBM^FT7+-A&7<+&J*5ex z%4U(>adt&{=89(U-Ca_;?YA%Jz(-Dops?7>YQ)wRWd7G!=_qbe|*b#1+<}1rA zdDnj|tI=fqM7?I*iAxg5w)Vjt<`kdg0^-VpV#>SBSN6c9D83Jd8G|U=!Z;MH z0>eQE&#mBz<^s46^j?u4pWjrb$OEh!kurw-X>SMe{Q#ZHZ-18ISI zyyI06ihRi60?)d7*>n)I(1p2L&U(qIIS+2z$!j#+qlqQx@5h|X4LRYF?@Pnw{ z^q~~uX%bz%r+?5e*yW$&2U|Pd;%aRd{;7_0rOzZ&%gY=unzK?4QgEM8gL6RnRS&4&g&TCLZ9zUcH_$LC9X#S@PO`1DQCC2 zotB+G@ZLl*<|(|ylo?X;Q+Hh1qZmtV&ptr?Pn1*w(zvWVgr52PWG~iDYD}@gn`C%m z#A{~q`6G$93#Jf|S(UgccwK)d!Mbb`*@!`=5lPdPX8^@IghQoSu#+eeS%}b&7OaK) zEW1_mfd?BW+}L*)4hg;`8Mv*LZjJoadE}PuvGXbV0D>Org7)U(xNCtHIf$(dt0T}Z z3QpI@8}hYWCG#&v^9H*dh%31Ll3`v6${V4)tpqTw)L#@v0ePW)Qk=R|QZ~yS8ilgYON7aQu|DlWu4|{LlS(O-&Up7Kmv|6~f$Vsm(8kp6_oa z9{kr*@b1R+f*a{4=m%(VLScUbTn~)ZZn_z5O}Y5)1|&^G;$Sv?ka5U3kYoyJ+_+9d zuJ9bll;MLICfy600f)FgQKe6=tozMER9mA;+&EjxtcJ!W059ghpUt`IY%T z!G@OOa*>!qXW468rl+z5Gw?z|qD}j|kNGyY?Ux+g_iIJ>A;H-z7`~&uBD(hEgak4a ztNz*8?b>NP$^?1qhi7#ZOW!oR`JJAEa()C($Hq&z=3PDkX)b808@w4IC~K$||r!3B_zwPJt#Ji?7)^T)Y9c|{PR zelbjf*q$~+w76a@C+)U_-N;?9!a!dya=HKd9{oJ-Bt6tPjg<{dcBg1-3{Yhp1Gmxr%vbs& zI|F=U|I~E{$8y`3@Al>+2vzA0S&BB%6KsGbU@24XQl1~T9P#`jue`B<5}{0i0oIw+IG<=m~xyj(q+f;81@D;JoB75A@9v4ZqX>mH#yt-!bCVAuS1cO@?c6n;u z4aL~n=^JdwAo^A+s=D*|m~3Xoqx}R!8U3Q$*UH^R(%!+GG5uNL84Vk=O>nudFH$k> zRw10~_VW?$Psx0z+%ggy)eg^K#u}MfD+J;}5mf(v(7=hAbkEEoN?aFB3&=tQk8>;d z?;nL#Z+n1GTtfGnM<8^Z%oWINr$+3z>^ZC>_RQIe=cTnsS7OAmtNOcl9vtYsVW_h!~E1u<@fpBC|533_9)oKb)sf z6hC2WHpI&(7Su&^OG2eZ2holae!(AUEzc2IVDhEG9pb;bxhD(@n(#HZ0hzJBdGW}F zqY!FTezNg%YoJypojVZgzx%W>LFf7-A93bn0g9I4wpdl2T`uyePJ3TnpL>6ZFleArH66o#>ocbAaFjAhG@J09Z)Ix`?BSa&M)InqnQ( z2f$Zz@ZH=mPl?ni+)xOyIMNpuO*>m@-B+-yAV<31GdJ>^{o2aJ%dQT1h7eca&XC3J zg$nn5Zga+%-%zSF6QJ4rb&tNhIisi-4!WBQp)x#&YvU5Oe=zhBtlMOmIlU`;%ePy99p$uYF}_T=un;3XM1*%SCcf zNZpmFPJC-`>Sr@MbpSW1etHSyN3Mpl!L5B`6L4f|?Xl21PL(U72N3(qGJYCFYtD&+ zwPaR~D+XEX(OItqm>k`3dGE>{!KP$IVtuSwAZb_F%6^35=J7KW-#SjL;y*ojp0W_0 z8_hY$;D3d&i*qo<`=DV#yf$>4mFAGJ9<|`|v%N`BvBgGRF7M>7&x~}Dmd)EPDUXNW zZ3$AQwP;p^U#_}lDBC_E$C*ZcVL##L-PqdCc+|uE07B{eQW7iD2gNaDO!-_Z+t$9i z9~@PXTcFqIdy;lqSMztuYDeQ|8{03+SABhDB(Vg(vM-wUDq6er49xOV4gyN*v!dtY zak<*RbaLVS9&Tvyl-Y$EXR)=isAK`6%kKI^J!)lkwN*T~HN{^=DxXbC9ve?yX18Oo zLs0b+Qc|acXwzvYz$M8g`SR7;_giDpZUGz3EXt$&x~qM7TQ(q0Fn>ourwDn-UrRfx z`(%tlpJaCI-8uZ3YI3QO$WJz3gsizb#35sml2;Br(q13LA^k5&+j*)tFdvt3(IP`0+{vSkcOX2!g+Z)VhbI@&Hcw|x47f)l$H+I zEzX+X>)+8GB{kVUErxVCS-C65W=s{5?G#(|$6>Xgu8gn8eFt|RNmR2jS!CM+IXiLm zj-R4*!F9`Rv$Yk086CmltM|5vOD)Shb$~LWv+_}bfmW0!2A|fibS--|Ma2@R8wcNH zp$rr{;TM`2I?HGW>v~#uE(|lo)a1OJrL_t#(CXn&h8d1hg=nI?v&nbOYi@^C@P2vl zbH0F;aoztru?O1&LulXyZGSr;5uB|&VuStB`3k2iRJx^#z;R2{&cMslapvVw7pl>3 zdgT`20zI6+MKszBlWuWzXuiOXE>MyK=kX`2iTq1!BmdZ&el&8$%ag*AfLd+}nIq>vLW*a6rXs9rs&{L7*KgTJOcW{c01bvp=yfCQ@R zp-vfz!Uh7O$i$Y~pQN8%1mu=c#Yi|OyI(S2em5OV#>4E}_?yhD0?;Ed$@Ciy1~(<% zsV!~0E_|6#+m}~hFN|h}_!}J8d*c_b2_Hwp!a9E^q%FZKK~K*?`y;`VVt?!T1Md=^ zldz()JTD^)S*a-IoxYE+`Vai^%z;8XfATJeg{-Jv!Y&w)D{eCX=-D_t(R>L3T~CI$ zoWzOF1eZ6{g?oLj(zU^F`-E0*|8b!^A16?uQtq;s4O|}ZojUn@=qWrWc_md-;oH{` zRbCj1of8$sS0Nr&AJ+ISm=0A5XG@>+kJGF?SMFY1uCckE!8$VUA59mrOD4?oow?)W0wz#d z1fL}8e+zSTG-IDq8%^1?o@FJn5i>ksM zMiG>40KR$j@irQ{+QyezcshJRCnw1BiQAP6cg zor98+f`NoI0)mp#Fd!-6&>%G^AfR+f51qmg(%mIFAWWX``2MW#TF+X~kI#Dk0XUnp z+4tG^eO<3>XH9-B4|BwPkn6iFf6H$*On`_?7Q05jrUh<}{m_M3#w=G&jw))b#q@ME zV%bKmD&Tl>Y;sTHNfI=K?b5ojpLoz=rCoTDTuZ`Ed=#OA`O|a!Vcl6BNxs`;$@%N+^0B7)#{)2e3`yL1 zV$*$!*+l2ceeo8^7kj$KT^(7Jh**#BHIRhtWf23lUIYRtifk2QtX!dbA3V;5lZCKu#vcg z`9;FP@UO}dys>5A29}+J<6obpw!6C)XMs8=m-iH#2eRvbF)*VzXiO8-!!f3F_~$F2 zx|B{8Z?^1^EEu2be9}U$$vd1bl2)x|?-EppRBtlnCq1D%dkc}ZyC{oM-8uA-gn6TU zCjT!BVDEnAhb-@*!I}~6UYhSto34Ee+TAaUGWx`v3gRm}2e=<~Z`>)%B0sqC$WTP? zMyQpcSi%t{r}EbRj`8QgD2asV**}(fI`&w7CA@Ip61tdYTI)RK6g-&G3EuDGHc>$} z$OEd@`YJDDv_RahKXP43hlUd4`jF!1jx8ghd52X>4bfrf0{%}A&PYD6jvqMa^b9vX zmS0t6d`cPG95e%_g*sjRLGLsgDd+p{!?Q2e4JT{f*+&6;8zg`EcDK?%;+V*bI*tz< zgevMUT9o%JLkF-_?t3vlE8}^C@lfp#I%6D?I_C=h9&IdfL-Xq#P?(Q*w(s?6!L!r< zmFWsiJA55%uX?Oho9X%c=3}Y5!z_2RV#QxOUVkxm(^zQ#Cilz(^G5G)#s<1RQM0P3 zX?V%?Axw})hBeJOVfYeYuLSp;8amlVZqLtCUOeM?lU8}bOqN%W>Fh(_{18X)vDpdU z_DXdUzJE=fPvem^eNO;Xo$*@62X$AVc@ug|LGDk(08OdmPSuPjjzGgPOW;zWT`IfFL9Vb-sxG*RE4-LZ(WWiJQb*g@{aHV9L zr&*0;&*U=|^MU+h&L%OU?Ku+gtwJwXF&6tgNB`IP5^aC!CfvVF4@Jcs2tJSp(HzX| zW7YJgbQftGg?d8uN;9q>@lqxPlOp4ncOE0WDDlI7c{{&4(W~@P=T$k5>|0@4!Stnt z+fQyL-HzR!Pm2%|RCE1`pOI&XHJ?EdKo8H>uKUrln~cUjB;+1Y z>zk^=2VE@u+}Io99AljC56wJE^ErqahnxpTZy449a4*!>+O)Y_r`PD?*QzTes*tmt zVLvVdwfvT+hGD0dJx;2}7o+RIWvOB0me30-ufDzFXpfe|Zw(@0G_+i%b$bXuy(WWdbIs^fW#q8@7B{r5eQ26Y81di{aP>Ej;W=3im_sOzLtJ}#2E)3~zG|l?IZIc7pXZgD-c%L!vwiro)#;(% zVYL`Ng3ZlQvS6S-?-coqO{n;eqMED50m1x5KjUQu!H@3Ko}-5U0aE;=RHXVSVm*7- z5m5iD8h~TwTT=prKnVTE>=OwD2w9is@H;Sg>c2c1b_iDBHn!`QQ;Qj_p{$oF`#%b<7wg4HA?#v z$10pao@HO^A%BDMgXh;)(N~@|P!;%XVrt4l9wLudM!fv8>MF{;lXk6-HX+oOzyHX4 zAjDrsORO!o9HpHqDi799V2*0VER}*@im|oJ(Tb_rPO%NgaAQYtP_OP+zTw>0zUh7D zSHqGDfI_{ku9RCP+g1no-WLD( z668JXe(UWWWzvM*3wnuPh1Pd^f$+}U1U_OsSs$YUge}=cj&K1I)Fb8O2rGZJP;k4w zFD|R5w`zT`d7xH4p?;P;FJqUM%kt&aJC3XrCVcio)_Fy;sQp*tG2FKt)Sah3E|!Kn zJ@3=}As~atJ_I{ZjeM^n=Dz#=3uMR_H=M~`epr;o$-WA{K(r;miFl5$#0z%}NuNr* zp+85c?1f1*qlw=dub}Z1r}zV6ecZ71$LGv%f8fh$|CmpLvy%>B7q6|UFC=SqG}Y|LejH_e&zG^&Q99Tr^3UECFaXP0C?$(NJS1alvT7kCPn|7!pW%-OTr;`8(6h zGo4pM_+$0C)EPZN1CIK7{BZ&@(b62{F|5O8K1hnIYbs6M1eYSgLOqnRA&xNdj~&Zv z+S+aEJln+IN!&@zA$AO7x_XSN-w5q@ppPB$ARi=gOY{6h6`D~YwRxC4E@~SuKl)Te zx%pXllkRSzQPsC!sX?pf*`EgEy`y=q;uh@_=1Q4BHa9g;$W#}3q zlxAR6raj&9c3yN<>tEvSxzHUdx?ui?5nx((i^iGVc(sT_MnlI;HZbr&yhgzLhC2?^ z@rSRsX6fhf=8Bv(-wm`fdA~W1dNGK#4j#Kl%2aBW_au=9zr! zm4|~^$Zea8{pU7P%3}lwfI~r;X?dm@v2Il?ZotiEBFQ<;L!M^Wt>vPjYNZg@ZEm1Y znlMH)l_*Avc0R$=VM~jIN>h=yet;$xXljOfpAW23a(B=F8dpNAXLmKAQo~O z*Co+EMybP$PJxxE)>U5^av3PPW%aEP+!DujB9zjhc?)ygDiCf7S9QLbhM3dwp5J*aF^!Cnc1$!$#Jh(6iiQ7}OMw9y`Y?#>z_alzhl%)NY3;d>{D zDf6Qh@6~*y)g%t_*iHW4AA}XPYW@sn>Pq?pE4RPB-&S>HS*&zwz=-rrgcbhGWWb73 z1^>}-m6T67T|!Em>lIWs4F5_s2^JOmqflBDy|Rm3NwfHO5~HT~HomfCpiH(`QsjVK z$eK5eAa|mNYA?$7&tJtTE^BQBQ9Ov5X7xkQ6RsqUR2blb;@8`8!(_URf4FuP`GtA6 zmS_XDWUUT~kKGM5e#~^VSA`d`BqQ{k8;%i>nM>5LTJ7t|q^m~vfhUWCdvg+b8>=d5 zK%uDjM8`Qukyhsw3ktw9w_k>)H_Z`0j;Oq}P9N}kfYF{^AU+`%H*kW-0 z&&C!3q9G8uXZ9G zls`f({nm&{Sjp0DW^bN}q0t%*Co-F2owR3!avkn2q9m|&wh{+xQ$AS@KS|zASqr1! zeqyJF@Z@iYs<(KfH{O)U9HMH3gT8g`g7O7U`*3RGNgw= zDjtNgww0=6ZESyT`}(spHv+m;Nb3^T_+1GcycjX z2o))DD@yCj_7$jp$;W2C4q3jO<;IJhF==Of*Sz;F{j`|F{!IFPX1e{r^3XPDs-X!D zaj}5tV1DB9u*i%-nQ-yI4eVsTc>6fzw~n)+4|!rS<)6LRf3RV);%bT0DY5>%u^2GX zZ;d{gP-k%sGmfPRqKxGZ2ldFhWBA!7iCykF56An1NbX-m9Pa104G48F|E8ggeizR( z@~r`Onr?3{mmIpAL1Vd>V1&dnaOOkLu~qO@YRHD`9_)aQ_T6t59b5Smhrp|yvwMbp zNU2!I!^GF@W}o~q%mroskBWZ!j&;g~DJ3T{E$}T1YY~^R8vQP-bJ_Vm8^RvK^cvHt zeN!0W8S^sp(DrLCe$O2CxdP~Xr*5bmC-!+Zny60htLSX>H$EL6$dfu}Fy^CO=T@aI zkh-afs(=_?76adcjv=4kzbVSDlV)pO@UUg_-nai{&)xY3D_f%R zQ+{WqFA?F9aS2ZOL(P$U$_FACe;II(cMwSxt~jHl1V6kivsZp8bhfgDqMv1l&PMmf z=sC0%i-keKsZa7M!Fobf@WG6vD~>E40{bKFP4hi;^!=}*Xif-$%pwt_h?zU#T@u%> zC8R1+=?+_-SraC|d%UkWk(F>H^c?!Z@aM&4X$>%DowlSw>d!7f+P7!WcdpcTa(#Bg za`*H0`j9fa!gxoAC*coS-;lcDE0*43GF~}R`~|jEiKMb zOW;O{`_ruCT4y#A#JU=m4|Hqan_KIbN^G(2Y2xh5MRWpXjXkDRJGDx?HB7^@hforHM=bGb9Pd~(|isvmJm~an}vt#{U!y5IaZ0oM2359??4`IZd3?k;3D3<=^1pZ(r13FKD4zqM<c&X*(DsCrJZR(R;rWsnF`* zH!=ZSowh{ttyV>beQp0c1yIqCgxviT=lDeszP0)343rJrZ5@Fa+2Lq`6SVsPZ}e^} z-YBTC?E~{q4vSeM!82 zDs^hf?Uku7nHm4HEt${YVWVV9)^(+2j^E|Nuat)(rGR_(jeS}6*KlhhIN2{ejX<5-o#pm$8z`7D?_HkzVUB$bY< z997=-gSql)yTwSh5i4_l!w4W}5C>A_Bb}EwEaI#&Y4O%2_}~cQy)Mv7(85W)l;f4( zlG>5;J42cLyATCUcY1WKg+VwEP+FfMPn`ZYFmn4hg!!@Ky@fRzwVJ|N$wS_iA&dR< zcRt36-Spp$3FE1v`s>L^p|sC+yq4PeD?TrxyoAc`MrEI>GiwdyCI||-MhQ+5`hJJCVNa8@X#UaQyqm^9kLj>A;eeuwi%S)tFPhtb2&=HfURZ5yc(@bkL1R+o$*eBff6bWc#y8AOnuw zIuRsX=zp-Fh6W-vnqNGNl!%!bkp#+gH1OznFs;I|SI=*5H7{%$KHB*Empfdi6S3dL z$xqEd05*$|VE5|j-?6VuR+er9TzmO`~@9zAdIU{v@$4U(E#9yA@ z-1#SmzF?d_;6{RHVez=^9_r*Vr$XM#vxl;6u{9b}Av({u30cXX4f&iuv9S}4C*MDU z?D5JwS#U~i*m8Z$$D2Az&T1K?>Z86oHocsdqS_OsKXV=vwR5d1AjnP2Bh%;>3=2S0 zxqb6jc3gXhxiac^@1TO~cEfnm?EU`=Exel|&08Xn2tGH&LMBfjVx`)!o z#rb}NaKLIozgeekt8a4ccZS%(s>A~3^7KM7TGLf^hA_PJjO#iPD0a zXXLLpIms2oppv5RpQR6}CSzui_~JD_8+>dh2itgM#LjnSKX%^-1fmZ8ocdR)QpjGi z%Ka|!Jo<`04H>g%Cb_ZgwknM_{x&kb zPbzsv947o-nU%5K+}fpc`ihF#MBadl zz1wAJ!<5`PFa9QSm%`6oHhza)awN#!EZ%rFdms)A^F%^pr<*%d=*+FnnAC5Cntki5 z4r8%>A(BR;wi}k`sG3_`swE_xR~^y0sn^6fY1FPz0>eRqkKtJ1E~Fz!rR-G#G$BL8 zGzywfK!JYQUuOH_p__=efCz6xAOqW2rNvwF^JTW3Q+wNgi~8}uMNuGCAufcON#Rha zil7sPmL(G8FO}olj$7X@9S;n6rI$X`;Uny|m>|1+-I344{>>2;!hdvaEv-`N1-Xu? z=G7ho!Vv;M;Ph(IbhIGMY`<~(>2L&z(q-*VltvtDWH+6%aE{;l$EJac@Z9o#(>;az zx(?Qw6;?SpKFj{!e;$Y<+^7{R*)CV}@R$`KWVN!8@nU|al^jH=#F@x6-6?>mTy0wG z7H@?q`FrN?pbgeO3g%sh0SMqXN6`8T?5=W!S?&Fx^$pmQB$M{Dw6y`&_9s6gPfLd3 z&g40j9mKRh-fw?)j5;j1TrfCOSSLILyUqWnS5Hfto6*mn@xO(%+vFq9{}{wxaPIPEPU$+gn%E(_+0SldD=L$d9H$_}P$9H?w%C zV>TOGFu7%dW@pMM1wvj>IPB;B?0})^-UZ0GhLs7YLCC>iN4SeC;2}O;%+Qv(7WoyI zSy$iiAb+LqaK#Od>)I=Z(Lq)1-ki;~x8huHUKUaqwil^@B^3or2?$=BX~0A@Ku2^x%MJZ0#B=xX{`i2falIqC)P4wSV8qXvY?bZ+v5a6C2~Y{JMf(g<-^iF0#Ks=m~*7YXF95#$Xy-`_M7iyrJ~BH!gyNS)AxJ8Kwpzy6&~U*KFK zw86qrcX=_e8|%F(n`ya#Dug-2bi)o{4i2f;NqNpTNj=HeA3J&kk*eGPl9wzh=a)}wV9HVBN&ZKcyH(-Mnr%Wx7Ut{JY??iw&g(EV{6%_m7~#LM}I~~ z)4d2Eo3^tcq?Y1&l=8gra-1aIm16EeRTFOl;Sc>+KVk14#F^8nca?_zrc>ysN@Dar z?G~lNvoB}XS%*V?5kckgJp*by4}n?khR7|pr%&gM8zjiY#Zk58(=r_Jr+BG!+r;We z3wrnotrJO9wy)y`0n`gm09$>(J7jfX_=ZVkE!s6(0;sb}`eiEo%vevm$lsb$`?`!I zWFM9Q-{;e!w=;!za*kDcxtyvV?Z#O$G+xMCLe?uvbME)UZoeDF56e7RIopAiwf9&} z-5&(KdDN>myNLEp@XJ3YF|2*Hy40j5ZcxNMY}uQcP^jT1p}kSS9bvB>fpg zx83OSAP&$;z&R2?Ka~`TMjsW zOXE?;{z*Shz1=$en$GCWh$L=yMJ{cl4*r2h=}VA_E!YA0ub1|#Z!}I4k?L3HQV1z% z)Va8!5`z4-oZ&Gt){X=?gklpbu9H9$dD$7WpW_=q#xbUGJWv0|5s}IFJ5K<8sq9XK zdCYoPJJa-CdAl>3>yLkipSFCWbt<}R=r*27q&MDM--jLK?Q?mHLRxL%5ysa`Vs@aJ zaBpfW?8fIr#|hfT7iI*Ppd$UPyFrC)AwyA5-Jd+#Bew553*xO~$&(9wHyO7ZlxU!# zOg)%*9XHD3Z@MXDFZ%6#mNC(qZ23AVdZn=+6iuvr>+vlDKdnijtfW_%wRle%ciRmc ztVHO#a5qZcrJDFiT}49uZzXfPd4cc3Fgsvi?~RMgQjNp#;&5f_?fQw99a$(gJ@8nx z#Z2U=!QAcr`okAJrKG2}q1)qe`H;X~`hIwf93O+fA>ze9)^H7kw z&975+hliKdkB?^el##@KAa*JaBA_PpMq;?vdD{wtd+*y#E87u{WnAT0BF2DLRY=wT z-iWiX_^f{B zEVgzx_MUPh89&?qwqA#9I6uBx_;#lWt4}@2|9ELd`;u$h@~gY!!YY>R_^fjBL(07SH9A7 zkbuv{U$6<{U2t}YnQj8-r)ZXqe&|dE%IZ}FM~7isR-nlFY&`IdkP^2L^1%>vdAtIy z3&XOCSnlQpyr~HMJLkxIqElNPTFK6?b3;`2y zVm?qpL)QElyRe7^pRTkX98dEA8gVSPR)LBb&ZM-HWG~}u33hfy57BQilbQt> zsMG!VmrywQc|vfZk)%Vv)nasd9owUV+&6_wtNXh(H$_}acCv=5$G{h7d3*2+Sg^F+ zn~5<#C7bh`-P37@5LYG#Efn%bPXjwdda;k~te5;nXon2ZBZC1a*x(Q4vf4MRgE^X; zUDVf{ZdlRtxgUTPb@;@-WIW)i(+>fRo8cSPj`nf*E``6TX8-3*cTC-ZdT0WoC~=HJc&iau1vJuH!z0D5SRTG z=@ZqJau?PacJlMXwIx#(u2Jdh5Q`Rj!{mC!a_|-stcOXCD8H%R>&zD%cwl9k@S^s= z-~Zj07ZUTZ!J@~a_+ZT}Pmq#(Yd`brnxscf#_t##<$E|I`VW)Oa~Xfvh8JEjk!1L{ zeuz<$_W=4UFZmI*pEeyno#q&AD4dn_6fh)8l{r5CqV}sf6RL%nU?F{Vr{|`}{D8SH z)?X%BnyhA%eQ2{c-N{;Kt2@Y_x*i~uDJ?_)!RQ@u-nDyD@@igQqGViCu0VMoWCKG# ztG!UqWp8(wI-b%wc(uSD5%3JkD!=9OO6atv+Am+wy1+ewh#z0`KpG0ufyB~f!`FD68mPy&@v_0Lvwjf$0GW) zK2uKDyw!W}hj>2xN$i&L7^jAX&cJ5$49IJH@feTJXxS{f^6``3N;C`}I;5vRVJRbz zqx@Od8}TY&uc*-q^>qWM)z;7T^z~kmpN(xFO^^psGUhA;zWI0lAiUz8S~+GM3K4cp zFx(iq8@AibhG7`c6US`1rj2z#2e->H*y+ra#zegW{p+~F27ep2)E z)o|XbpixtVOglbPN@%08Pws8%WBg;h+&z9=3Z;>X+61;Bpr@v~uD2oU+5fg~xgE~` zWW0Zo6sp8BsxZy;QQqHu)I?+u9jSOd(UcqkgV%D%gy2QtfY;RyormJZG3UH}4zl`` zU}fZ-N*4suPE-*YN>il47?u@?=^y1WUqV=t<Ltpe#J=!{D{mF=`%XuM1D`@EH(NB@Alz9SI zmgM_f7?}qS8D}A@VRVVAUsEvNMOi1uE|_7pK;(9pMkiFD)8aLZh*Xf4+5n`VtHGB5 zv-Sv*yRr-EdeQtNINj4y)B~uDvQhEqza>eYa5+^Fa}q8XP_E8ExRbp{Zg(HZef}ak zy~u$B__>>JdGs(0J!_Pc#pKN$&702LpNRqJ7Tk^n3^I2E+7X7rD}1=mTyL(|sA(d*=9AuS z7U7qxuk~O@FV>06_o-34Y6pDnArY8OL6yDiLaf`>((xjUAO_h5DKlGmuW2Y~8kc%y zSP*jJAXjK_;RbJ%+ehTek4Faha%sRA!2M?W;>Lae@#=#NuJ^v=Y!t;v8{UR(r@lQx zXE^qKusjx?Mp>0YLS@6jWibvWZ$lqmr&W{rO-R0)&It=Ar~HwCiwQwnZeN1-__Oj| z(tTzwt?pm!5m9|is21*xp3ruG%yQ&pL3&l2KwFjkCiGI9qhgGyZ4k~C<809x$I~W3 zqU7wnDWbV>_ZPZK#!I(=xQ_N?yy)}fTvFq<#1C|0xgWJWzZUXd5t1p*i1HP}tXPm3 zE53P6j)n|u@5_FqESD{3(WB|X8oAB7@Fa5Dgr1Y@Z>@8i?|eBHAF~M-?uHy%mx=W4 za|N;g9Yki-rtOG{JVW}y<;-BCm%Bd^zp(5g{Q@M$$Diz*Jq-y({RMZrn^v3ymQIa^`EV^I&W=Ux5T4B70S-Ywq9d7e4iG#&7fwf-4lAE7ygv_ z486{O$$BKBMCDn`n@-waZ6`nUl$0oWG85i9-c`W%joxhLyUxzhv{C#NN^+rkatLpPmEpI&;z5#svr(Mg^AGZwO{Yrr^ z0!aZfqgF~|8zCBkt()CQSYACZcpA3gYRXEY==h3P(mu0%724SES=Ua}NCvhvllE{*>?}XtdT1%*O6JS~_E|2WIB#4I(2!JGn zkSP-!`*n8{rcbQVgs(2%F;HNIYg4xH+_{(1nN)vj{eVi>D$+>7@)6IWM}P1F?PkWB z&Z83ck0w^;`|q&bpj*ces~m6``cS?Mv1U9e`mwUvVnz&gRP~_b)fVBR#3E|3xs1$v zctjWj`*81hm2GcjSbAoxT8i}p*(+C33xsSfbp%1od~0vH69gUzCJ5eQbuulkzw!1u z%H6=nuyQv><@j%Zt}y@kF3)GfXpwdjEV3oRcG zbFsv*V&lC+UxDV~WxuHV(Zm*PtlsZL#(mlQRj&5v?ZJ}W-Oh7*cH zp!wF06{lU^Yj>L-Ns<(q)myIinIkZGnx;fPLx5F`M$k2fonvUoSl|~yQ^|1Y=&5(5 z=%2P*a2r*6NAgI_@kkp`L)JjH6nO5=<)0f7r`Po2!*74(LHy2^Ay3iq9lj((H+8%c zL?Y2uw;4ZS85M;helt?!8-TdZO|yS3ETj zX_8VcmJ0=LguxFJ1@u0UJRzd&@+W#0k0--Vqne9!e(PE6 zz_P2mK;vWxa%puO6~;;{C5c;L&-?jz-bF0T$OUB`2kU*!^J5Z`vm4blseDjO5b2{` zj{ejlqQYj;V-Vig;ZCj;IFRq3mp@lxk{$y0b|eLIj$X7jJ(^!?BgldJjS9VxZS%^Od(?b)JNoBUmJ4Zl=Yf~T@BWY&7PwHqh}<$2 z{OMa@{a&-8&WKW1$D#&^CVz7%b!KzJ&QBu1+57!&v46b)-A|a!AzAlZ8KO-K;PVYq z)&cU6Ar1VWaBM*s{jL*@nlQ#Ks7EzRx{JdizQDiYG&kuwS2^o}@Y@VF-Xy`#q@%2C za??`3@13!loo(EEm1mdFD!qNHEHEv2X3YxrLCh;eian^3bR!p_ZJ_?G@T9s_CLM zrQVp}Qp468Rq3R~8%^9)gego($sfD3b*9vFx-}T83!gbsm%qBDOJE?RC&1nA|M-yz zK6pS#|M0={L%6h74EIUq`~I3|7v0KF_@Jh7UAP!$;=`E@*@Rt_5vLz?&-$Kkt!UJv z^Y$LrA!zLWK5U=Ak8xuZ_0*(=*s-9Vfa_o8(x*RX@jQSMZ)8rSnhL27k;o)G9|h~M z!{Binh%CK##y0Dqb8vbJlWoR*M`o!+*5h;SgIh@Vb$`o;4DD`__AIk>=@&N|K4RGu7j65k;ye9U zZNo)2|ANyBz6ejNn9@lQ#aX>v4;T|Cv#iMIIEV|%tyTM+_~~Ol~2=1 z7@jfXcW~ax<}Cr`3tUkPE1|@)-D>p8o9|jrHShgxI|e%5{>1q_oPM-QfTy+e<;w0U zu>)#!s8qrfOJ#e3qkc9y4}(FEoPHhD`MF~Wa<{?{W$11p_Ckh5el}u`Asz4c ze|O?`wZLa@6Ux} z9e~OPyuC6dUyg3!shIZNJxCUTDbxr^)Lmd9r$r`90REKjr1*9+7;%_W)ZFg&9b@I0 zr?rHyXgW^=6N*%@iXJIidBp<*3^5D6>L1PR!dW#@sC}0G*E&;@JsM}S+W#O))-$F>D#( zw2jW#1{J-=7@9#Q(Aj@MrdkvD>`~AjHfi7Q0xgWXyd_M3>A z8Zeu(7}ds(C-Fx$=7hw}wOsfXk97D`KA6tLi$Nl8Sj$MuM-&tUUOrR_YUK3#m3a$T z@&z3kD86kCy!sNobO+u@CX%G-ydX0H7!_zWiQV#H<3=y?Yo42~aB&x67u&FBKg30W z&+nzYe@dg_1S=Ga5}kB240~nq(|sKI9EB{usti8-QK2k)#(ozd^nMXX^)r?PgZkXt zs%$xr+kK!1ojkyvAtX84qBzI1CTJ+@{1%X6sM1>=>Y>#AC7OGmE?lo?@?F|#^k*36 z0>GqU4glQq#^kv~UN!4yAyGr1KLajXaFfQ$pe>;=u$Jac=2JeX(t5?!7PIXiH*~*( zfL=aDK$NCmKJ2)n<;djhvlGX~@IWk{_ZrT;(LJo?M$`d;^yX&ul|jt-&oKe6E9Acq z5HKVg6-_?r;>(1V+tM{wi+s7YvE6qaq*dUDuhV!Z0b)`g&lCaup;I{e`{yf*i3kFV^RE!6)c@mXHmn7Hh3eI&)6jA4HWE35M?q6md@X~c?ta-nWzxk`U^}{ zHE_fAfc|1|8cbp*=MnL21$e@A4wHqW5YYI-w|HIVYj{`EHt&i2a0utg*U9~<6ID?B zqrz06IzWUxlll%Y+^K?q;R=6hqH3a^s|9rYh~%j>CfRVQ7OW}jZ3o^&#Bq!}o^lMT zbnS+@i!!?^CJfGTH%!eBPfx`q(F}cvg2e7zm6`!dB!gbEm9chQmGsw{1c(AEc&W2not@~^~)4$yjghB7F)SuR{rh@F+>V)xz?s91*u zX^e3*!B%+N0NNr z7vG^np`R{{FKW46&#}c~cds&tod%c(VXbumk0X5^gLonAjtz`wcX%<*Ve&p2@R#|> z4_i{=qjXtcnIfb*VF8Y3vf=*h6l`Qk^cX0)^TpM3yr~Kg|3iF_>7VNKdbuu>-~H|C z*dSWo@A>p>0`XzJ+|H(Pq^}-BvW8cnx?{TAyu;+JdevVlrpv?E=9=Fh{0`*~%2oi3 zU*9$wHK&nx$O8jaYc!!7uvOZ^>wvDc44zDthrgu4Ja-P%m1f5@e1&nkP1rEl<7?PtATt<)G(JvV#E4EmyLk zzLVZx{k_h=@n>CTfvu=0-8TkX&-o{xs$w1mmq)_rt`X>v#Cgp3v~U4T`xSDK%M7^?%bk;?a{ zW`p+`RmzOm$?>7$Z)1CrZpuotGhL?-4Hva)ZcK6t$CX>gDfiW|=tA$KsNYjx9HS2i zF8WdKC_1iv<*^-w@3i9WEP?p*JQc!ZIfs%ES9)G#Yq7zNK0V7{c-Jzrd50pOYM6XnnLm!STOO&Ls_7OlN*2pUbvWR_=EDYB87bf&Mi-Dw_B2 zvlsBS|CN@Tos~4?kw3`q&FiUQaeIW?v3hj%2`)+>Uq`Hh*#&dIhXdWmU$QUW$u2tL z)>+}Z0fWQrMi6s3yuEurmv7@-ts~#m?x+INb*A2&wQxg08k5n2kHu6%7@8@s81L;! zU7%uzE8V5=`!jHu;%SRu>JTV$G0ntsk3|XIagkQ75}E&~D#ZNHczV4b(-3%t$j;hh zU5ruO<7Lh!ef2K39HFUpEbqW z&+bcUA>bC@?vsW!adI^e5xed{nmV71fj>oZHTjJcU9Py3Q>5(PMl!^cppSKGT8sSzz5j7` zfiUnHYmP)mmoMbZSpD126YvpVfbYN78deu+ST19+=}OG3bpUr24gO|V_460xF71S% z!F3#*lm4{|QRT&g>*P~=zHV|Z{w9e=+!ui@~$%Xjjd zes~6|$rI!_Fvk1tHuvU}Ga5I7)TZK6WmUDog5$0K2Y@bcH$6>g^$4OT0% zoQ9;UI6|5|eJg(liT>Wo^aFtKajkQcPHkZX=n#r`T?g5(NAph-wh-i)3}+s1nD_Kf zE#8abMk3aA9;MY*`$QiYMoo5T|A}dHJTddjHz5u1YgW7dwqc)|sKP`BnaaOmXqVae zp|NC9X-Ac>$Gw~nQ{KT$6j^rjCR>Q!#{QgaT`f1)+k8PUwysQU_4NW8+G=^@d6tV? z6@8Nv;M6pQ$KAEDD*zD-_aaSiJ{69k+jFd*B8lz!mlq=C?^DtNr+g9Y2@?!508M>O zgb1p?SP{xxR==#_he*tSLK|vMs4Tj(9`A_DP*6XfOq{){eLG>*5f3)E!#XH=B;8%! zF}mkpEoSRZra&#Mrlx<$b147?1o(Fi>JD8r$s7& zfVFPjxi(}rRHf`BmzfL-xqnsrxEebML%ZP|oxgNeUciFNfeFwv+UYX#hy5?OZSzH^ z!gNqiH8oJ-X7lCfehYt|>{}H?ckPQ9!_s(cpP2uG2X#Mhn9fKz70m102HD|%M9-LT zRF(J6L_4WNHY3Ht^cN)&{o(5pBFd2P=q{s^J04}6TlDnrN>I?WvIhT zRBEVpQ}aXS!tFcV@dcr2bLwc>gH616-toG^29*Bo!s)g96;EGE4#ph_%s?7m-4>wk zl)V?uLU=1_a-p1ClW&N`qGXoFnJ(ebI4kR@2 z!6iW694Q!CykXzbAQo14iZ^VsogcvG@6hH!o`~%*JE8hPk2kc2&`Jllb8K8P;PqC2 z9S@U%DM^Mc{sX;;AJafDfs4}a=sQzNO1ta9vV*#r{8i6XARSCm?T3Hx`Tmc1_^0sg zkJMNro-()|;k&mWNA-jRB&DeobTHFQh-n(*aX5rT8d|4+(R<>90 z9{pY+s1S}Db5Fm9UDP&V2@nHR_TEG80FUW8$4;VBFPV>D8<5u){y_@PuGN!*eexAI zpTbz0&4O$^C;U^yE#JR$3+nVdFEN^^z74b-wN8$-W8Nk8vNuA8C2UG|t%#otymrvJ zAyG20vU!_X9b75;YF{)Dg*-}XW*vuZw zd(~LiMM!0Uhm|gWNgnOHR4}w_1zlXfY`=80yx35vY+R?(>L*?}u4=>J@2yZDZUzqq zx+7AoXgDGB&YwPM#bRgHT?$%#&CSiJp(xP%0xeMA>vuk=ew>iYlWWWK79V0B_TshF z?z{dG6ivCxcGp+9gSO#k{xCc#fI2`$Ckrz?zu|uEzg?TtL0H4xLGYjz0`VAF_h%5u zGkms675YeK1gx!UZ+ttGtxkR#2I=Ot$QaFi6{yhC2~S^!n6{FUpDz)LxYceoW<`nm zEYE<&>=>;znwx!!7CP;}D~NJyH~G2}2_!~%R45NZxN;m)bRv<)Z?LF+ty-()x zsi#iw6v$3Asr6QZ{FlC>Hmzhlzl>*X5vR%0C4T=Xbn=8Qo8V4&j3>xXl*gcHc}ZX} zF7SL@i;$Xm3O)KMyLgg*1?85WPf&5KBjig`=IxdPlHU;SVr>Lj$-NZbjOk=$!rCx#2;fBIi&p9%TL({b2Fs?rO;S z2B=BeucV8@eX039sn(wyztn)O=O)b*pex0pso{hOJ1DLJGoYn%|LwYd5_stpbcaOt z|FQraFU^BIGrJ84K;?seg}zhxL51Q{0Tlm~2BlIpV|kRQrV^fg1D%_JoF#EsQNh_Ode~Atd{5?8?4IS%z#y$i5r0QwULZ z#+vNwjG60tuI~GNp5uOwYwLlpHr;u<4-PfQ9hnDYMPBeg`rejV zXV3v7`V|tyOI=jAL)qdub|@DRPmU>ENN>hrUdZU*0&RP*Z_`QdDRNSGaCOx0LwTwBq3lo+Mg{3gEd;ONe>^^sv3rW}#o{k4gW;Mm>CAHw2!WMLe8 z?EACy39}k^{moZFUyh?66(Z(Iiuz%+%yKgyL{lyX*IxVH|R>f!k z{N^t4zCj^ozn*m>oPyR6YtKH~RnvN+W*6G_T8(W?@NukJNFP_|9RZXTe~r8(mK`%xr&V&JMMPV1bh3Dkk8eOm*S)LjuQsu(2E4BJ{KGiC$>u@(bo%sBX&jDm_~p-zRjJr2FYYhSe5kKQu;hfE1Hs!bIWS_p ztG}=D{YJ5o9Yw2+OL%@DOgE^(=(nm)%m<#ZsT@UzV@l87nhTVVSi0ie{v^KBM;_{bV!bdV&E+4O?r-rxX4b|-V2R2Mt?j zuDO7V*j<*lt&6u?{@zJ*cty$On{5~&El!w?+sU{wzvmq^WVWA9U=y|=^yT{FS zDOj0&^V6645}01e%~p@6v+bS7y)1Vzr){a0(cYXMcl@u)9&8~&vlR@Yy%G0&Bv>*H zNz(_VvQx{iGsK@`@INa_G6v9_<}cfO7Qv6YPcno8o~hcpAP}0LoxFdpa|EnPi&C(89XdCW~2LbHHkF*TJbTw z9918gbx?Q=lhtRs99dBFd^IM$!f;*39h}R??0uV^J;%hdU_vVKo*C=&jaf7*f%C7| zKV6>ETI4>}EZBm#fFkSedK+FeGs}X~S%cz-(qG@*l}M#AOE4b(Bi5IT+N-Y{JAZF# zybM=n_z`nkQ6M?)$=5XYn<)g3>iosW=*Mzr=}AY4HTVD1h?XI&I*t0G`I6^6(brXT z%XJzx2E_74BXV(Aby-mP!Y1KI{d(p5b|UnIM5jvdjZ>xtE~}+?)4yz=Sp4vzic^9) zN-y~Ln3Hap;#h*O=#4Hx$EL--DNY0Wdz`3Ny(QG!d(!Y7=)rBN)op zpB|)ra;No^jq9H3Qdu+K2JabL@&~a&4z^Mw)6uTcAsa<{sEesvXjTTM4xfM8T0oIV z>-)W!bwRbx5qF{%l06c@UvAjh4kh0&wg(xKb_b{CMBB*JFP8)n~PQG0##-jIGP6%OooE|`k7Rz?Ffp$vek>)wcWmD62u z$W;U?cjac&oS@K|SuD30!O0Zi24cgp>8Xj(YyU>Zgm*=pj`{@og`Oa>Vb_r5l9U1 zxF1$-9q_&eytk|zr#A3HWc~&hp*tjaao8gHnWar-buFd14XP)F!js@iJSB*xoIKuXF6EHM+E%tN*>(k+c%Td(r|NwZ(;)v^La{yG ze1PxE_SUv#zQmo*{T30Q@JrXxCR`iUKzNlmOReNc))*=aWq07J z` zlAcIh##!uVY43+XG18?HHI@Bq!E0-pnQNovYY11O1mFg(hcWcJ?cpQyo}G%$fY((@K7JVWWY`OOE(0IhlhI7 z>{=5`zNucXo~k;WM$O%&r83FPB3}{{zEI|N^jV`|Ga*M-In4yUm%^Q()?qj%XMfO< zJ%Bt*$)~yQmwwoAm{I?51ob&OJYyT=XaO_#*Ky%q2eaRuAUZ{5?@%upH5Aq58MTb> zGK@GP({}7Weqd?Kxx?`Cm3+W4lmAI}ukT&Pl;IcdK;8S2;Ws}|lNKLgwQnP4ECCDD!Jo38vEOe0i z>Qh&bP`<*lF%-7aE`oL707xx<1Zd%|UdXW_InTi^hAOm1kR+{RUP7M9ok9;g*`T!= za1&||>wfwyMBE+B__H{W7V&uvIN$YYnDZ{17^t)fKIA~MTo1moafIdafkK}y0bMYB z(*2{u0*jIau@96l2dLqVNaU$g!@+{^%4fHO0l_D}?=Wlc%jWKmD3IaVPjM>hO+lyg z<}3y);QmIz&M5|z?=9=3o%PE*muxq>vCgN(d8Jo-Ph^AFn*9(R%U+K1!&DZq$_r_*ln?;$1Z58e`>MS?K zj&^DwH|Jw5|ZK)VR|3Mr4h7p?1)*u^W?hgx|}+)p8w8;u3JLI5uRJTyNM=5fU8 z(?NQ!H6w(@9irV*OMpky-vSNssEu`cuV~cLD?LXOU@gmcX))jfIQOa`k{)hLY+>Ts zgh4r*IZ`6a=a{--1RE0^<*lCTA_X#nH#}ny0}EQA=OfCka)#}|P$8pc7Aoz!SH|Jo zB)a$nVQO7{!7L-~C*Ks>msoc^G6@q=)%-|J^ZsG@mCq7qGhgzD%PrcjS}{{n#h0Yj zKjfvdlYu$#S$7)rBJsSrS&oHaHfmSW8>)XUTO?Z)SF4hTGQnETwcCSTKN7jIgc-b(@Gp-Y3uRMi-F&=us>HS%}IJWsMx#? zNbgRVc@a#dW&~tA1wt^a2VW?>X_U573ng^p5<9}J3>?MaQnR7O>sj7MDSu{4`42E- zw~x|451zpGEzoct8J9OFT_kCU8JB|+(zgDLu)O||yCa7O56wv&r5@l43@f;(+Gjg! zJM@|HeOA*&`D= zMGm5KATV!fVCMxQBW`?8r!nP=+{&}}LyyOd^Qe*@ss|lCyk-k~&*tv6b|;5rzbt-7YD3z|}`j8rk*JfzVFg-}0y zNbmM^{@l1CpS*9QV+LEuX1D5*$~sj)AY#h(`5J~f#?()GobH#dtO3{#uUiwfR%FkK( ze93_5!zYpfqW&KzO>rRy)&c<9Rf_67tL~kRV}{zg2VW3r=_xr>^Cg5xhz?gI?}q%n649dIuzq6C!0h6aS=Rd zV81N)>IVRhI$YSP)`F+wlmW|qn}zxrmo3PP^tIe7zLGvqQ7TY${g-W`M-cvinv^{b z<0+FN9wSnr$harDiY~jGF>q#9dLidO&JrwN8cy`X;spBwlFAQP26h^@SNCis3iR?;q$2+q z&>!JHh>ujYY9`y$J0$$5pFE}?+5cMfis+Q0L3ncYAuw@uLvxep^QUEs>0zl3!v~>6 zcoU$5FS$Bxaf(PGq!PyQiRrhtQ6DIRJL|U*Ifz!iF#vr6dIFtR?}kzQCxSrWP@Qs$ zfAP&+loS4FTR6i!P=h;cCI9#Bj;|?N*+$(X@t>xiJTN#p_;gL?wJ@#tGj;l>?iBXv z5_-yQpL<`vjU{Ei`EUkm6QL#NX=iLRIefmEOjV*#KJ&VQ10`W7Xd>EI_2dMH4wjXl z-QDTEepgNQCD(?aZqAqh5wV(}lLi%dUc)YE!i`V6QDbzD;3!{Ne!ZvD>y& z`p$UpjDDYD^E$hC44O`1HK3&N-dUQLAy#+y*{h^Bbje%T9IKR$I{S zEOgc!-F-PY5-e~4yS%&4Xg%wSKV4zeZKA#{jWi7aicz+U55N#8+K}6tqO}2W@~dD^ zQ8y9Cs0xTE7vS%X$h0T}eNe%7zA+CYCGX`N4A`{GXo=dV-#%iK)a6*Baml4k)*^P7E3;; z!pX1*6r$OHz0KXCf8K8-2mU(wE(4t`eBcZGDKw5ZbP5}m`(1uTN*uiClxp~JU)XC} za!~$De$P3~Y2Yl2+gqOHI&0?C%U>jwF=cbZgb%Mr?OdJ>SlmFd-ZY*;{k&m0^I7fz z&qp3CGM-%MeHVs7dGCICWrm!?l>)uVu4vFkLX<+RqjOK07Nrr6Iuc3Xm|ngTb(BO- zTk2RPO0i&b^xfTEq<8*9-B2<`ZFMVjXEbvV5Li?ZpD zmk&SQH6^CE--utTawU zSrmGbB!otN+H{ys$Vp&YLdX(%NyJ|nZ`pX|7C^(bmRFmO?J z;v&w&P(c2CB#~yLu^{OJgO=knAs6y2Ad8Sr{i-92@Gd!;^Gf!HM5#E=1JDPqH+&!r z#H;aF5mq~?uE^54@S;wB`ll7Wvr%_X{;=;vOmw_3cJ;=K;WObTdp@>ew$j5X7IsfL zm$+wEHu2LWy#C^O(G0|7mbM79n~oF{TEt$H?n5{N=*>D}KqZvNaW8#*Sjyv~#(Qa* zWO-JwB?b_LrZdc61C{{>s44QO7nU0?^}Gr=+7WxZEyR>$t_^X79WP`1U`1{jQo|KC;A%Z|vp|+lR24Ph$a%rV0UOvg~0n_tH zFD>iq9#=QHMnmEihq*6^e=RQqe@G-*?WqSWpWDt|Hd(Cdb&GQOOF%Qf5q|n!X&vpG z7yZLS(3d&m@apiR**-rJ3HB6x_8{!ZEBfG;DMWk0$C@u7wf(~LSl^o+=+=ohcO5O4 z>}*rnvA#wQL!`Fymuw;uox=PlIx8QaOc!U|Q=!rb$J`-OUwrgM=8AItn4=Jn&BwRm z+3=f+=@=LVW0iFrcsvDCB;4TgQHkyhX@{H^h6H56zEqBM9=5Nu>`W0fsF!H%04-+k zTGFfd9mq3qZJeKMWo#jkl8r2<47dgg9T5!&>_UM#y>z~G$9BttLWOO#&d2;#@Nmyd z)87<@jhBjO*_@PYYjBGWJgIqE2_?OC)kT_z5i)KEegB@Rpz?k&gDi$?LkJAm-~{M= zqe~P&(kA&FAHrLHZ9q*ij6rPUIRNmlL7IDeaw;M{9DZly-QB)9`GERB z;=szt)&f9A(LW_dN%QOBANV+?PP%d-_}t|{xtC(rUJQ3QB;D2Nag-lD7%MTYY!ieH zRQ0`0GM@(E_`6vCeFRUjc-XkZyA3HwpzY&x_p8aTzzLw0OuQd!4Hu@Yvi62ftn*BWQ@CO^3PLbE(rpx}zO}8=E zRr|!Z_orCpQ4Rw*-IgoI7`7>dh|0sEV>krGz`PhiJ$tNIX>peH>vr~o=5|R&w`DX2 z6seY6^6fmoIRFdO_-9u0%oE)O6}QIleV+ug6#p5jGuDu1D6=e1QL21LN zO+xhfB=nSAE52UJYh^pnd`>SndaATb6n#}pu;7lvR;01q|`2R~u^TIQn5DDhZ~$90;Ir*4qCgxeVqM5|KID}X-= z)M8oi9ImYcbDoFVdy0s;Hp1Z0%gb_I4G%yJp$HNUyTkcUBA#}JktgJSV6_3D{6zFj zh0j_Wv28b~@_aN};pStJfQ2@XMefa8pQ0%?83nVK`WBjum-NAJHNz9)&wH-*lSKOb z3Jy5+3%u=%VK{H1BRJR4_oB&rZeFZyO^1$;!#T*hSS03`Lprkem?{Ch-b(UnHQhM0 z)BtQJ(cOt&CZ!|W0*;TTn(i;v#i*Tq?)uv5cQ`xo$NuBuEa8m}?P)p3*|UPj3NHv)V6gc-;a{OZYNQ&`>wn zGf*ZqCUm0|54X#@3rb7cIAx$JR7r`N5y@LMnasS& zF^G&S&`$_TQ~y-^)#jeE7VCwx@uB9o6k~@aZtVjLrEl*t%m{cn5NBH__L3E0dWu&5 zir?;}VLTbB#5DwI4(v_qWeJNM@=lq@6AoIfaeXYWMUziiB$k%k)YD)6OnAgco-fIQo%m z?C&&W)$GY{>U?>kWd672I*QR}8NGrj+FbaYO3^rM+1yyM=RaA+%hg=JPW?ETSdx6J zcB%rC?CAEoIDGiYq&1_m!0u!VAfe9s35;CQ!6L8p-!}o91P^I=vv`~12d+#aFplo! z$ucQfH-CS-vzNjT!85v&5;&Jk8MdxsRJ&D5fuXl=KNrR{{QvH80!gUMwxaX@$QUO1`> zu)y(Dv*9dok}DYh;}^aKDD5NHK2GnD9nX=pLMohjhOf6pv-7)b{`2EaUidq<3jY1I zKbSf?8A<5J?$)%V<}3bslt*V@6VYxDffk>?DStJ0#(tnWRW z>o8FB<_+p;Q-R+5yFj5z|A4NNDE@o8eH8b;v5fC#Oq_ezfrILk4z^A;gQkOTVtlx= z>nVf>Y^v(+G0Q#SA1_Pu{?fQ*oXZwfh`JSBi26YDfmi0i{<6|z@@xiYzI5Rc8Wl!p zWToda>!^<#=Y|Z|sg1^L$~l~1U`*fY@NIq3KfXIarZIO3cE(bPF~QU_AhMS6>iBik zukZEk&=BNZDn3Y2(mI5jzZ}PBOoFxGQ{zR|#kIxVd&R_s*o$}aMQ&ctjhP=LB87IK z)m@Ogw9P-S!CuXx%^|HjQvG5A%r9@H^6#DNLY|)(mFH;r zge16nUTfvE7VJMYw@{^i@sL05)?KdYgoYvTXuqUOg`g+JY4uh|W)r%nZySGAX(8Vn zm{~#iA3c3}^t51BTkHd3154RrY-K=(uipUslX>S%SfkF%JQ${B?9o_=r%BG1|Kb2~ zV6NUAPN#6QA2m$$n0w;|~4?$^EGQWmmk%YrL<_`0j#;9-YT!~Q3? zga$6rGSlaa9_h+Bf{}uDX=kw}DFhkAyekrF^N+Srh7eW2tnh9$+3Gs_PYn=b*AUCOt9GIDJU6xW8iTN}B&2OS{?VCB_2 z4?gi}Y{3LL`6$_na2b>6Qjd@BYpOG5ka+yh%~|RJjZOb#nXCod%TAE@@=7TEgK714 zDH~P*YWdOAjUSd)Mk_&wC)*oWNEvB1>l=aJvyfL5LC0gE8&ue$Gh+z~-~u`Yap#9{ zA7UZO#S0Yr&(Ump&b=2&Czx8G7@Ew+>~<3yiW4C$R2a4!rtUr-qIDyblzD95ob$p; z;#|Z&3%!A61#45p0Yx!=#J-NS?`u7eIQdHLeo!5OuL>B+3*Es*QqNVi{9W!vi_f>! zd;S(!M|i9~+Fbneq-=G(sigB2vNF@W0c;C6^+ufk9$BgJ7$bRox_dUU%WO=jz6IXS zX=y$b&~|TYn4ue6XO;STc%NpY=di^ioRZ#~QDCg#zT5Ektou{ikxH^;-1}#+VBa<7 z+%uH?3EWTVDf5ao5hnZWi~l>y+$i_M^&dA-)p4L6G+IF7dipuDwCbYNjbWMf>vk(R zC+g#xA29qPB^iqS6XJNnP%IA?CfiEsKOxQnkp;I29ScXhzucg^s5?S3%+edvm`!m+ zU-iUB5%DsPee{s~&)HfSQVyd5qdf0pWHv?(9PLH9Dl`>?AUz>_ z=DZ+4%lr7xy`3gc2my%0rXXV-`5^o13^8UGIwa!Ok zgknvAh=(`G7}H1sBT39aW}2^(*(m47%NQtrgAe?JZ@2=PasY0qw^aIr!k$_%4RH5= zC*lIE7H2K)7etuBuSo>GD#F5#o`U0!zpeuo!qB`L{cJofMDBLG*LsWY`ZJ4~UxzFq zlCZeaLt`?IS_7J=f%o#JD$L1Ej~^vJkm==p*sZ6zqQzV4dqb!FlEicZu7+Lcfr?|H z4bJekUja+G%F3Tr-7N1mDxKWx4D3H|p+03I@|H%$nEDo0N^AxW?b~Ps5S+S3C8GRN z;*0zYGiI!)dt&zFwcN@=6Y9X)eojwJ==aAJ4`>eB>BEHh4~iI`^rItNlUb1D@Fr-)10w>p!L zmvLvT-W{@%q@7;lM#Ut$q*tZFl--r^+2N{eJfdmWPKy}Q6A(j^8Hf!Njy`#U(&CY# zE-ys;m}>OenvA8ye>Uw!+di!!PybS`_IMFiklDL>v!6QW@Mo0l>&hSLJhv+!kvz>} z1RupzB|(maL-;k?@hk%nvhkBc9Zt_kN`F^H`fJr(1F=fQ1+PUjOU)HnX0G#y313Y< z8+$!}LP&f;JJ5}I%`<>teDGEiFUVLUx(1U{som8s>C%u* zrCH}plOkTp!Gg!W!@-g#XB$(Ez!Hk?dwBuPi8VQABWl$#7f_B3)*6<60Am`M?7@E? z>!CqrmHj!Av^B8YX;HC2F^;{n%#&zq3M3~Yh9)YI=tD)<>Ns3f?QZyrmTK9B7hwqM zYk1h7lQ-Q+ucn(U1A;hvn}_&}0iHs_U!}*g;KPhHG}^l8a(9v8Ny?2e>Etz}K)k^| zKhen@EIRrRt#eIh^P=V!eX&NDgnp?VtTO*nf&1>RQs?$O!oND}RZox6G z!lU(~_F$6rI zBnaKJ@aj~BIH-J;ny3X{3Fy(ecXzz&g2|2Hcylm~s(XtMw?|jQv`S{dYhM6XaObQ)3YD8B>sKo2%yCvWyPUSdHenz0eIWSu8L7fPUSINxcZb_KEnb`qC@g7qOa zO$v@{2XztWwOKR;r~}xYOo}71V0FXRyxHG-dEl59{34)wyfOb>8^qD<)7^1RN3d9o9xG%?i)RM7j9j)Oc(g#zm`@7&k;8_<j~TRn1!-RZt3!u`XvN zAx3X@sVUW7fojd)4&oE=el(Wb?#J!(%i%wn?=jzN$RQN*vZm7!o(nwQ=O;~^quIrhuZxY=bv9+)h#BTy` zkoFGY-}IWRBVJ*98U`hf2=7f*ek}yOLxbJ)%K9rj;Q^*=~(NRG{QD& z!%J7iL*wE`x?RH{smbobwc&!z70~Ftg}@BTJeVk?oi=!Mos*M_H2tUE z2&=!w=s7c+6C*I{uKDT!Aqqo?iXkI0JQnzfJH=`%RTebOL zcssdpqdNOKR!J`+UzCnXMltQpf8*Qv|6qsy&yxQ)-?ktF`BALZBg)y3&U-pqyBLv9 zF9RRe(L>o!WUk9+Eb-eom3_R{fwT4mla>9R?4NQA(0OO8vKxKc=~o$WXaQZ6|2agU zdcGXtNbK3Ox)v-XuFrh|C!lP1`jM&8pEj<^>mE|BcLW@) zu;NLNC&(_|qt&PiWV$%Au1ga(cJ;DY-qlwh>aL;oFCo98{!9qHoNvXAWor+h)_&gg zLLIPR20NO>Z4;EnE{@3(*L(1MzG=JTCG@I0c9)G}uiXw4$EEK4wnwK@CPKI*4@%A> z@zLYs?_{EsRN(q7xOz%QU|;5<(hOJA>K#O1*QzHv{F- zqxt?(Q^MY*S6|-HN9ek3#-iJ_!zu+o6%Bi_a%%|>Th_ii3Q8y%{K?fyKh1-@)gTrme<@d;>LFnkJj5$L5w^X!~;XET9(0drK=@&XC= zDZBUR-TSmEe;k<%ddS-9N2DejO#a$mxLIHgZg58SLIdR4`4_yz^Z9;K35!3_cuOy& zW%Bo3_1qo9RrOHK6hWo}7C5SD(;^8o-&&uWSJ@~&oG0~BpQX&H_bgR+afC>Zt)x|j z4y6-vqlCO(X;X9I11q2xVT?A?-{&}^?Db2D%j%3x5`h`K{ql>&rGh{vn4DN4G~rAe zso8e%4KIbVzxl!X>(`wDZwPh%tOk+wNtSP=hzka*BPT53nl(4a<4Ug@Mm)nMRY&xg zdNB*}??=48iOOMlEuJr3!p{E3S{1oI*>z5su5+5zXK4@f*Z7889@3OyT@u&TlLM31 zxvW}&8*C~jC^zDdkb`2!?&RV?kWv8ZZ!CO0+MP~4Z>q3tZXUM0j|~-u&^)-ft#|%D zla!55$2RCh0eoLMkAY; z|9p?qed1{Sls^&anLK<$(P{i5!!_Sl(+Xvu@)!TlC9eO!T_SF&{aag-`e%`6OihRM zQa@BW*ap3zABmZ*bvZmJ5&T0uH-l{W5OM(uQd$Y$>mUgZw-7G(4u@J$N=04|s7RE9u0YAfMWn>$ z<1K5&g;?hEJNbnj%V^C<3@NKBgIBNhF<%?gG|2h#zdjuDTsNctZ6}_aXb3;_`ue~A zgT=Sk^ncsC%%|Mt|MiP!vB+kh{$IDsHY&0<<+0%BZYFM1g+h_1ZlU(sPyXxXCb0eg z^F@UE_6#x~+&iUfY}eo2_m5BZDYYTL9IxWNZ(|{N{C7uoS@sQ_tsyld&JR6)JFU99 z+>Kb%REfC?eh(mKtw0LC%r1rxs!1}A5(DJIRDTDfNsmQtctoo5{Z>6ij6((x$lv$Q z*AaNbdS*MtWf58(XomV?)S7eL;JVPBmTxQ(W6Jf@oUe%{ z{i9i1MM1GI_M*htw@^mM1D(BIoC95nQUDZ@L%mTqc$rZ%cFeW4YIZL8e0!NKxFdvg z=U?8|j9rH1Mcr*4X!cgb6A@bCKZ$s@aphhfJ<|;mOBa{&07&ofB{AEg*p=+|g1m{D zVB(1UlxSdZeywZ2b-mArG}|1HCGiCsfRyH`2+hVROh#EwrUsc|>D?5tmrq#)9w{Q| za&a!o-=au~BCMm-V_TqPn}3U8AK0-iXI&z2jNn4q2A|IPK!fLBZ@}gZIoj3O%3^P~ zYnUWecmhv;V0M=y!|s($X@JL6O@r}ukEvbmfmcCyNV0GEjz``O%6Yy|FuzFV|L*p6 z)`+*?FvTaBYMg6bA0e_ydq&_)YO-cqVyy#R=HtcjXLc}~(tpmUHah(fN!uVig*sS| zx4c(d6=m}IYO*X5A1$Df`sPiF{%v}G%j*}6u5z;^v&M;syJ|t~Y&TDR!259e#Z+%} zc6ACe{K)}J*ZUM=;`wXM*_Gm^j|SyzPo|*~2s3~vC?8%>U3%w|d;ov(U=prvx;r03 z`0bi(K7gx{ffzpQ)=W<%!H;m%uUy5S{}z{@_#RN&M;d!`))3mS)H(sv9wY(i(>h zai_*)_~D%W->$4h^}C8QdcQMPwXVC{G7G1PSd2Pi9I~WE^QLD4M={jz17JW96edByST&xa1k=n3||8QaWnBzWZ&-evTxH}TVd4Gu? z)*f;zmw7XitEg#n#w@ha7m&1^B(kj7ont2SszKu>P=6b*^*(HELTVzGfkhY)(2kU6`W%q}dZ%m;eW=*C3y&gm=?@$R2UaftI z_!#!_q6F_o%Ex!BBG;^YbUQS8R(NE?#h*h>@FV)>q%~ybWk+Ch&|3I`LPqqh+vl_< z4XHZkRY4?!Fd?EW+EVGFj~PW{@OJ@W}_3r z!vy)zuV}wQu`$tB5Rz1&=}Tzrrmsd#q3~ER2Q#=0d-UY7${4^qH4C*OE{@>}1`drE z6oNRMtdk~w-PG+=wQ{dfe*Rc8`4;@%n{joMQfDTKdY2$P-;>wI=3n)U!xuj$=aJDO zgyW(7GR{7KqfaUaQBPK~U?k!Bw0daS- zC~IrFpyepNyLG{qh^9z9)%}i!V@Icn3l%=DK7XtFWKR~(j8j44>B72I@IL=(5gc|K zi?AR5=iu5?OzbTqZDT7OCnH+;w4W+gULC+Ml#C?oWY?fJnxAYUaF~N>r;6Q#AicCO z$B3zusikx-xU@APnvUb|ur&5j`km2O7SYhtG1{HB-MQ~tTn}pbg7q)H8DfnbP9@;3q$ixd|ad;a=2iqwU;l;t4h0=XVk26}>zm!zWr8F5#QmKYcSMN zSV*i{ZhFj2XNE3EG+p%rBw~uX`MwDEYgpa7T{+j!mSM;`vD~P-3`_hE5X59A%Hpl` zeLKGtKAMfH-HA?L7c#5i6|JN#=#Fg8(iT@kWgaq4@}>#y^7XKxLg2csW720hj!4f0 zfh53dA5l}eVRnNO$$i>UTu_Yo~$UVbE?nF`$c~7%I!9?IDT}``eD&e4q6V=8;bB)N4jr3n+2W zgi4oal5sEv%i05ABRtZmMW*FHTYpwR>r>Jn3HO8qCwUJv=&q5?@X@AbFZ#(<-PI-= z7C&AN4Q`w14aj5RDe8s~J>+NmRWgRV-vT^3*PTXvrJ3m`lx1rCv}YBAo|t37a*Qnf z!Ck0J;t1;ZaZ58k&3Uv{iH13X4^J1w*`6u%PbM!Q?vVMjci7G^Hb*f*U_xaw{0>BG zCQZ2F5HV8eb#E-mN;=F*7zuu<$~uGwsC5r?@symuu8%C(9q|9hArBqqZNSoI(f7X) z07hrOfENJI|flc8RR+ObhsE=BEZ3VA;^_$7Hp}Sm)`)o|{dls}@ zKe?ZCUR$|4q=sF}*STVsEm8C7Y$V&S?lJ3GfYlKNYUsOEOH;D(*{Fp?aS>smVf}oT z0ZDwnHRVb&c-BE43hjDelYp}7=CvcnSpNJtkhznag)p8Z2Tolj4- z(-oXrx)UqQEq7nG9DASkA?9|9JM)6FTmqu25z@zx_YDxf{a2*)Tj$8ge}50(KR;p{ zpZlQ>T1TE*OcXYuJ1Ax+;SD+xp#$isViiD2QG|>t7wm4-&CXCU^H(GV4D9~Vm^|e>jne*=`O^sYC~~|?{Rq? zHGmU;GiEVGsJ-F0Nhl$e-(2YtjffYe{BhMnfGMT0Q`JEj)w`sRB6=aLcFRa8wwge#$!MpIy2x~gn?e7r zVEn<{N7UcDr{3+C-q=y)lZqR0K!egDE=0W7%kB4GJ0D}M#+)vWDYIdZ`&ILt{Wbv1&k;SICOfCVVrdS>^6IC|3PrfcY1}e`0GHovA&1Xm`!beP5i@4NR z+5~YE2#yX}?F%lB;kzKjKBlvt@;vT0vWTeer4l?2K<#pqyUwRH_U!bwRu?Xf;i4fP z_2XMgMwkjk>w&<*#e5?xuqAQ4h8CL9_dsBhysi^A^P_Jh(H`-PyI;LvStsrd~k?scsL zBYHj(wf7;YBP3^U?^Tj{LvULF&_oWkZx%>Oy;c?)kf$_7^PO z%M7JmH+laPPuFGg$f*V2uC~2pYB4^i4zl%xm$Qv-I|Tu|+moNowgq%^{#petJ)lcG z(od(yh)!Vg9zV*f7Igs}DP^{Pjn|{WH;BmGm4!4wG=enf(mnypCHP^SSV?gXGydia zrsA~NDIllKrRocG7av9ZnaE}IQ=;w#B{~=GO=^)JMO|vS!dfy}N=j7ReIi~VnDJIe zqlG^b_Hup2h0xP=`KVj2JTHT*j2Xwyq!y%nKMPjf%ohp6B8{RA?CmsC!}%cx_Cs*6 zSclm}GJ`J?4QYPQ=kK!;m*Ff!4sHr5e-OMo04ZgXK?;pd+E;K!Z|v6HFUpQ#U!)o0{W zoJh968eK^z_n?-}y_i)yu&(KY_|s;;yGw4?)_Ax>=NW8*aR+RR-+~{k$P|(WtyA{} zCcFMDO@Dc#BK-(3AIC>$N!|$gwjvkq@yIf~%n~zs{HHGdL@>p8mT*w3nI`@40TEtc z{O9wdo9o8h$@a@gf#zFZ9=%QZnz)HHB`q2rD7;y$a_v(*?BB*`0FEG!C} zHx4^)5;ORHe>757q^@XLW|k4mGOT!)%!I}elaGSAL%aX&1m~bn8Vprk+CC+RAy9wIycPHjxx)hR!VYfm(0nPPFPhh%q7%fBQ&z0>L z_;zt5h;;2xAtm7Bk@OoGxSd05*gBzE%YhciIQ|jBE)Ir2@)he` z7F^qh$>R?Ve1Y-9IYQH6#J^{|=|_ROR-{B8hAryoaH+0UhPX?@8{K7{4WdE6kLK~Z zDhr;6qC0S(c_AW9!MTw`(wQ}2acu-mk0szVT;>7SO~Ut(`CioRwmIFLVtg1wvbY}y z7Q+usjZ|UIir~%aT>h+ZbCIz(iu{gb#D%N)T}qFdZ{P%23p^gjJjjk!_=V>+#muwP znA6h%3Y6DR+v?{)>nmZB6J0ePyjB{eWo6+dOvj}+wU4)tErnD~RLT*rW6xcmD~{Ow z6;l2P=R2@YAt^dXEX%zceU8xPxmz9QxC~Rhc9o|@I%5TW>sHXr+Nw5i} z%_nl}hddvkBrCml*r{KTp%S-#@;}&n�!l_gj=IC{<7p5CWor1rQKWS||!C2rAM` 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
    =%jM8~~IxruTKs^0iYS8ljbs)$%J=T-ew9 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Ǜ&rL_qKTGg6m{9O*o(pR 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/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 + { + id: 'plugin.microsoft-calendar.service', + }, +); + +/** @public */ +export class MicrosoftCalendarApiClient { + private readonly authApi: OAuthApi; + private readonly fetchApi: FetchApi; + + constructor(options: { authApi: OAuthApi; fetchApi: FetchApi }) { + this.authApi = options.authApi; + this.fetchApi = options.fetchApi; + } + + private async get( + path: string, + params: { [key in string]: any } = {}, + headers?: any, + ): Promise { + const query = new URLSearchParams(params); + const url = new URL( + `${path}?${query.toString()}`, + 'https://graph.microsoft.com', + ); + const token = await this.authApi.getAccessToken(); + let temp: any = {}; + + if (headers && typeof headers === 'object') { + temp = { + ...headers, + }; + } + + if (token) { + temp.Authorization = `Bearer ${token}`; + } + + const response = await this.fetchApi.fetch(url.toString(), { + headers: temp, + }); + + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + + return response.json() as Promise; + } + + public async getCalendars(params?: any): Promise { + const data = await this.get<{ + id: string; + value: MicrosoftCalendar[]; + }>('v1.0/me/calendars', params); + + return data.value; + } + + public async getEvents( + calendarId: string, + params: { + startDateTime: string; + endDateTime: string; + }, + headers: { [key in string]: any }, + ): Promise { + const data = await this.get<{ + id: string; + value: [MicrosoftCalendarEvent]; + }>(`v1.0/me/calendars/${calendarId}/calendarview`, params, headers); + return data.value; + } +} diff --git a/plugins/microsoft-calendar/src/api/index.ts b/plugins/microsoft-calendar/src/api/index.ts new file mode 100644 index 0000000000..db4616b586 --- /dev/null +++ b/plugins/microsoft-calendar/src/api/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './client'; +export * from './types'; diff --git a/plugins/microsoft-calendar/src/api/types.ts b/plugins/microsoft-calendar/src/api/types.ts new file mode 100644 index 0000000000..f4cb2811c7 --- /dev/null +++ b/plugins/microsoft-calendar/src/api/types.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2023 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 { + Calendar as MicrosoftCalendar, + Event as MicrosoftCalendarEvent, + Attendee, + ResponseStatus, + DateTimeTimeZone, + EmailAddress, +} from '@microsoft/microsoft-graph-types'; + +export type { + MicrosoftCalendar, + MicrosoftCalendarEvent, + Attendee, + ResponseStatus, + DateTimeTimeZone, + EmailAddress, +}; + +export const ResponseStatusMap = { + needsAction: 'none', + accepted: 'accepted', + declined: 'declined', + maybe: 'tentativelyAccepted', + notResponded: 'notResponded', +}; diff --git a/plugins/microsoft-calendar/src/components/AttendeeChip.tsx b/plugins/microsoft-calendar/src/components/AttendeeChip.tsx new file mode 100644 index 0000000000..67dd601da7 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/AttendeeChip.tsx @@ -0,0 +1,89 @@ +/* + * 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 { BackstageTheme } from '@backstage/theme'; + +import { Badge, Chip, makeStyles } from '@material-ui/core'; +import CancelIcon from '@material-ui/icons/Cancel'; +import CheckIcon from '@material-ui/icons/CheckCircle'; + +import { Attendee, ResponseStatusMap } from '../api'; + +const useStyles = makeStyles((theme: BackstageTheme) => { + const getIconColor = (responseStatus?: string) => { + if (!responseStatus) return theme.palette.primary.light; + + return { + [ResponseStatusMap.accepted]: theme.palette.status.ok, + [ResponseStatusMap.declined]: theme.palette.status.error, + }[responseStatus]; + }; + + return { + responseStatus: { + color: ({ responseStatus }: { responseStatus?: string }) => + getIconColor(responseStatus), + }, + badge: { + right: 10, + top: 5, + '& svg': { + height: 16, + width: 16, + background: '#fff', + }, + }, + }; +}); + +const ResponseIcon = ({ responseStatus }: { responseStatus: string }) => { + if (responseStatus === ResponseStatusMap.accepted) { + return ; + } + if (responseStatus === ResponseStatusMap.declined) { + return ; + } + + return null; +}; + +type AttendeeChipProps = { + user: Attendee; +}; + +export const AttendeeChip = ({ user }: AttendeeChipProps) => { + const classes = useStyles({ responseStatus: user.status?.response || '' }); + + return ( + + } + > + + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/CalendarCard.tsx b/plugins/microsoft-calendar/src/components/CalendarCard.tsx new file mode 100644 index 0000000000..dba12bdea5 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/CalendarCard.tsx @@ -0,0 +1,145 @@ +/* + * 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 { sortBy } from 'lodash'; +import { DateTime } from 'luxon'; +import React, { useState } from 'react'; + +import { InfoCard, Progress } from '@backstage/core-components'; + +import { Box, IconButton, Typography } from '@material-ui/core'; +import PrevIcon from '@material-ui/icons/NavigateBefore'; +import NextIcon from '@material-ui/icons/NavigateNext'; + +import { useCalendarsQuery, useEventsQuery, useSignIn } from '../hooks'; +import calendarIcon from '../icons/calendar.svg'; +import { CalendarEvent } from './CalendarEvent'; +import { CalendarSelect } from './CalendarSelect'; +import { SignInContent } from './SignInContent'; +import { getStartDate } from './util'; +import useAsync from 'react-use/lib/useAsync'; + +export const CalendarCard = () => { + const [date, setDate] = useState(DateTime.now()); + const [selectedCalendarId, setSelectedCalendarId] = useState(''); + + const changeDay = (offset = 1) => { + setDate(prev => prev.plus({ day: offset })); + }; + + const { isSignedIn, isInitialized, signIn } = useSignIn(); + + useAsync(async () => signIn(true), [signIn]); + + const { + isLoading: isCalendarLoading, + isFetching: isCalendarFetching, + data: calendars = [], + } = useCalendarsQuery({ + enabled: isSignedIn, + }); + + const defaultCalendarId = calendars.find(c => c.isDefaultCalendar)?.id; + + const { data: events, isLoading: isEventLoading } = useEventsQuery({ + calendarId: selectedCalendarId || defaultCalendarId || '', + enabled: isSignedIn && calendars.length > 0, + timeMin: date.startOf('day').toISO(), + timeMax: date.endOf('day').toISO(), + timeZone: date.zoneName, + }); + + const showLoader = + (isCalendarLoading && isCalendarFetching) || + isEventLoading || + !isInitialized; + + return ( + + + Microsoft Calendar + + {isSignedIn ? ( + <> + changeDay(-1)} size="small"> + + + changeDay(1)} size="small"> + + + + + {date.toLocaleString({ + weekday: 'short', + month: 'short', + day: 'numeric', + })} + + + + + + + ) : ( + Agenda + )} + + } + deepLink={{ + link: 'https://outlook.office.com/calendar/', + title: 'Go to Calendar', + }} + > + + {showLoader && ( + + + + )} + {!isSignedIn && isInitialized && ( + signIn(false)} /> + )} + {!isEventLoading && !isCalendarLoading && isSignedIn && ( + + {events?.length === 0 && ( + + + No events + + + )} + {sortBy(events, [getStartDate]).map(event => ( + + ))} + + )} + + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/CalendarEvent.tsx b/plugins/microsoft-calendar/src/components/CalendarEvent.tsx new file mode 100644 index 0000000000..e6e5bf03fa --- /dev/null +++ b/plugins/microsoft-calendar/src/components/CalendarEvent.tsx @@ -0,0 +1,166 @@ +/* + * 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 classnames from 'classnames'; +import { + bindPopover, + bindTrigger, + usePopupState, +} from 'material-ui-popup-state/hooks'; +import React, { useState } from 'react'; + +import { Link } from '@backstage/core-components'; + +import { + Box, + Paper, + Popover, + Tooltip, + Typography, + makeStyles, +} from '@material-ui/core'; + +import webcamIcon from '../icons/webcam.svg'; +import { CalendarEventPopoverContent } from './CalendarEventPopoverContent'; +import { MicrosoftCalendarEvent } from '../api'; +import { + getOnlineMeetingLink, + getTimePeriod, + isAllDay, + isPassed, +} from './util'; + +const useStyles = makeStyles( + theme => ({ + event: { + display: 'flex', + alignItems: 'center', + marginBottom: theme.spacing(1), + cursor: 'pointer', + paddingRight: 12, + }, + declined: { + textDecoration: 'line-through', + }, + passed: { + opacity: 0.6, + transition: 'opacity 0.15s ease-in-out', + '&:hover': { + opacity: 1, + }, + }, + link: { + width: 48, + height: 48, + display: 'inline-block', + padding: 8, + borderRadius: '50%', + '&:hover': { + backgroundColor: theme.palette.grey[100], + }, + }, + calendarColor: () => ({ + width: 8, + borderTopLeftRadius: 4, + borderBottomLeftRadius: 4, + }), + }), + { + name: 'MicrosoftCalendarEvent', + }, +); + +export const CalendarEvent = ({ event }: { event: MicrosoftCalendarEvent }) => { + const classes = useStyles({ event }); + const popoverState = usePopupState({ + variant: 'popover', + popupId: event.id, + disableAutoFocus: true, + }); + const [hovered, setHovered] = useState(false); + const onlineMeetingLink = getOnlineMeetingLink(event); + + const { onClick, ...restBindProps } = bindTrigger(popoverState); + + return ( + <> + { + onClick(e); + }} + {...restBindProps} + onMouseEnter={() => setHovered(true)} + onMouseLeave={() => setHovered(false)} + elevation={hovered ? 4 : 1} + className={classnames(classes.event, { + [classes.passed]: isPassed(event), + })} + data-testid="microsoft-calendar-event" + > + + + + {event.subject} + + {!isAllDay(event) && ( + + {getTimePeriod(event)} + + )} + + + {event.isOnlineMeeting && ( + + { + e.stopPropagation(); + }} + noTrack + > + {/* we can use onlineMeetingProvider to show icon accordingly */} + Online Meeting link + + + )} + + + + + + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx b/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx new file mode 100644 index 0000000000..60def9b6e3 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx @@ -0,0 +1,128 @@ +/* + * 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 { sortBy } from 'lodash'; +import React from 'react'; +import DOMPurify from 'dompurify'; + +import { Link } from '@backstage/core-components'; +import { + Box, + Divider, + IconButton, + Tooltip, + Typography, + makeStyles, +} from '@material-ui/core'; +import ArrowForwardIcon from '@material-ui/icons/ArrowForward'; + +import { AttendeeChip } from './AttendeeChip'; +import { MicrosoftCalendarEvent } from '../api'; +import { getTimePeriod, getOnlineMeetingLink } from './util'; + +const useStyles = makeStyles( + theme => { + return { + description: { + wordBreak: 'break-word', + '& a': { + color: theme.palette.primary.main, + fontWeight: 500, + }, + }, + divider: { + marginTop: theme.spacing(2), + marginBottom: theme.spacing(2), + }, + }; + }, + { + name: 'GCalendarEventPopoverContent', + }, +); + +type CalendarEventPopoverProps = { + event: MicrosoftCalendarEvent; +}; + +export const CalendarEventPopoverContent = ({ + event, +}: CalendarEventPopoverProps) => { + const classes = useStyles({ event }); + const onlineMeetingLink = getOnlineMeetingLink(event); + + return ( + + + + {event.subject} + {getTimePeriod(event)} + + {event.webLink && ( + + {}} + noTrack + > + + + + + + )} + + {onlineMeetingLink && ( + {}} noTrack> + Join Online Meeting + + )} + + {event.bodyPreview && ( + <> + + + + )} + + {event.attendees && ( + <> + + + Attendees + + {sortBy(event.attendees || [], 'emailAddress').map(user => ( + + ))} + + + )} + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/CalendarSelect.tsx b/plugins/microsoft-calendar/src/components/CalendarSelect.tsx new file mode 100644 index 0000000000..59e2376079 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/CalendarSelect.tsx @@ -0,0 +1,92 @@ +/* + * 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 { sortBy } from 'lodash'; +import React from 'react'; + +import { + Checkbox, + FormControl, + Input, + ListItemText, + MenuItem, + Select, + Typography, + makeStyles, +} from '@material-ui/core'; +import { MicrosoftCalendar } from '../api'; + +const useStyles = makeStyles( + { + formControl: { + width: 120, + }, + selectedCalendars: { + textOverflow: 'ellipsis', + overflow: 'hidden', + }, + }, + { + name: 'MicrosoftCalendarSelect', + }, +); + +type CalendarSelectProps = { + disabled: boolean; + selectedCalendarId?: string; + setSelectedCalendarId: (value: string) => void; + calendars: MicrosoftCalendar[]; +}; + +export const CalendarSelect = ({ + disabled, + selectedCalendarId, + setSelectedCalendarId, + calendars, +}: CalendarSelectProps) => { + const classes = useStyles(); + return ( + + } + renderValue={selected => { + return ( + + {calendars.find(c => c.id === selected)?.name} + + ); + }} + MenuProps={{ + PaperProps: { + style: { + width: 350, + }, + }, + }} + > + {sortBy(calendars, 'name').map(c => ( + + + + + ))} + + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/MicrosoftCalendar.tsx b/plugins/microsoft-calendar/src/components/MicrosoftCalendar.tsx new file mode 100644 index 0000000000..3bb15f7762 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/MicrosoftCalendar.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 { QueryClient, QueryClientProvider } from '@tanstack/react-query'; + +import { CalendarCard } from './CalendarCard'; + +const queryClient = new QueryClient(); + +export const MicrosoftCalendar = () => { + return ( + + + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/SignInContent.tsx b/plugins/microsoft-calendar/src/components/SignInContent.tsx new file mode 100644 index 0000000000..d33698f68c --- /dev/null +++ b/plugins/microsoft-calendar/src/components/SignInContent.tsx @@ -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 React from 'react'; +import { Box, Button, styled } from '@material-ui/core'; +import { CalendarEvent } from './CalendarEvent'; +import mockEvents from './eventMock.json'; +import { MicrosoftCalendarEvent } from '../api'; + +type Props = { + handleAuthClick: React.MouseEventHandler; +}; + +const TransparentBox = styled(Box)({ + opacity: 0.3, + filter: 'blur(1.5px)', +}); + +export const SignInContent = ({ handleAuthClick }: Props) => { + return ( + + + {(mockEvents as MicrosoftCalendarEvent[]).map(event => ( + + ))} + + + + + + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/eventMock.json b/plugins/microsoft-calendar/src/components/eventMock.json new file mode 100644 index 0000000000..b648d1b486 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/eventMock.json @@ -0,0 +1,138 @@ +[ + { + "id": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MAFRAAgI2vdUnGxAAEYAAAAABZfL1rFDfUO0G4cMgXCC1gcApFI7gxQldkOLWHDOlgt60AAAAAABDQAApFI7gxQldkOLWHDOlgt60AAAYl_I0AAAEA==", + "createdDateTime": "2022-12-22T08:28:36.6131501Z", + "lastModifiedDateTime": "2023-01-20T05:24:31.9666518Z", + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAd5KhaA==", + "categories": [], + "transactionId": null, + "originalStartTimeZone": "India Standard Time", + "originalEndTimeZone": "India Standard Time", + "iCalUId": "040000008200E00074C5B7101A82E00807E7011006D3A5A92DC7D80100000000000000001000000002BB709705E28C4493E46124FF07DD89", + "reminderMinutesBeforeStart": 15, + "isReminderOn": true, + "hasAttachments": false, + "subject": "Abhay Soni", + "bodyPreview": "", + "importance": "normal", + "sensitivity": "normal", + "isAllDay": false, + "isCancelled": false, + "isOrganizer": false, + "responseRequested": true, + "seriesMasterId": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=", + "showAs": "tentative", + "type": "occurrence", + "webLink": "", + "onlineMeetingUrl": "", + "isOnlineMeeting": true, + "onlineMeetingProvider": "teamsForBusiness", + "allowNewTimeProposals": true, + "occurrenceId": "OID.AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=.2023-01-16", + "isDraft": false, + "hideAttendees": false, + "responseStatus": { + "response": "notResponded", + "time": "0001-01-01T00:00:00Z" + }, + "body": { + "contentType": "html", + "content": "" + }, + "start": { + "dateTime": "2023-01-16T11:00:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "end": { + "dateTime": "2023-01-16T11:30:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "location": { + "displayName": "", + "locationType": "default", + "uniqueIdType": "unknown", + "address": {}, + "coordinates": {} + }, + "locations": [], + "recurrence": null, + "attendees": [], + "organizer": { + "emailAddress": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + "onlineMeeting": { + "joinUrl": "https://abhay-soni-developer.github.io/MyReusme/" + } + }, + { + "id": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MAFRAAgI2vdUnGxAAEYAAAAABZfL1rFDfUO0G4cMgXCC1gcApFI7gxQldkOLWHDOlgt60AAAAAABDQAApFI7gxQldkOLWHDOlgt60AAAYl_I0AAAEA==", + "createdDateTime": "2022-12-22T08:28:36.6131501Z", + "lastModifiedDateTime": "2023-01-20T05:24:31.9666518Z", + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAd5KhaA==", + "categories": [], + "transactionId": null, + "originalStartTimeZone": "India Standard Time", + "originalEndTimeZone": "India Standard Time", + "iCalUId": "040000008200E00074C5B7101A82E00807E7011006D3A5A92DC7D80100000000000000001000000002BB709705E28C4493E46124FF07DD89", + "reminderMinutesBeforeStart": 15, + "isReminderOn": true, + "hasAttachments": false, + "subject": "https://abhay-soni-developer.github.io/MyReusme/", + "bodyPreview": "", + "importance": "normal", + "sensitivity": "normal", + "isAllDay": false, + "isCancelled": false, + "isOrganizer": false, + "responseRequested": true, + "seriesMasterId": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=", + "showAs": "tentative", + "type": "occurrence", + "webLink": "", + "onlineMeetingUrl": "", + "isOnlineMeeting": true, + "onlineMeetingProvider": "teamsForBusiness", + "allowNewTimeProposals": true, + "occurrenceId": "OID.AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=.2023-01-16", + "isDraft": false, + "hideAttendees": false, + "responseStatus": { + "response": "notResponded", + "time": "0001-01-01T00:00:00Z" + }, + "body": { + "contentType": "html", + "content": "" + }, + "start": { + "dateTime": "2023-01-16T11:00:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "end": { + "dateTime": "2023-01-16T11:30:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "location": { + "displayName": "", + "locationType": "default", + "uniqueIdType": "unknown", + "address": {}, + "coordinates": {} + }, + "locations": [], + "recurrence": null, + "attendees": [], + "organizer": { + "emailAddress": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + "onlineMeeting": { + "joinUrl": "https://abhay-soni-developer.github.io/MyReusme/" + } + } +] diff --git a/plugins/microsoft-calendar/src/components/index.ts b/plugins/microsoft-calendar/src/components/index.ts new file mode 100644 index 0000000000..8149695804 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/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 { MicrosoftCalendar } from './MicrosoftCalendar'; diff --git a/plugins/microsoft-calendar/src/components/util.ts b/plugins/microsoft-calendar/src/components/util.ts new file mode 100644 index 0000000000..08055569cf --- /dev/null +++ b/plugins/microsoft-calendar/src/components/util.ts @@ -0,0 +1,80 @@ +/* + * 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 { DateTime } from 'luxon'; + +import { MicrosoftCalendarEvent } from '../api'; + +export function getOnlineMeetingLink(event: MicrosoftCalendarEvent) { + const onlineEntrypoint = + event.onlineMeeting?.joinUrl || event.onlineMeetingUrl; + if (onlineEntrypoint) { + return onlineEntrypoint; + } + return ''; +} + +export function getTimePeriod(event: MicrosoftCalendarEvent) { + if (isAllDay(event)) { + return getAllDayTimePeriod(event); + } + + const format: Intl.DateTimeFormatOptions = { + hour: '2-digit', + minute: '2-digit', + }; + + const startTime = DateTime.fromISO(event.start?.dateTime || ''); + const endTime = DateTime.fromISO(event.end?.dateTime || ''); + + return `${startTime.toLocaleString(format)} - ${endTime.toLocaleString( + format, + )}`; +} + +function getAllDayTimePeriod(event: MicrosoftCalendarEvent) { + const format: Intl.DateTimeFormatOptions = { month: 'long', day: 'numeric' }; + const startTime = DateTime.fromISO(event.start?.dateTime || ''); + const endTime = DateTime.fromISO(event.end?.dateTime || '').minus({ day: 1 }); + + if (startTime.toISO() === endTime.toISO()) { + return startTime.toLocaleString(format); + } + + return `${startTime.toLocaleString(format)} - ${endTime.toLocaleString( + format, + )}`; +} + +export function isPassed(event: MicrosoftCalendarEvent) { + if (!event.end?.dateTime) return false; + const eventDate = DateTime.fromISO(event.end?.dateTime!); + return DateTime.now() >= eventDate; +} + +export function isAllDay(event: MicrosoftCalendarEvent) { + // if('isAllDay' in event) { + // return event.isAllDay; + // } + + const startTime = DateTime.fromISO(event.start?.dateTime || ''); + const endTime = DateTime.fromISO(event.end?.dateTime || ''); + + return endTime.diff(startTime, 'day').days >= 1; +} + +export function getStartDate(event: MicrosoftCalendarEvent) { + return DateTime.fromISO(event.start?.dateTime || ''); +} diff --git a/plugins/microsoft-calendar/src/hooks/index.ts b/plugins/microsoft-calendar/src/hooks/index.ts new file mode 100644 index 0000000000..a10f6a6c3a --- /dev/null +++ b/plugins/microsoft-calendar/src/hooks/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 { useCalendarsQuery } from './useCalendarsQuery'; +export { useEventsQuery } from './useEventsQuery'; +export { useSignIn } from './useSignIn'; diff --git a/plugins/microsoft-calendar/src/hooks/useCalendarsQuery.ts b/plugins/microsoft-calendar/src/hooks/useCalendarsQuery.ts new file mode 100644 index 0000000000..47a7990b58 --- /dev/null +++ b/plugins/microsoft-calendar/src/hooks/useCalendarsQuery.ts @@ -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 { useQuery } from '@tanstack/react-query'; + +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; + +import { microsoftCalendarApiRef } from '../api'; + +type Options = { + enabled: boolean; + refreshTime?: number; +}; + +export const useCalendarsQuery = ({ enabled }: Options) => { + const calendarApi = useApi(microsoftCalendarApiRef); + const errorApi = useApi(errorApiRef); + + return useQuery( + ['calendars-list'], + async () => { + const calendars = []; + const value = await calendarApi.getCalendars(); + calendars.push(...value); + return calendars; + }, + { + enabled, + // old data will be returned if last request was made within 3 mins. + staleTime: 180000, + refetchInterval: 3600000, + onError: () => { + errorApi.post({ + name: 'API error', + message: 'Failed to fetch calendars.', + }); + }, + }, + ); +}; diff --git a/plugins/microsoft-calendar/src/hooks/useEventsQuery.ts b/plugins/microsoft-calendar/src/hooks/useEventsQuery.ts new file mode 100644 index 0000000000..9e0bb8fa12 --- /dev/null +++ b/plugins/microsoft-calendar/src/hooks/useEventsQuery.ts @@ -0,0 +1,63 @@ +/* + * 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 { compact, unescape } from 'lodash'; +// import { useMemo } from 'react'; +import { useQuery } from '@tanstack/react-query'; + +import { useApi } from '@backstage/core-plugin-api'; + +import { microsoftCalendarApiRef } from '../api'; + +type Options = { + calendarId: string; + timeMin: string; + timeMax: string; + enabled?: boolean; + timeZone?: string; + refreshTime?: number; +}; + +export const useEventsQuery = ({ + calendarId, + enabled, + timeMin, + timeMax, + timeZone, +}: Options) => { + const calendarApi = useApi(microsoftCalendarApiRef); + return useQuery( + ['calendarEvents', calendarId, timeMin, timeMax, timeZone], + async () => { + const data = await calendarApi.getEvents( + calendarId, + { + startDateTime: timeMin, + endDateTime: timeMax, + }, + { + Prefer: `outlook.timezone="${timeZone}"`, + }, + ); + return data; + }, + { + cacheTime: 300000, + enabled, + refetchInterval: 60000, + refetchIntervalInBackground: true, + }, + ); +}; diff --git a/plugins/microsoft-calendar/src/hooks/useSignIn.ts b/plugins/microsoft-calendar/src/hooks/useSignIn.ts new file mode 100644 index 0000000000..8b3ac54f92 --- /dev/null +++ b/plugins/microsoft-calendar/src/hooks/useSignIn.ts @@ -0,0 +1,39 @@ +/* + * 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 { useCallback, useState } from 'react'; + +import { microsoftAuthApiRef, useApi } from '@backstage/core-plugin-api'; + +export const useSignIn = () => { + const [isSignedIn, setSignedIn] = useState(false); + const [isInitialized, setInitialized] = useState(false); + const authApi = useApi(microsoftAuthApiRef); + + const signIn = useCallback( + async (optional = false) => { + const token = await authApi.getAccessToken('Calendars.Read', { + optional, + instantPopup: !optional, + }); + + setSignedIn(!!token); + setInitialized(true); + }, + [authApi, setSignedIn], + ); + + return { isSignedIn, isInitialized, signIn }; +}; diff --git a/plugins/microsoft-calendar/src/icons/calendar.svg b/plugins/microsoft-calendar/src/icons/calendar.svg new file mode 100644 index 0000000000..79895da87a --- /dev/null +++ b/plugins/microsoft-calendar/src/icons/calendar.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/microsoft-calendar/src/icons/webcam.svg b/plugins/microsoft-calendar/src/icons/webcam.svg new file mode 100644 index 0000000000..356bb69215 --- /dev/null +++ b/plugins/microsoft-calendar/src/icons/webcam.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/microsoft-calendar/src/index.ts b/plugins/microsoft-calendar/src/index.ts new file mode 100644 index 0000000000..5d37eb048d --- /dev/null +++ b/plugins/microsoft-calendar/src/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 { MicrosoftCalendar } from './plugin'; +export { MicrosoftCalendarApiClient, microsoftCalendarApiRef } from './api'; diff --git a/plugins/microsoft-calendar/src/plugin.test.ts b/plugins/microsoft-calendar/src/plugin.test.ts new file mode 100644 index 0000000000..7da86e176b --- /dev/null +++ b/plugins/microsoft-calendar/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2023 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 { microsoftCalendarPlugin } from './plugin'; + +describe('microsoft-calendar', () => { + it('should export plugin', () => { + expect(microsoftCalendarPlugin).toBeDefined(); + }); +}); diff --git a/plugins/microsoft-calendar/src/plugin.ts b/plugins/microsoft-calendar/src/plugin.ts new file mode 100644 index 0000000000..6c67ef33b4 --- /dev/null +++ b/plugins/microsoft-calendar/src/plugin.ts @@ -0,0 +1,53 @@ +/* + * Copyright 2023 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 { + createPlugin, + microsoftAuthApiRef, + fetchApiRef, + createApiFactory, + createComponentExtension, +} from '@backstage/core-plugin-api'; +import { + microsoftCalendarApiRef, + MicrosoftCalendarApiClient, +} from './api/index'; +import { rootRouteRef } from './routes'; + +export const microsoftCalendarPlugin = createPlugin({ + id: 'microsoft-calendar', + routes: { + root: rootRouteRef, + }, + apis: [ + createApiFactory({ + api: microsoftCalendarApiRef, + deps: { authApi: microsoftAuthApiRef, fetchApi: fetchApiRef }, + factory(deps) { + return new MicrosoftCalendarApiClient(deps); + }, + }), + ], +}); + +/** @public */ +export const MicrosoftCalendar = microsoftCalendarPlugin.provide( + createComponentExtension({ + name: 'MicrosoftCalendar', + component: { + lazy: () => import('./components').then(m => m.MicrosoftCalendar), + }, + }), +); diff --git a/plugins/microsoft-calendar/src/routes.ts b/plugins/microsoft-calendar/src/routes.ts new file mode 100644 index 0000000000..c257690e24 --- /dev/null +++ b/plugins/microsoft-calendar/src/routes.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2023 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 } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + id: 'microsoft-calendar', +}); diff --git a/plugins/microsoft-calendar/src/setupTests.ts b/plugins/microsoft-calendar/src/setupTests.ts new file mode 100644 index 0000000000..73dd8dce47 --- /dev/null +++ b/plugins/microsoft-calendar/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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/yarn.lock b/yarn.lock index 7c65c54e5f..9d9d1b38e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6895,6 +6895,39 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-microsoft-calendar@workspace:^, @backstage/plugin-microsoft-calendar@workspace:plugins/microsoft-calendar": + version: 0.0.0-use.local + resolution: "@backstage/plugin-microsoft-calendar@workspace:plugins/microsoft-calendar" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@microsoft/microsoft-graph-types": ^2.25.0 + "@tanstack/react-query": ^4.1.3 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/user-event": ^14.0.0 + "@types/node": ^16.11.26 + classnames: ^2.3.1 + cross-fetch: ^3.1.5 + dompurify: ^2.3.6 + lodash: ^4.17.21 + luxon: ^3.0.0 + material-ui-popup-state: ^1.9.3 + msw: ^0.49.0 + react-use: ^17.2.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + languageName: unknown + linkType: soft + "@backstage/plugin-newrelic-dashboard@workspace:^, @backstage/plugin-newrelic-dashboard@workspace:plugins/newrelic-dashboard": version: 0.0.0-use.local resolution: "@backstage/plugin-newrelic-dashboard@workspace:plugins/newrelic-dashboard" @@ -11514,7 +11547,7 @@ __metadata: languageName: node linkType: hard -"@microsoft/microsoft-graph-types@npm:^2.6.0": +"@microsoft/microsoft-graph-types@npm:^2.25.0, @microsoft/microsoft-graph-types@npm:^2.6.0": version: 2.25.0 resolution: "@microsoft/microsoft-graph-types@npm:2.25.0" checksum: b311385e0a51f827082af5a016f35b1d6cd4d861121e8767b3279ab1a17475977cddbbdcc208abdddf0f953fd6ce4634d3c302e317cf50af4cb6111385347b4f @@ -22194,6 +22227,7 @@ __metadata: "@backstage/plugin-kafka": "workspace:^" "@backstage/plugin-kubernetes": "workspace:^" "@backstage/plugin-lighthouse": "workspace:^" + "@backstage/plugin-microsoft-calendar": "workspace:^" "@backstage/plugin-newrelic": "workspace:^" "@backstage/plugin-newrelic-dashboard": "workspace:^" "@backstage/plugin-org": "workspace:^" From 6dcc785d9a523d36fa037628256a72c42808ae05 Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Wed, 1 Feb 2023 12:53:44 +0530 Subject: [PATCH 324/423] readme modified Signed-off-by: Abhay-soni-developer --- plugins/microsoft-calendar/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/microsoft-calendar/README.md b/plugins/microsoft-calendar/README.md index e170491569..a7c42da3f7 100644 --- a/plugins/microsoft-calendar/README.md +++ b/plugins/microsoft-calendar/README.md @@ -8,6 +8,10 @@ You can use this plugin by import MicrosoftCalendar from "@internal/plugin-micro > import { MicrosoftCalendar } from "@internal/plugin-microsoft-calendar" +> +> +> + ![MicrosoftCalendar plugin screenshot](./docs/microsoft-calendar-plugin.png) You can also serve the plugin in isolation by running `yarn start` in the plugin directory. From 910f6abfa625fdf757f9f7604c48075bd9cd7ab5 Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Wed, 1 Feb 2023 17:40:10 +0530 Subject: [PATCH 325/423] changes according to feedback Signed-off-by: Abhay-soni-developer --- plugins/microsoft-calendar/README.md | 2 +- plugins/microsoft-calendar/src/components/util.ts | 4 ---- plugins/microsoft-calendar/src/hooks/useEventsQuery.ts | 2 -- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/plugins/microsoft-calendar/README.md b/plugins/microsoft-calendar/README.md index a7c42da3f7..11af933cf6 100644 --- a/plugins/microsoft-calendar/README.md +++ b/plugins/microsoft-calendar/README.md @@ -4,7 +4,7 @@ Welcome to the microsoft-calendar plugin! _This plugin was created through the Backstage CLI_ -You can use this plugin by import MicrosoftCalendar from "@internal/plugin-microsoft-calendar" +You can use this plugin by import MicrosoftCalendar from "@backstage/plugin-microsoft-calendar" > import { MicrosoftCalendar } from "@internal/plugin-microsoft-calendar" diff --git a/plugins/microsoft-calendar/src/components/util.ts b/plugins/microsoft-calendar/src/components/util.ts index 08055569cf..dd52402d9d 100644 --- a/plugins/microsoft-calendar/src/components/util.ts +++ b/plugins/microsoft-calendar/src/components/util.ts @@ -65,10 +65,6 @@ export function isPassed(event: MicrosoftCalendarEvent) { } export function isAllDay(event: MicrosoftCalendarEvent) { - // if('isAllDay' in event) { - // return event.isAllDay; - // } - const startTime = DateTime.fromISO(event.start?.dateTime || ''); const endTime = DateTime.fromISO(event.end?.dateTime || ''); diff --git a/plugins/microsoft-calendar/src/hooks/useEventsQuery.ts b/plugins/microsoft-calendar/src/hooks/useEventsQuery.ts index 9e0bb8fa12..5e9dc76812 100644 --- a/plugins/microsoft-calendar/src/hooks/useEventsQuery.ts +++ b/plugins/microsoft-calendar/src/hooks/useEventsQuery.ts @@ -13,8 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -// import { compact, unescape } from 'lodash'; -// import { useMemo } from 'react'; import { useQuery } from '@tanstack/react-query'; import { useApi } from '@backstage/core-plugin-api'; From 44412375bb922736ded1d63605d480b0c57a1208 Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Thu, 2 Feb 2023 09:23:23 +0530 Subject: [PATCH 326/423] added changeset and dev Signed-off-by: Abhay-soni-developer --- .changeset/rotten-birds-build.md | 7 + plugins/microsoft-calendar/dev/index.tsx | 40 ++- plugins/microsoft-calendar/dev/mock.json | 305 +++++++++++++++++++++++ 3 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 .changeset/rotten-birds-build.md create mode 100644 plugins/microsoft-calendar/dev/mock.json diff --git a/.changeset/rotten-birds-build.md b/.changeset/rotten-birds-build.md new file mode 100644 index 0000000000..8ba9248165 --- /dev/null +++ b/.changeset/rotten-birds-build.md @@ -0,0 +1,7 @@ +--- +'example-app': minor +'@backstage/plugin-microsoft-calendar': patch +--- + +created new plugin @backstage/plugin-microsoft-calendar and added it to plugins directory +updated example-app homepage to show microsoft-calendar widget. diff --git a/plugins/microsoft-calendar/dev/index.tsx b/plugins/microsoft-calendar/dev/index.tsx index 18c5e8c08d..f2189ba3bc 100644 --- a/plugins/microsoft-calendar/dev/index.tsx +++ b/plugins/microsoft-calendar/dev/index.tsx @@ -16,12 +16,48 @@ import React from 'react'; import { createDevApp } from '@backstage/dev-utils'; import { microsoftCalendarPlugin, MicrosoftCalendar } from '../src/plugin'; +import { microsoftCalendarApiRef } from '../src'; +import responseMock from './mock.json'; +import { microsoftAuthApiRef } from '@backstage/core-plugin-api'; +import { Content, Page } from '@backstage/core-components'; +import { Grid } from '@material-ui/core'; createDevApp() .registerPlugin(microsoftCalendarPlugin) + .registerApi({ + api: microsoftAuthApiRef, + deps: {}, + factory: () => + ({ + async getAccessToken() { + return Promise.resolve('token'); + }, + } as unknown as typeof microsoftAuthApiRef.T), + }) + .registerApi({ + api: microsoftCalendarApiRef, + deps: {}, + factory: () => + ({ + async getCalendars() { + return Promise.resolve(responseMock.calendars); + }, + async getEvents() { + return Promise.resolve(responseMock.events); + }, + } as unknown as typeof microsoftCalendarApiRef.T), + }) .addPage({ - element: , - title: 'Root Page', + element: ( + + + + + + + + ), + title: 'Microsoft-Calendar Plugin Demo', path: '/microsoft-calendar', }) .render(); diff --git a/plugins/microsoft-calendar/dev/mock.json b/plugins/microsoft-calendar/dev/mock.json new file mode 100644 index 0000000000..b305e187eb --- /dev/null +++ b/plugins/microsoft-calendar/dev/mock.json @@ -0,0 +1,305 @@ +{ + "calendars": [ + { + "id": "AQMkADQyMDdlODU1AC05OGNiLTRhZmItOGM2Mi1kODZhMzJkYWU2OTAARgAAAwWXy9axQ31DtBuHDIFwgtYHAKRSO4MUJXZDi1hwzpYLetAAAAIBBgAAAKRSO4MUJXZDi1hwzpYLetAAAAIyswAAAA==", + "name": "Calendar", + "color": "lightBlue", + "hexColor": "#9fe1e7", + "isDefaultCalendar": true, + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAAAADYw==", + "canShare": true, + "canViewPrivateItems": true, + "canEdit": true, + "allowedOnlineMeetingProviders": ["teamsForBusiness"], + "defaultOnlineMeetingProvider": "teamsForBusiness", + "isTallyingResponses": true, + "isRemovable": false, + "owner": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + { + "id": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAEGAACkUjuDFCV2Q4tYcM6WC3rQAAAZs65BAAA=", + "name": "United Kingdom holidays", + "color": "auto", + "hexColor": "", + "isDefaultCalendar": false, + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAGanqjg==", + "canShare": false, + "canViewPrivateItems": true, + "canEdit": false, + "allowedOnlineMeetingProviders": [], + "defaultOnlineMeetingProvider": "unknown", + "isTallyingResponses": false, + "isRemovable": true, + "owner": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + { + "id": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAEGAACkUjuDFCV2Q4tYcM6WC3rQAAAZs65CAAA=", + "name": "Birthdays1", + "color": "auto", + "hexColor": "", + "isDefaultCalendar": false, + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAGanrfQ==", + "canShare": false, + "canViewPrivateItems": true, + "canEdit": false, + "allowedOnlineMeetingProviders": [], + "defaultOnlineMeetingProvider": "unknown", + "isTallyingResponses": false, + "isRemovable": true, + "owner": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + { + "id": "AQMkADQyMDdlODU1AC05OGNiLTRhZmItOGM2Mi1kODZhMzJkYWU2OTAARgAAAwWXy9axQ31DtBuHDIFwgtYHAKRSO4MUJXZDi1hwzpYLetAAAAIBBgAAAKRSO4MUJXZDi1hwzpYLetAAAAIytQAAAA==", + "name": "Birthdays", + "color": "auto", + "hexColor": "#92e1c0", + "isDefaultCalendar": false, + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAAAADdw==", + "canShare": false, + "canViewPrivateItems": true, + "canEdit": false, + "allowedOnlineMeetingProviders": [], + "defaultOnlineMeetingProvider": "unknown", + "isTallyingResponses": false, + "isRemovable": true, + "owner": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + { + "id": "AQMkADQyMDdlODU1AC05OGNiLTRhZmItOGM2Mi1kODZhMzJkYWU2OTAARgAAAwWXy9axQ31DtBuHDIFwgtYHAKRSO4MUJXZDi1hwzpYLetAAAAIBBgAAAKRSO4MUJXZDi1hwzpYLetAAAAIytgAAAA==", + "name": "Holidays in India", + "color": "auto", + "hexColor": "#16a765", + "isDefaultCalendar": false, + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAAAADug==", + "canShare": false, + "canViewPrivateItems": true, + "canEdit": false, + "allowedOnlineMeetingProviders": [], + "defaultOnlineMeetingProvider": "unknown", + "isTallyingResponses": false, + "isRemovable": true, + "owner": { + "name": "Abhay Soni", + "address": "abhay.s@statusneo.com" + } + } + ], + "events": [ + { + "id": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MAFRAAgI2vdUnGxAAEYAAAAABZfL1rFDfUO0G4cMgXCC1gcApFI7gxQldkOLWHDOlgt60AAAAAABDQAApFI7gxQldkOLWHDOlgt60AAAYl_I0AAAEA==", + "createdDateTime": "2022-12-22T08:28:36.6131501Z", + "lastModifiedDateTime": "2023-01-20T05:24:31.9666518Z", + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAd5KhaA==", + "categories": [], + "transactionId": null, + "originalStartTimeZone": "India Standard Time", + "originalEndTimeZone": "India Standard Time", + "iCalUId": "040000008200E00074C5B7101A82E00807E7011006D3A5A92DC7D80100000000000000001000000002BB709705E28C4493E46124FF07DD89", + "reminderMinutesBeforeStart": 15, + "isReminderOn": true, + "hasAttachments": false, + "subject": "Abhay Soni", + "bodyPreview": "", + "importance": "normal", + "sensitivity": "normal", + "isAllDay": false, + "isCancelled": false, + "isOrganizer": false, + "responseRequested": true, + "seriesMasterId": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=", + "showAs": "tentative", + "type": "occurrence", + "webLink": "", + "onlineMeetingUrl": "", + "isOnlineMeeting": true, + "onlineMeetingProvider": "teamsForBusiness", + "allowNewTimeProposals": true, + "occurrenceId": "OID.AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=.2023-01-16", + "isDraft": false, + "hideAttendees": false, + "responseStatus": { + "response": "notResponded", + "time": "0001-01-01T00:00:00Z" + }, + "body": { + "contentType": "html", + "content": "" + }, + "start": { + "dateTime": "2023-01-16T11:00:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "end": { + "dateTime": "2023-01-16T11:30:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "location": { + "displayName": "", + "locationType": "default", + "uniqueIdType": "unknown", + "address": {}, + "coordinates": {} + }, + "locations": [], + "recurrence": null, + "attendees": [ + { + "type": "required", + "status": { + "response": "none", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "Nishkarsh Raj", + "address": "nishkarshraj@nishkarsh.com" + } + }, + { + "type": "required", + "status": { + "response": "accepted", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "Hakam Ram", + "address": "hakam_ram@ram.com" + } + }, + { + "type": "required", + "status": { + "response": "declined", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + } + ], + "organizer": { + "emailAddress": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + "onlineMeeting": { + "joinUrl": "https://abhay-soni-developer.github.io/MyReusme/" + } + }, + { + "id": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MAFRAAgI2vdUnGxAAEYAAAAABZfL1rFDfUO0G4cMgXCC1gcApFI7gxQldkOLWHDOlgt60AAAAAABDQAApFI7gxQldkOLWHDOlgt60AAAYl_I0AAAEA==", + "createdDateTime": "2022-12-22T08:28:36.6131501Z", + "lastModifiedDateTime": "2023-01-20T05:24:31.9666518Z", + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAd5KhaA==", + "categories": [], + "transactionId": null, + "originalStartTimeZone": "India Standard Time", + "originalEndTimeZone": "India Standard Time", + "iCalUId": "040000008200E00074C5B7101A82E00807E7011006D3A5A92DC7D80100000000000000001000000002BB709705E28C4493E46124FF07DD89", + "reminderMinutesBeforeStart": 15, + "isReminderOn": true, + "hasAttachments": false, + "subject": "https://abhay-soni-developer.github.io/MyReusme/", + "bodyPreview": "", + "importance": "normal", + "sensitivity": "normal", + "isAllDay": false, + "isCancelled": false, + "isOrganizer": false, + "responseRequested": true, + "seriesMasterId": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=", + "showAs": "tentative", + "type": "occurrence", + "webLink": "", + "onlineMeetingUrl": "", + "isOnlineMeeting": true, + "onlineMeetingProvider": "teamsForBusiness", + "allowNewTimeProposals": true, + "occurrenceId": "OID.AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=.2023-01-16", + "isDraft": false, + "hideAttendees": false, + "responseStatus": { + "response": "notResponded", + "time": "0001-01-01T00:00:00Z" + }, + "attendees": [ + { + "type": "required", + "status": { + "response": "none", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "Nishkarsh Raj", + "address": "nishkarshraj@nishkarsh.com" + } + }, + { + "type": "required", + "status": { + "response": "accepted", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "Hakam Ram", + "address": "hakam_ram@ram.com" + } + }, + { + "type": "required", + "status": { + "response": "declined", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + } + ], + "body": { + "contentType": "html", + "content": "" + }, + "start": { + "dateTime": "2023-01-16T11:00:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "end": { + "dateTime": "2023-01-16T11:30:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "location": { + "displayName": "", + "locationType": "default", + "uniqueIdType": "unknown", + "address": {}, + "coordinates": {} + }, + "locations": [], + "recurrence": null, + "organizer": { + "emailAddress": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + "onlineMeeting": { + "joinUrl": "https://abhay-soni-developer.github.io/MyReusme/" + } + } + ] +} From 97e2f07f80656ebad062a7d9ad23574f61b846a3 Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Thu, 2 Feb 2023 09:35:25 +0530 Subject: [PATCH 327/423] updated changeset Signed-off-by: Abhay-soni-developer --- .changeset/rotten-birds-build.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/rotten-birds-build.md b/.changeset/rotten-birds-build.md index 8ba9248165..dba7504450 100644 --- a/.changeset/rotten-birds-build.md +++ b/.changeset/rotten-birds-build.md @@ -1,5 +1,4 @@ --- -'example-app': minor '@backstage/plugin-microsoft-calendar': patch --- From 384febd92a774772bdbbb1643ab5f323257e9bb8 Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Thu, 2 Feb 2023 10:27:14 +0530 Subject: [PATCH 328/423] readme fixed Signed-off-by: Abhay-soni-developer --- plugins/microsoft-calendar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/microsoft-calendar/README.md b/plugins/microsoft-calendar/README.md index 11af933cf6..71e547cf9e 100644 --- a/plugins/microsoft-calendar/README.md +++ b/plugins/microsoft-calendar/README.md @@ -6,7 +6,7 @@ _This plugin was created through the Backstage CLI_ You can use this plugin by import MicrosoftCalendar from "@backstage/plugin-microsoft-calendar" -> import { MicrosoftCalendar } from "@internal/plugin-microsoft-calendar" +> import { MicrosoftCalendar } from "@backstage/plugin-microsoft-calendar" > > From 3cf71bd666a96ef799bdf729f41fc3c020160c2c Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Mon, 6 Feb 2023 12:29:19 +0530 Subject: [PATCH 329/423] readme modified Signed-off-by: Abhay-soni-developer --- plugins/microsoft-calendar/README.md | 48 ++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/plugins/microsoft-calendar/README.md b/plugins/microsoft-calendar/README.md index 71e547cf9e..76a879b098 100644 --- a/plugins/microsoft-calendar/README.md +++ b/plugins/microsoft-calendar/README.md @@ -1,18 +1,48 @@ -# microsoft-calendar - -Welcome to the microsoft-calendar plugin! +# Microsoft-Calendar Plugin +Welcome to the Microsoft calendar plugin! _This plugin was created through the Backstage CLI_ -You can use this plugin by import MicrosoftCalendar from "@backstage/plugin-microsoft-calendar" +## Features -> import { MicrosoftCalendar } from "@backstage/plugin-microsoft-calendar" +1. You can switch between calendars, using the select menu on the calendar card header. +2. Card showing the list of events on the selected date and the selected calendar (provided by Outlook calendar). +3. Link to join the online meeting on the event card if provided. so you can join your meetings right away hassle-free. +4. Hovering over the event will pop over a card showing the event summary message, and list of attendees. +5. attendee's chips will have a badge over them symbolizing their responses. + - green --> accepted + - red --> declined + - nothing --> not responded yet -> -> -> +## Setup -![MicrosoftCalendar plugin screenshot](./docs/microsoft-calendar-plugin.png) +The following sections will help you set up the Microsoft calendar plugin. + +### Microsoft azure authentication provider + +> You need to setup [microsoft azure authentication provider](https://backstage.io/docs/auth/microsoft/provider), before you move forward with any of the below step if you have'nt already. + +1. Install the plugin by running this command + +```bash +# From the Backstage repository root +yarn add --cwd packages/app @backstage/plugin-microsoft-calendar +``` + +You need to first import the Microsoft calendar React component from "@backstage/plugin-microsoft-calendar". +You can then use the provided component Microsoft calendar in the backstage frontend where ever you want + +```tsx +import { MicrosoftCalendar } from '@backstage/plugin-microsoft-calendar'; + +// ... + + +; +// ... +``` + +![Microsoft Calendar plugin demo](https://user-images.githubusercontent.com/23618736/215717491-25db5fa6-b237-487f-8c00-28f572e8da05.mp4) You can also serve the plugin in isolation by running `yarn start` in the plugin directory. This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads. From 6d0eb9e9627d939847eb871d1c045a3883781d95 Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Mon, 6 Feb 2023 12:38:01 +0530 Subject: [PATCH 330/423] readme modified Signed-off-by: Abhay-soni-developer --- plugins/microsoft-calendar/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/microsoft-calendar/README.md b/plugins/microsoft-calendar/README.md index 76a879b098..f2b7964135 100644 --- a/plugins/microsoft-calendar/README.md +++ b/plugins/microsoft-calendar/README.md @@ -29,8 +29,8 @@ The following sections will help you set up the Microsoft calendar plugin. yarn add --cwd packages/app @backstage/plugin-microsoft-calendar ``` -You need to first import the Microsoft calendar React component from "@backstage/plugin-microsoft-calendar". -You can then use the provided component Microsoft calendar in the backstage frontend where ever you want +2. Import the Microsoft calendar React component from "@backstage/plugin-microsoft-calendar". +3. You can then use the provided react component MicrosoftCalendar in the backstage frontend where ever you want ```tsx import { MicrosoftCalendar } from '@backstage/plugin-microsoft-calendar'; @@ -44,6 +44,8 @@ import { MicrosoftCalendar } from '@backstage/plugin-microsoft-calendar'; ![Microsoft Calendar plugin demo](https://user-images.githubusercontent.com/23618736/215717491-25db5fa6-b237-487f-8c00-28f572e8da05.mp4) +![Sample](./docs/microsoft-calendar-plugin.png) + You can also serve the plugin in isolation by running `yarn start` in the plugin directory. This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads. It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory. From 5e7293f93e008bd8a37567ac285f85eb32cbfd36 Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Tue, 7 Feb 2023 03:30:11 +0530 Subject: [PATCH 331/423] feedback changes incorporated Signed-off-by: Abhay-soni-developer --- .changeset/rotten-birds-build.md | 6 ++-- packages/app/src/components/home/HomePage.tsx | 4 +-- plugins/microsoft-calendar/api-report.md | 6 ++-- plugins/microsoft-calendar/dev/index.tsx | 4 +-- .../src/components/CalendarCard.tsx | 6 +--- .../src/components/CalendarEvent.tsx | 6 ++-- .../CalendarEventPopoverContent.tsx | 28 +++++++++---------- plugins/microsoft-calendar/src/index.ts | 2 +- plugins/microsoft-calendar/src/plugin.ts | 8 ++---- plugins/microsoft-calendar/src/routes.ts | 20 ------------- 10 files changed, 30 insertions(+), 60 deletions(-) delete mode 100644 plugins/microsoft-calendar/src/routes.ts diff --git a/.changeset/rotten-birds-build.md b/.changeset/rotten-birds-build.md index dba7504450..3a1de3768a 100644 --- a/.changeset/rotten-birds-build.md +++ b/.changeset/rotten-birds-build.md @@ -1,6 +1,6 @@ --- -'@backstage/plugin-microsoft-calendar': patch +'@backstage/plugin-microsoft-calendar': minor --- -created new plugin @backstage/plugin-microsoft-calendar and added it to plugins directory -updated example-app homepage to show microsoft-calendar widget. +Created a new Frontend plugin @backstage/plugin-microsoft-calendar and added it to plugins directory. +please refer to readme (readme.md)[./../plugins/microsoft-calendar/README.md] for step wise instruction to setup the plugin in your backstage frontend app. diff --git a/packages/app/src/components/home/HomePage.tsx b/packages/app/src/components/home/HomePage.tsx index b0491df93f..29023738af 100644 --- a/packages/app/src/components/home/HomePage.tsx +++ b/packages/app/src/components/home/HomePage.tsx @@ -27,7 +27,7 @@ import { import { Content, Header, Page } from '@backstage/core-components'; import { HomePageSearchBar } from '@backstage/plugin-search'; import { HomePageCalendar } from '@backstage/plugin-gcalendar'; -import { MicrosoftCalendar } from '@backstage/plugin-microsoft-calendar'; +import { MicrosoftCalendarCard } from '@backstage/plugin-microsoft-calendar'; import Grid from '@material-ui/core/Grid'; import React from 'react'; @@ -116,7 +116,7 @@ export const homePage = ( - + diff --git a/plugins/microsoft-calendar/api-report.md b/plugins/microsoft-calendar/api-report.md index 38187b39b2..a68b070c32 100644 --- a/plugins/microsoft-calendar/api-report.md +++ b/plugins/microsoft-calendar/api-report.md @@ -11,9 +11,6 @@ import { Event as Event_2 } from '@microsoft/microsoft-graph-types'; import { FetchApi } from '@backstage/core-plugin-api'; import { OAuthApi } from '@backstage/core-plugin-api'; -// @public (undocumented) -export const MicrosoftCalendar: () => JSX.Element; - // @public (undocumented) export class MicrosoftCalendarApiClient { constructor(options: { authApi: OAuthApi; fetchApi: FetchApi }); @@ -35,5 +32,8 @@ export class MicrosoftCalendarApiClient { // @public (undocumented) export const microsoftCalendarApiRef: ApiRef; +// @public (undocumented) +export const MicrosoftCalendarCard: () => JSX.Element; + // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/microsoft-calendar/dev/index.tsx b/plugins/microsoft-calendar/dev/index.tsx index f2189ba3bc..d611bca20c 100644 --- a/plugins/microsoft-calendar/dev/index.tsx +++ b/plugins/microsoft-calendar/dev/index.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; import { createDevApp } from '@backstage/dev-utils'; -import { microsoftCalendarPlugin, MicrosoftCalendar } from '../src/plugin'; +import { microsoftCalendarPlugin, MicrosoftCalendarCard } from '../src/plugin'; import { microsoftCalendarApiRef } from '../src'; import responseMock from './mock.json'; import { microsoftAuthApiRef } from '@backstage/core-plugin-api'; @@ -52,7 +52,7 @@ createDevApp() - + diff --git a/plugins/microsoft-calendar/src/components/CalendarCard.tsx b/plugins/microsoft-calendar/src/components/CalendarCard.tsx index dba12bdea5..dd94bad148 100644 --- a/plugins/microsoft-calendar/src/components/CalendarCard.tsx +++ b/plugins/microsoft-calendar/src/components/CalendarCard.tsx @@ -131,11 +131,7 @@ export const CalendarCard = () => { )} {sortBy(events, [getStartDate]).map(event => ( - + ))} )} diff --git a/plugins/microsoft-calendar/src/components/CalendarEvent.tsx b/plugins/microsoft-calendar/src/components/CalendarEvent.tsx index e6e5bf03fa..e56e25a09b 100644 --- a/plugins/microsoft-calendar/src/components/CalendarEvent.tsx +++ b/plugins/microsoft-calendar/src/components/CalendarEvent.tsx @@ -71,11 +71,11 @@ const useStyles = makeStyles( backgroundColor: theme.palette.grey[100], }, }, - calendarColor: () => ({ + calendarColor: { width: 8, borderTopLeftRadius: 4, borderBottomLeftRadius: 4, - }), + }, }), { name: 'MicrosoftCalendarEvent', @@ -83,7 +83,7 @@ const useStyles = makeStyles( ); export const CalendarEvent = ({ event }: { event: MicrosoftCalendarEvent }) => { - const classes = useStyles({ event }); + const classes = useStyles(); const popoverState = usePopupState({ variant: 'popover', popupId: event.id, diff --git a/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx b/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx index 60def9b6e3..601474aaa3 100644 --- a/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx +++ b/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx @@ -33,21 +33,19 @@ import { MicrosoftCalendarEvent } from '../api'; import { getTimePeriod, getOnlineMeetingLink } from './util'; const useStyles = makeStyles( - theme => { - return { - description: { - wordBreak: 'break-word', - '& a': { - color: theme.palette.primary.main, - fontWeight: 500, - }, + theme => ({ + description: { + wordBreak: 'break-word', + '& a': { + color: theme.palette.primary.main, + fontWeight: 500, }, - divider: { - marginTop: theme.spacing(2), - marginBottom: theme.spacing(2), - }, - }; - }, + }, + divider: { + marginTop: theme.spacing(2), + marginBottom: theme.spacing(2), + }, + }), { name: 'GCalendarEventPopoverContent', }, @@ -60,7 +58,7 @@ type CalendarEventPopoverProps = { export const CalendarEventPopoverContent = ({ event, }: CalendarEventPopoverProps) => { - const classes = useStyles({ event }); + const classes = useStyles(); const onlineMeetingLink = getOnlineMeetingLink(event); return ( diff --git a/plugins/microsoft-calendar/src/index.ts b/plugins/microsoft-calendar/src/index.ts index 5d37eb048d..6867ca31ac 100644 --- a/plugins/microsoft-calendar/src/index.ts +++ b/plugins/microsoft-calendar/src/index.ts @@ -13,5 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { MicrosoftCalendar } from './plugin'; +export { MicrosoftCalendarCard } from './plugin'; export { MicrosoftCalendarApiClient, microsoftCalendarApiRef } from './api'; diff --git a/plugins/microsoft-calendar/src/plugin.ts b/plugins/microsoft-calendar/src/plugin.ts index 6c67ef33b4..644d368d97 100644 --- a/plugins/microsoft-calendar/src/plugin.ts +++ b/plugins/microsoft-calendar/src/plugin.ts @@ -24,13 +24,9 @@ import { microsoftCalendarApiRef, MicrosoftCalendarApiClient, } from './api/index'; -import { rootRouteRef } from './routes'; export const microsoftCalendarPlugin = createPlugin({ id: 'microsoft-calendar', - routes: { - root: rootRouteRef, - }, apis: [ createApiFactory({ api: microsoftCalendarApiRef, @@ -43,9 +39,9 @@ export const microsoftCalendarPlugin = createPlugin({ }); /** @public */ -export const MicrosoftCalendar = microsoftCalendarPlugin.provide( +export const MicrosoftCalendarCard = microsoftCalendarPlugin.provide( createComponentExtension({ - name: 'MicrosoftCalendar', + name: 'MicrosoftCalendarCard', component: { lazy: () => import('./components').then(m => m.MicrosoftCalendar), }, diff --git a/plugins/microsoft-calendar/src/routes.ts b/plugins/microsoft-calendar/src/routes.ts deleted file mode 100644 index c257690e24..0000000000 --- a/plugins/microsoft-calendar/src/routes.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2023 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 } from '@backstage/core-plugin-api'; - -export const rootRouteRef = createRouteRef({ - id: 'microsoft-calendar', -}); From 7a3559a2497c15313da1301a87e163331aea434a Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Tue, 7 Feb 2023 03:38:51 +0530 Subject: [PATCH 332/423] changeset modified Signed-off-by: Abhay-soni-developer --- .changeset/rotten-birds-build.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/rotten-birds-build.md b/.changeset/rotten-birds-build.md index 3a1de3768a..f45577ede5 100644 --- a/.changeset/rotten-birds-build.md +++ b/.changeset/rotten-birds-build.md @@ -3,4 +3,4 @@ --- Created a new Frontend plugin @backstage/plugin-microsoft-calendar and added it to plugins directory. -please refer to readme (readme.md)[./../plugins/microsoft-calendar/README.md] for step wise instruction to setup the plugin in your backstage frontend app. +please refer to readme [readme.md](./../plugins/microsoft-calendar/README.md) for step wise instruction to setup the plugin in your backstage frontend app. From 695b71c2a2f1a4836aa21acf47f8ba3d3452a3ee Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Tue, 7 Feb 2023 03:39:19 +0530 Subject: [PATCH 333/423] changeset modified Signed-off-by: Abhay-soni-developer --- .changeset/rotten-birds-build.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/rotten-birds-build.md b/.changeset/rotten-birds-build.md index f45577ede5..c79123411a 100644 --- a/.changeset/rotten-birds-build.md +++ b/.changeset/rotten-birds-build.md @@ -3,4 +3,4 @@ --- Created a new Frontend plugin @backstage/plugin-microsoft-calendar and added it to plugins directory. -please refer to readme [readme.md](./../plugins/microsoft-calendar/README.md) for step wise instruction to setup the plugin in your backstage frontend app. +please refer to [readme.md](./../plugins/microsoft-calendar/README.md) for step wise instruction to setup the plugin in your backstage frontend app. From 915aba819c356fc21914e55e4c413c25fa47c31e Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Wed, 8 Feb 2023 00:13:30 +0530 Subject: [PATCH 334/423] updated component name Signed-off-by: Abhay-soni-developer --- .../src/components/CalendarEventPopoverContent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx b/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx index 601474aaa3..715a1ad276 100644 --- a/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx +++ b/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx @@ -47,7 +47,7 @@ const useStyles = makeStyles( }, }), { - name: 'GCalendarEventPopoverContent', + name: 'MicrosoftCalendarEventPopoverContent', }, ); From 95510bca16210d1b0f30fda6d661269798fb56d9 Mon Sep 17 00:00:00 2001 From: Abhay-soni-developer Date: Wed, 8 Feb 2023 16:19:50 +0530 Subject: [PATCH 335/423] removed param from getCalendar function paramters Signed-off-by: Abhay-soni-developer --- plugins/microsoft-calendar/src/api/client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/microsoft-calendar/src/api/client.ts b/plugins/microsoft-calendar/src/api/client.ts index 57aaead452..fe842b5aef 100644 --- a/plugins/microsoft-calendar/src/api/client.ts +++ b/plugins/microsoft-calendar/src/api/client.ts @@ -69,11 +69,11 @@ export class MicrosoftCalendarApiClient { return response.json() as Promise; } - public async getCalendars(params?: any): Promise { + public async getCalendars(): Promise { const data = await this.get<{ id: string; value: MicrosoftCalendar[]; - }>('v1.0/me/calendars', params); + }>('v1.0/me/calendars'); return data.value; } From 593ea8127bca2915055f08ede6cd02923ed78d06 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 8 Feb 2023 16:13:20 +0100 Subject: [PATCH 336/423] chore: codeowners fix Signed-off-by: blam --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bb6f8da19b..1c6171cb01 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -59,6 +59,7 @@ yarn.lock @backstage/maintainers @back /plugins/kafka-backend @backstage/maintainers @nirga @andrewthauer /plugins/kubernetes @backstage/maintainers @backstage/warpspeed /plugins/kubernetes-* @backstage/maintainers @backstage/warpspeed +/plugins/microsoft-calendar @backstage/maintainers @abhay-soni-developer /plugins/newrelic-dashboard @backstage/maintainers @mufaddal7 /plugins/playlist @backstage/maintainers @kuangp /plugins/playlist-* @backstage/maintainers @kuangp From f2beeeef4ac7f56d2e6a2c9afc9f4c59d0775ef3 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 8 Feb 2023 16:14:55 +0100 Subject: [PATCH 337/423] chore: fixing changeset Signed-off-by: blam --- .changeset/rotten-birds-build.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.changeset/rotten-birds-build.md b/.changeset/rotten-birds-build.md index c79123411a..24bcb599bd 100644 --- a/.changeset/rotten-birds-build.md +++ b/.changeset/rotten-birds-build.md @@ -2,5 +2,6 @@ '@backstage/plugin-microsoft-calendar': minor --- -Created a new Frontend plugin @backstage/plugin-microsoft-calendar and added it to plugins directory. -please refer to [readme.md](./../plugins/microsoft-calendar/README.md) for step wise instruction to setup the plugin in your backstage frontend app. +Created a new plugin `@backstage/plugin-microsoft-calendar` to display events from a Microsoft Calendar. + +please refer to the [README.md](https://backstage.io/docs/plugins/microsoft-calendar/README.md) for step-by-step instructions to setup the plugin in your Backstage instance. From 9ae00e86be9847a3f0eba9112c3804490744bdb3 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 8 Feb 2023 16:19:31 +0100 Subject: [PATCH 338/423] chore: fix changeset Signed-off-by: blam --- .changeset/rotten-birds-build.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/rotten-birds-build.md b/.changeset/rotten-birds-build.md index 24bcb599bd..e165129998 100644 --- a/.changeset/rotten-birds-build.md +++ b/.changeset/rotten-birds-build.md @@ -4,4 +4,4 @@ Created a new plugin `@backstage/plugin-microsoft-calendar` to display events from a Microsoft Calendar. -please refer to the [README.md](https://backstage.io/docs/plugins/microsoft-calendar/README.md) for step-by-step instructions to setup the plugin in your Backstage instance. +please refer to the [README.md](https://github.com/backstage/backstage/blob/master/plugins/microsoft-calendar/README.md) for step-by-step instructions to setup the plugin in your Backstage instance. From 8ed1c3b3785919776ea16ef245879aceea1e69dc Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 8 Feb 2023 16:40:47 +0100 Subject: [PATCH 339/423] chore: fixing api-reports Signed-off-by: blam --- plugins/microsoft-calendar/api-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/microsoft-calendar/api-report.md b/plugins/microsoft-calendar/api-report.md index a68b070c32..d6839f19ea 100644 --- a/plugins/microsoft-calendar/api-report.md +++ b/plugins/microsoft-calendar/api-report.md @@ -15,7 +15,7 @@ import { OAuthApi } from '@backstage/core-plugin-api'; export class MicrosoftCalendarApiClient { constructor(options: { authApi: OAuthApi; fetchApi: FetchApi }); // (undocumented) - getCalendars(params?: any): Promise; + getCalendars(): Promise; // (undocumented) getEvents( calendarId: string, From d3a25fd4d3e6ace9c0e9b995cd0a88101a923116 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 8 Feb 2023 17:08:41 +0100 Subject: [PATCH 340/423] chore: fixing readme and vale Signed-off-by: blam --- plugins/microsoft-calendar/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/microsoft-calendar/README.md b/plugins/microsoft-calendar/README.md index f2b7964135..73a66b15f5 100644 --- a/plugins/microsoft-calendar/README.md +++ b/plugins/microsoft-calendar/README.md @@ -20,7 +20,7 @@ The following sections will help you set up the Microsoft calendar plugin. ### Microsoft azure authentication provider -> You need to setup [microsoft azure authentication provider](https://backstage.io/docs/auth/microsoft/provider), before you move forward with any of the below step if you have'nt already. +> You need to setup [Microsoft Azure authentication provider](https://backstage.io/docs/auth/microsoft/provider), before you move forward with any of the below step if you haven't already. 1. Install the plugin by running this command @@ -29,8 +29,8 @@ The following sections will help you set up the Microsoft calendar plugin. yarn add --cwd packages/app @backstage/plugin-microsoft-calendar ``` -2. Import the Microsoft calendar React component from "@backstage/plugin-microsoft-calendar". -3. You can then use the provided react component MicrosoftCalendar in the backstage frontend where ever you want +2. Import the Microsoft calendar React component from `@backstage/plugin-microsoft-calendar`. +3. You can then use the provided React component `MicrosoftCalendar` in the backstage frontend where ever you want ```tsx import { MicrosoftCalendar } from '@backstage/plugin-microsoft-calendar'; From 9c4a72dff0240564cac1502b9717a25849ba3fea Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Fri, 27 Jan 2023 10:28:43 +0100 Subject: [PATCH 341/423] Add aria label for mobile sidebar links Signed-off-by: Raghunandan --- packages/core-components/src/layout/Sidebar/SidebarGroup.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx b/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx index 15d22599b5..70fec8a294 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx @@ -23,7 +23,7 @@ import { makeStyles } from '@material-ui/core/styles'; import React, { useContext } from 'react'; import { useLocation } from 'react-router-dom'; import { Link } from '../../components'; -import { SidebarConfigContext, SidebarConfig } from './config'; +import { SidebarConfig, SidebarConfigContext } from './config'; import { MobileSidebarContext } from './MobileSidebar'; import { useSidebarPinState } from './SidebarPinStateContext'; @@ -109,6 +109,7 @@ const MobileSidebarGroup = (props: SidebarGroupProps) => { value={value} selected={selected} classes={classes} + aria-label={label} /> ); }; From 43b397609ae24b4bba528a930b65017f59a55981 Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Fri, 27 Jan 2023 10:29:57 +0100 Subject: [PATCH 342/423] Add aria label for support button in mobile, close button in support popover Signed-off-by: Raghunandan --- .../src/components/SupportButton/SupportButton.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/core-components/src/components/SupportButton/SupportButton.tsx b/packages/core-components/src/components/SupportButton/SupportButton.tsx index 7bb9aab9b5..35cf228f52 100644 --- a/packages/core-components/src/components/SupportButton/SupportButton.tsx +++ b/packages/core-components/src/components/SupportButton/SupportButton.tsx @@ -16,8 +16,6 @@ import { useApp } from '@backstage/core-plugin-api'; import { BackstageTheme } from '@backstage/theme'; -import { makeStyles } from '@material-ui/core/styles'; -import useMediaQuery from '@material-ui/core/useMediaQuery'; import Box from '@material-ui/core/Box'; import Button from '@material-ui/core/Button'; import DialogActions from '@material-ui/core/DialogActions'; @@ -27,7 +25,9 @@ import ListItem from '@material-ui/core/ListItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import Popover from '@material-ui/core/Popover'; +import { makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; +import useMediaQuery from '@material-ui/core/useMediaQuery'; import React, { MouseEventHandler, useState } from 'react'; import { SupportItem, SupportItemLink, useSupportConfig } from '../../hooks'; import { HelpIcon } from '../../icons'; @@ -111,13 +111,14 @@ export function SupportButton(props: SupportButtonProps) { size="small" onClick={onClickHandler} data-testid="support-button" + aria-label="Support" > ) : ( From cdaf09ee409a9b52f8800971366ef0d17655a894 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Wed, 8 Feb 2023 11:16:20 -0500 Subject: [PATCH 343/423] Update API report. Signed-off-by: Aramis Sennyey --- plugins/catalog-graph/api-report.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugins/catalog-graph/api-report.md b/plugins/catalog-graph/api-report.md index 0f4b4170ad..f7444c5f1b 100644 --- a/plugins/catalog-graph/api-report.md +++ b/plugins/catalog-graph/api-report.md @@ -66,10 +66,7 @@ export enum Direction { // @public export const EntityCatalogGraphCard: ( - props: Omit< - EntityRelationsGraphProps, - 'className' | 'onNodeClick' | 'rootEntityNames' - > & { + props: Partial & { variant?: InfoCardVariants | undefined; height?: number | undefined; title?: string | undefined; From 68ce7d04172936c0435f76fa422ce72f664e326e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 8 Feb 2023 16:47:35 +0100 Subject: [PATCH 344/423] changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/dull-pianos-shave.md | 5 +++++ packages/core-components/src/layout/Sidebar/SidebarGroup.tsx | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .changeset/dull-pianos-shave.md diff --git a/.changeset/dull-pianos-shave.md b/.changeset/dull-pianos-shave.md new file mode 100644 index 0000000000..8fae999bda --- /dev/null +++ b/.changeset/dull-pianos-shave.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Added aria labels on the support button and sidebar diff --git a/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx b/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx index 70fec8a294..1eb1423c61 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx @@ -109,7 +109,6 @@ const MobileSidebarGroup = (props: SidebarGroupProps) => { value={value} selected={selected} classes={classes} - aria-label={label} /> ); }; From 2f31d45f06c2d92e76cb1c472e2179bded2577d4 Mon Sep 17 00:00:00 2001 From: Waldir Montoya Date: Wed, 8 Feb 2023 11:47:13 -0500 Subject: [PATCH 345/423] Add Organizational and Other headers Signed-off-by: Waldir Montoya --- .../features/software-catalog/system-model.md | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/docs/features/software-catalog/system-model.md b/docs/features/software-catalog/system-model.md index a71bfefc39..16ad48abcf 100644 --- a/docs/features/software-catalog/system-model.md +++ b/docs/features/software-catalog/system-model.md @@ -63,6 +63,17 @@ BigTable databases, Pub/Sub topics, S3 buckets or CDNs. Modelling them together with components and systems will better allow us to visualize resource footprint, and create tooling around them. +##Organizational Entities + +### User + +A user describes a person, such as an employee, a contractor, or similar. + +### Group + +A group describes an organizational entity, such as for example a team, a +business unit, or a loose collection of people in an interest group. + ## Ecosystem Modeling A large catalogue of components, APIs and resources can be highly granular and @@ -109,14 +120,7 @@ product or use-case, share the same entity types in their APIs, and integrate well with each other. Other domains could be “Content Ingestion”, “Ads” or “Search”. -### User - -A user describes a person, such as an employee, a contractor, or similar. - -### Group - -A group describes an organizational entity, such as for example a team, a -business unit, or a loose collection of people in an interest group. +##Other ### Location From a53d06afe5b9cee29037538d342c187f144d0c9b Mon Sep 17 00:00:00 2001 From: Jamie Klassen Date: Mon, 30 Jan 2023 09:11:36 -0500 Subject: [PATCH 346/423] Document the proxy endpoint Signed-off-by: Jamie Klassen --- .changeset/tidy-kings-cough.md | 5 ++ docs/features/kubernetes/proxy.md | 90 +++++++++++++++++++ microsite/sidebars.json | 3 +- plugins/kubernetes-backend/api-report.md | 2 +- .../src/service/KubernetesProxy.ts | 2 +- 5 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 .changeset/tidy-kings-cough.md create mode 100644 docs/features/kubernetes/proxy.md diff --git a/.changeset/tidy-kings-cough.md b/.changeset/tidy-kings-cough.md new file mode 100644 index 0000000000..e908572c8b --- /dev/null +++ b/.changeset/tidy-kings-cough.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +--- + +The name of the header used to specify a cluster to the proxy endpoint is now visible in the API reference. diff --git a/docs/features/kubernetes/proxy.md b/docs/features/kubernetes/proxy.md new file mode 100644 index 0000000000..a98cdfd16b --- /dev/null +++ b/docs/features/kubernetes/proxy.md @@ -0,0 +1,90 @@ +--- +id: proxy +title: Kubernetes Backend Proxy Endpoint +sidebar_label: Proxy +description: Interacting with the Kubernetes API in Backstage plugins +--- + +[Contributors](../../overview/glossary#backstage-user-profiles) wanting to +create developer portal experiences based on data from Kubernetes (e.g. for +interacting with [Custom +Resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) +beyond the default behaviors of the existing Kubernetes plugin) can leverage the +Kubernetes backend plugin's proxy endpoint to allow them to make arbitrary +requests to the [REST +API](https://kubernetes.io/docs/reference/using-api/api-concepts/). + +Here is a snippet fetching namespaces from a cluster configured with the +`google` [auth provider](./configuration#clustersauthprovider): + +```typescript +import { + discoveryApiRef, + googleAuthApiRef, + useApi, +} from '@backstage/core-plugin-api'; + +const CLUSTER_NAME = ''; // use a known cluster name + +// get a bearer token from Google +const googleAuthApi = useApi(googleAuthApiRef); +const token = await googleAuthApi.getAccessToken( + 'https://www.googleapis.com/auth/cloud-platform', +); + +const discoveryApi = useApi(discoveryApiRef); +const kubernetesBaseUrl = await discoveryApi.getBaseUrl('kubernetes'); +const kubernetesProxyEndpoint = `${kubernetesBaseUrl}/proxy`; + +// fetch namespaces +await fetch(`${kubernetesProxyEndpoint}/api/v1/namespaces`, { + method: 'GET', + headers: { + 'X-Kubernetes-Cluster': CLUSTER_NAME, + Authorization: `Bearer ${token}`, + }, +}); +``` + +## How it works + +The proxy will interpret the +[`X-Kubernetes-Cluster` +header](../../reference/plugin-kubernetes-backend.header_kubernetes_cluster) +as the name of the cluster to target. This name will be compared to each cluster +returned by all the configured [cluster +locators](./kubernetes/configuration#clusterlocatormethods) +-- the first cluster whose [`name` field](./configuration#clustersname) matches +the value in the header will be targeted. + +Then the request will be forwarded verbatim (but with the endpoint's base URL +prefix stripped) to the cluster. + +## Authentication + +Until some security and permission decisions are made (see [this +conversation](https://github.com/backstage/backstage/pull/13026/files#r1029376939) +for context), contributors consuming the proxy endpoint in their plugin code are +responsible for negotiating their own bearer token out-of-band. This requires +knowing some auth details about the cluster being contacted -- in practice, only +clusters with [client side auth +providers](./authentication#client-side-providers) can reasonably be reached. + +The proxy has no provisions for mTLS, so it cannot be used to connect to +clusters using the [x509 Client +Certs](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) +authentication strategy. [Bearer +tokens](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#putting-a-bearer-token-in-a-request) +will be forwarded as-is. + +## Other known limitations + +The proxy as it was released in [Backstage +1.9](https://github.com/backstage/backstage/blob/master/docs/releases/v1.9.0-changelog.md#patch-changes-15) +has a few known bugs: + +- [#15901](https://github.com/backstage/backstage/issues/15901) - it cannot + reliably target clusters who share the same name with another located cluster. +- [#16018](https://github.com/backstage/backstage/issues/16018) - it does not + forward request bodies, making it incapable of supporting `POST`, `PUT` or + `PATCH` verbs in practice. diff --git a/microsite/sidebars.json b/microsite/sidebars.json index f051d3c70b..6baeb20e8b 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -87,7 +87,8 @@ "features/kubernetes/installation", "features/kubernetes/configuration", "features/kubernetes/authentication", - "features/kubernetes/troubleshooting" + "features/kubernetes/troubleshooting", + "features/kubernetes/proxy" ] }, { diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index 4ec043a8f9..006f980c56 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -141,7 +141,7 @@ export class GoogleServiceAccountAuthTranslator ): Promise; } -// @alpha +// @public export const HEADER_KUBERNETES_CLUSTER: string; // @alpha (undocumented) diff --git a/plugins/kubernetes-backend/src/service/KubernetesProxy.ts b/plugins/kubernetes-backend/src/service/KubernetesProxy.ts index 9d88d2ab84..cb36c647ac 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesProxy.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesProxy.ts @@ -32,7 +32,7 @@ export const APPLICATION_JSON: string = 'application/json'; /** * The header that is used to specify the cluster name. * - * @alpha + * @public */ export const HEADER_KUBERNETES_CLUSTER: string = 'X-Kubernetes-Cluster'; From 05c26fd47567978174633a145d645ac24eac2ac6 Mon Sep 17 00:00:00 2001 From: Jamie Klassen Date: Mon, 30 Jan 2023 10:19:50 -0500 Subject: [PATCH 347/423] remove relative links Otherwise, `scripts/verify-links.js` will fail. Signed-off-by: Jamie Klassen --- docs/features/kubernetes/proxy.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/features/kubernetes/proxy.md b/docs/features/kubernetes/proxy.md index a98cdfd16b..859bcb0b3c 100644 --- a/docs/features/kubernetes/proxy.md +++ b/docs/features/kubernetes/proxy.md @@ -5,7 +5,7 @@ sidebar_label: Proxy description: Interacting with the Kubernetes API in Backstage plugins --- -[Contributors](../../overview/glossary#backstage-user-profiles) wanting to +[Contributors](https://backstage.io/docs/overview/glossary#backstage-user-profiles) wanting to create developer portal experiences based on data from Kubernetes (e.g. for interacting with [Custom Resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) @@ -15,7 +15,7 @@ requests to the [REST API](https://kubernetes.io/docs/reference/using-api/api-concepts/). Here is a snippet fetching namespaces from a cluster configured with the -`google` [auth provider](./configuration#clustersauthprovider): +`google` [auth provider](https://backstage.io/docs/features/kubernetes/configuration#clustersauthprovider): ```typescript import { @@ -50,11 +50,11 @@ await fetch(`${kubernetesProxyEndpoint}/api/v1/namespaces`, { The proxy will interpret the [`X-Kubernetes-Cluster` -header](../../reference/plugin-kubernetes-backend.header_kubernetes_cluster) +header](https://backstage.io/docs/reference/plugin-kubernetes-backend.header_kubernetes_cluster) as the name of the cluster to target. This name will be compared to each cluster returned by all the configured [cluster -locators](./kubernetes/configuration#clusterlocatormethods) --- the first cluster whose [`name` field](./configuration#clustersname) matches +locators](https://backstage.io/docs/features/kubernetes/configuration#clusterlocatormethods) +-- the first cluster whose [`name` field](https://backstage.io/docs/features/kubernetes/configuration#clustersname) matches the value in the header will be targeted. Then the request will be forwarded verbatim (but with the endpoint's base URL @@ -68,7 +68,7 @@ for context), contributors consuming the proxy endpoint in their plugin code are responsible for negotiating their own bearer token out-of-band. This requires knowing some auth details about the cluster being contacted -- in practice, only clusters with [client side auth -providers](./authentication#client-side-providers) can reasonably be reached. +providers](https://backstage.io/docs/features/kubernetes/authentication#client-side-providers) can reasonably be reached. The proxy has no provisions for mTLS, so it cannot be used to connect to clusters using the [x509 Client From 6a8e82797ff313eea50f433467c2367704d6e25e Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 8 Feb 2023 19:06:08 +0100 Subject: [PATCH 348/423] chore: bump actions to latest Signed-off-by: blam --- .github/workflows/pr.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index d7ae00d3a9..db7d141abd 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -18,7 +18,7 @@ jobs: if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) steps: - name: PR sync - uses: backstage/actions/pr-sync@v0.6.1 + uses: backstage/actions/pr-sync@v0.6.2 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} From 7126b48d6a1e2022ea225a59ae1cc126f1868925 Mon Sep 17 00:00:00 2001 From: Jamie Klassen Date: Wed, 8 Feb 2023 13:31:49 -0500 Subject: [PATCH 349/423] update known issues since #16018 was fixed Signed-off-by: Jamie Klassen --- docs/features/kubernetes/proxy.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/features/kubernetes/proxy.md b/docs/features/kubernetes/proxy.md index 859bcb0b3c..5848d62e3e 100644 --- a/docs/features/kubernetes/proxy.md +++ b/docs/features/kubernetes/proxy.md @@ -81,10 +81,7 @@ will be forwarded as-is. The proxy as it was released in [Backstage 1.9](https://github.com/backstage/backstage/blob/master/docs/releases/v1.9.0-changelog.md#patch-changes-15) -has a few known bugs: +has a known bug: - [#15901](https://github.com/backstage/backstage/issues/15901) - it cannot reliably target clusters who share the same name with another located cluster. -- [#16018](https://github.com/backstage/backstage/issues/16018) - it does not - forward request bodies, making it incapable of supporting `POST`, `PUT` or - `PATCH` verbs in practice. From 45e5ea9d931b78a9c1f07511d44940c93c8489e8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 20:09:58 +0000 Subject: [PATCH 350/423] chore(deps): update backstage/actions action to v0.6.2 Signed-off-by: Renovate Bot --- .github/workflows/automate_changeset_feedback.yml | 2 +- .github/workflows/ci.yml | 6 +++--- .github/workflows/cron.yml | 2 +- .github/workflows/deploy_docker-image.yml | 2 +- .github/workflows/deploy_nightly.yml | 2 +- .github/workflows/deploy_packages.yml | 4 ++-- .github/workflows/issue.yaml | 2 +- .github/workflows/pr-review-comment.yaml | 2 +- .github/workflows/sync_code-formatting.yml | 2 +- .github/workflows/sync_snyk-github-issues.yml | 2 +- .github/workflows/uffizzi-build.yml | 2 +- .github/workflows/verify_e2e-linux.yml | 2 +- .github/workflows/verify_kubernetes.yml | 2 +- .github/workflows/verify_storybook.yml | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index aaf0bb1294..d1dcd97644 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -28,7 +28,7 @@ jobs: ref: 'refs/pull/${{ github.event.pull_request.number }}/merge' - name: fetch base run: git fetch --depth 1 origin ${{ github.base_ref }} - - uses: backstage/actions/changeset-feedback@v0.6.0 + - uses: backstage/actions/changeset-feedback@v0.6.2 name: Generate feedback with: diff-ref: 'origin/master' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 16573cf5b8..18af36c8c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -63,7 +63,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -181,7 +181,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 2e6573ede8..be27a732d6 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -8,7 +8,7 @@ jobs: cron: runs-on: ubuntu-latest steps: - - uses: backstage/actions/cron@v0.6.0 + - uses: backstage/actions/cron@v0.6.2 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index 909a36199c..d45cc557d5 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -26,7 +26,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index c9cd22640c..49907042b5 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -26,7 +26,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index fa43271a96..058f4f6089 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -68,7 +68,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -145,7 +145,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index 9f2e5827be..e64f919bdb 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -10,4 +10,4 @@ jobs: if: github.repository == 'backstage/backstage' steps: - name: Issue sync - uses: backstage/actions/issue-sync@v0.6.0 + uses: backstage/actions/issue-sync@v0.6.2 diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index 261ce56177..52db29c699 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -35,7 +35,7 @@ jobs: const prNumber = artifact.name.slice('pr_number-'.length) core.setOutput('pr-number', prNumber); - - uses: backstage/actions/re-review@v0.6.0 + - uses: backstage/actions/re-review@v0.6.2 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index b84fe5c2e6..7b0cbbbb01 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -20,7 +20,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index dfd114c66a..a89b7c8e65 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -23,7 +23,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index 714b108898..30a3489264 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -27,7 +27,7 @@ jobs: registry-url: https://registry.npmjs.org/ - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: linux-v16 diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index 16ddb04086..4fda0749c0 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -52,7 +52,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_kubernetes.yml b/.github/workflows/verify_kubernetes.yml index 6d8a7682b5..83280f8e85 100644 --- a/.github/workflows/verify_kubernetes.yml +++ b/.github/workflows/verify_kubernetes.yml @@ -28,7 +28,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index 38b685c539..8cde5b6e9b 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -35,7 +35,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: storybook yarn install From df3cd9e275629c3f52609abd59ffb31b0344c842 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Feb 2023 00:44:35 +0000 Subject: [PATCH 351/423] chore(deps): bump @sideway/formula from 3.0.0 to 3.0.1 Bumps [@sideway/formula](https://github.com/sideway/formula) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/sideway/formula/releases) - [Commits](https://github.com/sideway/formula/compare/v3.0.0...v3.0.1) --- updated-dependencies: - dependency-name: "@sideway/formula" dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7c65c54e5f..ee9b7e3f1a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13034,9 +13034,9 @@ __metadata: linkType: hard "@sideway/formula@npm:^3.0.0": - version: 3.0.0 - resolution: "@sideway/formula@npm:3.0.0" - checksum: 8ae26a0ed6bc84f7310be6aae6eb9d81e97f382619fc69025d346871a707eaab0fa38b8c857e3f0c35a19923de129f42d35c50b8010c928d64aab41578580ec4 + version: 3.0.1 + resolution: "@sideway/formula@npm:3.0.1" + checksum: e4beeebc9dbe2ff4ef0def15cec0165e00d1612e3d7cea0bc9ce5175c3263fc2c818b679bd558957f49400ee7be9d4e5ac90487e1625b4932e15c4aa7919c57a languageName: node linkType: hard From 965b0155ddbd2034b87e92260b9949f68e7ae756 Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Thu, 9 Feb 2023 08:02:22 +0000 Subject: [PATCH 352/423] add test for sync heartbeat Signed-off-by: Brian Fletcher --- .../src/service/DocsSynchronizer.test.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts b/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts index 1445079d12..52a3b82651 100644 --- a/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts +++ b/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts @@ -32,6 +32,7 @@ import { DocsBuilder, shouldCheckForUpdate } from '../DocsBuilder'; import { DocsSynchronizer, DocsSynchronizerSyncOpts } from './DocsSynchronizer'; jest.mock('../DocsBuilder'); +jest.useFakeTimers(); jest.mock('node-fetch', () => ({ __esModule: true, @@ -130,6 +131,8 @@ describe('DocsSynchronizer', () => { const logger = MockedDocsBuilder.mock.calls[0][0].logger; + jest.advanceTimersByTime(10001); + logger.info('Some more log'); return true; @@ -144,13 +147,19 @@ describe('DocsSynchronizer', () => { generators, }); - expect(mockResponseHandler.log).toHaveBeenCalledTimes(3); + expect(mockResponseHandler.log).toHaveBeenCalledTimes(4); expect(mockResponseHandler.log).toHaveBeenCalledWith('Some log'); expect(mockResponseHandler.log).toHaveBeenCalledWith('Another log'); expect(mockResponseHandler.log).toHaveBeenCalledWith( expect.stringMatching(/info.*Some more log/), ); + expect(mockResponseHandler.log).toHaveBeenCalledWith( + expect.stringMatching( + /info.*The docs building process is taking a little bit longer to process this entity. Please bear with us/, + ), + ); + expect(mockResponseHandler.finish).toHaveBeenCalledWith({ updated: true, }); From 51fcb684cb9b4e4a916798c3c83801b2c3ad2cb7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Feb 2023 08:46:36 +0000 Subject: [PATCH 353/423] chore(deps): update dependency eslint-plugin-testing-library to v5.10.1 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 17c8fd3f2c..f3ff87e778 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21853,13 +21853,13 @@ __metadata: linkType: hard "eslint-plugin-testing-library@npm:^5.9.1": - version: 5.10.0 - resolution: "eslint-plugin-testing-library@npm:5.10.0" + version: 5.10.1 + resolution: "eslint-plugin-testing-library@npm:5.10.1" dependencies: "@typescript-eslint/utils": ^5.43.0 peerDependencies: eslint: ^7.5.0 || ^8.0.0 - checksum: 3278fc4683a99d24ac2b6d2ed0359db1b0509674350e4b9a958a226f57b4b90e070c02e1f4c2806da885d8025c1e8c952cb9a5e9751e69baac3d12cfe6804000 + checksum: fbc24ce8cbd03bee283ae520f023bd52f10d21fb25bd66c5a09a0e0ad17997bae559450438ce0b4fcc38b4e14b6802f18482c41d2bc72bf1a8e1a12a91766572 languageName: node linkType: hard From 0c03164e21be4f1a3e8d0aab9c9d78fe7867a281 Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Thu, 9 Feb 2023 11:22:01 +0100 Subject: [PATCH 354/423] Update slow-sloths-do.md Signed-off-by: Ben Lambert --- .changeset/slow-sloths-do.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/slow-sloths-do.md b/.changeset/slow-sloths-do.md index 7d9cc263de..2d86d477bf 100644 --- a/.changeset/slow-sloths-do.md +++ b/.changeset/slow-sloths-do.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-catalog-graph': minor +'@backstage/plugin-catalog-graph': patch --- -Expose additional props on the CatalogGraphCard to allow for custom node & label rendering or kind/relation filtering. +Expose additional props on the `CatalogGraphCard` to allow for custom node & label rendering or kind/relation filtering. From 8ca64daec8889a4807460234e46fc27e9a326af2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Feb 2023 10:48:46 +0000 Subject: [PATCH 355/423] chore(deps): update dependency better-sqlite3 to v8.1.0 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 067b2f13ae..bd9682a1d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17523,13 +17523,13 @@ __metadata: linkType: hard "better-sqlite3@npm:^8.0.0": - version: 8.0.1 - resolution: "better-sqlite3@npm:8.0.1" + version: 8.1.0 + resolution: "better-sqlite3@npm:8.1.0" dependencies: bindings: ^1.5.0 node-gyp: latest prebuild-install: ^7.1.0 - checksum: 533b2cc32bd54e2a943a4f63e079f8cc8945879b7a0ebd2085b948824ea067792f6f903ab75ba75d7cafc5f8f973354cdf9a042fa6216e077925d07a8df1bead + checksum: 7e6b4c33142f4b2ee2e60d3926b4db682feb0d09554efdaf7bea53cd5bef406ca0a5115ab9b411458daa45ba14973252ebd6853a3cdf94e4fd49cc8291730ade languageName: node linkType: hard From fb19c3fbe83a9a632013460c5b862e318d9d1240 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Feb 2023 11:32:25 +0000 Subject: [PATCH 356/423] chore(deps): update microsoft/setup-msbuild action to v1.3.1 Signed-off-by: Renovate Bot --- .github/workflows/verify_e2e-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index 8a49b8fe31..145eefbd26 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -49,7 +49,7 @@ jobs: with: node-version: ${{ matrix.node-version }} - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v1.1.3 + uses: microsoft/setup-msbuild@v1.3.1 - name: setup chrome uses: browser-actions/setup-chrome@latest - name: yarn install From 57fc2e9011113b3441b411705030d72a79dcb148 Mon Sep 17 00:00:00 2001 From: albertojuanL Date: Thu, 9 Feb 2023 13:03:27 +0100 Subject: [PATCH 357/423] Fix changeset info Signed-off-by: albertojuanL --- .changeset/brown-kings-wait.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/brown-kings-wait.md b/.changeset/brown-kings-wait.md index 01ff1ae5eb..db3fc0ee86 100644 --- a/.changeset/brown-kings-wait.md +++ b/.changeset/brown-kings-wait.md @@ -1,5 +1,5 @@ --- -'@backstage/catalog-client': patch +'@backstage/plugin-catalog': patch --- The list of entities takes into account the title when its different from the name to sort the entities. From 896566906b4417352c7364b328843cd64189c1e2 Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Wed, 1 Feb 2023 15:43:03 -0500 Subject: [PATCH 358/423] chore(elasticSearch): export utility function Signed-off-by: Phil Kuang --- .changeset/chatty-lemons-reply.md | 5 +++++ plugins/search-backend-module-elasticsearch/api-report.md | 5 +++++ .../src/engines/ElasticSearchSearchEngine.ts | 3 +++ .../src/engines/index.ts | 5 ++++- plugins/search-backend-module-elasticsearch/src/index.ts | 6 +++++- 5 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 .changeset/chatty-lemons-reply.md diff --git a/.changeset/chatty-lemons-reply.md b/.changeset/chatty-lemons-reply.md new file mode 100644 index 0000000000..118f832646 --- /dev/null +++ b/.changeset/chatty-lemons-reply.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-module-elasticsearch': patch +--- + +Export `decodeElasticSearchPageCursor` utility function diff --git a/plugins/search-backend-module-elasticsearch/api-report.md b/plugins/search-backend-module-elasticsearch/api-report.md index 9e3ca40ec7..8545e3fd8f 100644 --- a/plugins/search-backend-module-elasticsearch/api-report.md +++ b/plugins/search-backend-module-elasticsearch/api-report.md @@ -67,6 +67,11 @@ export interface BaseElasticSearchClientOptions { Transport?: ElasticSearchTransportConstructor; } +// @public (undocumented) +export function decodeElasticSearchPageCursor(pageCursor?: string): { + page: number; +}; + // @public (undocumented) export interface ElasticSearchAgentOptions { // (undocumented) diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts index 9edad973de..c2f4224db3 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts @@ -408,6 +408,9 @@ export class ElasticSearchSearchEngine implements SearchEngine { } } +/** + * @public + */ export function decodePageCursor(pageCursor?: string): { page: number } { if (!pageCursor) { return { page: 0 }; diff --git a/plugins/search-backend-module-elasticsearch/src/engines/index.ts b/plugins/search-backend-module-elasticsearch/src/engines/index.ts index 8c3b9e3c6d..cb24bdc56a 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/index.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/index.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -export { ElasticSearchSearchEngine } from './ElasticSearchSearchEngine'; +export { + decodePageCursor as decodeElasticSearchPageCursor, + ElasticSearchSearchEngine, +} from './ElasticSearchSearchEngine'; export { isOpenSearchCompatible } from './ElasticSearchClientOptions'; export type { BaseElasticSearchClientOptions, diff --git a/plugins/search-backend-module-elasticsearch/src/index.ts b/plugins/search-backend-module-elasticsearch/src/index.ts index cb4f62098a..e0b05014cc 100644 --- a/plugins/search-backend-module-elasticsearch/src/index.ts +++ b/plugins/search-backend-module-elasticsearch/src/index.ts @@ -20,7 +20,11 @@ * @packageDocumentation */ -export { ElasticSearchSearchEngine, isOpenSearchCompatible } from './engines'; +export { + decodeElasticSearchPageCursor, + ElasticSearchSearchEngine, + isOpenSearchCompatible, +} from './engines'; export type { BaseElasticSearchClientOptions, ElasticSearchAgentOptions, From b7705e176cbffed812124440860078754014ccd6 Mon Sep 17 00:00:00 2001 From: Ainhoa Larumbe Date: Thu, 9 Feb 2023 14:36:38 +0000 Subject: [PATCH 359/423] Use table header color that meets a11y color contrast requirements Signed-off-by: Ainhoa Larumbe --- .changeset/nasty-kids-deny.md | 5 +++++ packages/theme/src/baseTheme.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/nasty-kids-deny.md diff --git a/.changeset/nasty-kids-deny.md b/.changeset/nasty-kids-deny.md new file mode 100644 index 0000000000..4a434eb1f6 --- /dev/null +++ b/.changeset/nasty-kids-deny.md @@ -0,0 +1,5 @@ +--- +'@backstage/theme': patch +--- + +Use same table header color as @backstage/core-components Table to meet accessibility color contrast requirements. This change affects material-ui tables. diff --git a/packages/theme/src/baseTheme.ts b/packages/theme/src/baseTheme.ts index 5e222c0c3e..53f3a3ef2b 100644 --- a/packages/theme/src/baseTheme.ts +++ b/packages/theme/src/baseTheme.ts @@ -159,7 +159,7 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { head: { wordBreak: 'break-word', overflow: 'hidden', - color: 'rgb(179, 179, 179)', + color: theme.palette.textSubtle, fontWeight: 'normal', lineHeight: '1', }, From 5b7cd5580db81b00f573037b34fd3202a2c02fe6 Mon Sep 17 00:00:00 2001 From: Dominik Schwank Date: Thu, 9 Feb 2023 17:45:46 +0100 Subject: [PATCH 360/423] fix: move backend-test-utils to devDependencies The backend-test-utils should only be used as devDependencies. Otherwise they might cause trouble while installing related plugins in docker images. Signed-off-by: Dominik Schwank --- .changeset/red-toes-suffer.md | 9 +++++++++ plugins/bazaar-backend/package.json | 2 +- .../package.json | 2 +- plugins/kubernetes-backend/package.json | 2 +- plugins/playlist-backend/package.json | 2 +- plugins/vault-backend/package.json | 2 +- 6 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 .changeset/red-toes-suffer.md diff --git a/.changeset/red-toes-suffer.md b/.changeset/red-toes-suffer.md new file mode 100644 index 0000000000..3d819fb298 --- /dev/null +++ b/.changeset/red-toes-suffer.md @@ -0,0 +1,9 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-playlist-backend': patch +'@backstage/plugin-bazaar-backend': patch +'@backstage/plugin-vault-backend': patch +--- + +Moving the backend-test-utils to devDependencies. diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index d67bba4eb5..5fba3fcbb3 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -25,7 +25,6 @@ "dependencies": { "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", - "@backstage/backend-test-utils": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", @@ -37,6 +36,7 @@ "yn": "^4.0.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^" }, "files": [ diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index b29771c74d..f6ea81996e 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -36,7 +36,6 @@ "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-tasks": "workspace:^", - "@backstage/backend-test-utils": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", @@ -56,6 +55,7 @@ }, "devDependencies": { "@backstage/backend-app-api": "workspace:^", + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/plugin-catalog-backend": "workspace:^" }, diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 5b49d18543..002a5e2651 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -36,7 +36,6 @@ "dependencies": { "@azure/identity": "^2.0.4", "@backstage/backend-common": "workspace:^", - "@backstage/backend-test-utils": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", @@ -66,6 +65,7 @@ "yn": "^4.0.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/aws4": "^1.5.1", "@types/http-proxy-middleware": "^0.19.3", diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index 5cbce033b4..cc3e62eb5a 100644 --- a/plugins/playlist-backend/package.json +++ b/plugins/playlist-backend/package.json @@ -23,7 +23,6 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", - "@backstage/backend-test-utils": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", @@ -43,6 +42,7 @@ "zod": "~3.18.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", "msw": "^0.49.0", diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index 88545aaeb1..ae7c89a61c 100644 --- a/plugins/vault-backend/package.json +++ b/plugins/vault-backend/package.json @@ -35,7 +35,6 @@ "dependencies": { "@backstage/backend-common": "workspace:^", "@backstage/backend-tasks": "workspace:^", - "@backstage/backend-test-utils": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@types/express": "*", @@ -50,6 +49,7 @@ "yn": "^5.0.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/compression": "^1.7.2", "@types/supertest": "^2.0.8", From adf027d6c073f36a01e675dc3b863f0ad6ae5153 Mon Sep 17 00:00:00 2001 From: Matthew Thomas Date: Thu, 9 Feb 2023 18:34:38 +0000 Subject: [PATCH 361/423] docs: add custom action plugin for snyk import Signed-off-by: Matthew Thomas --- docs/features/software-templates/writing-custom-actions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index dfbd4b0a42..ffe3312501 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -168,5 +168,6 @@ scaffolder backend: | Scaffolder Git Actions | [plugin-scaffolder-git-actions](https://www.npmjs.com/package/@mdude2314/backstage-plugin-scaffolder-git-actions) | [Drew Hill](https://github.com/arhill05) | | Azure Pipeline Actions | [scaffolder-backend-module-azure-pipelines](https://www.npmjs.com/package/@parfuemerie-douglas/scaffolder-backend-module-azure-pipelines) | [Parfümerie Douglas](https://github.com/Parfuemerie-Douglas) | | Azure Repository Actions | [scaffolder-backend-module-azure-repositories](https://www.npmjs.com/package/@parfuemerie-douglas/scaffolder-backend-module-azure-repositories) | [Parfümerie Douglas](https://github.com/Parfuemerie-Douglas) | +| Snyk Import Project | [plugin-scaffolder-backend-module-snyk](https://www.npmjs.com/package/@ma11hewthomas/plugin-scaffolder-backend-module-snyk) | [Matthew Thomas](https://github.com/Ma11hewThomas) | Have fun! 🚀 From 5a4fa8859b2e9f1049392f65457f9cac7f1d4ef5 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Thu, 9 Feb 2023 13:29:00 -0600 Subject: [PATCH 362/423] Updated LinksGroup to use Link over ListItem Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .changeset/stale-houses-push.md | 5 +++++ .../Cards/Group/GroupProfile/GroupProfileCard.stories.tsx | 2 +- plugins/org/src/components/Cards/Meta/LinksGroup.tsx | 7 +++++-- 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 .changeset/stale-houses-push.md diff --git a/.changeset/stale-houses-push.md b/.changeset/stale-houses-push.md new file mode 100644 index 0000000000..53296f3efe --- /dev/null +++ b/.changeset/stale-houses-push.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-org': patch +--- + +Updated `LinksGroup` to use `Link` over `ListItem` as this makes the links more obvious and follows the pattern already used in the `GroupProfileCard`. Also updated the `GroupProfileCard` `ExtraDetails` story in Storybook to enable the `showLinks` feature whith this off there is no difference between it and the `default` story. diff --git a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.stories.tsx b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.stories.tsx index cfb3d847a4..f183ab4d8e 100644 --- a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.stories.tsx +++ b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.stories.tsx @@ -123,7 +123,7 @@ export const ExtraDetails = () => ( - + diff --git a/plugins/org/src/components/Cards/Meta/LinksGroup.tsx b/plugins/org/src/components/Cards/Meta/LinksGroup.tsx index eeade18411..dfc654c14b 100644 --- a/plugins/org/src/components/Cards/Meta/LinksGroup.tsx +++ b/plugins/org/src/components/Cards/Meta/LinksGroup.tsx @@ -23,6 +23,7 @@ import { Divider, } from '@material-ui/core'; import React from 'react'; +import { Link } from '@backstage/core-components'; const WebLink = ({ href, @@ -33,9 +34,11 @@ const WebLink = ({ text?: string; Icon?: IconComponent; }) => ( - + {Icon ? : } - {text} + + {text} + ); From b6f7c46c77d0ecb4863e8813c87eb66708944884 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Thu, 9 Feb 2023 13:32:50 -0600 Subject: [PATCH 363/423] Fixed typo in changeset Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .changeset/stale-houses-push.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/stale-houses-push.md b/.changeset/stale-houses-push.md index 53296f3efe..ef2213ed7b 100644 --- a/.changeset/stale-houses-push.md +++ b/.changeset/stale-houses-push.md @@ -2,4 +2,4 @@ '@backstage/plugin-org': patch --- -Updated `LinksGroup` to use `Link` over `ListItem` as this makes the links more obvious and follows the pattern already used in the `GroupProfileCard`. Also updated the `GroupProfileCard` `ExtraDetails` story in Storybook to enable the `showLinks` feature whith this off there is no difference between it and the `default` story. +Updated `LinksGroup` to use `Link` over `ListItem` as this makes the links more obvious and follows the pattern already used in the `GroupProfileCard`. Also updated the `GroupProfileCard` `ExtraDetails` story in Storybook to enable the `showLinks` feature with this off there is no difference between it and the `default` story. From 22ccd2d8881f5d2389af7618ce0b09a4df7be1ea Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Thu, 9 Feb 2023 18:20:59 -0500 Subject: [PATCH 364/423] Fix regex string in documentation. Signed-off-by: Aramis Sennyey --- docs/integrations/gitlab/discovery.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/gitlab/discovery.md b/docs/integrations/gitlab/discovery.md index 51c34b67ac..41e50cd747 100644 --- a/docs/integrations/gitlab/discovery.md +++ b/docs/integrations/gitlab/discovery.md @@ -24,7 +24,7 @@ catalog: branch: main # Optional. Uses `master` as default group: example-group # Optional. Group and subgroup (if needed) to look for repositories. If not present the whole instance will be scanned entityFilename: catalog-info.yaml # Optional. Defaults to `catalog-info.yaml` - projectPattern: /[\s\S]*/ # Optional. Filters found projects based on provided patter. Defaults to `/[\s\S]*/`, what means to not filter anything + projectPattern: '[\s\S]*' # Optional. Filters found projects based on provided patter. Defaults to `[\s\S]*`, what means to not filter anything schedule: # optional; same options as in TaskScheduleDefinition # supports cron, ISO duration, "human duration" as used in code frequency: { minutes: 30 } From c12a71e3c2647d80e2e3deb3c34ddbf2cd735257 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Thu, 9 Feb 2023 18:23:17 -0500 Subject: [PATCH 365/423] Spelling. Signed-off-by: Aramis Sennyey --- docs/integrations/gitlab/discovery.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/gitlab/discovery.md b/docs/integrations/gitlab/discovery.md index 41e50cd747..5a4dc8abdd 100644 --- a/docs/integrations/gitlab/discovery.md +++ b/docs/integrations/gitlab/discovery.md @@ -24,7 +24,7 @@ catalog: branch: main # Optional. Uses `master` as default group: example-group # Optional. Group and subgroup (if needed) to look for repositories. If not present the whole instance will be scanned entityFilename: catalog-info.yaml # Optional. Defaults to `catalog-info.yaml` - projectPattern: '[\s\S]*' # Optional. Filters found projects based on provided patter. Defaults to `[\s\S]*`, what means to not filter anything + projectPattern: '[\s\S]*' # Optional. Filters found projects based on provided patter. Defaults to `[\s\S]*`, which means to not filter anything schedule: # optional; same options as in TaskScheduleDefinition # supports cron, ISO duration, "human duration" as used in code frequency: { minutes: 30 } From 5febb216fe3077de2bb6aef8b84cf550c64a60a5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 8 Feb 2023 14:21:20 +0100 Subject: [PATCH 366/423] backend-plugin-api: refactor CacheService to lift up client methods to the service Signed-off-by: Patrik Oldsberg --- .changeset/chilled-brooms-jog.md | 7 +++ .changeset/eighty-knives-repeat.md | 6 ++ .changeset/twenty-pugs-explain.md | 5 ++ packages/backend-app-api/api-report.md | 7 +-- .../cache/cacheServiceFactory.ts | 2 +- packages/backend-common/api-report.md | 21 +++++-- .../src/cache/CacheClient.test.ts | 42 ++++++++++--- .../backend-common/src/cache/CacheClient.ts | 54 ++++++++++------- .../src/cache/CacheManager.test.ts | 6 +- .../backend-common/src/cache/CacheManager.ts | 54 ++++++++++++----- packages/backend-common/src/cache/index.ts | 5 +- packages/backend-common/src/cache/types.ts | 16 ++++- packages/backend-common/src/legacy.ts | 2 + packages/backend-plugin-api/api-report.md | 16 ++--- .../src/services/definitions/CacheService.ts | 59 ++++++++----------- .../src/services/definitions/index.ts | 5 +- .../adr-backend/src/service/router.test.ts | 2 + plugins/auth-backend/api-report.md | 4 +- .../cloudflare-access/provider.test.ts | 1 + .../src/cache/TechDocsCache.test.ts | 1 + 20 files changed, 200 insertions(+), 115 deletions(-) create mode 100644 .changeset/chilled-brooms-jog.md create mode 100644 .changeset/eighty-knives-repeat.md create mode 100644 .changeset/twenty-pugs-explain.md diff --git a/.changeset/chilled-brooms-jog.md b/.changeset/chilled-brooms-jog.md new file mode 100644 index 0000000000..d848246b2b --- /dev/null +++ b/.changeset/chilled-brooms-jog.md @@ -0,0 +1,7 @@ +--- +'@backstage/backend-common': patch +--- + +**BREAKING**: The `CacheClient` interface must now also implement the `withOptions` method. The `.get()` method has also received a type parameter that helps ensure that `undefined` in the event of a cache miss is handled. + +Added a `cacheToPluginCacheManager` helper that converts a `CacheService` into a legacy `PluginCacheManager` instance. diff --git a/.changeset/eighty-knives-repeat.md b/.changeset/eighty-knives-repeat.md new file mode 100644 index 0000000000..3e32a3589d --- /dev/null +++ b/.changeset/eighty-knives-repeat.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-app-api': patch +'@backstage/backend-common': patch +--- + +Updated to match the new `CacheService` interface. diff --git a/.changeset/twenty-pugs-explain.md b/.changeset/twenty-pugs-explain.md new file mode 100644 index 0000000000..9ac77d2ffb --- /dev/null +++ b/.changeset/twenty-pugs-explain.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +**BREAKING**: The `CacheService` has been changed to remove the indirection of `getClient`, instead making the `CacheClient` methods directly available on the `CacheService`. In order to allow for the creation of clients with default options, there is now a new `.withOptions` method that must be implemented as part of the service interface. diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index 9329610a4c..e99135b3ec 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -6,6 +6,7 @@ /// import { BackendFeature } from '@backstage/backend-plugin-api'; +import { CacheClient } from '@backstage/backend-common'; import { Config } from '@backstage/config'; import { ConfigService } from '@backstage/backend-plugin-api'; import { CorsOptions } from 'cors'; @@ -22,7 +23,6 @@ import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoadConfigOptionsRemote } from '@backstage/config-loader'; import { LoggerService } from '@backstage/backend-plugin-api'; import { PermissionsService } from '@backstage/backend-plugin-api'; -import { PluginCacheManager } from '@backstage/backend-common'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { RequestHandler } from 'express'; @@ -48,10 +48,7 @@ export interface Backend { } // @public (undocumented) -export const cacheServiceFactory: () => ServiceFactory< - PluginCacheManager, - 'plugin' ->; +export const cacheServiceFactory: () => ServiceFactory; // @public (undocumented) export interface ConfigFactoryOptions { diff --git a/packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts b/packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts index 3ccd2a2fac..2208249280 100644 --- a/packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts +++ b/packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts @@ -31,6 +31,6 @@ export const cacheServiceFactory = createServiceFactory({ return CacheManager.fromConfig(config); }, async factory({ plugin }, manager) { - return manager.forPlugin(plugin.getId()); + return manager.forPlugin(plugin.getId()).getClient(); }, }); diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index e77a58b34c..d21ef30a0b 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -13,9 +13,9 @@ import { BackendFeature } from '@backstage/backend-plugin-api'; import { BitbucketCloudIntegration } from '@backstage/integration'; import { BitbucketIntegration } from '@backstage/integration'; import { BitbucketServerIntegration } from '@backstage/integration'; -import { CacheClient } from '@backstage/backend-plugin-api'; -import { CacheClientOptions } from '@backstage/backend-plugin-api'; -import { CacheClientSetOptions } from '@backstage/backend-plugin-api'; +import { CacheService as CacheClient } from '@backstage/backend-plugin-api'; +import { CacheServiceOptions as CacheClientOptions } from '@backstage/backend-plugin-api'; +import { CacheServiceSetOptions as CacheClientSetOptions } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { ConfigService } from '@backstage/backend-plugin-api'; import cors from 'cors'; @@ -38,7 +38,6 @@ import { Logger } from 'winston'; import { LoggerService } from '@backstage/backend-plugin-api'; import { MergeResult } from 'isomorphic-git'; import { PermissionsService } from '@backstage/backend-plugin-api'; -import { CacheService as PluginCacheManager } from '@backstage/backend-plugin-api'; import { DatabaseService as PluginDatabaseManager } from '@backstage/backend-plugin-api'; import { DiscoveryService as PluginEndpointDiscovery } from '@backstage/backend-plugin-api'; import { PluginMetadataService } from '@backstage/backend-plugin-api'; @@ -199,6 +198,11 @@ export type CacheManagerOptions = { onError?: (err: Error) => void; }; +// @public (undocumented) +export function cacheToPluginCacheManager( + cache: CacheClient, +): PluginCacheManager; + // @public export const coloredFormat: winston.Logform.Format; @@ -528,7 +532,7 @@ export const legacyPlugin: ( default: LegacyCreateRouter< TransformedEnv< { - cache: PluginCacheManager; + cache: CacheClient; config: ConfigService; database: PluginDatabaseManager; discovery: PluginEndpointDiscovery; @@ -541,6 +545,7 @@ export const legacyPlugin: ( }, { logger: (log: LoggerService) => Logger; + cache: (cache: CacheClient) => PluginCacheManager; } > >; @@ -581,7 +586,11 @@ export function makeLegacyPlugin< // @public export function notFoundHandler(): RequestHandler; -export { PluginCacheManager }; +// @public (undocumented) +export interface PluginCacheManager { + // (undocumented) + getClient(options?: CacheClientOptions): CacheClient; +} export { PluginDatabaseManager }; diff --git a/packages/backend-common/src/cache/CacheClient.test.ts b/packages/backend-common/src/cache/CacheClient.test.ts index 8a5779550a..245d8687c9 100644 --- a/packages/backend-common/src/cache/CacheClient.test.ts +++ b/packages/backend-common/src/cache/CacheClient.test.ts @@ -32,7 +32,7 @@ describe('CacheClient', () => { describe('CacheClient.get', () => { it('calls client with normalized key', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const key = 'somekey'; await sut.get(key); @@ -41,7 +41,7 @@ describe('CacheClient', () => { }); it('calls client with normalized key (very long key)', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const key = 'x'.repeat(251); await sut.get(key); @@ -53,7 +53,7 @@ describe('CacheClient', () => { }); it('rejects on underlying error', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const expectedError = new Error('Some runtime error'); client.get = jest.fn().mockRejectedValue(expectedError); @@ -61,7 +61,7 @@ describe('CacheClient', () => { }); it('resolves what underlying client resolves', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const expectedValue = 'some value'; client.get = jest.fn().mockResolvedValue(expectedValue); @@ -73,7 +73,7 @@ describe('CacheClient', () => { describe('CacheClient.set', () => { it('calls client with normalized key', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const key = 'somekey'; await sut.set(key, {}); @@ -84,7 +84,7 @@ describe('CacheClient', () => { }); it('passes ttl to client when given', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const expectedTtl = 3600; await sut.set('someKey', {}, { ttl: expectedTtl }); @@ -95,7 +95,7 @@ describe('CacheClient', () => { }); it('rejects on underlying error if configured', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const expectedError = new Error('Some runtime error'); client.set = jest.fn().mockRejectedValue(expectedError); @@ -105,7 +105,7 @@ describe('CacheClient', () => { describe('CacheClient.delete', () => { it('calls client with normalized key', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const key = 'somekey'; await sut.delete(key); @@ -116,11 +116,35 @@ describe('CacheClient', () => { }); it('rejects on underlying error if configured', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const expectedError = new Error('Some runtime error'); client.delete = jest.fn().mockRejectedValue(expectedError); return expect(sut.delete('someKey')).rejects.toEqual(expectedError); }); }); + + describe('CacheClient.withOptions', () => { + it('merges together options to create a new instance', async () => { + const factory = jest.fn(); + const sut = new DefaultCacheClient(client, factory, { foo: 1 } as any); + expect(factory).not.toHaveBeenCalled(); + + const sutA = await sut.withOptions({}); + expect(factory).toHaveBeenLastCalledWith({ foo: 1 }); + + const sutA2 = await sutA.withOptions({ bar: 2 } as any); + expect(factory).toHaveBeenCalledWith({ foo: 1, bar: 2 }); + + await sutA2.withOptions({ foo: 3 } as any); + expect(factory).toHaveBeenCalledWith({ foo: 3, bar: 2 }); + + // calling .withOptions should not mutate state + const sutB = await sut.withOptions({ foo: 2 } as any); + expect(factory).toHaveBeenLastCalledWith({ foo: 2 }); + + await sutB.withOptions({ bar: 3 } as any); + expect(factory).toHaveBeenLastCalledWith({ foo: 2, bar: 3 }); + }); + }); }); diff --git a/packages/backend-common/src/cache/CacheClient.ts b/packages/backend-common/src/cache/CacheClient.ts index 47cb786f14..24ee7ac455 100644 --- a/packages/backend-common/src/cache/CacheClient.ts +++ b/packages/backend-common/src/cache/CacheClient.ts @@ -15,50 +15,64 @@ */ import { - CacheClient, - CacheClientSetOptions, + CacheService, + CacheServiceOptions, + CacheServiceSetOptions, } from '@backstage/backend-plugin-api'; import { JsonValue } from '@backstage/types'; import { createHash } from 'crypto'; import Keyv from 'keyv'; -export type { - CacheClient, - CacheClientSetOptions, -} from '@backstage/backend-plugin-api'; - -type CacheClientArgs = { - client: Keyv; -}; +export type CacheClientFactory = (options: CacheServiceOptions) => Keyv; /** - * A basic, concrete implementation of the CacheClient, suitable for almost + * A basic, concrete implementation of the CacheService, suitable for almost * all uses in Backstage. */ -export class DefaultCacheClient implements CacheClient { - private readonly client: Keyv; +export class DefaultCacheClient implements CacheService { + #client: Keyv; + #clientFactory: CacheClientFactory; + #options: CacheServiceOptions; - constructor({ client }: CacheClientArgs) { - this.client = client; + constructor( + client: Keyv, + clientFactory: CacheClientFactory, + options: CacheServiceOptions, + ) { + this.#client = client; + this.#clientFactory = clientFactory; + this.#options = options; } - async get(key: string): Promise { + async get( + key: string, + ): Promise { const k = this.getNormalizedKey(key); - return await this.client.get(k); + const value = await this.#client.get(k); + return value as TValue | undefined; } async set( key: string, value: JsonValue, - opts: CacheClientSetOptions = {}, + opts: CacheServiceSetOptions = {}, ): Promise { const k = this.getNormalizedKey(key); - await this.client.set(k, value, opts.ttl); + await this.#client.set(k, value, opts.ttl); } async delete(key: string): Promise { const k = this.getNormalizedKey(key); - await this.client.delete(k); + await this.#client.delete(k); + } + + withOptions(options: CacheServiceOptions): CacheService { + const newOptions = { ...this.#options, ...options }; + return new DefaultCacheClient( + this.#clientFactory(newOptions), + this.#clientFactory, + newOptions, + ); } /** diff --git a/packages/backend-common/src/cache/CacheManager.test.ts b/packages/backend-common/src/cache/CacheManager.test.ts index 50b775af25..3239be4d0e 100644 --- a/packages/backend-common/src/cache/CacheManager.test.ts +++ b/packages/backend-common/src/cache/CacheManager.test.ts @@ -94,7 +94,7 @@ describe('CacheManager', () => { const client = DefaultCacheClient as jest.Mock; const mockCalls = client.mock.calls.splice(-1); - const realClient = mockCalls[0][0].client as Keyv; + const realClient = mockCalls[0][0] as Keyv; expect(realClient.on).toHaveBeenCalledWith('error', expect.any(Function)); }); @@ -233,7 +233,7 @@ describe('CacheManager', () => { // Retrieve the error handler attached to the cache client. const client = DefaultCacheClient as jest.Mock; const mockCalls = client.mock.calls.splice(-1); - const realClient = mockCalls[0][0].client as Keyv; + const realClient = mockCalls[0][0] as Keyv; const realOnError = realClient.on as jest.Mock; const realHandler = realOnError.mock.calls.splice(-1)[0][1]; @@ -259,7 +259,7 @@ describe('CacheManager', () => { // Retrieve the error handler attached to the cache client. const client = DefaultCacheClient as jest.Mock; const mockCalls = client.mock.calls.splice(-1); - const realClient = mockCalls[0][0].client as Keyv; + const realClient = mockCalls[0][0] as Keyv; const realOnError = realClient.on as jest.Mock; const realHandler = realOnError.mock.calls.splice(-1)[0][1]; diff --git a/packages/backend-common/src/cache/CacheManager.ts b/packages/backend-common/src/cache/CacheManager.ts index 4f7f5403a8..12ece42854 100644 --- a/packages/backend-common/src/cache/CacheManager.ts +++ b/packages/backend-common/src/cache/CacheManager.ts @@ -18,9 +18,13 @@ import { Config } from '@backstage/config'; import Keyv from 'keyv'; import KeyvMemcache from '@keyv/memcache'; import KeyvRedis from '@keyv/redis'; -import { LoggerService } from '@backstage/backend-plugin-api'; +import { + CacheService, + CacheServiceOptions, + LoggerService, +} from '@backstage/backend-plugin-api'; import { getRootLogger } from '../logging'; -import { DefaultCacheClient, CacheClient } from './CacheClient'; +import { DefaultCacheClient } from './CacheClient'; import { NoStore } from './NoStore'; import { CacheManagerOptions, PluginCacheManager } from './types'; @@ -99,23 +103,32 @@ export class CacheManager { */ forPlugin(pluginId: string): PluginCacheManager { return { - getClient: (opts = {}): CacheClient => { - const concreteClient = this.getClientWithTtl(pluginId, opts.defaultTtl); + getClient: (defaultOptions = {}) => { + const clientFactory = (options: CacheServiceOptions) => { + const concreteClient = this.getClientWithTtl( + pluginId, + options.defaultTtl, + ); - // Always provide an error handler to avoid stopping the process. - concreteClient.on('error', (err: Error) => { - // In all cases, just log the error. - this.logger.error('Failed to create cache client', err); + // Always provide an error handler to avoid stopping the process. + concreteClient.on('error', (err: Error) => { + // In all cases, just log the error. + this.logger.error('Failed to create cache client', err); - // Invoke any custom error handler if provided. - if (typeof this.errorHandler === 'function') { - this.errorHandler(err); - } - }); + // Invoke any custom error handler if provided. + if (typeof this.errorHandler === 'function') { + this.errorHandler(err); + } + }); - return new DefaultCacheClient({ - client: concreteClient, - }); + return concreteClient; + }; + + return new DefaultCacheClient( + clientFactory(defaultOptions), + clientFactory, + defaultOptions, + ); }, }; } @@ -164,3 +177,12 @@ export class CacheManager { }); } } + +/** @public */ +export function cacheToPluginCacheManager( + cache: CacheService, +): PluginCacheManager { + return { + getClient: (opts: CacheServiceOptions) => cache.withOptions(opts), + }; +} diff --git a/packages/backend-common/src/cache/index.ts b/packages/backend-common/src/cache/index.ts index 26e6c102d8..0187aa45d5 100644 --- a/packages/backend-common/src/cache/index.ts +++ b/packages/backend-common/src/cache/index.ts @@ -14,9 +14,10 @@ * limitations under the License. */ -export type { CacheClient, CacheClientSetOptions } from './CacheClient'; -export { CacheManager } from './CacheManager'; +export { CacheManager, cacheToPluginCacheManager } from './CacheManager'; export type { + CacheClient, + CacheClientSetOptions, PluginCacheManager, CacheManagerOptions, CacheClientOptions, diff --git a/packages/backend-common/src/cache/types.ts b/packages/backend-common/src/cache/types.ts index eeeafde5b6..93fa0ac77c 100644 --- a/packages/backend-common/src/cache/types.ts +++ b/packages/backend-common/src/cache/types.ts @@ -15,10 +15,15 @@ */ import { LoggerService } from '@backstage/backend-plugin-api'; +import { + CacheService, + CacheServiceOptions, +} from '@backstage/backend-plugin-api'; export type { - CacheService as PluginCacheManager, - CacheClientOptions, + CacheService as CacheClient, + CacheServiceSetOptions as CacheClientSetOptions, + CacheServiceOptions as CacheClientOptions, } from '@backstage/backend-plugin-api'; /** @@ -38,3 +43,10 @@ export type CacheManagerOptions = { */ onError?: (err: Error) => void; }; + +/** + * @public + */ +export interface PluginCacheManager { + getClient(options?: CacheServiceOptions): CacheService; +} diff --git a/packages/backend-common/src/legacy.ts b/packages/backend-common/src/legacy.ts index 214e65e0c7..408966f3bc 100644 --- a/packages/backend-common/src/legacy.ts +++ b/packages/backend-common/src/legacy.ts @@ -20,6 +20,7 @@ import { ServiceRef, } from '@backstage/backend-plugin-api'; import { RequestHandler } from 'express'; +import { cacheToPluginCacheManager } from './cache'; import { loggerToWinstonLogger } from './logging'; /** @@ -119,5 +120,6 @@ export const legacyPlugin = makeLegacyPlugin( }, { logger: log => loggerToWinstonLogger(log), + cache: cache => cacheToPluginCacheManager(cache), }, ); diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index 6a0b5e51e7..5e64502b78 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -72,31 +72,27 @@ export interface BackendPluginRegistrationPoints { } // @public -export interface CacheClient { +export interface CacheService { delete(key: string): Promise; - get(key: string): Promise; + get(key: string): Promise; set( key: string, value: JsonValue, - options?: CacheClientSetOptions, + options?: CacheServiceSetOptions, ): Promise; + withOptions(options: CacheServiceOptions): CacheService; } // @public -export type CacheClientOptions = { +export type CacheServiceOptions = { defaultTtl?: number; }; // @public -export type CacheClientSetOptions = { +export type CacheServiceSetOptions = { ttl?: number; }; -// @public -export interface CacheService { - getClient: (options?: CacheClientOptions) => CacheClient; -} - // @public (undocumented) export interface ConfigService extends Config {} diff --git a/packages/backend-plugin-api/src/services/definitions/CacheService.ts b/packages/backend-plugin-api/src/services/definitions/CacheService.ts index 2702fdac6d..ccf88823b0 100644 --- a/packages/backend-plugin-api/src/services/definitions/CacheService.ts +++ b/packages/backend-plugin-api/src/services/definitions/CacheService.ts @@ -17,29 +17,11 @@ import { JsonValue } from '@backstage/types'; /** - * Manages access to cache stores that plugins get. + * Options passed to {@link CacheService.set}. * * @public */ -export interface CacheService { - /** - * Provides backend plugins cache connections for themselves. - * - * @remarks - * - * The purpose of this method is to allow plugins to get isolated data stores - * so that plugins are discouraged from cache-level integration and/or cache - * key collisions. - */ - getClient: (options?: CacheClientOptions) => CacheClient; -} - -/** - * Options passed to {@link CacheClient.set}. - * - * @public - */ -export type CacheClientSetOptions = { +export type CacheServiceSetOptions = { /** * Optional TTL in milliseconds. Defaults to the TTL provided when the client * was set up (or no TTL if none are provided). @@ -48,17 +30,31 @@ export type CacheClientSetOptions = { }; /** - * A pre-configured, storage agnostic cache client suitable for use by + * Options passed to {@link CacheService.withOptions}. + * + * @public + */ +export type CacheServiceOptions = { + /** + * An optional default TTL (in milliseconds) to be set when getting a client + * instance. If not provided, data will persist indefinitely by default (or + * can be configured per entry at set-time). + */ + defaultTtl?: number; +}; + +/** + * A pre-configured, storage agnostic cache service suitable for use by * Backstage plugins. * * @public */ -export interface CacheClient { +export interface CacheService { /** * Reads data from a cache store for the given key. If no data was found, * returns undefined. */ - get(key: string): Promise; + get(key: string): Promise; /** * Writes the given data to a cache store, associated with the given key. An @@ -68,25 +64,16 @@ export interface CacheClient { set( key: string, value: JsonValue, - options?: CacheClientSetOptions, + options?: CacheServiceSetOptions, ): Promise; /** * Removes the given key from the cache store. */ delete(key: string): Promise; -} -/** - * Options given when constructing a {@link CacheClient}. - * - * @public - */ -export type CacheClientOptions = { /** - * An optional default TTL (in milliseconds) to be set when getting a client - * instance. If not provided, data will persist indefinitely by default (or - * can be configured per entry at set-time). + * Creates a new {@link CacheService} instance with the given options. */ - defaultTtl?: number; -}; + withOptions(options: CacheServiceOptions): CacheService; +} diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index 35c2f0251c..0122bc0be8 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -17,9 +17,8 @@ export { coreServices } from './coreServices'; export type { CacheService, - CacheClient, - CacheClientOptions, - CacheClientSetOptions, + CacheServiceOptions, + CacheServiceSetOptions, } from './CacheService'; export type { ConfigService } from './ConfigService'; export type { DatabaseService } from './DatabaseService'; diff --git a/plugins/adr-backend/src/service/router.test.ts b/plugins/adr-backend/src/service/router.test.ts index fbbd6e8532..f12b29c70a 100644 --- a/plugins/adr-backend/src/service/router.test.ts +++ b/plugins/adr-backend/src/service/router.test.ts @@ -107,6 +107,8 @@ class MockCacheClient implements CacheClient { async delete(key: string) { delete this.itemRegistry[key]; } + + withOptions = () => this; } describe('createRouter', () => { diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 88cb33863e..f6b19189cd 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -7,7 +7,7 @@ import { BackstageIdentityResponse } from '@backstage/plugin-auth-node'; import { BackstageSignInResult } from '@backstage/plugin-auth-node'; -import { CacheClient } from '@backstage/backend-plugin-api'; +import { CacheService } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { Entity } from '@backstage/catalog-model'; @@ -486,7 +486,7 @@ export const providers: Readonly<{ signIn: { resolver: SignInResolver; }; - cache?: CacheClient | undefined; + cache?: CacheService | undefined; }) => AuthProviderFactory; resolvers: Readonly<{ emailMatchingUserEntityProfileEmail: () => SignInResolver; diff --git a/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts b/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts index 6653bc38cb..1abca4bdf4 100644 --- a/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts +++ b/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts @@ -83,6 +83,7 @@ const mockCacheClient = { get: jest.fn(), set: jest.fn(), delete: jest.fn(), + withOptions: jest.fn(), }; jest.mock('jose'); diff --git a/plugins/techdocs-backend/src/cache/TechDocsCache.test.ts b/plugins/techdocs-backend/src/cache/TechDocsCache.test.ts index 039f1db09f..fa4c81682c 100644 --- a/plugins/techdocs-backend/src/cache/TechDocsCache.test.ts +++ b/plugins/techdocs-backend/src/cache/TechDocsCache.test.ts @@ -31,6 +31,7 @@ describe('TechDocsCache', () => { get: jest.fn(), set: jest.fn(), delete: jest.fn(), + withOptions: jest.fn(), }; CacheUnderTest = TechDocsCache.fromConfig(new ConfigReader({}), { cache: MockClient, From b1d8ea5e6f324443d3856e0cdf524293311b9821 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Feb 2023 10:26:01 +0000 Subject: [PATCH 367/423] chore(deps): bump @sideway/formula in /microsite-next Bumps [@sideway/formula](https://github.com/sideway/formula) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/sideway/formula/releases) - [Commits](https://github.com/sideway/formula/compare/v3.0.0...v3.0.1) --- updated-dependencies: - dependency-name: "@sideway/formula" dependency-type: indirect ... Signed-off-by: dependabot[bot] --- microsite-next/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index e03c6d93c5..251ae303c0 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -2382,9 +2382,9 @@ __metadata: linkType: hard "@sideway/formula@npm:^3.0.0": - version: 3.0.0 - resolution: "@sideway/formula@npm:3.0.0" - checksum: 8ae26a0ed6bc84f7310be6aae6eb9d81e97f382619fc69025d346871a707eaab0fa38b8c857e3f0c35a19923de129f42d35c50b8010c928d64aab41578580ec4 + version: 3.0.1 + resolution: "@sideway/formula@npm:3.0.1" + checksum: e4beeebc9dbe2ff4ef0def15cec0165e00d1612e3d7cea0bc9ce5175c3263fc2c818b679bd558957f49400ee7be9d4e5ac90487e1625b4932e15c4aa7919c57a languageName: node linkType: hard From e81a6e0ab5964c8b1e58ce152180b73d2b0a9a4f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 10 Feb 2023 11:27:29 +0100 Subject: [PATCH 368/423] core-components: better URL validation in Link component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Patrik Oldsberg --- .changeset/red-pugs-tap.md | 5 +++++ .../core-components/src/components/Link/Link.test.tsx | 9 +++++++++ packages/core-components/src/components/Link/Link.tsx | 11 +++++++++++ 3 files changed, 25 insertions(+) create mode 100644 .changeset/red-pugs-tap.md diff --git a/.changeset/red-pugs-tap.md b/.changeset/red-pugs-tap.md new file mode 100644 index 0000000000..85da2b7990 --- /dev/null +++ b/.changeset/red-pugs-tap.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Updated Link URL validation to be more strict. diff --git a/packages/core-components/src/components/Link/Link.test.tsx b/packages/core-components/src/components/Link/Link.test.tsx index 3538b79052..09e1293726 100644 --- a/packages/core-components/src/components/Link/Link.test.tsx +++ b/packages/core-components/src/components/Link/Link.test.tsx @@ -173,4 +173,13 @@ describe('', () => { }); }); }); + + it('throws an error when attempting to link to script code', () => { + expect(() => + // eslint-disable-next-line no-script-url + render(wrapInTestApp(Script)), + ).toThrowErrorMatchingInlineSnapshot( + `"Link component rejected javascript: URL as a security precaution"`, + ); + }); }); diff --git a/packages/core-components/src/components/Link/Link.tsx b/packages/core-components/src/components/Link/Link.tsx index 440fcb811f..bb753e10bd 100644 --- a/packages/core-components/src/components/Link/Link.tsx +++ b/packages/core-components/src/components/Link/Link.tsx @@ -55,6 +55,11 @@ const useStyles = makeStyles( export const isExternalUri = (uri: string) => /^([a-z+.-]+):/.test(uri); +// See https://github.com/facebook/react/blob/f0cf832e1d0c8544c36aa8b310960885a11a847c/packages/react-dom-bindings/src/shared/sanitizeURL.js +const scriptProtocolPattern = + // eslint-disable-next-line no-control-regex + /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i; + export type LinkProps = Omit & Omit & { to: string; @@ -144,6 +149,12 @@ export const Link = React.forwardRef( const external = isExternalUri(to); const newWindow = external && !!/^https?:/.exec(to); + if (scriptProtocolPattern.test(to)) { + throw new Error( + 'Link component rejected javascript: URL as a security precaution', + ); + } + const handleClick = (event: React.MouseEvent) => { onClick?.(event); if (!noTrack) { From 3ab148535476554ee0e8f03efdb222df7c2dd982 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 12:56:15 +0100 Subject: [PATCH 369/423] chore: added FieldOverrides to the scaffolder form Signed-off-by: blam --- .../FieldOverrides/DescriptionField.tsx | 22 +++++++++++++++++++ .../Stepper/FieldOverrides/index.ts | 16 ++++++++++++++ .../src/next/components/Stepper/Stepper.tsx | 3 ++- 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/DescriptionField.tsx create mode 100644 plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/index.ts diff --git a/plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/DescriptionField.tsx b/plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/DescriptionField.tsx new file mode 100644 index 0000000000..eded38beee --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/DescriptionField.tsx @@ -0,0 +1,22 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { MarkdownContent } from '@backstage/core-components'; +import { FieldProps } from '@rjsf/utils'; + +export const DescriptionField = ({ description }: FieldProps) => + description && ; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/index.ts b/plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/index.ts new file mode 100644 index 0000000000..d6d0bf3499 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { DescriptionField } from './DescriptionField'; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index f802121597..dc04bb1f47 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -39,6 +39,7 @@ import { FormProps } from '../../types'; import { LayoutOptions } from '../../../layouts'; import { useTransformSchemaToProps } from '../../hooks/useTransformSchemaToProps'; import { hasErrors } from './utils'; +import * as FieldOverrides from './FieldOverrides'; const useStyles = makeStyles(theme => ({ backButton: { @@ -175,7 +176,7 @@ export const Stepper = (stepperProps: StepperProps) => { schema={currentStep.schema} uiSchema={currentStep.uiSchema} onSubmit={handleNext} - fields={extensions} + fields={{ ...FieldOverrides, ...extensions }} showErrorList={false} onChange={handleChange} {...(props.FormProps ?? {})} From a07750745b9ab19054577bceff223b5d198558fa Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 12:57:34 +0100 Subject: [PATCH 370/423] chore: added changeset Signed-off-by: blam --- .changeset/heavy-comics-applaud.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/heavy-comics-applaud.md diff --git a/.changeset/heavy-comics-applaud.md b/.changeset/heavy-comics-applaud.md new file mode 100644 index 0000000000..faa0aabb4c --- /dev/null +++ b/.changeset/heavy-comics-applaud.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': minor +--- + +Added `DescriptionField` field override to the `next/scaffolder` From 71f8fc209f1dd1859f4eced426d36f3c47c4c685 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Fri, 10 Feb 2023 12:51:07 +0100 Subject: [PATCH 371/423] fix(techdocs-cli): Fix proxying to mkdocs The domain localhost may point to both 127.0.0.1 and ::1, ipv4 and ipv6 and when node tries to lookup localhost it might prefer ipv6 while mkdocs is only listening on ipv4. This tells node-proxy to target the ipv4 address instead of relying on localhost hostname lookup. Signed-off-by: Nikolai R Kristiansen --- packages/techdocs-cli/src/commands/serve/serve.ts | 2 +- packages/techdocs-cli/src/lib/httpServer.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/techdocs-cli/src/commands/serve/serve.ts b/packages/techdocs-cli/src/commands/serve/serve.ts index 48e48d4f66..b779731fae 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -127,7 +127,7 @@ export default async function serve(opts: OptionValues) { const httpServer = new HTTPServer( previewAppPath, port, - opts.mkdocsPort, + mkdocsExpectedDevAddr, opts.verbose, ); diff --git a/packages/techdocs-cli/src/lib/httpServer.ts b/packages/techdocs-cli/src/lib/httpServer.ts index c4bd5b823a..08987f3f1d 100644 --- a/packages/techdocs-cli/src/lib/httpServer.ts +++ b/packages/techdocs-cli/src/lib/httpServer.ts @@ -23,26 +23,26 @@ export default class HTTPServer { private readonly proxyEndpoint: string; private readonly backstageBundleDir: string; private readonly backstagePort: number; - private readonly mkdocsPort: number; + private readonly mkdocsTargetAddress: string; private readonly verbose: boolean; constructor( backstageBundleDir: string, backstagePort: number, - mkdocsPort: number, + mkdocsTargetAddress: string, verbose: boolean, ) { this.proxyEndpoint = '/api/techdocs/'; this.backstageBundleDir = backstageBundleDir; this.backstagePort = backstagePort; - this.mkdocsPort = mkdocsPort; + this.mkdocsTargetAddress = mkdocsTargetAddress; this.verbose = verbose; } // Create a Proxy for mkdocs server private createProxy() { const proxy = httpProxy.createProxyServer({ - target: `http://localhost:${this.mkdocsPort}`, + target: this.mkdocsTargetAddress, }); return (request: http.IncomingMessage): [httpProxy, string] => { From dcacf94912bb733202eb945c66a802c12f800cb5 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Fri, 10 Feb 2023 13:09:50 +0100 Subject: [PATCH 372/423] docs: Add changeset Signed-off-by: Nikolai R Kristiansen --- .changeset/flat-lizards-poke.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/flat-lizards-poke.md diff --git a/.changeset/flat-lizards-poke.md b/.changeset/flat-lizards-poke.md new file mode 100644 index 0000000000..bc180836fa --- /dev/null +++ b/.changeset/flat-lizards-poke.md @@ -0,0 +1,10 @@ +--- +'@techdocs/cli': patch +--- + +Fix proxying to mkdocs + +The domain localhost may point to both 127.0.0.1 and ::1, ipv4 and ipv6 +and when node tries to lookup localhost it might prefer ipv6 while mkdocs +is only listening on ipv4. This tells node-proxy to target the ipv4 address +instead of relying on localhost hostname lookup. From 5637ebed924ef04c23cb7e8cfd67f79724d17053 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 10 Feb 2023 13:28:42 +0100 Subject: [PATCH 373/423] core-components: global override for window.open MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Patrik Oldsberg --- .changeset/gorgeous-ligers-burn.md | 5 +++++ .../src/components/Link/Link.test.tsx | 11 ++++++++++ .../src/components/Link/Link.tsx | 21 +++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 .changeset/gorgeous-ligers-burn.md diff --git a/.changeset/gorgeous-ligers-burn.md b/.changeset/gorgeous-ligers-burn.md new file mode 100644 index 0000000000..f1d8f2cf5f --- /dev/null +++ b/.changeset/gorgeous-ligers-burn.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Added a global override for `window.open` that helps prevent security vulnerabilities. diff --git a/packages/core-components/src/components/Link/Link.test.tsx b/packages/core-components/src/components/Link/Link.test.tsx index 09e1293726..682c4bea8a 100644 --- a/packages/core-components/src/components/Link/Link.test.tsx +++ b/packages/core-components/src/components/Link/Link.test.tsx @@ -183,3 +183,14 @@ describe('', () => { ); }); }); + +describe('window.open', () => { + it('throws an error when attempting to open script code', () => { + expect(() => + // eslint-disable-next-line no-script-url + window.open("javascript:alert('hello')"), + ).toThrowErrorMatchingInlineSnapshot( + `"Rejected window.open() with a javascript: URL as a security precaution"`, + ); + }); +}); diff --git a/packages/core-components/src/components/Link/Link.tsx b/packages/core-components/src/components/Link/Link.tsx index bb753e10bd..be91753ea3 100644 --- a/packages/core-components/src/components/Link/Link.tsx +++ b/packages/core-components/src/components/Link/Link.tsx @@ -60,6 +60,27 @@ const scriptProtocolPattern = // eslint-disable-next-line no-control-regex /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i; +// We install this globally in order to prevent javascript: URL XSS attacks via window.open +const originalWindowOpen = window.open as typeof window.open & { + __backstage?: true; +}; +if (originalWindowOpen && !originalWindowOpen.__backstage) { + const newOpen = function open( + this: Window, + ...args: Parameters + ) { + const url = String(args[0]); + if (scriptProtocolPattern.test(url)) { + throw new Error( + 'Rejected window.open() with a javascript: URL as a security precaution', + ); + } + return originalWindowOpen.apply(this, args); + }; + newOpen.__backstage = true; + window.open = newOpen; +} + export type LinkProps = Omit & Omit & { to: string; From de908df2d054d483681a6ce4d424b5184ee67872 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Wed, 8 Feb 2023 15:23:07 -0500 Subject: [PATCH 374/423] dev environment now utilizes mock PagerDuty API By making use of a mock PagerDuty API to render the `EntityPagerDuty` component via a `yarn start`-created dev environment, this unblocks development for contributors who don't otherwise have access to the PagerDuty API. Signed-off-by: Mike Ball --- plugins/pagerduty/dev/index.tsx | 152 +++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 3 deletions(-) diff --git a/plugins/pagerduty/dev/index.tsx b/plugins/pagerduty/dev/index.tsx index 676eb687a4..e45e0ffd8f 100644 --- a/plugins/pagerduty/dev/index.tsx +++ b/plugins/pagerduty/dev/index.tsx @@ -13,7 +13,153 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createDevApp } from '@backstage/dev-utils'; -import { pagerDutyPlugin } from '../src/plugin'; -createDevApp().registerPlugin(pagerDutyPlugin).render(); +import React from 'react'; +import { Entity } from '@backstage/catalog-model'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { createDevApp } from '@backstage/dev-utils'; +import { pagerDutyPlugin, EntityPagerDutyCard } from '../src/plugin'; +import { pagerDutyApiRef } from '../src/api'; +import { PagerDutyApi, PagerDutyTriggerAlarmRequest } from '../src/api/types'; +import { + PagerDutyIncident, + PagerDutyChangeEvent, +} from '../src/components/types'; + +const mockEntity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'backstage', + description: 'backstage.io', + annotations: { + 'github.com/project-slug': 'backstage/backstage', + 'pagerduty.com/service-id': 'foo', + 'pagerduty.com/integration-key': 'foo', + }, + }, + spec: { + lifecycle: 'production', + type: 'website', + owner: 'user:guest', + }, +}; + +const mockPagerDutyApi: PagerDutyApi = { + async getServiceByEntity(entity: Entity) { + return { + service: { + name: entity.metadata.name, + integrationKey: 'key', + id: '123', + html_url: 'http://service', + escalation_policy: { + id: '123', + html_url: 'http://escalationpolicy', + user: { + id: '123', + summary: 'summary', + email: 'email@email.com', + html_url: 'http://user', + name: 'some-user', + }, + }, + }, + }; + }, + + async getIncidentsByServiceId(serviceId: string) { + const incident = (title: string) => { + return { + id: '123', + title: title, + status: 'acknowledged', + html_url: 'http://incident', + assignments: [ + { + assignee: { + id: '123', + summary: 'Jane Doe', + html_url: 'http://assignee', + }, + }, + ], + serviceId: serviceId, + created_at: '2015-10-06T21:30:42Z', + } as PagerDutyIncident; + }; + + return { + incidents: [ + incident('Some Alerting Incident'), + incident('Another Alerting Incident'), + ], + }; + }, + + async getChangeEventsByServiceId(serviceId: string) { + const changeEvent = (description: string) => { + return { + id: serviceId, + source: 'some-source', + html_url: 'http://changeevent', + links: [ + { + href: 'http://link', + text: 'link text', + }, + ], + summary: description, + timestamp: '2018-10-06T21:30:42Z', + } as PagerDutyChangeEvent; + }; + + return { + change_events: [ + changeEvent('us-east-1 deployment'), + changeEvent('us-west-2 deployment'), + ], + }; + }, + + async getOnCallByPolicyId() { + const oncall = (name: string, escalation: number) => { + return { + user: { + id: '123', + name: name, + html_url: 'http://assignee', + summary: 'summary', + email: 'email@email.com', + }, + escalation_level: escalation, + }; + }; + + return { + oncalls: [oncall('Jane Doe', 1), oncall('John Doe', 2)], + }; + }, + + async triggerAlarm(request: PagerDutyTriggerAlarmRequest) { + return new Response(request.description); + }, +}; + +createDevApp() + .registerApi({ + api: pagerDutyApiRef, + deps: {}, + factory: () => mockPagerDutyApi, + }) + .registerPlugin(pagerDutyPlugin) + .addPage({ + path: '/pagerduty', + title: 'PagerDuty', + element: ( + + + + ), + }) + .render(); From 5a2faa801fd5d4ac8b9df68834c4cf8c86f12192 Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Fri, 10 Feb 2023 14:29:04 +0100 Subject: [PATCH 375/423] Incorporated feedback Signed-off-by: bnechyporenko --- .../Stepper/createAsyncValidators.test.ts | 55 +++++++++++++++++++ .../Stepper/createAsyncValidators.ts | 38 +++++++++---- .../TemplatePage/createValidator.test.ts | 4 +- 3 files changed, 85 insertions(+), 12 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index fe8b41a9f3..3c4442afea 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -272,4 +272,59 @@ describe('createAsyncValidators', () => { }, }); }); + + it('should call a validator for array property from a custom field extension', async () => { + const schema: JsonObject = { + type: 'object', + properties: { + tags: { + title: 'Tags', + type: 'array', + items: { + type: 'string', + 'ui:field': 'TagField', + }, + }, + }, + }; + + const validators = { TagField: jest.fn() }; + + const validate = createAsyncValidators(schema, validators, { + apiHolder: { get: jest.fn() }, + }); + + await validate({ + tags: ['tag-1', 'tag-2'], + }); + + expect(validators.TagField).toHaveBeenCalled(); + }); + + it('should does not call a validator if no ui field specified', async () => { + const schema: JsonObject = { + type: 'object', + properties: { + tags: { + title: 'Tags', + type: 'array', + items: { + type: 'string', + }, + }, + }, + }; + + const validators = { TagField: jest.fn() }; + + const validate = createAsyncValidators(schema, validators, { + apiHolder: { get: jest.fn() }, + }); + + await validate({ + tags: ['asd', 'asd$'], + }); + + expect(validators.TagField).not.toHaveBeenCalled(); + }); }); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index 86b7619b34..b524944719 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -15,7 +15,7 @@ */ import { FieldValidation } from '@rjsf/utils'; -import type { JsonObject } from '@backstage/types'; +import type { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; import { Draft07 as JSONSchema } from 'json-schema-library'; import { createFieldValidation } from '../../lib'; @@ -44,20 +44,38 @@ export const createAsyncValidators = ( const parsedSchema = new JSONSchema(rootSchema); const formValidation: FormValidation = {}; + const validateForm = async ( + validatorName: string, + key: string, + value: JsonValue | undefined, + ) => { + const validator = validators[validatorName]; + if (validator) { + const fieldValidation = createFieldValidation(); + try { + await validator(value, fieldValidation, { ...context, formData }); + } catch (ex) { + fieldValidation.addError(ex.message); + } + formValidation[key] = fieldValidation; + } + }; + for (const [key, value] of Object.entries(current)) { const path = `${pathPrefix}/${key}`; const definitionInSchema = parsedSchema.getSchema(path, formData); if (definitionInSchema && 'ui:field' in definitionInSchema) { - const validator = validators[definitionInSchema['ui:field']]; - if (validator) { - const fieldValidation = createFieldValidation(); - try { - await validator(value, fieldValidation, { ...context, formData }); - } catch (ex) { - fieldValidation.addError(ex.message); - } - formValidation[key] = fieldValidation; + if ('ui:field' in definitionInSchema) { + await validateForm(definitionInSchema['ui:field'], key, value); + } + } else if ( + definitionInSchema && + definitionInSchema.items && + 'ui:field' in definitionInSchema.items + ) { + if ('ui:field' in definitionInSchema.items) { + await validateForm(definitionInSchema.items['ui:field'], key, value); } } else if (isObject(value)) { formValidation[key] = await validate(formData, path, value); diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts index 777de0cc36..f5be77811a 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts @@ -57,7 +57,7 @@ describe('createValidator', () => { apiHolder: apiHolderMock, }; - it('Should call validator for object property from a custom field extension', () => { + it('should call validator for object property from a custom field extension', () => { /* GIVEN */ const rootSchema = { title: 'Title', @@ -89,7 +89,7 @@ describe('createValidator', () => { expect(result.p1.addError).toHaveBeenCalledTimes(1); }); - it('Should call validator for array property from a custom field extension', () => { + it('should call validator for array property from a custom field extension', () => { /* GIVEN */ const rootSchema = { title: 'My form', From 7c145f21ecb62e619823055fb0215c211312d12a Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 14:38:39 +0100 Subject: [PATCH 376/423] chore: make the new TemplateEditor journey work with the new form work Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 7 +- .../src/next/components/Form/Form.tsx | 23 ++ .../src/next/components/Form/index.ts | 17 ++ .../src/next/components/Stepper/Stepper.tsx | 8 +- .../src/next/components/index.ts | 1 + plugins/scaffolder/package.json | 1 + plugins/scaffolder/src/next/Router/Router.tsx | 14 + .../CustomFieldExplorer.tsx | 196 ++++++++++++++ .../DirectoryEditorContext.tsx | 243 ++++++++++++++++++ .../TemplateEditorPage/DryRunContext.test.tsx | 44 ++++ .../next/TemplateEditorPage/DryRunContext.tsx | 179 +++++++++++++ .../DryRunResults/DryRunResults.test.tsx | 118 +++++++++ .../DryRunResults/DryRunResults.tsx | 91 +++++++ .../DryRunResults/DryRunResultsList.test.tsx | 95 +++++++ .../DryRunResults/DryRunResultsList.tsx | 83 ++++++ .../DryRunResults/DryRunResultsSplitView.tsx | 55 ++++ .../DryRunResults/DryRunResultsView.test.tsx | 99 +++++++ .../DryRunResults/DryRunResultsView.tsx | 195 ++++++++++++++ .../TemplateEditorPage/DryRunResults/index.ts | 17 ++ .../TemplateEditorPage/TemplateEditor.tsx | 94 +++++++ .../TemplateEditorBrowser.test.tsx | 55 ++++ .../TemplateEditorBrowser.tsx | 100 +++++++ .../TemplateEditorPage/TemplateEditorForm.tsx | 234 +++++++++++++++++ .../TemplateEditorIntro.tsx | 144 +++++++++++ .../TemplateEditorPage.test.tsx | 58 +++++ .../TemplateEditorPage/TemplateEditorPage.tsx | 107 ++++++++ .../TemplateEditorTextArea.tsx | 153 +++++++++++ .../TemplateFormPreviewer.tsx | 219 ++++++++++++++++ .../src/next/TemplateEditorPage/index.ts | 17 ++ yarn.lock | 1 + 30 files changed, 2661 insertions(+), 7 deletions(-) create mode 100644 plugins/scaffolder-react/src/next/components/Form/Form.tsx create mode 100644 plugins/scaffolder-react/src/next/components/Form/index.ts create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/index.ts diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 72a0b92eef..33246d8bea 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -7,13 +7,14 @@ import { ApiHolder } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; +import { ComponentType } from 'react'; import { Dispatch } from 'react'; import { Extension } from '@backstage/core-plugin-api'; import { FieldProps } from '@rjsf/core'; import { FieldProps as FieldProps_2 } from '@rjsf/utils'; import { FieldValidation } from '@rjsf/core'; import { FieldValidation as FieldValidation_2 } from '@rjsf/utils'; -import type { FormProps as FormProps_2 } from '@rjsf/core-v5'; +import { FormProps as FormProps_2 } from '@rjsf/core-v5'; import { IconComponent } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; @@ -22,6 +23,7 @@ import { Observable } from '@backstage/types'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; +import { RJSFSchema } from '@rjsf/utils'; import { SetStateAction } from 'react'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; @@ -126,6 +128,9 @@ export type FieldExtensionOptions< schema?: CustomFieldExtensionSchema; }; +// @alpha (undocumented) +export const Form: ComponentType>; + // @public export type FormProps = Pick< FormProps_2, diff --git a/plugins/scaffolder-react/src/next/components/Form/Form.tsx b/plugins/scaffolder-react/src/next/components/Form/Form.tsx new file mode 100644 index 0000000000..79bcaa8475 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/Form/Form.tsx @@ -0,0 +1,23 @@ +/* + * 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 { withTheme } from '@rjsf/core-v5'; + +// TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly +// which is what we're using here as the default types, it needs to depend on @rjsf/core-v5 because +// of the re-writing we're doing. Once we've migrated, we can import this the exact same as before. +/** @alpha */ +export const Form = withTheme(require('@rjsf/material-ui-v5').Theme); diff --git a/plugins/scaffolder-react/src/next/components/Form/index.ts b/plugins/scaffolder-react/src/next/components/Form/index.ts new file mode 100644 index 0000000000..6f780e92a4 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/Form/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 { Form } from './Form'; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index dc04bb1f47..bb2844fd52 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -22,7 +22,7 @@ import { Button, makeStyles, } from '@material-ui/core'; -import { type IChangeEvent, withTheme } from '@rjsf/core-v5'; +import { type IChangeEvent } from '@rjsf/core-v5'; import { ErrorSchema } from '@rjsf/utils'; import React, { useCallback, useMemo, useState, type ReactNode } from 'react'; import { NextFieldExtensionOptions } from '../../extensions'; @@ -40,6 +40,7 @@ import { LayoutOptions } from '../../../layouts'; import { useTransformSchemaToProps } from '../../hooks/useTransformSchemaToProps'; import { hasErrors } from './utils'; import * as FieldOverrides from './FieldOverrides'; +import { Form } from '../Form'; const useStyles = makeStyles(theme => ({ backButton: { @@ -75,11 +76,6 @@ export type StepperProps = { layouts?: LayoutOptions[]; }; -// TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly -// which is what we're using here as the default types, it needs to depend on @rjsf/core-v5 because -// of the re-writing we're doing. Once we've migrated, we can import this the exact same as before. -const Form = withTheme(require('@rjsf/material-ui-v5').Theme); - /** * The `Stepper` component is the Wizard that is rendered when a user selects a template * @alpha diff --git a/plugins/scaffolder-react/src/next/components/index.ts b/plugins/scaffolder-react/src/next/components/index.ts index 05e5a1105a..60a8fd9a51 100644 --- a/plugins/scaffolder-react/src/next/components/index.ts +++ b/plugins/scaffolder-react/src/next/components/index.ts @@ -19,3 +19,4 @@ export * from './ReviewState'; export * from './TemplateGroup'; export * from './Workflow'; export * from './TemplateOutputs'; +export * from './Form'; diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 86f9100deb..08381732c2 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -58,6 +58,7 @@ "@rjsf/core": "^3.2.1", "@rjsf/material-ui": "^3.2.1", "@rjsf/utils": "5.1.0", + "@rjsf/validator-ajv8": "5.1.0", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", "git-url-parse": "^13.0.0", diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 049579e16c..ded344b048 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -32,6 +32,7 @@ import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default'; import { nextActionsRouteRef, + nextEditRouteRef, nextScaffolderListTaskRouteRef, nextScaffolderTaskRouteRef, nextSelectedTemplateRouteRef, @@ -40,6 +41,7 @@ import { ErrorPage } from '@backstage/core-components'; import { OngoingTask } from '../OngoingTask'; import { ActionsPage } from '../../components/ActionsPage'; import { ListTasksPage } from '../../components/ListTasksPage'; +import { TemplateEditorPage } from '../TemplateEditorPage'; /** * The Props for the Scaffolder Router @@ -130,6 +132,18 @@ export const Router = (props: PropsWithChildren) => { /> } /> + + + + } + /> + } /> ({ + root: { + gridArea: 'pageContent', + display: 'grid', + gridTemplateAreas: ` + "controls controls" + "fieldForm preview" + `, + gridTemplateRows: 'auto 1fr', + gridTemplateColumns: '1fr 1fr', + }, + controls: { + gridArea: 'controls', + display: 'flex', + flexFlow: 'row nowrap', + alignItems: 'center', + margin: theme.spacing(1), + }, + fieldForm: { + gridArea: 'fieldForm', + }, + preview: { + gridArea: 'preview', + }, +})); + +export const CustomFieldExplorer = ({ + customFieldExtensions = [], + onClose, +}: { + customFieldExtensions?: NextFieldExtensionOptions[]; + onClose?: () => void; +}) => { + const classes = useStyles(); + const fieldOptions = customFieldExtensions.filter(field => !!field.schema); + const [selectedField, setSelectedField] = useState(fieldOptions[0]); + const [fieldFormState, setFieldFormState] = useState({}); + const [refreshKey, setRefreshKey] = useState(Date.now()); + const sampleFieldTemplate = useMemo( + () => + yaml.stringify({ + parameters: [ + { + title: `${selectedField.name} Example`, + properties: { + [selectedField.name]: { + type: selectedField.schema?.returnValue?.type, + 'ui:field': selectedField.name, + 'ui:options': fieldFormState, + }, + }, + }, + ], + }), + [fieldFormState, selectedField], + ); + + const fieldComponents = useMemo(() => { + return Object.fromEntries( + customFieldExtensions.map(({ name, component }) => [name, component]), + ); + }, [customFieldExtensions]); + + const handleSelectionChange = useCallback( + selection => { + setSelectedField(selection); + setFieldFormState({}); + }, + [setFieldFormState, setSelectedField], + ); + + const handleFieldConfigChange = useCallback( + state => { + setFieldFormState(state); + // Force TemplateEditorForm to re-render since some fields + // may not be responsive to ui:option changes + setRefreshKey(Date.now()); + }, + [setFieldFormState, setRefreshKey], + ); + + return ( +
    +
    + + + Choose Custom Field Extension + + + + + + + +
    +
    + + + +
    handleFieldConfigChange(e.formData)} + validator={validator} + schema={selectedField.schema?.uiOptions || {}} + > + +
    +
    +
    +
    +
    + + + + + + + null} + /> +
    +
    + ); +}; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx new file mode 100644 index 0000000000..0edf390bfe --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx @@ -0,0 +1,243 @@ +/* + * 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 { ErrorPanel, Progress } from '@backstage/core-components'; +import { useAsync, useRerender } from '@react-hookz/web'; +import React, { createContext, ReactNode, useContext, useEffect } from 'react'; +import { + TemplateDirectoryAccess, + TemplateFileAccess, +} from '../../lib/filesystem'; + +const MAX_SIZE = 1024 * 1024; +const MAX_SIZE_MESSAGE = 'This file is too large to be displayed'; + +interface DirectoryEditorFile { + /** The path of the file relative to the root directory */ + path: string; + /** The staged content of the file */ + content: string; + /** Whether the staged content matches what is on disk */ + dirty: boolean; + + /** Update the staged content of the file without saving */ + updateContent(content: string): void; + /** Save the staged content of the file to disk */ + save(): Promise; + /** Reload the staged content of the file from disk */ + reload(): Promise; +} + +interface DirectoryEditor { + /** A list of all files in the edited directory */ + files: Array; + + /** The currently selected file */ + selectedFile: DirectoryEditorFile | undefined; + /** Switch the selected file */ + setSelectedFile(path: string | undefined): void; + + /** Save all files to disk */ + save(): Promise; + /** Reload all files from disk */ + reload(): Promise; + + subscribe(listener: () => void): () => void; +} + +class DirectoryEditorFileManager implements DirectoryEditorFile { + readonly #access: TemplateFileAccess; + readonly #signalUpdate: () => void; + + #content?: string; + #savedContent?: string; + + constructor(access: TemplateFileAccess, signalUpdate: () => void) { + this.#access = access; + this.#signalUpdate = signalUpdate; + } + + get path() { + return this.#access.path; + } + + get content() { + return this.#content ?? MAX_SIZE_MESSAGE; + } + + updateContent(content: string): void { + if (this.#content === undefined) { + return; + } + this.#content = content; + this.#signalUpdate(); + } + + get dirty() { + return this.#content !== this.#savedContent; + } + + async save(): Promise { + if (this.#content !== undefined) { + await this.#access.save(this.#content); + this.#savedContent = this.#content; + this.#signalUpdate(); + } + } + + async reload(): Promise { + const file = await this.#access.file(); + if (file.size > MAX_SIZE) { + if (this.#content !== undefined) { + this.#content = undefined; + this.#savedContent = undefined; + this.#signalUpdate(); + } + return; + } + + const content = await file.text(); + if (this.#content !== content) { + this.#content = content; + this.#savedContent = content; + this.#signalUpdate(); + } + } +} + +class DirectoryEditorManager implements DirectoryEditor { + readonly #access: TemplateDirectoryAccess; + readonly #listeners = new Set<() => void>(); + + #files: DirectoryEditorFile[] = []; + #selectedFile: DirectoryEditorFile | undefined; + + constructor(access: TemplateDirectoryAccess) { + this.#access = access; + } + + get files() { + return this.#files; + } + + get selectedFile() { + return this.#selectedFile; + } + + setSelectedFile = (path: string | undefined): void => { + const prev = this.#selectedFile; + const next = this.#files.find(file => file.path === path); + if (prev !== next) { + this.#selectedFile = next; + this.#signalUpdate(); + } + }; + + get dirty() { + return this.#files.some(file => file.dirty); + } + + async save(): Promise { + await Promise.all(this.#files.map(file => file.save())); + } + + async reload(): Promise { + const selectedPath = this.#selectedFile?.path; + + const files = await this.#access.listFiles(); + const fileManagers = await Promise.all( + files.map(async file => { + const manager = new DirectoryEditorFileManager( + file, + this.#signalUpdate, + ); + await manager.reload(); + return manager; + }), + ); + this.#files.length = 0; + this.#files.push(...fileManagers); + + this.setSelectedFile(selectedPath); + this.#signalUpdate(); + } + + subscribe(listener: () => void): () => void { + this.#listeners.add(listener); + return () => { + this.#listeners.delete(listener); + }; + } + + #signalUpdate = () => { + this.#listeners.forEach(listener => listener()); + }; +} + +const DirectoryEditorContext = createContext( + undefined, +); + +export function useDirectoryEditor(): DirectoryEditor { + const value = useContext(DirectoryEditorContext); + const rerender = useRerender(); + + useEffect(() => value?.subscribe(rerender), [value, rerender]); + + if (!value) { + throw new Error('must be used within a DirectoryEditorProvider'); + } + return value; +} + +interface DirectoryEditorProviderProps { + directory: TemplateDirectoryAccess; + children?: ReactNode; +} + +export function DirectoryEditorProvider(props: DirectoryEditorProviderProps) { + const { directory } = props; + + const [{ result, error }, { execute }] = useAsync( + async (dir: TemplateDirectoryAccess) => { + const manager = new DirectoryEditorManager(dir); + await manager.reload(); + + const firstYaml = manager.files.find(file => file.path.match(/\.ya?ml$/)); + if (firstYaml) { + manager.setSelectedFile(firstYaml.path); + } + + return manager; + }, + ); + + useEffect(() => { + execute(directory); + }, [execute, directory]); + + if (error) { + return ; + } else if (!result) { + return ; + } + + return ( + + {props.children} + + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx new file mode 100644 index 0000000000..36a62f1b8a --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx @@ -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 { base64EncodeContent } from './DryRunContext'; + +// eslint-disable-next-line no-restricted-imports +import { TextEncoder } from 'util'; + +window.TextEncoder = TextEncoder; + +describe('base64EncodeContent', () => { + it('encodes text files', () => { + expect(base64EncodeContent('abc')).toBe('YWJj'); + expect(base64EncodeContent('abc'.repeat(1000000))).toBe( + window.btoa(''), + ); + }); + + it('encodes binary files', () => { + expect(base64EncodeContent('\x00\x01\x02')).toBe('AAEC'); + expect(base64EncodeContent('😅')).toBe('8J+YhQ=='); + // Triggers chunking + expect(base64EncodeContent('😅'.repeat(18000))).toBe( + '8J+YhfCfmIXwn5iF8J+YhfCfmIXwn5iF'.repeat(3000), + ); + // Triggers size check + expect(base64EncodeContent('😅'.repeat(1000000))).toBe( + window.btoa(''), + ); + }); +}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx new file mode 100644 index 0000000000..a617eebe1e --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx @@ -0,0 +1,179 @@ +/* + * 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 yaml from 'yaml'; +import { useApi } from '@backstage/core-plugin-api'; +import { JsonObject } from '@backstage/types'; +import React, { + createContext, + ReactNode, + useCallback, + useContext, + useMemo, + useRef, + useState, +} from 'react'; +import { + scaffolderApiRef, + ScaffolderDryRunResponse, +} from '@backstage/plugin-scaffolder-react'; + +const MAX_CONTENT_SIZE = 64 * 1024; +const CHUNK_SIZE = 32 * 1024; + +interface DryRunOptions { + templateContent: string; + values: JsonObject; + files: Array<{ path: string; content: string }>; +} + +interface DryRunResult extends ScaffolderDryRunResponse { + id: number; +} + +interface DryRun { + results: DryRunResult[]; + selectedResult: DryRunResult | undefined; + + selectResult(id: number): void; + deleteResult(id: number): void; + execute(options: DryRunOptions): Promise; +} + +const DryRunContext = createContext(undefined); + +interface DryRunProviderProps { + children: ReactNode; +} + +export function base64EncodeContent(content: string): string { + if (content.length > MAX_CONTENT_SIZE) { + return window.btoa(''); + } + + try { + return window.btoa(content); + } catch { + const decoder = new TextEncoder(); + const buffer = decoder.encode(content); + + const chunks = new Array(); + for (let offset = 0; offset < buffer.length; offset += CHUNK_SIZE) { + chunks.push( + String.fromCharCode(...buffer.slice(offset, offset + CHUNK_SIZE)), + ); + } + return window.btoa(chunks.join('')); + } +} + +export function DryRunProvider(props: DryRunProviderProps) { + const scaffolderApi = useApi(scaffolderApiRef); + + const [state, setState] = useState< + Pick + >({ + results: [], + selectedResult: undefined, + }); + const idRef = useRef(1); + + const selectResult = useCallback((id: number) => { + setState(prevState => { + const result = prevState.results.find(r => r.id === id); + if (result === prevState.selectedResult) { + return prevState; + } + return { + results: prevState.results, + selectedResult: result, + }; + }); + }, []); + + const deleteResult = useCallback((id: number) => { + setState(prevState => { + const index = prevState.results.findIndex(r => r.id === id); + if (index === -1) { + return prevState; + } + const newResults = prevState.results.slice(); + const [deleted] = newResults.splice(index, 1); + return { + results: newResults, + selectedResult: + prevState.selectedResult?.id === deleted.id + ? newResults[0] + : prevState.selectedResult, + }; + }); + }, []); + + const execute = useCallback( + async (options: DryRunOptions) => { + if (!scaffolderApi.dryRun) { + throw new Error('Scaffolder API does not support dry-run'); + } + + const parsed = yaml.parse(options.templateContent); + + const response = await scaffolderApi.dryRun({ + template: parsed, + values: options.values, + secrets: {}, + directoryContents: options.files.map(file => ({ + path: file.path, + base64Content: base64EncodeContent(file.content), + })), + }); + + const result = { + ...response, + id: idRef.current++, + }; + + setState(prevState => ({ + results: [...prevState.results, result], + selectedResult: prevState.selectedResult ?? result, + })); + }, + [scaffolderApi], + ); + + const dryRun = useMemo( + () => ({ + ...state, + selectResult, + deleteResult, + execute, + }), + [state, selectResult, deleteResult, execute], + ); + + return ( + + {props.children} + + ); +} + +export function useDryRun(): DryRun { + const value = useContext(DryRunContext); + if (!value) { + throw new Error('must be used within a DryRunProvider'); + } + return value; +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx new file mode 100644 index 0000000000..0267093ee6 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx @@ -0,0 +1,118 @@ +/* + * 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 { act, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React, { useEffect } from 'react'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; +import { DryRunProvider, useDryRun } from '../DryRunContext'; +import { DryRunResults } from './DryRunResults'; + +function DryRunRemote({ + execute, + remove, +}: { + execute?: boolean; + remove?: boolean; +}) { + const dryRun = useDryRun(); + + useEffect(() => { + if (execute) { + dryRun.execute({ + templateContent: '', + values: {}, + files: [], + }); + } + if (remove) { + if (dryRun.selectedResult) { + dryRun.deleteResult(dryRun.selectedResult.id); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [execute, remove]); + + return null; +} + +const mockScaffolderApi = { + dryRun: async () => ({ + directoryContents: [], + log: [], + output: {}, + steps: [], + }), +}; + +describe('DryRunResults', () => { + it('renders without exploding', async () => { + await renderInTestApp( + + + + + , + ); + expect(screen.getByText('Dry-run results')).toBeInTheDocument(); + }); + + it('expands when dry-run result is added and toggles on click, and disappears when results are gone', async () => { + const { rerender } = await renderInTestApp( + + + + + + , + ); + + expect(screen.getByText('Files')).not.toBeVisible(); + + await act(async () => { + rerender( + + + + + + , + ); + }); + + expect(screen.getByText('Files')).toBeVisible(); + + await userEvent.click(screen.getByText('Dry-run results')); + await waitFor(() => expect(screen.getByText('Files')).not.toBeVisible()); + + await userEvent.click(screen.getByText('Dry-run results')); + expect(screen.getByText('Files')).toBeVisible(); + + await act(async () => { + rerender( + + + + + + , + ); + }); + + await waitFor(() => expect(screen.getByText('Files')).not.toBeVisible()); + }); +}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx new file mode 100644 index 0000000000..ae9374438f --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx @@ -0,0 +1,91 @@ +/* + * 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 { BackstageTheme } from '@backstage/theme'; +import Accordion from '@material-ui/core/Accordion'; +import AccordionDetails from '@material-ui/core/AccordionDetails'; +import AccordionSummary from '@material-ui/core/AccordionSummary'; +import Divider from '@material-ui/core/Divider'; +import { makeStyles } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography'; +import ExpandMoreIcon from '@material-ui/icons/ExpandLess'; +import { usePrevious } from '@react-hookz/web'; +import React, { useEffect, useState } from 'react'; +import { useDryRun } from '../DryRunContext'; +import { DryRunResultsList } from './DryRunResultsList'; +import { DryRunResultsView } from './DryRunResultsView'; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + header: { + height: 48, + minHeight: 0, + '&.Mui-expanded': { + height: 48, + minHeight: 0, + }, + }, + content: { + display: 'grid', + background: theme.palette.background.default, + gridTemplateColumns: '180px auto 1fr', + gridTemplateRows: '1fr', + padding: 0, + height: 400, + }, +})); + +export function DryRunResults() { + const classes = useStyles(); + const dryRun = useDryRun(); + const [expanded, setExpanded] = useState(false); + const [hidden, setHidden] = useState(true); + + const resultsLength = dryRun.results.length; + const prevResultsLength = usePrevious(resultsLength); + useEffect(() => { + if (prevResultsLength === 0 && resultsLength === 1) { + setHidden(false); + setExpanded(true); + } else if (prevResultsLength === 1 && resultsLength === 0) { + setExpanded(false); + } + }, [prevResultsLength, resultsLength]); + + return ( + <> + + + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx new file mode 100644 index 0000000000..706f284db1 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx @@ -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 { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { act, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React, { useEffect } from 'react'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; +import { DryRunProvider, useDryRun } from '../DryRunContext'; +import { DryRunResultsList } from './DryRunResultsList'; + +function DryRunRemote({ execute }: { execute?: number }) { + const dryRun = useDryRun(); + + useEffect(() => { + if (execute) { + dryRun.execute({ + templateContent: '', + values: {}, + files: [], + }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [execute]); + + return null; +} + +const mockScaffolderApi = { + dryRun: async () => ({ + directoryContents: [], + log: [], + output: {}, + steps: [], + }), +}; + +describe('DryRunResultsList', () => { + it('renders without exploding', async () => { + const rendered = await renderInTestApp( + + + + + , + ); + expect(rendered.baseElement.querySelector('ul')).toBeEmptyDOMElement(); + }); + + it('adds new result items and deletes them', async () => { + const { rerender } = await renderInTestApp( + + + + + + , + ); + + expect(screen.getByText('Result 1')).toBeInTheDocument(); + expect(screen.queryByText('Result 2')).not.toBeInTheDocument(); + + await act(async () => { + rerender( + + + + + + , + ); + }); + + expect(screen.getByText('Result 1')).toBeInTheDocument(); + expect(screen.getByText('Result 2')).toBeInTheDocument(); + + await userEvent.click(screen.getAllByLabelText('delete')[0]); + + expect(screen.queryByText('Result 1')).not.toBeInTheDocument(); + expect(screen.getByText('Result 2')).toBeInTheDocument(); + }); +}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx new file mode 100644 index 0000000000..462c3b58fd --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx @@ -0,0 +1,83 @@ +/* + * 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 { BackstageTheme } from '@backstage/theme'; +import IconButton from '@material-ui/core/IconButton'; +import List from '@material-ui/core/List'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemIcon from '@material-ui/core/ListItemIcon'; +import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; +import ListItemText from '@material-ui/core/ListItemText'; +import { makeStyles } from '@material-ui/core/styles'; +import CancelIcon from '@material-ui/icons/Cancel'; +import CheckIcon from '@material-ui/icons/Check'; +import DeleteIcon from '@material-ui/icons/Delete'; +import React from 'react'; +import { useDryRun } from '../DryRunContext'; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + root: { + overflowY: 'auto', + background: theme.palette.background.default, + }, + iconSuccess: { + minWidth: 0, + marginRight: theme.spacing(1), + color: theme.palette.status.ok, + }, + iconFailure: { + minWidth: 0, + marginRight: theme.spacing(1), + color: theme.palette.status.error, + }, +})); + +export function DryRunResultsList() { + const classes = useStyles(); + const dryRun = useDryRun(); + + return ( + + {dryRun.results.map(result => { + const failed = result.log.some(l => l.body.status === 'failed'); + return ( + dryRun.selectResult(result.id)} + > + + {failed ? : } + + + + dryRun.deleteResult(result.id)} + > + + + + + ); + })} + + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx new file mode 100644 index 0000000000..b554a1c0c0 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx @@ -0,0 +1,55 @@ +/* + * 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 { makeStyles } from '@material-ui/core/styles'; +import Divider from '@material-ui/core/Divider'; +import React, { Children, ReactNode } from 'react'; +import classNames from 'classnames'; + +const useStyles = makeStyles(theme => ({ + root: { + display: 'grid', + gridTemplateColumns: '280px auto 3fr', + gridTemplateRows: '1fr', + }, + child: { + overflowY: 'auto', + height: '100%', + minHeight: 0, + }, + firstChild: { + background: theme.palette.background.paper, + }, +})); + +export function DryRunResultsSplitView(props: { children: ReactNode }) { + const classes = useStyles(); + const childArray = Children.toArray(props.children); + + if (childArray.length !== 2) { + throw new Error('must have exactly 2 children'); + } + + return ( +
    +
    + {childArray[0]} +
    + +
    {childArray[1]}
    +
    + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx new file mode 100644 index 0000000000..c2d8d3a2a4 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx @@ -0,0 +1,99 @@ +/* + * 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, TestApiProvider } from '@backstage/test-utils'; +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React, { ReactNode, useEffect } from 'react'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; +import { DryRunProvider, useDryRun } from '../DryRunContext'; +import { DryRunResultsView } from './DryRunResultsView'; + +// The inside needs mocking to render in jsdom +jest.mock('react-virtualized-auto-sizer', () => ({ + __esModule: true, + default: (props: { + children: (size: { width: number; height: number }) => ReactNode; + }) => <>{props.children({ width: 400, height: 200 })}, +})); + +function DryRunRemote() { + const dryRun = useDryRun(); + + useEffect(() => { + dryRun.execute({ + templateContent: '', + values: {}, + files: [], + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return null; +} + +describe('DryRunResultsView', () => { + it('renders a result', async () => { + await renderInTestApp( + ({ + directoryContents: [ + { + path: 'foo.txt', + base64Content: window.btoa('Foo Content'), + executable: false, + }, + ], + log: [{ body: { message: 'Foo Message', stepId: 'foo' } }], + output: { + links: [{ title: 'Foo Link', url: 'http://example.com' }], + }, + steps: [{ id: 'foo', action: 'foo', name: 'Foo' }], + }), + }, + ], + ]} + > + + + + + , + { + mountedRoutes: { + '/catalog/:kind/:namespace/:name': entityRouteRef, + }, + }, + ); + + expect(screen.getByText('foo.txt')).toBeInTheDocument(); + expect(screen.getByText('Foo Content')).toBeInTheDocument(); + + expect(screen.queryByText('Foo Message')).not.toBeInTheDocument(); + expect(screen.queryByText('Foo Link')).not.toBeInTheDocument(); + + await userEvent.click(screen.getByText('Log')); + expect(screen.getByText('Foo Message')).toBeInTheDocument(); + + await userEvent.click(screen.getByText('Output')); + expect(screen.getByText('Foo Link')).toBeInTheDocument(); + }); +}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx new file mode 100644 index 0000000000..852ec05a82 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx @@ -0,0 +1,195 @@ +/* + * 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 { LogViewer } from '@backstage/core-components'; +import { StreamLanguage } from '@codemirror/language'; +import { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml'; +import Box from '@material-ui/core/Box'; +import Divider from '@material-ui/core/Divider'; +import { makeStyles } from '@material-ui/core/styles'; +import Tab from '@material-ui/core/Tab'; +import Tabs from '@material-ui/core/Tabs'; +import CodeMirror from '@uiw/react-codemirror'; +import React, { useEffect, useMemo, useState } from 'react'; +import { FileBrowser } from '../../../components/FileBrowser'; +import { TaskStatusStepper } from '../../../components/TaskPage/TaskPage'; +import { TaskPageLinks } from '../../../components/TaskPage/TaskPageLinks'; +import { useDryRun } from '../DryRunContext'; +import { DryRunResultsSplitView } from './DryRunResultsSplitView'; + +const useStyles = makeStyles({ + root: { + display: 'flex', + flexFlow: 'column nowrap', + }, + contentWrapper: { + flex: 1, + position: 'relative', + }, + content: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + + display: 'flex', + '& > *': { + flex: 1, + }, + }, + codeMirror: { + height: '100%', + overflowY: 'auto', + }, +}); + +function FilesContent() { + const classes = useStyles(); + const { selectedResult } = useDryRun(); + const [selectedPath, setSelectedPath] = useState(''); + const selectedFile = selectedResult?.directoryContents.find( + f => f.path === selectedPath, + ); + + useEffect(() => { + if (selectedResult) { + const [firstFile] = selectedResult.directoryContents; + if (firstFile) { + setSelectedPath(firstFile.path); + } else { + setSelectedPath(''); + } + } + return undefined; + }, [selectedResult]); + + if (!selectedResult) { + return null; + } + return ( + + file.path)} + /> + + + ); +} +function LogContent() { + const { selectedResult } = useDryRun(); + const [currentStepId, setUserSelectedStepId] = useState(); + + const steps = useMemo(() => { + if (!selectedResult) { + return []; + } + return ( + selectedResult.steps.map(step => { + const stepLog = selectedResult.log.filter( + l => l.body.stepId === step.id, + ); + return { + id: step.id, + name: step.name, + logString: stepLog.map(l => l.body.message).join('\n'), + status: stepLog[stepLog.length - 1]?.body.status ?? 'completed', + }; + }) ?? [] + ); + }, [selectedResult]); + + if (!selectedResult) { + return null; + } + + const selectedStep = steps.find(s => s.id === currentStepId) ?? steps[0]; + + return ( + + + + + ); +} + +function OutputContent() { + const classes = useStyles(); + const { selectedResult } = useDryRun(); + + if (!selectedResult) { + return null; + } + + return ( + + + {selectedResult.output?.links?.length && ( + + )} + + + + ); +} + +export function DryRunResultsView() { + const classes = useStyles(); + const [selectedTab, setSelectedTab] = useState<'files' | 'log' | 'output'>( + 'files', + ); + + return ( +
    + setSelectedTab(v)}> + + + + + + +
    +
    + {selectedTab === 'files' && } + {selectedTab === 'log' && } + {selectedTab === 'output' && } +
    +
    +
    + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts new file mode 100644 index 0000000000..af8ef5214f --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/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 { DryRunResults } from './DryRunResults'; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx new file mode 100644 index 0000000000..c5556c3b06 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx @@ -0,0 +1,94 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { makeStyles } from '@material-ui/core'; +import React, { useState } from 'react'; +import type { + LayoutOptions, + NextFieldExtensionOptions, +} from '@backstage/plugin-scaffolder-react'; +import { TemplateDirectoryAccess } from '../../lib/filesystem'; +import { DirectoryEditorProvider } from './DirectoryEditorContext'; +import { DryRunProvider } from './DryRunContext'; +import { DryRunResults } from './DryRunResults'; +import { TemplateEditorBrowser } from './TemplateEditorBrowser'; +import { TemplateEditorForm } from './TemplateEditorForm'; +import { TemplateEditorTextArea } from './TemplateEditorTextArea'; + +const useStyles = makeStyles({ + // Reset and fix sizing to make sure scrolling behaves correctly + root: { + gridArea: 'pageContent', + + display: 'grid', + gridTemplateAreas: ` + "browser editor preview" + "results results results" + `, + gridTemplateColumns: '1fr 3fr 2fr', + gridTemplateRows: '1fr auto', + }, + browser: { + gridArea: 'browser', + overflow: 'auto', + }, + editor: { + gridArea: 'editor', + overflow: 'auto', + }, + preview: { + gridArea: 'preview', + overflow: 'auto', + }, + results: { + gridArea: 'results', + }, +}); + +export const TemplateEditor = (props: { + directory: TemplateDirectoryAccess; + fieldExtensions?: NextFieldExtensionOptions[]; + layouts?: LayoutOptions[]; + onClose?: () => void; +}) => { + const classes = useStyles(); + + const [errorText, setErrorText] = useState(); + + return ( + + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    + ); +}; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx new file mode 100644 index 0000000000..cec311a5cd --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx @@ -0,0 +1,55 @@ +/* + * 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 } from '@backstage/test-utils'; +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import { MockFileSystemAccess } from '../../lib/filesystem/MockFileSystemAccess'; +import { DirectoryEditorProvider } from './DirectoryEditorContext'; +import { TemplateEditorBrowser } from './TemplateEditorBrowser'; + +Blob.prototype.text = async function text() { + return new Promise(resolve => { + const reader = new FileReader(); + reader.onload = () => resolve(reader.result as string); + reader.readAsText(this); + }); +}; + +describe('TemplateEditorBrowser', () => { + it('should render files and expand dirs without exploding', async () => { + await renderInTestApp( + + + , + ); + + await expect(screen.findByText('foo.txt')).resolves.toBeInTheDocument(); + expect(screen.getByText('dir')).toBeInTheDocument(); + expect(screen.queryByText('bar.txt')).not.toBeInTheDocument(); + expect(screen.queryByText('baz.txt')).not.toBeInTheDocument(); + + await userEvent.click(screen.getByText('dir')); + expect(screen.getByText('bar.txt')).toBeInTheDocument(); + expect(screen.getByText('baz.txt')).toBeInTheDocument(); + }); +}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx new file mode 100644 index 0000000000..a668aa1868 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx @@ -0,0 +1,100 @@ +/* + * 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 { Divider, IconButton, makeStyles, Tooltip } from '@material-ui/core'; +import CloseIcon from '@material-ui/icons/Close'; +import RefreshIcon from '@material-ui/icons/Refresh'; +import SaveIcon from '@material-ui/icons/Save'; +import React from 'react'; +import { FileBrowser } from '../../components/FileBrowser'; + +import { useDirectoryEditor } from './DirectoryEditorContext'; + +const useStyles = makeStyles(theme => ({ + button: { + padding: theme.spacing(1), + }, + buttons: { + display: 'flex', + flexFlow: 'row nowrap', + alignItems: 'center', + justifyContent: 'flex-start', + }, + buttonsGap: { + flex: '1 1 auto', + }, + buttonsDivider: { + marginBottom: theme.spacing(1), + }, +})); + +/** The local file browser for the template editor */ +export function TemplateEditorBrowser(props: { onClose?: () => void }) { + const classes = useStyles(); + const directoryEditor = useDirectoryEditor(); + const changedFiles = directoryEditor.files.filter(file => file.dirty); + + const handleClose = () => { + if (!props.onClose) { + return; + } + if (changedFiles.length > 0) { + // eslint-disable-next-line no-alert + const accepted = window.confirm( + 'Are you sure? Unsaved changes will be lost', + ); + if (!accepted) { + return; + } + } + props.onClose(); + }; + + return ( + <> +
    + + !file.dirty)} + onClick={() => directoryEditor.save()} + > + + + + + directoryEditor.reload()} + > + + + +
    + + + + + +
    + + file.path)} + /> + + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx new file mode 100644 index 0000000000..0ac604c75d --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx @@ -0,0 +1,234 @@ +/* + * 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 { useApiHolder } from '@backstage/core-plugin-api'; +import { JsonObject, JsonValue } from '@backstage/types'; +import { makeStyles } from '@material-ui/core/styles'; +import React, { Component, ReactNode, useState } from 'react'; +import useDebounce from 'react-use/lib/useDebounce'; +import yaml from 'yaml'; +import { + LayoutOptions, + NextFieldExtensionOptions, + Stepper, + TemplateParameterSchema, +} from '@backstage/plugin-scaffolder-react'; + +import { useDirectoryEditor } from './DirectoryEditorContext'; +import { useDryRun } from './DryRunContext'; + +const useStyles = makeStyles({ + containerWrapper: { + position: 'relative', + width: '100%', + height: '100%', + }, + container: { + position: 'absolute', + top: 0, + bottom: 0, + left: 0, + right: 0, + overflow: 'auto', + }, +}); + +interface ErrorBoundaryProps { + invalidator: unknown; + setErrorText(errorText: string | undefined): void; + children: ReactNode; +} + +interface ErrorBoundaryState { + shouldRender: boolean; +} + +class ErrorBoundary extends Component { + state = { + shouldRender: true, + }; + + componentDidUpdate(prevProps: { invalidator: unknown }) { + if (prevProps.invalidator !== this.props.invalidator) { + this.setState({ shouldRender: true }); + } + } + + componentDidCatch(error: Error) { + this.props.setErrorText(error.message); + this.setState({ shouldRender: false }); + } + + render() { + return this.state.shouldRender ? this.props.children : null; + } +} + +interface TemplateEditorFormProps { + content?: string; + /** Setting this to true will cause the content to be parsed as if it is the template entity spec */ + contentIsSpec?: boolean; + setErrorText: (errorText?: string) => void; + onDryRun?: (data: JsonObject) => Promise; + fieldExtensions?: NextFieldExtensionOptions[]; + layouts?: LayoutOptions[]; +} + +function isJsonObject(value: JsonValue | undefined): value is JsonObject { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +/** Shows the a template form that is parsed from the provided content */ +export function TemplateEditorForm(props: TemplateEditorFormProps) { + const { + content, + contentIsSpec, + onDryRun, + setErrorText, + fieldExtensions = [], + layouts = [], + } = props; + const classes = useStyles(); + const apiHolder = useApiHolder(); + + const [steps, setSteps] = useState(); + + useDebounce( + () => { + try { + if (!content) { + setSteps(undefined); + return; + } + const parsed: JsonValue = yaml.parse(content); + + if (!isJsonObject(parsed)) { + setSteps(undefined); + return; + } + + let rootObj = parsed; + if (!contentIsSpec) { + const isTemplate = + String(parsed.kind).toLocaleLowerCase('en-US') === 'template'; + if (!isTemplate) { + setSteps(undefined); + return; + } + + rootObj = isJsonObject(parsed.spec) ? parsed.spec : {}; + } + + const { parameters } = rootObj; + + if (!Array.isArray(parameters)) { + setErrorText('Template parameters must be an array'); + setSteps(undefined); + return; + } + + setErrorText(); + setSteps( + parameters.flatMap(param => + isJsonObject(param) + ? [ + { + title: String(param.title), + schema: param, + }, + ] + : [], + ), + ); + } catch (e) { + setErrorText(e.message); + } + }, + 250, + [contentIsSpec, content, apiHolder], + ); + + if (!steps) { + return null; + } + + return ( +
    +
    + + { + await onDryRun?.(data); + }} + layouts={layouts} + components={{ createButtonText: onDryRun && 'Try It' }} + /> + +
    +
    + ); +} + +/** A version of the TemplateEditorForm that is connected to the DirectoryEditor and DryRun contexts */ +export function TemplateEditorFormDirectoryEditorDryRun( + props: Pick< + TemplateEditorFormProps, + 'setErrorText' | 'fieldExtensions' | 'layouts' + >, +) { + const { setErrorText, fieldExtensions = [], layouts } = props; + const dryRun = useDryRun(); + + const directoryEditor = useDirectoryEditor(); + const { selectedFile } = directoryEditor; + + const handleDryRun = async (values: JsonObject) => { + if (!selectedFile) { + return; + } + + try { + await dryRun.execute({ + templateContent: selectedFile.content, + values, + files: directoryEditor.files, + }); + setErrorText(); + } catch (e) { + setErrorText(String(e.cause || e)); + throw e; + } + }; + + const content = + selectedFile && selectedFile.path.match(/\.ya?ml$/) + ? selectedFile.content + : undefined; + + return ( + + ); +} + +TemplateEditorForm.DirectoryEditorDryRun = + TemplateEditorFormDirectoryEditorDryRun; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx new file mode 100644 index 0000000000..61e6c46964 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx @@ -0,0 +1,144 @@ +/* + * 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 Card from '@material-ui/core/Card'; +import CardActionArea from '@material-ui/core/CardActionArea'; +import CardContent from '@material-ui/core/CardContent'; +import Tooltip from '@material-ui/core/Tooltip'; +import Typography from '@material-ui/core/Typography'; +import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined'; +import { makeStyles } from '@material-ui/core/styles'; +import { WebFileSystemAccess } from '../../lib/filesystem'; + +const useStyles = makeStyles(theme => ({ + introText: { + textAlign: 'center', + marginTop: theme.spacing(2), + }, + card: { + position: 'relative', + maxWidth: 340, + marginTop: theme.spacing(4), + margin: theme.spacing(0, 2), + }, + infoIcon: { + position: 'absolute', + top: theme.spacing(1), + right: theme.spacing(1), + }, +})); + +interface EditorIntroProps { + style?: JSX.IntrinsicElements['div']['style']; + onSelect?: (option: 'local' | 'form' | 'field-explorer') => void; +} + +export function TemplateEditorIntro(props: EditorIntroProps) { + const classes = useStyles(); + const supportsLoad = WebFileSystemAccess.isSupported(); + + const cardLoadLocal = ( + + props.onSelect?.('local')} + > + + + Load Template Directory + + + Load a local template directory, allowing you to both edit and try + executing your own template. + + + + {!supportsLoad && ( +
    + + + +
    + )} +
    + ); + + const cardFormEditor = ( + + props.onSelect?.('form')}> + + + Edit Template Form + + + Preview and edit a template form, either using a sample template or + by loading a template from the catalog. + + + + + ); + + const cardFieldExplorer = ( + + props.onSelect?.('field-explorer')}> + + + Custom Field Explorer + + + View and play around with available installed custom field + extensions. + + + + + ); + + return ( +
    + + Get started by choosing one of the options below + +
    + {supportsLoad && cardLoadLocal} + {cardFormEditor} + {!supportsLoad && cardLoadLocal} + {cardFieldExplorer} +
    +
    + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx new file mode 100644 index 0000000000..bf9cd8c464 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.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 { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import { TemplateEditorPage } from './TemplateEditorPage'; + +describe('TemplateEditorPage', () => { + it('renders without exploding', async () => { + await renderInTestApp(); + + expect(screen.getByText('Load Template Directory')).toBeInTheDocument(); + expect(screen.getByText('Edit Template Form')).toBeInTheDocument(); + }); + + it('template directory loading should not be supported in Jest', async () => { + await renderInTestApp(); + + expect( + screen.getByRole('button', { name: /Load Template Directory/ }), + ).toBeDisabled(); + }); + + it('should be able to continue to form preview', async () => { + await renderInTestApp( + + + , + ); + + await userEvent.click(screen.getByText('Edit Template Form')); + + expect(screen.getByLabelText('Load Existing Template')).toBeInTheDocument(); + }); +}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx new file mode 100644 index 0000000000..03e1619bc8 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx @@ -0,0 +1,107 @@ +/* + * 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, { useState } from 'react'; +import { Content, Header, Page } from '@backstage/core-components'; +import { + TemplateDirectoryAccess, + WebFileSystemAccess, +} from '../../lib/filesystem'; +import { CustomFieldExplorer } from './CustomFieldExplorer'; +import { TemplateEditorIntro } from './TemplateEditorIntro'; +import { TemplateEditor } from './TemplateEditor'; +import { TemplateFormPreviewer } from './TemplateFormPreviewer'; +import { + NextFieldExtensionOptions, + type LayoutOptions, +} from '@backstage/plugin-scaffolder-react'; + +type Selection = + | { + type: 'local'; + directory: TemplateDirectoryAccess; + } + | { + type: 'form'; + } + | { + type: 'field-explorer'; + }; + +interface TemplateEditorPageProps { + defaultPreviewTemplate?: string; + customFieldExtensions?: NextFieldExtensionOptions[]; + layouts?: LayoutOptions[]; +} + +export function TemplateEditorPage(props: TemplateEditorPageProps) { + const [selection, setSelection] = useState(); + + let content: JSX.Element | null = null; + if (selection?.type === 'local') { + content = ( + setSelection(undefined)} + layouts={props.layouts} + /> + ); + } else if (selection?.type === 'form') { + content = ( + setSelection(undefined)} + layouts={props.layouts} + /> + ); + } else if (selection?.type === 'field-explorer') { + content = ( + setSelection(undefined)} + /> + ); + } else { + content = ( + + { + if (option === 'local') { + WebFileSystemAccess.requestDirectoryAccess() + .then(directory => setSelection({ type: 'local', directory })) + .catch(() => {}); + } else if (option === 'form') { + setSelection({ type: 'form' }); + } else if (option === 'field-explorer') { + setSelection({ type: 'field-explorer' }); + } + }} + /> + + ); + } + + return ( + +
    + {content} + + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx new file mode 100644 index 0000000000..588b0cd4ba --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx @@ -0,0 +1,153 @@ +/* + * 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 { StreamLanguage } from '@codemirror/language'; +import { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml'; +import { showPanel } from '@codemirror/view'; +import { IconButton, makeStyles, Paper, Tooltip } from '@material-ui/core'; +import RefreshIcon from '@material-ui/icons/Refresh'; +import SaveIcon from '@material-ui/icons/Save'; +import { useKeyboardEvent } from '@react-hookz/web'; +import CodeMirror from '@uiw/react-codemirror'; +import React, { useMemo } from 'react'; +import { useDirectoryEditor } from './DirectoryEditorContext'; + +const useStyles = makeStyles(theme => ({ + container: { + position: 'relative', + width: '100%', + height: '100%', + }, + codeMirror: { + position: 'absolute', + top: 0, + bottom: 0, + left: 0, + right: 0, + }, + errorPanel: { + color: theme.palette.error.main, + lineHeight: 2, + margin: theme.spacing(0, 1), + }, + floatingButtons: { + position: 'absolute', + top: theme.spacing(1), + right: theme.spacing(3), + }, + floatingButton: { + padding: theme.spacing(1), + }, +})); + +/** A wrapper around CodeMirror with an error panel and extra actions available */ +export function TemplateEditorTextArea(props: { + content?: string; + onUpdate?: (content: string) => void; + errorText?: string; + onSave?: () => void; + onReload?: () => void; +}) { + const { errorText } = props; + const classes = useStyles(); + + const panelExtension = useMemo(() => { + if (!errorText) { + return showPanel.of(null); + } + + const dom = document.createElement('div'); + dom.classList.add(classes.errorPanel); + dom.textContent = errorText; + return showPanel.of(() => ({ dom, bottom: true })); + }, [classes, errorText]); + + useKeyboardEvent( + e => e.key === 's' && (e.ctrlKey || e.metaKey), + e => { + e.preventDefault(); + if (props.onSave) { + props.onSave(); + } + }, + ); + + return ( +
    + + {(props.onSave || props.onReload) && ( +
    + + {props.onSave && ( + + props.onSave?.()} + > + + + + )} + {props.onReload && ( + + props.onReload?.()} + > + + + + )} + +
    + )} +
    + ); +} + +/** A version of the TemplateEditorTextArea that is connected to the DirectoryEditor context */ +export function TemplateEditorDirectoryEditorTextArea(props: { + errorText?: string; +}) { + const directoryEditor = useDirectoryEditor(); + + const actions = directoryEditor.selectedFile?.dirty + ? { + onSave: () => directoryEditor.save(), + onReload: () => directoryEditor.reload(), + } + : { + onReload: () => directoryEditor.reload(), + }; + + return ( + directoryEditor.selectedFile?.updateContent(content)} + {...actions} + /> + ); +} + +TemplateEditorTextArea.DirectoryEditor = TemplateEditorDirectoryEditorTextArea; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx new file mode 100644 index 0000000000..c5f84a4b66 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -0,0 +1,219 @@ +/* + * 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 { alertApiRef, useApi } from '@backstage/core-plugin-api'; +import { + catalogApiRef, + humanizeEntityRef, +} from '@backstage/plugin-catalog-react'; +import { + FormControl, + IconButton, + InputLabel, + LinearProgress, + makeStyles, + MenuItem, + Select, +} from '@material-ui/core'; +import CloseIcon from '@material-ui/icons/Close'; +import React, { useCallback, useState } from 'react'; +import useAsync from 'react-use/lib/useAsync'; +import yaml from 'yaml'; +import { + NextFieldExtensionOptions, + type LayoutOptions, +} from '@backstage/plugin-scaffolder-react'; +import { TemplateEditorForm } from './TemplateEditorForm'; +import { TemplateEditorTextArea } from './TemplateEditorTextArea'; + +const EXAMPLE_TEMPLATE_PARAMS_YAML = `# Edit the template parameters below to see how they will render in the scaffolder form UI +parameters: + - title: Fill in some steps + required: + - name + properties: + name: + title: Name + type: string + description: Unique name of the component + owner: + title: Owner + type: string + description: Owner of the component + ui:field: OwnerPicker + ui:options: + catalogFilter: + kind: Group + - title: Choose a location + required: + - repoUrl + properties: + repoUrl: + title: Repository Location + type: string + ui:field: RepoUrlPicker + ui:options: + allowedHosts: + - github.com +steps: + - id: fetch-base + name: Fetch Base + action: fetch:template + input: + url: ./template + values: + name: \${{parameters.name}} +`; + +type TemplateOption = { + label: string; + value: Entity; +}; + +const useStyles = makeStyles(theme => ({ + root: { + gridArea: 'pageContent', + display: 'grid', + gridTemplateAreas: ` + "controls controls" + "textArea preview" + `, + gridTemplateRows: 'auto 1fr', + gridTemplateColumns: '1fr 1fr', + }, + controls: { + gridArea: 'controls', + display: 'flex', + flexFlow: 'row nowrap', + alignItems: 'center', + margin: theme.spacing(1), + }, + textArea: { + gridArea: 'textArea', + }, + preview: { + gridArea: 'preview', + }, +})); + +export const TemplateFormPreviewer = ({ + defaultPreviewTemplate = EXAMPLE_TEMPLATE_PARAMS_YAML, + customFieldExtensions = [], + onClose, + layouts = [], +}: { + defaultPreviewTemplate?: string; + customFieldExtensions?: NextFieldExtensionOptions[]; + onClose?: () => void; + layouts?: LayoutOptions[]; +}) => { + const classes = useStyles(); + const alertApi = useApi(alertApiRef); + const catalogApi = useApi(catalogApiRef); + const [selectedTemplate, setSelectedTemplate] = useState(''); + const [errorText, setErrorText] = useState(); + const [templateOptions, setTemplateOptions] = useState([]); + const [templateYaml, setTemplateYaml] = useState(defaultPreviewTemplate); + + const { loading } = useAsync( + () => + catalogApi + .getEntities({ + filter: { kind: 'template' }, + fields: [ + 'kind', + 'metadata.namespace', + 'metadata.name', + 'metadata.title', + 'spec.parameters', + 'spec.steps', + 'spec.output', + ], + }) + .then(({ items }) => + setTemplateOptions( + items.map(template => ({ + label: + template.metadata.title ?? + humanizeEntityRef(template, { defaultKind: 'template' }), + value: template, + })), + ), + ) + .catch(e => + alertApi.post({ + message: `Error loading exisiting templates: ${e.message}`, + severity: 'error', + }), + ), + [catalogApi], + ); + + const handleSelectChange = useCallback( + selected => { + setSelectedTemplate(selected); + setTemplateYaml(yaml.stringify(selected.spec)); + }, + [setTemplateYaml], + ); + + return ( + <> + {loading && } +
    +
    + + + Load Existing Template + + + + + + + +
    +
    + +
    +
    + +
    +
    + + ); +}; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/index.ts b/plugins/scaffolder/src/next/TemplateEditorPage/index.ts new file mode 100644 index 0000000000..7ec6bddb64 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/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 { TemplateEditorPage } from './TemplateEditorPage'; diff --git a/yarn.lock b/yarn.lock index 1621cdc5b1..24c2ea1f70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7589,6 +7589,7 @@ __metadata: "@rjsf/core": ^3.2.1 "@rjsf/material-ui": ^3.2.1 "@rjsf/utils": 5.1.0 + "@rjsf/validator-ajv8": 5.1.0 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 From a5213796886dd87616cd9e584021d2efaca3e0e8 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 14:41:26 +0100 Subject: [PATCH 377/423] chore: added changeset Signed-off-by: blam --- .changeset/honest-timers-pull.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/honest-timers-pull.md diff --git a/.changeset/honest-timers-pull.md b/.changeset/honest-timers-pull.md new file mode 100644 index 0000000000..d11d260a22 --- /dev/null +++ b/.changeset/honest-timers-pull.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder-react': minor +'@backstage/plugin-scaffolder': minor +--- + +Migrating the `TemplateEditorPage` to work with the new components from `@backstage/plugin-scaffolder-react` From 73981f9407db1985536bac01da29b0e870a93548 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 15:42:47 +0100 Subject: [PATCH 378/423] chore: removed some unneeded code, just use the one that exists Signed-off-by: blam --- .../DirectoryEditorContext.tsx | 243 ------------------ .../TemplateEditorPage/DryRunContext.test.tsx | 44 ---- .../next/TemplateEditorPage/DryRunContext.tsx | 179 ------------- .../DryRunResults/DryRunResults.test.tsx | 118 --------- .../DryRunResults/DryRunResults.tsx | 91 ------- .../DryRunResults/DryRunResultsList.test.tsx | 95 ------- .../DryRunResults/DryRunResultsList.tsx | 83 ------ .../DryRunResults/DryRunResultsSplitView.tsx | 55 ---- .../DryRunResults/DryRunResultsView.test.tsx | 99 ------- .../DryRunResults/DryRunResultsView.tsx | 195 -------------- .../TemplateEditorPage/DryRunResults/index.ts | 17 -- .../TemplateEditorPage/TemplateEditor.tsx | 10 +- .../TemplateEditorBrowser.test.tsx | 55 ---- .../TemplateEditorBrowser.tsx | 100 ------- .../TemplateEditorPage/TemplateEditorForm.tsx | 5 +- .../TemplateEditorPage.test.tsx | 58 ----- .../TemplateEditorTextArea.tsx | 153 ----------- .../TemplateFormPreviewer.tsx | 2 +- 18 files changed, 8 insertions(+), 1594 deletions(-) delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx deleted file mode 100644 index 0edf390bfe..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx +++ /dev/null @@ -1,243 +0,0 @@ -/* - * 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 { ErrorPanel, Progress } from '@backstage/core-components'; -import { useAsync, useRerender } from '@react-hookz/web'; -import React, { createContext, ReactNode, useContext, useEffect } from 'react'; -import { - TemplateDirectoryAccess, - TemplateFileAccess, -} from '../../lib/filesystem'; - -const MAX_SIZE = 1024 * 1024; -const MAX_SIZE_MESSAGE = 'This file is too large to be displayed'; - -interface DirectoryEditorFile { - /** The path of the file relative to the root directory */ - path: string; - /** The staged content of the file */ - content: string; - /** Whether the staged content matches what is on disk */ - dirty: boolean; - - /** Update the staged content of the file without saving */ - updateContent(content: string): void; - /** Save the staged content of the file to disk */ - save(): Promise; - /** Reload the staged content of the file from disk */ - reload(): Promise; -} - -interface DirectoryEditor { - /** A list of all files in the edited directory */ - files: Array; - - /** The currently selected file */ - selectedFile: DirectoryEditorFile | undefined; - /** Switch the selected file */ - setSelectedFile(path: string | undefined): void; - - /** Save all files to disk */ - save(): Promise; - /** Reload all files from disk */ - reload(): Promise; - - subscribe(listener: () => void): () => void; -} - -class DirectoryEditorFileManager implements DirectoryEditorFile { - readonly #access: TemplateFileAccess; - readonly #signalUpdate: () => void; - - #content?: string; - #savedContent?: string; - - constructor(access: TemplateFileAccess, signalUpdate: () => void) { - this.#access = access; - this.#signalUpdate = signalUpdate; - } - - get path() { - return this.#access.path; - } - - get content() { - return this.#content ?? MAX_SIZE_MESSAGE; - } - - updateContent(content: string): void { - if (this.#content === undefined) { - return; - } - this.#content = content; - this.#signalUpdate(); - } - - get dirty() { - return this.#content !== this.#savedContent; - } - - async save(): Promise { - if (this.#content !== undefined) { - await this.#access.save(this.#content); - this.#savedContent = this.#content; - this.#signalUpdate(); - } - } - - async reload(): Promise { - const file = await this.#access.file(); - if (file.size > MAX_SIZE) { - if (this.#content !== undefined) { - this.#content = undefined; - this.#savedContent = undefined; - this.#signalUpdate(); - } - return; - } - - const content = await file.text(); - if (this.#content !== content) { - this.#content = content; - this.#savedContent = content; - this.#signalUpdate(); - } - } -} - -class DirectoryEditorManager implements DirectoryEditor { - readonly #access: TemplateDirectoryAccess; - readonly #listeners = new Set<() => void>(); - - #files: DirectoryEditorFile[] = []; - #selectedFile: DirectoryEditorFile | undefined; - - constructor(access: TemplateDirectoryAccess) { - this.#access = access; - } - - get files() { - return this.#files; - } - - get selectedFile() { - return this.#selectedFile; - } - - setSelectedFile = (path: string | undefined): void => { - const prev = this.#selectedFile; - const next = this.#files.find(file => file.path === path); - if (prev !== next) { - this.#selectedFile = next; - this.#signalUpdate(); - } - }; - - get dirty() { - return this.#files.some(file => file.dirty); - } - - async save(): Promise { - await Promise.all(this.#files.map(file => file.save())); - } - - async reload(): Promise { - const selectedPath = this.#selectedFile?.path; - - const files = await this.#access.listFiles(); - const fileManagers = await Promise.all( - files.map(async file => { - const manager = new DirectoryEditorFileManager( - file, - this.#signalUpdate, - ); - await manager.reload(); - return manager; - }), - ); - this.#files.length = 0; - this.#files.push(...fileManagers); - - this.setSelectedFile(selectedPath); - this.#signalUpdate(); - } - - subscribe(listener: () => void): () => void { - this.#listeners.add(listener); - return () => { - this.#listeners.delete(listener); - }; - } - - #signalUpdate = () => { - this.#listeners.forEach(listener => listener()); - }; -} - -const DirectoryEditorContext = createContext( - undefined, -); - -export function useDirectoryEditor(): DirectoryEditor { - const value = useContext(DirectoryEditorContext); - const rerender = useRerender(); - - useEffect(() => value?.subscribe(rerender), [value, rerender]); - - if (!value) { - throw new Error('must be used within a DirectoryEditorProvider'); - } - return value; -} - -interface DirectoryEditorProviderProps { - directory: TemplateDirectoryAccess; - children?: ReactNode; -} - -export function DirectoryEditorProvider(props: DirectoryEditorProviderProps) { - const { directory } = props; - - const [{ result, error }, { execute }] = useAsync( - async (dir: TemplateDirectoryAccess) => { - const manager = new DirectoryEditorManager(dir); - await manager.reload(); - - const firstYaml = manager.files.find(file => file.path.match(/\.ya?ml$/)); - if (firstYaml) { - manager.setSelectedFile(firstYaml.path); - } - - return manager; - }, - ); - - useEffect(() => { - execute(directory); - }, [execute, directory]); - - if (error) { - return ; - } else if (!result) { - return ; - } - - return ( - - {props.children} - - ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx deleted file mode 100644 index 36a62f1b8a..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 { base64EncodeContent } from './DryRunContext'; - -// eslint-disable-next-line no-restricted-imports -import { TextEncoder } from 'util'; - -window.TextEncoder = TextEncoder; - -describe('base64EncodeContent', () => { - it('encodes text files', () => { - expect(base64EncodeContent('abc')).toBe('YWJj'); - expect(base64EncodeContent('abc'.repeat(1000000))).toBe( - window.btoa(''), - ); - }); - - it('encodes binary files', () => { - expect(base64EncodeContent('\x00\x01\x02')).toBe('AAEC'); - expect(base64EncodeContent('😅')).toBe('8J+YhQ=='); - // Triggers chunking - expect(base64EncodeContent('😅'.repeat(18000))).toBe( - '8J+YhfCfmIXwn5iF8J+YhfCfmIXwn5iF'.repeat(3000), - ); - // Triggers size check - expect(base64EncodeContent('😅'.repeat(1000000))).toBe( - window.btoa(''), - ); - }); -}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx deleted file mode 100644 index a617eebe1e..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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 yaml from 'yaml'; -import { useApi } from '@backstage/core-plugin-api'; -import { JsonObject } from '@backstage/types'; -import React, { - createContext, - ReactNode, - useCallback, - useContext, - useMemo, - useRef, - useState, -} from 'react'; -import { - scaffolderApiRef, - ScaffolderDryRunResponse, -} from '@backstage/plugin-scaffolder-react'; - -const MAX_CONTENT_SIZE = 64 * 1024; -const CHUNK_SIZE = 32 * 1024; - -interface DryRunOptions { - templateContent: string; - values: JsonObject; - files: Array<{ path: string; content: string }>; -} - -interface DryRunResult extends ScaffolderDryRunResponse { - id: number; -} - -interface DryRun { - results: DryRunResult[]; - selectedResult: DryRunResult | undefined; - - selectResult(id: number): void; - deleteResult(id: number): void; - execute(options: DryRunOptions): Promise; -} - -const DryRunContext = createContext(undefined); - -interface DryRunProviderProps { - children: ReactNode; -} - -export function base64EncodeContent(content: string): string { - if (content.length > MAX_CONTENT_SIZE) { - return window.btoa(''); - } - - try { - return window.btoa(content); - } catch { - const decoder = new TextEncoder(); - const buffer = decoder.encode(content); - - const chunks = new Array(); - for (let offset = 0; offset < buffer.length; offset += CHUNK_SIZE) { - chunks.push( - String.fromCharCode(...buffer.slice(offset, offset + CHUNK_SIZE)), - ); - } - return window.btoa(chunks.join('')); - } -} - -export function DryRunProvider(props: DryRunProviderProps) { - const scaffolderApi = useApi(scaffolderApiRef); - - const [state, setState] = useState< - Pick - >({ - results: [], - selectedResult: undefined, - }); - const idRef = useRef(1); - - const selectResult = useCallback((id: number) => { - setState(prevState => { - const result = prevState.results.find(r => r.id === id); - if (result === prevState.selectedResult) { - return prevState; - } - return { - results: prevState.results, - selectedResult: result, - }; - }); - }, []); - - const deleteResult = useCallback((id: number) => { - setState(prevState => { - const index = prevState.results.findIndex(r => r.id === id); - if (index === -1) { - return prevState; - } - const newResults = prevState.results.slice(); - const [deleted] = newResults.splice(index, 1); - return { - results: newResults, - selectedResult: - prevState.selectedResult?.id === deleted.id - ? newResults[0] - : prevState.selectedResult, - }; - }); - }, []); - - const execute = useCallback( - async (options: DryRunOptions) => { - if (!scaffolderApi.dryRun) { - throw new Error('Scaffolder API does not support dry-run'); - } - - const parsed = yaml.parse(options.templateContent); - - const response = await scaffolderApi.dryRun({ - template: parsed, - values: options.values, - secrets: {}, - directoryContents: options.files.map(file => ({ - path: file.path, - base64Content: base64EncodeContent(file.content), - })), - }); - - const result = { - ...response, - id: idRef.current++, - }; - - setState(prevState => ({ - results: [...prevState.results, result], - selectedResult: prevState.selectedResult ?? result, - })); - }, - [scaffolderApi], - ); - - const dryRun = useMemo( - () => ({ - ...state, - selectResult, - deleteResult, - execute, - }), - [state, selectResult, deleteResult, execute], - ); - - return ( - - {props.children} - - ); -} - -export function useDryRun(): DryRun { - const value = useContext(DryRunContext); - if (!value) { - throw new Error('must be used within a DryRunProvider'); - } - return value; -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx deleted file mode 100644 index 0267093ee6..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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 { act, screen, waitFor } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React, { useEffect } from 'react'; -import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; -import { DryRunProvider, useDryRun } from '../DryRunContext'; -import { DryRunResults } from './DryRunResults'; - -function DryRunRemote({ - execute, - remove, -}: { - execute?: boolean; - remove?: boolean; -}) { - const dryRun = useDryRun(); - - useEffect(() => { - if (execute) { - dryRun.execute({ - templateContent: '', - values: {}, - files: [], - }); - } - if (remove) { - if (dryRun.selectedResult) { - dryRun.deleteResult(dryRun.selectedResult.id); - } - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [execute, remove]); - - return null; -} - -const mockScaffolderApi = { - dryRun: async () => ({ - directoryContents: [], - log: [], - output: {}, - steps: [], - }), -}; - -describe('DryRunResults', () => { - it('renders without exploding', async () => { - await renderInTestApp( - - - - - , - ); - expect(screen.getByText('Dry-run results')).toBeInTheDocument(); - }); - - it('expands when dry-run result is added and toggles on click, and disappears when results are gone', async () => { - const { rerender } = await renderInTestApp( - - - - - - , - ); - - expect(screen.getByText('Files')).not.toBeVisible(); - - await act(async () => { - rerender( - - - - - - , - ); - }); - - expect(screen.getByText('Files')).toBeVisible(); - - await userEvent.click(screen.getByText('Dry-run results')); - await waitFor(() => expect(screen.getByText('Files')).not.toBeVisible()); - - await userEvent.click(screen.getByText('Dry-run results')); - expect(screen.getByText('Files')).toBeVisible(); - - await act(async () => { - rerender( - - - - - - , - ); - }); - - await waitFor(() => expect(screen.getByText('Files')).not.toBeVisible()); - }); -}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx deleted file mode 100644 index ae9374438f..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 { BackstageTheme } from '@backstage/theme'; -import Accordion from '@material-ui/core/Accordion'; -import AccordionDetails from '@material-ui/core/AccordionDetails'; -import AccordionSummary from '@material-ui/core/AccordionSummary'; -import Divider from '@material-ui/core/Divider'; -import { makeStyles } from '@material-ui/core/styles'; -import Typography from '@material-ui/core/Typography'; -import ExpandMoreIcon from '@material-ui/icons/ExpandLess'; -import { usePrevious } from '@react-hookz/web'; -import React, { useEffect, useState } from 'react'; -import { useDryRun } from '../DryRunContext'; -import { DryRunResultsList } from './DryRunResultsList'; -import { DryRunResultsView } from './DryRunResultsView'; - -const useStyles = makeStyles((theme: BackstageTheme) => ({ - header: { - height: 48, - minHeight: 0, - '&.Mui-expanded': { - height: 48, - minHeight: 0, - }, - }, - content: { - display: 'grid', - background: theme.palette.background.default, - gridTemplateColumns: '180px auto 1fr', - gridTemplateRows: '1fr', - padding: 0, - height: 400, - }, -})); - -export function DryRunResults() { - const classes = useStyles(); - const dryRun = useDryRun(); - const [expanded, setExpanded] = useState(false); - const [hidden, setHidden] = useState(true); - - const resultsLength = dryRun.results.length; - const prevResultsLength = usePrevious(resultsLength); - useEffect(() => { - if (prevResultsLength === 0 && resultsLength === 1) { - setHidden(false); - setExpanded(true); - } else if (prevResultsLength === 1 && resultsLength === 0) { - setExpanded(false); - } - }, [prevResultsLength, resultsLength]); - - return ( - <> - - - ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx deleted file mode 100644 index 706f284db1..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 { act, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React, { useEffect } from 'react'; -import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; -import { DryRunProvider, useDryRun } from '../DryRunContext'; -import { DryRunResultsList } from './DryRunResultsList'; - -function DryRunRemote({ execute }: { execute?: number }) { - const dryRun = useDryRun(); - - useEffect(() => { - if (execute) { - dryRun.execute({ - templateContent: '', - values: {}, - files: [], - }); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [execute]); - - return null; -} - -const mockScaffolderApi = { - dryRun: async () => ({ - directoryContents: [], - log: [], - output: {}, - steps: [], - }), -}; - -describe('DryRunResultsList', () => { - it('renders without exploding', async () => { - const rendered = await renderInTestApp( - - - - - , - ); - expect(rendered.baseElement.querySelector('ul')).toBeEmptyDOMElement(); - }); - - it('adds new result items and deletes them', async () => { - const { rerender } = await renderInTestApp( - - - - - - , - ); - - expect(screen.getByText('Result 1')).toBeInTheDocument(); - expect(screen.queryByText('Result 2')).not.toBeInTheDocument(); - - await act(async () => { - rerender( - - - - - - , - ); - }); - - expect(screen.getByText('Result 1')).toBeInTheDocument(); - expect(screen.getByText('Result 2')).toBeInTheDocument(); - - await userEvent.click(screen.getAllByLabelText('delete')[0]); - - expect(screen.queryByText('Result 1')).not.toBeInTheDocument(); - expect(screen.getByText('Result 2')).toBeInTheDocument(); - }); -}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx deleted file mode 100644 index 462c3b58fd..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 { BackstageTheme } from '@backstage/theme'; -import IconButton from '@material-ui/core/IconButton'; -import List from '@material-ui/core/List'; -import ListItem from '@material-ui/core/ListItem'; -import ListItemIcon from '@material-ui/core/ListItemIcon'; -import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; -import ListItemText from '@material-ui/core/ListItemText'; -import { makeStyles } from '@material-ui/core/styles'; -import CancelIcon from '@material-ui/icons/Cancel'; -import CheckIcon from '@material-ui/icons/Check'; -import DeleteIcon from '@material-ui/icons/Delete'; -import React from 'react'; -import { useDryRun } from '../DryRunContext'; - -const useStyles = makeStyles((theme: BackstageTheme) => ({ - root: { - overflowY: 'auto', - background: theme.palette.background.default, - }, - iconSuccess: { - minWidth: 0, - marginRight: theme.spacing(1), - color: theme.palette.status.ok, - }, - iconFailure: { - minWidth: 0, - marginRight: theme.spacing(1), - color: theme.palette.status.error, - }, -})); - -export function DryRunResultsList() { - const classes = useStyles(); - const dryRun = useDryRun(); - - return ( - - {dryRun.results.map(result => { - const failed = result.log.some(l => l.body.status === 'failed'); - return ( - dryRun.selectResult(result.id)} - > - - {failed ? : } - - - - dryRun.deleteResult(result.id)} - > - - - - - ); - })} - - ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx deleted file mode 100644 index b554a1c0c0..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 { makeStyles } from '@material-ui/core/styles'; -import Divider from '@material-ui/core/Divider'; -import React, { Children, ReactNode } from 'react'; -import classNames from 'classnames'; - -const useStyles = makeStyles(theme => ({ - root: { - display: 'grid', - gridTemplateColumns: '280px auto 3fr', - gridTemplateRows: '1fr', - }, - child: { - overflowY: 'auto', - height: '100%', - minHeight: 0, - }, - firstChild: { - background: theme.palette.background.paper, - }, -})); - -export function DryRunResultsSplitView(props: { children: ReactNode }) { - const classes = useStyles(); - const childArray = Children.toArray(props.children); - - if (childArray.length !== 2) { - throw new Error('must have exactly 2 children'); - } - - return ( -
    -
    - {childArray[0]} -
    - -
    {childArray[1]}
    -
    - ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx deleted file mode 100644 index c2d8d3a2a4..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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, TestApiProvider } from '@backstage/test-utils'; -import { screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React, { ReactNode, useEffect } from 'react'; -import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; -import { DryRunProvider, useDryRun } from '../DryRunContext'; -import { DryRunResultsView } from './DryRunResultsView'; - -// The inside needs mocking to render in jsdom -jest.mock('react-virtualized-auto-sizer', () => ({ - __esModule: true, - default: (props: { - children: (size: { width: number; height: number }) => ReactNode; - }) => <>{props.children({ width: 400, height: 200 })}, -})); - -function DryRunRemote() { - const dryRun = useDryRun(); - - useEffect(() => { - dryRun.execute({ - templateContent: '', - values: {}, - files: [], - }); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return null; -} - -describe('DryRunResultsView', () => { - it('renders a result', async () => { - await renderInTestApp( - ({ - directoryContents: [ - { - path: 'foo.txt', - base64Content: window.btoa('Foo Content'), - executable: false, - }, - ], - log: [{ body: { message: 'Foo Message', stepId: 'foo' } }], - output: { - links: [{ title: 'Foo Link', url: 'http://example.com' }], - }, - steps: [{ id: 'foo', action: 'foo', name: 'Foo' }], - }), - }, - ], - ]} - > - - - - - , - { - mountedRoutes: { - '/catalog/:kind/:namespace/:name': entityRouteRef, - }, - }, - ); - - expect(screen.getByText('foo.txt')).toBeInTheDocument(); - expect(screen.getByText('Foo Content')).toBeInTheDocument(); - - expect(screen.queryByText('Foo Message')).not.toBeInTheDocument(); - expect(screen.queryByText('Foo Link')).not.toBeInTheDocument(); - - await userEvent.click(screen.getByText('Log')); - expect(screen.getByText('Foo Message')).toBeInTheDocument(); - - await userEvent.click(screen.getByText('Output')); - expect(screen.getByText('Foo Link')).toBeInTheDocument(); - }); -}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx deleted file mode 100644 index 852ec05a82..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx +++ /dev/null @@ -1,195 +0,0 @@ -/* - * 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 { LogViewer } from '@backstage/core-components'; -import { StreamLanguage } from '@codemirror/language'; -import { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml'; -import Box from '@material-ui/core/Box'; -import Divider from '@material-ui/core/Divider'; -import { makeStyles } from '@material-ui/core/styles'; -import Tab from '@material-ui/core/Tab'; -import Tabs from '@material-ui/core/Tabs'; -import CodeMirror from '@uiw/react-codemirror'; -import React, { useEffect, useMemo, useState } from 'react'; -import { FileBrowser } from '../../../components/FileBrowser'; -import { TaskStatusStepper } from '../../../components/TaskPage/TaskPage'; -import { TaskPageLinks } from '../../../components/TaskPage/TaskPageLinks'; -import { useDryRun } from '../DryRunContext'; -import { DryRunResultsSplitView } from './DryRunResultsSplitView'; - -const useStyles = makeStyles({ - root: { - display: 'flex', - flexFlow: 'column nowrap', - }, - contentWrapper: { - flex: 1, - position: 'relative', - }, - content: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, - - display: 'flex', - '& > *': { - flex: 1, - }, - }, - codeMirror: { - height: '100%', - overflowY: 'auto', - }, -}); - -function FilesContent() { - const classes = useStyles(); - const { selectedResult } = useDryRun(); - const [selectedPath, setSelectedPath] = useState(''); - const selectedFile = selectedResult?.directoryContents.find( - f => f.path === selectedPath, - ); - - useEffect(() => { - if (selectedResult) { - const [firstFile] = selectedResult.directoryContents; - if (firstFile) { - setSelectedPath(firstFile.path); - } else { - setSelectedPath(''); - } - } - return undefined; - }, [selectedResult]); - - if (!selectedResult) { - return null; - } - return ( - - file.path)} - /> - - - ); -} -function LogContent() { - const { selectedResult } = useDryRun(); - const [currentStepId, setUserSelectedStepId] = useState(); - - const steps = useMemo(() => { - if (!selectedResult) { - return []; - } - return ( - selectedResult.steps.map(step => { - const stepLog = selectedResult.log.filter( - l => l.body.stepId === step.id, - ); - return { - id: step.id, - name: step.name, - logString: stepLog.map(l => l.body.message).join('\n'), - status: stepLog[stepLog.length - 1]?.body.status ?? 'completed', - }; - }) ?? [] - ); - }, [selectedResult]); - - if (!selectedResult) { - return null; - } - - const selectedStep = steps.find(s => s.id === currentStepId) ?? steps[0]; - - return ( - - - - - ); -} - -function OutputContent() { - const classes = useStyles(); - const { selectedResult } = useDryRun(); - - if (!selectedResult) { - return null; - } - - return ( - - - {selectedResult.output?.links?.length && ( - - )} - - - - ); -} - -export function DryRunResultsView() { - const classes = useStyles(); - const [selectedTab, setSelectedTab] = useState<'files' | 'log' | 'output'>( - 'files', - ); - - return ( -
    - setSelectedTab(v)}> - - - - - - -
    -
    - {selectedTab === 'files' && } - {selectedTab === 'log' && } - {selectedTab === 'output' && } -
    -
    -
    - ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts deleted file mode 100644 index af8ef5214f..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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 { DryRunResults } from './DryRunResults'; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx index c5556c3b06..4cdd383f83 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx @@ -20,12 +20,12 @@ import type { NextFieldExtensionOptions, } from '@backstage/plugin-scaffolder-react'; import { TemplateDirectoryAccess } from '../../lib/filesystem'; -import { DirectoryEditorProvider } from './DirectoryEditorContext'; -import { DryRunProvider } from './DryRunContext'; -import { DryRunResults } from './DryRunResults'; -import { TemplateEditorBrowser } from './TemplateEditorBrowser'; +import { DirectoryEditorProvider } from '../../components/TemplateEditorPage/DirectoryEditorContext'; +import { DryRunProvider } from '../../components/TemplateEditorPage/DryRunContext'; +import { DryRunResults } from '../../components/TemplateEditorPage/DryRunResults'; +import { TemplateEditorBrowser } from '../../components/TemplateEditorPage/TemplateEditorBrowser'; import { TemplateEditorForm } from './TemplateEditorForm'; -import { TemplateEditorTextArea } from './TemplateEditorTextArea'; +import { TemplateEditorTextArea } from '../../components/TemplateEditorPage/TemplateEditorTextArea'; const useStyles = makeStyles({ // Reset and fix sizing to make sure scrolling behaves correctly diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx deleted file mode 100644 index cec311a5cd..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 } from '@backstage/test-utils'; -import { screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React from 'react'; -import { MockFileSystemAccess } from '../../lib/filesystem/MockFileSystemAccess'; -import { DirectoryEditorProvider } from './DirectoryEditorContext'; -import { TemplateEditorBrowser } from './TemplateEditorBrowser'; - -Blob.prototype.text = async function text() { - return new Promise(resolve => { - const reader = new FileReader(); - reader.onload = () => resolve(reader.result as string); - reader.readAsText(this); - }); -}; - -describe('TemplateEditorBrowser', () => { - it('should render files and expand dirs without exploding', async () => { - await renderInTestApp( - - - , - ); - - await expect(screen.findByText('foo.txt')).resolves.toBeInTheDocument(); - expect(screen.getByText('dir')).toBeInTheDocument(); - expect(screen.queryByText('bar.txt')).not.toBeInTheDocument(); - expect(screen.queryByText('baz.txt')).not.toBeInTheDocument(); - - await userEvent.click(screen.getByText('dir')); - expect(screen.getByText('bar.txt')).toBeInTheDocument(); - expect(screen.getByText('baz.txt')).toBeInTheDocument(); - }); -}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx deleted file mode 100644 index a668aa1868..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 { Divider, IconButton, makeStyles, Tooltip } from '@material-ui/core'; -import CloseIcon from '@material-ui/icons/Close'; -import RefreshIcon from '@material-ui/icons/Refresh'; -import SaveIcon from '@material-ui/icons/Save'; -import React from 'react'; -import { FileBrowser } from '../../components/FileBrowser'; - -import { useDirectoryEditor } from './DirectoryEditorContext'; - -const useStyles = makeStyles(theme => ({ - button: { - padding: theme.spacing(1), - }, - buttons: { - display: 'flex', - flexFlow: 'row nowrap', - alignItems: 'center', - justifyContent: 'flex-start', - }, - buttonsGap: { - flex: '1 1 auto', - }, - buttonsDivider: { - marginBottom: theme.spacing(1), - }, -})); - -/** The local file browser for the template editor */ -export function TemplateEditorBrowser(props: { onClose?: () => void }) { - const classes = useStyles(); - const directoryEditor = useDirectoryEditor(); - const changedFiles = directoryEditor.files.filter(file => file.dirty); - - const handleClose = () => { - if (!props.onClose) { - return; - } - if (changedFiles.length > 0) { - // eslint-disable-next-line no-alert - const accepted = window.confirm( - 'Are you sure? Unsaved changes will be lost', - ); - if (!accepted) { - return; - } - } - props.onClose(); - }; - - return ( - <> -
    - - !file.dirty)} - onClick={() => directoryEditor.save()} - > - - - - - directoryEditor.reload()} - > - - - -
    - - - - - -
    - - file.path)} - /> - - ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx index 0ac604c75d..5dc841cf20 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx @@ -25,9 +25,8 @@ import { Stepper, TemplateParameterSchema, } from '@backstage/plugin-scaffolder-react'; - -import { useDirectoryEditor } from './DirectoryEditorContext'; -import { useDryRun } from './DryRunContext'; +import { useDryRun } from '../../components/TemplateEditorPage/DryRunContext'; +import { useDirectoryEditor } from '../../components/TemplateEditorPage/DirectoryEditorContext'; const useStyles = makeStyles({ containerWrapper: { diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx deleted file mode 100644 index bf9cd8c464..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React from 'react'; -import { TemplateEditorPage } from './TemplateEditorPage'; - -describe('TemplateEditorPage', () => { - it('renders without exploding', async () => { - await renderInTestApp(); - - expect(screen.getByText('Load Template Directory')).toBeInTheDocument(); - expect(screen.getByText('Edit Template Form')).toBeInTheDocument(); - }); - - it('template directory loading should not be supported in Jest', async () => { - await renderInTestApp(); - - expect( - screen.getByRole('button', { name: /Load Template Directory/ }), - ).toBeDisabled(); - }); - - it('should be able to continue to form preview', async () => { - await renderInTestApp( - - - , - ); - - await userEvent.click(screen.getByText('Edit Template Form')); - - expect(screen.getByLabelText('Load Existing Template')).toBeInTheDocument(); - }); -}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx deleted file mode 100644 index 588b0cd4ba..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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 { StreamLanguage } from '@codemirror/language'; -import { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml'; -import { showPanel } from '@codemirror/view'; -import { IconButton, makeStyles, Paper, Tooltip } from '@material-ui/core'; -import RefreshIcon from '@material-ui/icons/Refresh'; -import SaveIcon from '@material-ui/icons/Save'; -import { useKeyboardEvent } from '@react-hookz/web'; -import CodeMirror from '@uiw/react-codemirror'; -import React, { useMemo } from 'react'; -import { useDirectoryEditor } from './DirectoryEditorContext'; - -const useStyles = makeStyles(theme => ({ - container: { - position: 'relative', - width: '100%', - height: '100%', - }, - codeMirror: { - position: 'absolute', - top: 0, - bottom: 0, - left: 0, - right: 0, - }, - errorPanel: { - color: theme.palette.error.main, - lineHeight: 2, - margin: theme.spacing(0, 1), - }, - floatingButtons: { - position: 'absolute', - top: theme.spacing(1), - right: theme.spacing(3), - }, - floatingButton: { - padding: theme.spacing(1), - }, -})); - -/** A wrapper around CodeMirror with an error panel and extra actions available */ -export function TemplateEditorTextArea(props: { - content?: string; - onUpdate?: (content: string) => void; - errorText?: string; - onSave?: () => void; - onReload?: () => void; -}) { - const { errorText } = props; - const classes = useStyles(); - - const panelExtension = useMemo(() => { - if (!errorText) { - return showPanel.of(null); - } - - const dom = document.createElement('div'); - dom.classList.add(classes.errorPanel); - dom.textContent = errorText; - return showPanel.of(() => ({ dom, bottom: true })); - }, [classes, errorText]); - - useKeyboardEvent( - e => e.key === 's' && (e.ctrlKey || e.metaKey), - e => { - e.preventDefault(); - if (props.onSave) { - props.onSave(); - } - }, - ); - - return ( -
    - - {(props.onSave || props.onReload) && ( -
    - - {props.onSave && ( - - props.onSave?.()} - > - - - - )} - {props.onReload && ( - - props.onReload?.()} - > - - - - )} - -
    - )} -
    - ); -} - -/** A version of the TemplateEditorTextArea that is connected to the DirectoryEditor context */ -export function TemplateEditorDirectoryEditorTextArea(props: { - errorText?: string; -}) { - const directoryEditor = useDirectoryEditor(); - - const actions = directoryEditor.selectedFile?.dirty - ? { - onSave: () => directoryEditor.save(), - onReload: () => directoryEditor.reload(), - } - : { - onReload: () => directoryEditor.reload(), - }; - - return ( - directoryEditor.selectedFile?.updateContent(content)} - {...actions} - /> - ); -} - -TemplateEditorTextArea.DirectoryEditor = TemplateEditorDirectoryEditorTextArea; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx index c5f84a4b66..1476cda2d0 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -37,7 +37,7 @@ import { type LayoutOptions, } from '@backstage/plugin-scaffolder-react'; import { TemplateEditorForm } from './TemplateEditorForm'; -import { TemplateEditorTextArea } from './TemplateEditorTextArea'; +import { TemplateEditorTextArea } from '../../components/TemplateEditorPage/TemplateEditorTextArea'; const EXAMPLE_TEMPLATE_PARAMS_YAML = `# Edit the template parameters below to see how they will render in the scaffolder form UI parameters: From e9a8ce97d0f53a6b52294e5e8b280e5419d366c6 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 15:45:30 +0100 Subject: [PATCH 379/423] chore: remove some more uneeded code Signed-off-by: blam --- .../TemplateEditorIntro.tsx | 144 ------------------ .../TemplateEditorPage/TemplateEditorPage.tsx | 2 +- 2 files changed, 1 insertion(+), 145 deletions(-) delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx deleted file mode 100644 index 61e6c46964..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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 Card from '@material-ui/core/Card'; -import CardActionArea from '@material-ui/core/CardActionArea'; -import CardContent from '@material-ui/core/CardContent'; -import Tooltip from '@material-ui/core/Tooltip'; -import Typography from '@material-ui/core/Typography'; -import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined'; -import { makeStyles } from '@material-ui/core/styles'; -import { WebFileSystemAccess } from '../../lib/filesystem'; - -const useStyles = makeStyles(theme => ({ - introText: { - textAlign: 'center', - marginTop: theme.spacing(2), - }, - card: { - position: 'relative', - maxWidth: 340, - marginTop: theme.spacing(4), - margin: theme.spacing(0, 2), - }, - infoIcon: { - position: 'absolute', - top: theme.spacing(1), - right: theme.spacing(1), - }, -})); - -interface EditorIntroProps { - style?: JSX.IntrinsicElements['div']['style']; - onSelect?: (option: 'local' | 'form' | 'field-explorer') => void; -} - -export function TemplateEditorIntro(props: EditorIntroProps) { - const classes = useStyles(); - const supportsLoad = WebFileSystemAccess.isSupported(); - - const cardLoadLocal = ( - - props.onSelect?.('local')} - > - - - Load Template Directory - - - Load a local template directory, allowing you to both edit and try - executing your own template. - - - - {!supportsLoad && ( -
    - - - -
    - )} -
    - ); - - const cardFormEditor = ( - - props.onSelect?.('form')}> - - - Edit Template Form - - - Preview and edit a template form, either using a sample template or - by loading a template from the catalog. - - - - - ); - - const cardFieldExplorer = ( - - props.onSelect?.('field-explorer')}> - - - Custom Field Explorer - - - View and play around with available installed custom field - extensions. - - - - - ); - - return ( -
    - - Get started by choosing one of the options below - -
    - {supportsLoad && cardLoadLocal} - {cardFormEditor} - {!supportsLoad && cardLoadLocal} - {cardFieldExplorer} -
    -
    - ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx index 03e1619bc8..92387fd69d 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx @@ -20,13 +20,13 @@ import { WebFileSystemAccess, } from '../../lib/filesystem'; import { CustomFieldExplorer } from './CustomFieldExplorer'; -import { TemplateEditorIntro } from './TemplateEditorIntro'; import { TemplateEditor } from './TemplateEditor'; import { TemplateFormPreviewer } from './TemplateFormPreviewer'; import { NextFieldExtensionOptions, type LayoutOptions, } from '@backstage/plugin-scaffolder-react'; +import { TemplateEditorIntro } from '../../components/TemplateEditorPage/TemplateEditorIntro'; type Selection = | { From 72a33126892cdaaf79e058d12e0b705976d40da3 Mon Sep 17 00:00:00 2001 From: Jim Shingler Date: Fri, 10 Feb 2023 20:56:27 -0500 Subject: [PATCH 380/423] Fixing Documentation of GitLab Org Data Spell out PAT and fix time and resourcs Signed-off-by: Jim Shingler --- docs/integrations/gitlab/org.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/integrations/gitlab/org.md b/docs/integrations/gitlab/org.md index 100b2c09fd..2ab72b4bd6 100644 --- a/docs/integrations/gitlab/org.md +++ b/docs/integrations/gitlab/org.md @@ -20,9 +20,9 @@ integrations: ``` This will query all users and groups from your gitlab installation. Depending on the size -of the Gitlab Instance, this can take some time our resources. +of the Gitlab Instance, this can take some time and resources. -The token that is used for the Organization Integration, has to be an Admin PAT. +The token that is used for the Organization Integration, has to be an Admin Personal Access Token (PAT). ```yaml catalog: From aece6c57d24b2f24daba70b122f02d6def41563c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 11 Feb 2023 10:54:25 +0100 Subject: [PATCH 381/423] catalog-model: improve location reference validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrik Oldsberg Co-authored-by: Fredrik Adelöw --- .changeset/purple-panthers-know.md | 5 +++++ .../catalog-model/src/location/helpers.test.ts | 9 +++++++++ packages/catalog-model/src/location/helpers.ts | 17 +++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 .changeset/purple-panthers-know.md diff --git a/.changeset/purple-panthers-know.md b/.changeset/purple-panthers-know.md new file mode 100644 index 0000000000..c53c6d8890 --- /dev/null +++ b/.changeset/purple-panthers-know.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-model': patch +--- + +Add additional validation for location references. diff --git a/packages/catalog-model/src/location/helpers.test.ts b/packages/catalog-model/src/location/helpers.test.ts index 91a2137611..28267dcf37 100644 --- a/packages/catalog-model/src/location/helpers.test.ts +++ b/packages/catalog-model/src/location/helpers.test.ts @@ -50,6 +50,9 @@ describe('parseLocationRef', () => { expect(() => parseLocationRef('https://bleh')).toThrow( "Invalid location ref 'https://bleh', please prefix it with 'url:', e.g. 'url:https://bleh'", ); + expect(() => parseLocationRef('url:javascript:alert()')).toThrow( + "Invalid location ref 'url:javascript:alert()', target is a javascript: URL", + ); }); }); @@ -70,6 +73,12 @@ describe('stringifyLocationRef', () => { expect(() => stringifyLocationRef({ type: 'hello', target: '' })).toThrow( 'Unable to stringify location ref, empty target', ); + expect(() => + // eslint-disable-next-line no-script-url + stringifyLocationRef({ type: 'url', target: 'javascript:alert()' }), + ).toThrow( + "Invalid location ref 'url:javascript:alert()', target is a javascript: URL", + ); }); }); diff --git a/packages/catalog-model/src/location/helpers.ts b/packages/catalog-model/src/location/helpers.ts index 6f9800c5a2..a2f4d84f6f 100644 --- a/packages/catalog-model/src/location/helpers.ts +++ b/packages/catalog-model/src/location/helpers.ts @@ -17,6 +17,11 @@ import { Entity, stringifyEntityRef } from '../entity'; import { ANNOTATION_LOCATION, ANNOTATION_SOURCE_LOCATION } from './annotation'; +// See https://github.com/facebook/react/blob/f0cf832e1d0c8544c36aa8b310960885a11a847c/packages/react-dom-bindings/src/shared/sanitizeURL.js +const scriptProtocolPattern = + // eslint-disable-next-line no-control-regex + /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i; + /** * Parses a string form location reference. * @@ -56,6 +61,12 @@ export function parseLocationRef(ref: string): { ); } + if (scriptProtocolPattern.test(target)) { + throw new TypeError( + `Invalid location ref '${ref}', target is a javascript: URL`, + ); + } + return { type, target }; } @@ -78,6 +89,12 @@ export function stringifyLocationRef(ref: { throw new TypeError(`Unable to stringify location ref, empty target`); } + if (scriptProtocolPattern.test(target)) { + throw new TypeError( + `Invalid location ref '${type}:${target}', target is a javascript: URL`, + ); + } + return `${type}:${target}`; } From 071354eb7deecdb9bd15c9df379e6067cec37436 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 11 Feb 2023 11:11:16 +0100 Subject: [PATCH 382/423] catalog-backend: add additional validation in stitching step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrik Oldsberg Co-authored-by: Fredrik Adelöw --- .changeset/big-bags-glow.md | 5 + .../catalog-backend/src/integration.test.ts | 127 ++++++++++++++---- .../catalog-backend/src/stitching/Stitcher.ts | 15 +++ 3 files changed, 121 insertions(+), 26 deletions(-) create mode 100644 .changeset/big-bags-glow.md diff --git a/.changeset/big-bags-glow.md b/.changeset/big-bags-glow.md new file mode 100644 index 0000000000..eb606838fd --- /dev/null +++ b/.changeset/big-bags-glow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Add additional validation as security precations for output entities. diff --git a/plugins/catalog-backend/src/integration.test.ts b/plugins/catalog-backend/src/integration.test.ts index 4ba046834b..f0f916a78d 100644 --- a/plugins/catalog-backend/src/integration.test.ts +++ b/plugins/catalog-backend/src/integration.test.ts @@ -52,9 +52,14 @@ import { } from '@backstage/plugin-catalog-node'; import { RefreshStateItem } from './database/types'; import { DefaultProviderDatabase } from './database/DefaultProviderDatabase'; +import { InputError } from '@backstage/errors'; const voidLogger = getVoidLogger(); +type ProgressTrackerWithErrorReports = ProgressTracker & { + reportError(unprocessedEntity: Entity, errors: Error[]): void; +}; + class TestProvider implements EntityProvider { #connection?: EntityProviderConnection; @@ -74,10 +79,10 @@ class TestProvider implements EntityProvider { } } -class ProxyProgressTracker implements ProgressTracker { - #inner: ProgressTracker; +class ProxyProgressTracker implements ProgressTrackerWithErrorReports { + #inner: ProgressTrackerWithErrorReports; - constructor(inner: ProgressTracker) { + constructor(inner: ProgressTrackerWithErrorReports) { this.#inner = inner; } @@ -85,12 +90,16 @@ class ProxyProgressTracker implements ProgressTracker { return this.#inner.processStart(item, voidLogger); } - setTracker(tracker: ProgressTracker) { + setTracker(tracker: ProgressTrackerWithErrorReports) { this.#inner = tracker; } + + reportError(unprocessedEntity: Entity, errors: Error[]): void { + this.#inner.reportError(unprocessedEntity, errors); + } } -class NoopProgressTracker implements ProgressTracker { +class NoopProgressTracker implements ProgressTrackerWithErrorReports { static emptyTracking = { markFailed() {}, markProcessorsCompleted() {}, @@ -102,18 +111,20 @@ class NoopProgressTracker implements ProgressTracker { processStart() { return NoopProgressTracker.emptyTracking; } + + reportError() {} } -class WaitingProgressTracker implements ProgressTracker { - #resolve: (errors: Record) => void; - #promise: Promise>; +class WaitingProgressTracker implements ProgressTrackerWithErrorReports { + #resolve: (errors: Record) => void; + #promise: Promise>; #counts = new Map(); - #errors = new Map(); + #errors = new Map(); #inFlight = new Array>(); constructor(private readonly entityRefs?: Set) { - let resolve: (errors: Record) => void; - this.#promise = new Promise>(_resolve => { + let resolve: (errors: Record) => void; + this.#promise = new Promise>(_resolve => { resolve = _resolve; }); this.#resolve = resolve!; @@ -143,7 +154,7 @@ class WaitingProgressTracker implements ProgressTracker { }; return { markFailed: (error: Error) => { - this.#errors.set(item.entityRef, error); + this.#errors.set(item.entityRef, [error]); onDone(); resolve(); }, @@ -154,7 +165,6 @@ class WaitingProgressTracker implements ProgressTracker { resolve(); }, markSuccessfulWithErrors: () => { - this.#errors.delete(item.entityRef); onDone(); resolve(); }, @@ -165,7 +175,11 @@ class WaitingProgressTracker implements ProgressTracker { }; } - async wait(): Promise> { + reportError(unprocessedEntity: Entity, errors: Error[]): void { + this.#errors.set(stringifyEntityRef(unprocessedEntity), errors); + } + + async wait(): Promise> { return this.#promise; } @@ -191,10 +205,6 @@ class TestHarness { location: LocationSpec, emit: CatalogProcessorEmit, ): Promise; - onProcessingError?(event: { - unprocessedEntity: Entity; - errors: Error[]; - }): void; }) { const config = new ConfigReader( options?.config ?? { @@ -271,13 +281,7 @@ class TestHarness { () => createHash('sha1'), 50, event => { - if (options?.onProcessingError) { - options.onProcessingError(event); - } else { - throw new Error( - `Catalog processing error, ${event.errors.join(', ')}`, - ); - } + proxyProgressTracker.reportError(event.unprocessedEntity, event.errors); }, proxyProgressTracker, ); @@ -388,7 +392,13 @@ describe('Catalog Backend Integration', () => { triggerError = true; - await expect(harness.process()).resolves.toEqual({}); + await expect(harness.process()).resolves.toEqual({ + 'component:default/test': [ + new InputError( + 'Processor Object threw an error while preprocessing; caused by Error: NOPE', + ), + ], + }); await expect(harness.getOutputEntities()).resolves.toEqual({ 'component:default/test': { @@ -685,4 +695,69 @@ describe('Catalog Backend Integration', () => { .annotations!['backstage.io/orphan'], ).toBeUndefined(); }); + + it('should reject insecure URLs', async () => { + const harness = await TestHarness.create(); + + await harness.setInputEntities([ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'test', + annotations: { + 'backstage.io/managed-by-location': 'url:.', + 'backstage.io/managed-by-origin-location': 'url:.', + 'backstage.io/view-url': ' javascript:bad()', + 'backstage.io/edit-url': ' javascript:alert()', + }, + }, + }, + ]); + + await expect(harness.process()).resolves.toEqual({}); + + await expect(harness.getOutputEntities()).resolves.toEqual({ + 'component:default/test': { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: expect.objectContaining({ + name: 'test', + annotations: expect.objectContaining({ + 'backstage.io/view-url': + 'https://backstage.io/annotation-rejected-for-security-reasons', + 'backstage.io/edit-url': + 'https://backstage.io/annotation-rejected-for-security-reasons', + }), + }), + relations: [], + }, + }); + }); + + it('should reject insecure location URLs', async () => { + const harness = await TestHarness.create(); + + await harness.setInputEntities([ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'test', + annotations: { + 'backstage.io/managed-by-location': 'url:javascript:bad()', + 'backstage.io/managed-by-origin-location': 'url:javascript:alert()', + }, + }, + }, + ]); + + await expect(harness.process()).resolves.toEqual({ + 'component:default/test': [ + new TypeError( + "Invalid location ref 'url:javascript:bad()', target is a javascript: URL", + ), + ], + }); + }); }); diff --git a/plugins/catalog-backend/src/stitching/Stitcher.ts b/plugins/catalog-backend/src/stitching/Stitcher.ts index 4742c81933..bdf9f8791a 100644 --- a/plugins/catalog-backend/src/stitching/Stitcher.ts +++ b/plugins/catalog-backend/src/stitching/Stitcher.ts @@ -17,6 +17,8 @@ import { ENTITY_STATUS_CATALOG_PROCESSING_TYPE } from '@backstage/catalog-client'; import { AlphaEntity, + ANNOTATION_EDIT_URL, + ANNOTATION_VIEW_URL, EntityRelation, EntityStatusItem, } from '@backstage/catalog-model'; @@ -32,6 +34,11 @@ import { import { buildEntitySearch } from './buildEntitySearch'; import { BATCH_SIZE, generateStableHash } from './util'; +// See https://github.com/facebook/react/blob/f0cf832e1d0c8544c36aa8b310960885a11a847c/packages/react-dom-bindings/src/shared/sanitizeURL.js +const scriptProtocolPattern = + // eslint-disable-next-line no-control-regex + /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i; + /** * Performs the act of stitching - to take all of the various outputs from the * ingestion process, and stitching them together into the final entity JSON @@ -166,6 +173,14 @@ export class Stitcher { })); } } + // We opt to do this check here as we otherwise can't guarantee that it will be run after all processors + for (const annotation of [ANNOTATION_VIEW_URL, ANNOTATION_EDIT_URL]) { + const value = entity.metadata.annotations?.[annotation]; + if (typeof value === 'string' && scriptProtocolPattern.test(value)) { + entity.metadata.annotations![annotation] = + 'https://backstage.io/annotation-rejected-for-security-reasons'; + } + } // TODO: entityRef is lower case and should be uppercase in the final // result From 1aec041c3451f0e7ac33b01035c0bc7d86007bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Fri, 10 Feb 2023 19:31:53 +0100 Subject: [PATCH 383/423] Handle eager deletion even in the face of duplicate references MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/itchy-rings-rule.md | 5 + .../database/DefaultCatalogDatabase.test.ts | 1 + .../database/DefaultProviderDatabase.test.ts | 34 +++ .../deleteWithEagerPruningOfChildren.test.ts | 278 ++++++++++++++++++ .../deleteWithEagerPruningOfChildren.ts | 178 ++++++----- 5 files changed, 419 insertions(+), 77 deletions(-) create mode 100644 .changeset/itchy-rings-rule.md create mode 100644 plugins/catalog-backend/src/database/operations/provider/deleteWithEagerPruningOfChildren.test.ts diff --git a/.changeset/itchy-rings-rule.md b/.changeset/itchy-rings-rule.md new file mode 100644 index 0000000000..3e8b9e8b2b --- /dev/null +++ b/.changeset/itchy-rings-rule.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Fixed an issue where entities sometimes were not properly deleted during a full mutation. diff --git a/plugins/catalog-backend/src/database/DefaultCatalogDatabase.test.ts b/plugins/catalog-backend/src/database/DefaultCatalogDatabase.test.ts index b873f6a985..827ab58ebe 100644 --- a/plugins/catalog-backend/src/database/DefaultCatalogDatabase.test.ts +++ b/plugins/catalog-backend/src/database/DefaultCatalogDatabase.test.ts @@ -105,6 +105,7 @@ describe('DefaultCatalogDatabase', () => { 'location:default/root-2', ]); }, + 60_000, ); }); }); diff --git a/plugins/catalog-backend/src/database/DefaultProviderDatabase.test.ts b/plugins/catalog-backend/src/database/DefaultProviderDatabase.test.ts index 140925b6fd..09bec187fa 100644 --- a/plugins/catalog-backend/src/database/DefaultProviderDatabase.test.ts +++ b/plugins/catalog-backend/src/database/DefaultProviderDatabase.test.ts @@ -745,5 +745,39 @@ describe('DefaultProviderDatabase', () => { }, 60_000, ); + + it.each(databases.eachSupportedId())( + 'should gracefully handle accidental duplicate refresh state references when deletion happens during a full sync, %p', + async databaseId => { + const fakeLogger = { debug: jest.fn() }; + const { knex, db } = await createDatabase( + databaseId, + fakeLogger as any, + ); + + await createLocations(knex, ['component:default/a']); + + await insertRefRow(knex, { + source_key: 'a', + target_entity_ref: 'component:default/a', + }); + await insertRefRow(knex, { + source_key: 'a', + target_entity_ref: 'component:default/a', + }); + + await db.transaction(async tx => { + await db.replaceUnprocessedEntities(tx, { + type: 'full', + sourceKey: 'a', + items: [], + }); + }); + + const state = await knex('refresh_state').select(); + expect(state).toEqual([]); + }, + 60_000, + ); }); }); diff --git a/plugins/catalog-backend/src/database/operations/provider/deleteWithEagerPruningOfChildren.test.ts b/plugins/catalog-backend/src/database/operations/provider/deleteWithEagerPruningOfChildren.test.ts new file mode 100644 index 0000000000..8ab94df64a --- /dev/null +++ b/plugins/catalog-backend/src/database/operations/provider/deleteWithEagerPruningOfChildren.test.ts @@ -0,0 +1,278 @@ +/* + * Copyright 2023 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 * as uuid from 'uuid'; +import { applyDatabaseMigrations } from '../../migrations'; +import { DbRefreshStateReferencesRow, DbRefreshStateRow } from '../../tables'; +import { deleteWithEagerPruningOfChildren } from './deleteWithEagerPruningOfChildren'; + +describe('deleteWithEagerPruningOfChildren', () => { + const databases = TestDatabases.create({ + ids: ['MYSQL_8', 'POSTGRES_13', 'POSTGRES_9', 'SQLITE_3'], + }); + + async function createDatabase(databaseId: TestDatabaseId) { + const knex = await databases.init(databaseId); + await applyDatabaseMigrations(knex); + return knex; + } + + async function run( + knex: Knex, + options: { entityRefs: string[]; sourceKey: string }, + ): Promise { + let result: number; + await knex.transaction( + async tx => { + // We can't return here, as knex swallows the return type in case the + // transaction is rolled back: + // https://github.com/knex/knex/blob/e37aeaa31c8ef9c1b07d2e4d3ec6607e557d800d/lib/transaction.js#L136 + result = await deleteWithEagerPruningOfChildren({ tx, ...options }); + }, + { + // If we explicitly trigger a rollback, don't fail. + doNotRejectOnRollback: true, + }, + ); + return result!; + } + + async function insertReference( + knex: Knex, + ...refs: DbRefreshStateReferencesRow[] + ) { + return knex('refresh_state_references').insert( + refs, + ); + } + + async function insertEntity(knex: Knex, ...entityRefs: string[]) { + for (const ref of entityRefs) { + await knex('refresh_state').insert({ + entity_id: uuid.v4(), + entity_ref: ref, + unprocessed_entity: '{}', + processed_entity: '{}', + errors: '[]', + next_update_at: '2021-04-01 13:37:00', + last_discovery_at: '2021-04-01 13:37:00', + }); + } + } + + async function remainingEntities(knex: Knex) { + const rows = await knex('refresh_state') + .orderBy('entity_ref') + .select('entity_ref'); + return rows.map(r => r.entity_ref); + } + + it.each(databases.eachSupportedId())( + 'works for the simple path, %p', + async databaseId => { + /* + P1 - E1 - E2 + + P1 - E3 + + P1 - E4 + + P2 - E5 + + Scenario: P1 issues delete for E1 and E3 + + Result: E1, E2, and E3 deleted; E4 and E5 remain + */ + const knex = await createDatabase(databaseId); + await insertEntity(knex, 'E1', 'E2', 'E3', 'E4', 'E5'); + await insertReference( + knex, + { source_key: 'P1', target_entity_ref: 'E1' }, + { source_entity_ref: 'E1', target_entity_ref: 'E2' }, + { source_key: 'P1', target_entity_ref: 'E3' }, + { source_key: 'P1', target_entity_ref: 'E4' }, + { source_key: 'P2', target_entity_ref: 'E5' }, + ); + await run(knex, { sourceKey: 'P1', entityRefs: ['E1', 'E3'] }); + await expect(remainingEntities(knex)).resolves.toEqual(['E4', 'E5']); + }, + 60_000, + ); + + it.each(databases.eachSupportedId())( + 'works when there are multiple identical references, %p', + async databaseId => { + /* + P1 + \ + E1 + / + P1 + + P1 - E2 + + Scenario: P1 issues delete for E1 + + Result: E1 deleted; E2 remains + */ + const knex = await createDatabase(databaseId); + await insertEntity(knex, 'E1', 'E2'); + await insertReference( + knex, + { source_key: 'P1', target_entity_ref: 'E1' }, + { source_key: 'P1', target_entity_ref: 'E1' }, + { source_key: 'P1', target_entity_ref: 'E2' }, + ); + await run(knex, { sourceKey: 'P1', entityRefs: ['E1'] }); + await expect(remainingEntities(knex)).resolves.toEqual(['E2']); + }, + 60_000, + ); + + it.each(databases.eachSupportedId())( + 'leaves out things that have roots in other source keys, %p', + async databaseId => { + /* + P1 - E1 + \ + E2 + / + P2 - E3 + + Scenario: P1 issues delete for E1 + + Result: E1 deleted; E2 and E3 remain + */ + const knex = await createDatabase(databaseId); + await insertEntity(knex, 'E1', 'E2', 'E3'); + await insertReference( + knex, + { source_key: 'P1', target_entity_ref: 'E1' }, + { source_entity_ref: 'E1', target_entity_ref: 'E2' }, + { source_key: 'P2', target_entity_ref: 'E3' }, + { source_entity_ref: 'E3', target_entity_ref: 'E2' }, + ); + await run(knex, { sourceKey: 'P1', entityRefs: ['E1'] }); + await expect(remainingEntities(knex)).resolves.toEqual(['E2', 'E3']); + }, + 60_000, + ); + + it.each(databases.eachSupportedId())( + 'leaves out things that have several different roots for the same source key, %p', + async databaseId => { + /* + P1 - E1 + \ + E2 + / + P1 - E3 + + Scenario: P1 issues delete for E1 + + Result: E1 deleted; E2 and E3 remain + */ + const knex = await createDatabase(databaseId); + await insertEntity(knex, 'E1', 'E2', 'E3'); + await insertReference( + knex, + { source_key: 'P1', target_entity_ref: 'E1' }, + { source_entity_ref: 'E1', target_entity_ref: 'E2' }, + { source_key: 'P1', target_entity_ref: 'E3' }, + { source_entity_ref: 'E3', target_entity_ref: 'E2' }, + ); + await run(knex, { sourceKey: 'P1', entityRefs: ['E1'] }); + await expect(remainingEntities(knex)).resolves.toEqual(['E2', 'E3']); + }, + 60_000, + ); + + it.each(databases.eachSupportedId())( + 'handles cycles and diamonds gracefully, %p', + async databaseId => { + /* + P1 - E1 <-> E2 + \ + E4 E6 + / \ / + P1 -- E3 -- E5 + + Scenario: P1 issues delete for E1, then for E3 + + Result: Everything deleted, but in two steps + */ + const knex = await createDatabase(databaseId); + await insertEntity(knex, 'E1', 'E2', 'E3', 'E4', 'E5', 'E6'); + await insertReference( + knex, + { source_key: 'P1', target_entity_ref: 'E1' }, + { source_entity_ref: 'E1', target_entity_ref: 'E2' }, + { source_entity_ref: 'E2', target_entity_ref: 'E1' }, + { source_entity_ref: 'E2', target_entity_ref: 'E6' }, + { source_key: 'P1', target_entity_ref: 'E3' }, + { source_entity_ref: 'E3', target_entity_ref: 'E4' }, + { source_entity_ref: 'E4', target_entity_ref: 'E5' }, + { source_entity_ref: 'E3', target_entity_ref: 'E5' }, + { source_entity_ref: 'E5', target_entity_ref: 'E6' }, + ); + await run(knex, { sourceKey: 'P1', entityRefs: ['E1'] }); + await expect(remainingEntities(knex)).resolves.toEqual([ + 'E3', + 'E4', + 'E5', + 'E6', + ]); + await run(knex, { sourceKey: 'P1', entityRefs: ['E3'] }); + await expect(remainingEntities(knex)).resolves.toEqual([]); + }, + 60_000, + ); + + it.each(databases.eachSupportedId())( + 'silently ignores attempts to delete things that are not your own and/or are not roots, %p', + async databaseId => { + /* + P1 - E1 - E2 + + P1 - E3 + + P2 - E4 + + Scenario: P1 issues delete for E2, E3, and E4 + + Result: E3 is deleted; E1, E2 and E4 remain + */ + const knex = await createDatabase(databaseId); + await insertEntity(knex, 'E1', 'E2', 'E3', 'E4'); + await insertReference( + knex, + { source_key: 'P1', target_entity_ref: 'E1' }, + { source_entity_ref: 'E1', target_entity_ref: 'E2' }, + { source_key: 'P1', target_entity_ref: 'E3' }, + { source_key: 'P2', target_entity_ref: 'E4' }, + ); + await run(knex, { sourceKey: 'P1', entityRefs: ['E2', 'E3', 'E4'] }); + await expect(remainingEntities(knex)).resolves.toEqual([ + 'E1', + 'E2', + 'E4', + ]); + }, + 60_000, + ); +}); diff --git a/plugins/catalog-backend/src/database/operations/provider/deleteWithEagerPruningOfChildren.ts b/plugins/catalog-backend/src/database/operations/provider/deleteWithEagerPruningOfChildren.ts index 3d642cbf3a..c600825d6f 100644 --- a/plugins/catalog-backend/src/database/operations/provider/deleteWithEagerPruningOfChildren.ts +++ b/plugins/catalog-backend/src/database/operations/provider/deleteWithEagerPruningOfChildren.ts @@ -31,113 +31,137 @@ export async function deleteWithEagerPruningOfChildren(options: { sourceKey: string; }): Promise { const { tx, entityRefs, sourceKey } = options; - let removedCount = 0; - - const rootId = () => - tx.raw( - tx.client.config.client.includes('mysql') - ? 'CAST(NULL as UNSIGNED INT)' - : 'CAST(NULL as INT)', - [], - ); // Split up the operation by (large) chunks, so that we do not hit database // limits for the number of permitted bindings on a precompiled statement + let removedCount = 0; for (const refs of lodash.chunk(entityRefs, 1000)) { /* WITH RECURSIVE -- All the nodes that can be reached downwards from our root - descendants(root_id, entity_ref) AS ( - SELECT id, target_entity_ref + descendants(entity_ref) AS ( + SELECT target_entity_ref FROM refresh_state_references - WHERE source_key = "R1" AND target_entity_ref = "A" + WHERE source_key = "R1" AND target_entity_ref IN [...refs] UNION - SELECT descendants.root_id, target_entity_ref + SELECT target_entity_ref FROM descendants JOIN refresh_state_references ON source_entity_ref = descendants.entity_ref ), - -- All the nodes that can be reached upwards from the descendants - ancestors(root_id, via_entity_ref, to_entity_ref) AS ( - SELECT CAST(NULL as INT), entity_ref, entity_ref + -- All the individual relations that can be reached upwards from each descendant + ancestors(source_key, source_entity_ref, target_entity_ref, subject) AS ( + SELECT source_key, source_entity_ref, target_entity_ref, descendants.entity_ref FROM descendants + JOIN refresh_state_references ON refresh_state_references.target_entity_ref = descendants.entity_ref UNION SELECT - CASE WHEN source_key IS NOT NULL THEN id ELSE NULL END, - source_entity_ref, - ancestors.to_entity_ref + refresh_state_references.source_key, + refresh_state_references.source_entity_ref, + refresh_state_references.target_entity_ref, + ancestors.subject FROM ancestors - JOIN refresh_state_references ON target_entity_ref = ancestors.via_entity_ref + JOIN refresh_state_references ON refresh_state_references.target_entity_ref = ancestors.source_entity_ref ) -- Start out with all of the descendants SELECT descendants.entity_ref FROM descendants - -- Expand with all ancestors that point to those, but aren't the current root - LEFT OUTER JOIN ancestors - ON ancestors.to_entity_ref = descendants.entity_ref - AND ancestors.root_id IS NOT NULL - AND ancestors.root_id != descendants.root_id - -- Exclude all lines that had such a foreign ancestor - WHERE ancestors.root_id IS NULL; + -- Exclude those who seem to have a root relation somewhere upwards that's not part of our own deletion + WHERE NOT EXISTS ( + SELECT * FROM ancestors + WHERE ancestors.subject = descendants.entity_ref + AND ancestors.source_key IS NOT NULL + AND (ancestors.source_key != "R1" OR ancestors.target_entity_ref NOT IN [...refs]) + ) */ removedCount += await tx('refresh_state') .whereIn('entity_ref', function orphanedEntityRefs(orphans) { return ( orphans // All the nodes that can be reached downwards from our root - .withRecursive('descendants', function descendants(outer) { - return outer - .select({ root_id: 'id', entity_ref: 'target_entity_ref' }) - .from('refresh_state_references') - .where('source_key', sourceKey) - .whereIn('target_entity_ref', refs) - .union(function recursive(inner) { - return inner - .select({ - root_id: 'descendants.root_id', - entity_ref: 'refresh_state_references.target_entity_ref', - }) - .from('descendants') - .join('refresh_state_references', { - 'descendants.entity_ref': - 'refresh_state_references.source_entity_ref', - }); - }); - }) - // All the nodes that can be reached upwards from the descendants - .withRecursive('ancestors', function ancestors(outer) { - return outer - .select({ - root_id: rootId(), - via_entity_ref: 'entity_ref', - to_entity_ref: 'entity_ref', - }) - .from('descendants') - .union(function recursive(inner) { - return inner - .select({ - root_id: tx.raw( - 'CASE WHEN source_key IS NOT NULL THEN id ELSE NULL END', - [], - ), - via_entity_ref: 'source_entity_ref', - to_entity_ref: 'ancestors.to_entity_ref', - }) - .from('ancestors') - .join('refresh_state_references', { - target_entity_ref: 'ancestors.via_entity_ref', - }); - }); - }) + .withRecursive( + 'descendants', + ['entity_ref'], + function descendants(outer) { + return outer + .select({ entity_ref: 'target_entity_ref' }) + .from('refresh_state_references') + .where('source_key', '=', sourceKey) + .whereIn('target_entity_ref', refs) + .union(function recursive(inner) { + return inner + .select({ + entity_ref: + 'refresh_state_references.target_entity_ref', + }) + .from('descendants') + .join('refresh_state_references', { + 'descendants.entity_ref': + 'refresh_state_references.source_entity_ref', + }); + }); + }, + ) + // All the relations that can be reached upwards from each descendant + .withRecursive( + 'ancestors', + [ + 'source_key', + 'source_entity_ref', + 'target_entity_ref', + 'subject', + ], + function ancestors(outer) { + return outer + .select({ + source_key: 'refresh_state_references.source_key', + source_entity_ref: + 'refresh_state_references.source_entity_ref', + target_entity_ref: + 'refresh_state_references.target_entity_ref', + subject: 'descendants.entity_ref', + }) + .from('descendants') + .join('refresh_state_references', { + 'refresh_state_references.target_entity_ref': + 'descendants.entity_ref', + }) + .union(function recursive(inner) { + return inner + .select({ + source_key: 'refresh_state_references.source_key', + source_entity_ref: + 'refresh_state_references.source_entity_ref', + target_entity_ref: + 'refresh_state_references.target_entity_ref', + subject: 'ancestors.subject', + }) + .from('ancestors') + .join('refresh_state_references', { + 'refresh_state_references.target_entity_ref': + 'ancestors.source_entity_ref', + }); + }); + }, + ) // Start out with all of the descendants .select('descendants.entity_ref') .from('descendants') - // Expand with all ancestors that point to those, but aren't the current root - .leftOuterJoin('ancestors', function keepaliveRoots() { - this.on('ancestors.to_entity_ref', '=', 'descendants.entity_ref'); - this.andOnNotNull('ancestors.root_id'); - this.andOn('ancestors.root_id', '!=', 'descendants.root_id'); + // Exclude those who seem to have a root relation somewhere upwards that's not part of our own deletion + .whereNotExists(function otherAncestors(outer) { + outer + .from('ancestors') + .where( + 'ancestors.subject', + '=', + tx.ref('descendants.entity_ref'), + ) + .whereNotNull('ancestors.source_key') + .andWhere(function differentRoot(inner) { + inner + .where('ancestors.source_key', '!=', sourceKey) + .orWhereNotIn('ancestors.target_entity_ref', refs); + }); }) - .whereNull('ancestors.root_id') ); }) .delete(); From a9c50af76baa9616d16dc7ef775d86bba5a7b772 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 11 Feb 2023 14:39:17 +0100 Subject: [PATCH 384/423] cli: fix webpack loader file extension checks Signed-off-by: Patrik Oldsberg --- .changeset/few-trees-cross.md | 5 +++++ packages/cli/src/lib/bundler/transforms.ts | 9 +++++---- 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 .changeset/few-trees-cross.md diff --git a/.changeset/few-trees-cross.md b/.changeset/few-trees-cross.md new file mode 100644 index 0000000000..ed70c3bddb --- /dev/null +++ b/.changeset/few-trees-cross.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Fixed Webpack loader patterns so that they properly match the file suffix only. diff --git a/packages/cli/src/lib/bundler/transforms.ts b/packages/cli/src/lib/bundler/transforms.ts index 9a93f550dd..e0308f5c2d 100644 --- a/packages/cli/src/lib/bundler/transforms.ts +++ b/packages/cli/src/lib/bundler/transforms.ts @@ -107,7 +107,7 @@ export const transforms = (options: TransformOptions): Transforms => { ], }, { - test: /\.(js|mjs|cjs)/, + test: /\.(js|mjs|cjs)$/, resolve: { fullySpecified: false, }, @@ -141,9 +141,10 @@ export const transforms = (options: TransformOptions): Transforms => { /\.gif$/, /\.jpe?g$/, /\.png$/, - /\.frag/, - { and: [/\.svg/, { not: [/\.icon\.svg/] }] }, - /\.xml/, + /\.frag$/, + /\.vert$/, + { and: [/\.svg$/, { not: [/\.icon\.svg$/] }] }, + /\.xml$/, ], type: 'asset/resource', generator: { From 9fc1e58a5d0d9d5c311a1984740f21471e1a5a7c Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Sat, 11 Feb 2023 09:58:08 -0500 Subject: [PATCH 385/423] chore: Fix install instructions Signed-off-by: Adam Harvey --- plugins/explore-backend/README.md | 11 +++++------ plugins/explore/README.md | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/explore-backend/README.md b/plugins/explore-backend/README.md index 3edf48249a..86f60ae226 100644 --- a/plugins/explore-backend/README.md +++ b/plugins/explore-backend/README.md @@ -76,10 +76,9 @@ To index explore tools you will need to register the search collator in the ```diff +import { ToolDocumentCollatorFactory } from '@backstage/plugin-explore-backend'; -async function createSearchEngine( - env: PluginEnvironment, -): Promise { - ... +... + ++ // collator gathers entities from explore. + indexBuilder.addCollator({ + schedule, + factory: ToolDocumentCollatorFactory.fromConfig(env.config, { @@ -87,8 +86,8 @@ async function createSearchEngine( + logger: env.logger, + }), + }); - ... -} + +... ``` ### Wire up the Frontend diff --git a/plugins/explore/README.md b/plugins/explore/README.md index 2388d97ac1..0bb7258ae6 100644 --- a/plugins/explore/README.md +++ b/plugins/explore/README.md @@ -30,7 +30,7 @@ any path for the route, but we recommend the following: ```diff // packages/app/src/App.tsx -+ import { ExplorePage, explorePlugin } from '@backstage/plugin-explore'; ++ import { ExplorePage } from '@backstage/plugin-explore'; ... From 75cfee5688850b432d79a112ea90bdee3c6b0450 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 19 Nov 2022 16:43:29 -0600 Subject: [PATCH 386/423] Added linguist frontend, backend, and common plugins Signed-off-by: Andre Wanlin Removed refresh and permissions Signed-off-by: Andre Wanlin Small database refactor and improved naming Signed-off-by: Andre Wanlin Refactor stringifyEntityRef usage Signed-off-by: Andre Wanlin Fixed up yarn.lock Signed-off-by: Andre Wanlin --- .changeset/serious-horses-juggle.md | 7 + packages/app/package.json | 2 + .../app/src/components/catalog/EntityPage.tsx | 12 ++ packages/backend/package.json | 1 + packages/backend/src/index.ts | 3 + packages/backend/src/plugins/linguist.ts | 40 ++++ .../components/artist-lookup-component.yaml | 2 + plugins/linguist-backend/.eslintrc.js | 1 + plugins/linguist-backend/README.md | 94 ++++++++++ plugins/linguist-backend/api-report.md | 86 +++++++++ plugins/linguist-backend/config.d.ts | 27 +++ .../migrations/20221115_init.js | 67 +++++++ plugins/linguist-backend/package.json | 57 ++++++ .../src/api/LinguistBackendApi.ts | 173 ++++++++++++++++++ plugins/linguist-backend/src/api/index.ts | 17 ++ .../src/db/LinguistBackendDatabase.ts | 103 +++++++++++ plugins/linguist-backend/src/db/index.ts | 18 ++ plugins/linguist-backend/src/index.ts | 20 ++ plugins/linguist-backend/src/run.ts | 33 ++++ .../src/service/router.test.ts | 83 +++++++++ .../linguist-backend/src/service/router.ts | 108 +++++++++++ .../src/service/standaloneServer.ts | 76 ++++++++ plugins/linguist-backend/src/setupTests.ts | 17 ++ plugins/linguist-common/.eslintrc.js | 1 + plugins/linguist-common/README.md | 3 + plugins/linguist-common/api-report.md | 50 +++++ plugins/linguist-common/package.json | 35 ++++ plugins/linguist-common/src/constants.ts | 18 ++ plugins/linguist-common/src/index.ts | 18 ++ plugins/linguist-common/src/setupTests.ts | 16 ++ plugins/linguist-common/src/types.ts | 54 ++++++ plugins/linguist/.eslintrc.js | 1 + plugins/linguist/README.md | 88 +++++++++ plugins/linguist/api-report.md | 21 +++ plugins/linguist/dev/index.tsx | 27 +++ plugins/linguist/docs/linguist-no-data.png | Bin 0 -> 12616 bytes plugins/linguist/docs/linguist-no-refresh.png | Bin 0 -> 15731 bytes plugins/linguist/docs/linguist-with-data.png | Bin 0 -> 22018 bytes plugins/linguist/package.json | 63 +++++++ plugins/linguist/src/api/LinguistApi.ts | 26 +++ plugins/linguist/src/api/LinguistClient.ts | 59 ++++++ plugins/linguist/src/api/index.ts | 18 ++ .../components/LinguistCard/LinguistCard.tsx | 153 ++++++++++++++++ .../src/components/LinguistCard/index.ts | 17 ++ plugins/linguist/src/hooks/index.ts | 17 ++ plugins/linguist/src/hooks/useLanguages.ts | 41 +++++ plugins/linguist/src/index.ts | 20 ++ plugins/linguist/src/plugin.test.ts | 22 +++ plugins/linguist/src/plugin.ts | 53 ++++++ plugins/linguist/src/setupTests.ts | 18 ++ yarn.lock | 130 +++++++++++-- 51 files changed, 2005 insertions(+), 11 deletions(-) create mode 100644 .changeset/serious-horses-juggle.md create mode 100644 packages/backend/src/plugins/linguist.ts create mode 100644 plugins/linguist-backend/.eslintrc.js create mode 100644 plugins/linguist-backend/README.md create mode 100644 plugins/linguist-backend/api-report.md create mode 100644 plugins/linguist-backend/config.d.ts create mode 100644 plugins/linguist-backend/migrations/20221115_init.js create mode 100644 plugins/linguist-backend/package.json create mode 100644 plugins/linguist-backend/src/api/LinguistBackendApi.ts create mode 100644 plugins/linguist-backend/src/api/index.ts create mode 100644 plugins/linguist-backend/src/db/LinguistBackendDatabase.ts create mode 100644 plugins/linguist-backend/src/db/index.ts create mode 100644 plugins/linguist-backend/src/index.ts create mode 100644 plugins/linguist-backend/src/run.ts create mode 100644 plugins/linguist-backend/src/service/router.test.ts create mode 100644 plugins/linguist-backend/src/service/router.ts create mode 100644 plugins/linguist-backend/src/service/standaloneServer.ts create mode 100644 plugins/linguist-backend/src/setupTests.ts create mode 100644 plugins/linguist-common/.eslintrc.js create mode 100644 plugins/linguist-common/README.md create mode 100644 plugins/linguist-common/api-report.md create mode 100644 plugins/linguist-common/package.json create mode 100644 plugins/linguist-common/src/constants.ts create mode 100644 plugins/linguist-common/src/index.ts create mode 100644 plugins/linguist-common/src/setupTests.ts create mode 100644 plugins/linguist-common/src/types.ts create mode 100644 plugins/linguist/.eslintrc.js create mode 100644 plugins/linguist/README.md create mode 100644 plugins/linguist/api-report.md create mode 100644 plugins/linguist/dev/index.tsx create mode 100644 plugins/linguist/docs/linguist-no-data.png create mode 100644 plugins/linguist/docs/linguist-no-refresh.png create mode 100644 plugins/linguist/docs/linguist-with-data.png create mode 100644 plugins/linguist/package.json create mode 100644 plugins/linguist/src/api/LinguistApi.ts create mode 100644 plugins/linguist/src/api/LinguistClient.ts create mode 100644 plugins/linguist/src/api/index.ts create mode 100644 plugins/linguist/src/components/LinguistCard/LinguistCard.tsx create mode 100644 plugins/linguist/src/components/LinguistCard/index.ts create mode 100644 plugins/linguist/src/hooks/index.ts create mode 100644 plugins/linguist/src/hooks/useLanguages.ts create mode 100644 plugins/linguist/src/index.ts create mode 100644 plugins/linguist/src/plugin.test.ts create mode 100644 plugins/linguist/src/plugin.ts create mode 100644 plugins/linguist/src/setupTests.ts diff --git a/.changeset/serious-horses-juggle.md b/.changeset/serious-horses-juggle.md new file mode 100644 index 0000000000..13be1d9715 --- /dev/null +++ b/.changeset/serious-horses-juggle.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-linguist': minor +'@backstage/plugin-linguist-backend': minor +'@backstage/plugin-linguist-common': minor +--- + +Introduced the Linguist plugin, checkout the plugin's `README.md` for more details! diff --git a/packages/app/package.json b/packages/app/package.json index 80ee11ea15..8c26254268 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -42,6 +42,8 @@ "@backstage/plugin-kubernetes": "workspace:^", "@backstage/plugin-lighthouse": "workspace:^", "@backstage/plugin-microsoft-calendar": "workspace:^", + "@backstage/plugin-linguist": "workspace:^", + "@backstage/plugin-linguist-common": "workspace:^", "@backstage/plugin-newrelic": "workspace:^", "@backstage/plugin-newrelic-dashboard": "workspace:^", "@backstage/plugin-org": "workspace:^", diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 3ab0e83238..9118347414 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -157,6 +157,10 @@ import { LightBox, } from '@backstage/plugin-techdocs-module-addons-contrib'; import { EntityCostInsightsContent } from '@backstage/plugin-cost-insights'; +import { + isLinguistAvailable, + EntityLinguistCard, +} from '@backstage/plugin-linguist'; const customEntityFilterKind = ['Component', 'API', 'System']; @@ -406,6 +410,14 @@ const overviewContent = ( + + + + + + + + diff --git a/packages/backend/package.json b/packages/backend/package.json index 3678c1f9ae..776aa18862 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -50,6 +50,7 @@ "@backstage/plugin-kafka-backend": "workspace:^", "@backstage/plugin-kubernetes-backend": "workspace:^", "@backstage/plugin-lighthouse-backend": "workspace:^", + "@backstage/plugin-linguist-backend": "workspace:^", "@backstage/plugin-permission-backend": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index b68b162e52..eb2befca65 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -63,6 +63,7 @@ import permission from './plugins/permission'; import playlist from './plugins/playlist'; import adr from './plugins/adr'; import lighthouse from './plugins/lighthouse'; +import linguist from './plugins/linguist'; import { PluginEnvironment } from './types'; import { ServerPermissionClient } from '@backstage/plugin-permission-node'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; @@ -154,6 +155,7 @@ async function main() { const eventBasedEntityProviders = await catalogEventBasedProviders( catalogEnv, ); + const linguistEnv = useHotMemoize(module, () => createEnv('linguist')); const apiRouter = Router(); apiRouter.use( @@ -180,6 +182,7 @@ async function main() { apiRouter.use('/playlist', await playlist(playlistEnv)); apiRouter.use('/explore', await explore(exploreEnv)); apiRouter.use('/adr', await adr(adrEnv)); + apiRouter.use('/linguist', await linguist(linguistEnv)); apiRouter.use(notFoundHandler()); await lighthouse(lighthouseEnv); diff --git a/packages/backend/src/plugins/linguist.ts b/packages/backend/src/plugins/linguist.ts new file mode 100644 index 0000000000..d8e56f658b --- /dev/null +++ b/packages/backend/src/plugins/linguist.ts @@ -0,0 +1,40 @@ +/* + * 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 { TaskScheduleDefinition } from '@backstage/backend-tasks'; +import { createRouter } from '@backstage/plugin-linguist-backend'; +import { Router } from 'express'; +import type { PluginEnvironment } from '../types'; + +export default async function createPlugin( + env: PluginEnvironment, +): Promise { + const schedule: TaskScheduleDefinition = { + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 15 }, + }; + + return createRouter({ + logger: env.logger, + config: env.config, + reader: env.reader, + discovery: env.discovery, + database: env.database, + scheduler: env.scheduler, + schedule: schedule, + }); +} diff --git a/packages/catalog-model/examples/components/artist-lookup-component.yaml b/packages/catalog-model/examples/components/artist-lookup-component.yaml index c0022762b4..a3a3780c84 100644 --- a/packages/catalog-model/examples/components/artist-lookup-component.yaml +++ b/packages/catalog-model/examples/components/artist-lookup-component.yaml @@ -28,6 +28,8 @@ metadata: - url: https://example.com/alert title: Alerts icon: alert + annotations: + backstage.io/linguist: 'https://github.com/backstage/backstage/tree/master/plugins/playlist' spec: type: service lifecycle: experimental diff --git a/plugins/linguist-backend/.eslintrc.js b/plugins/linguist-backend/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/linguist-backend/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/linguist-backend/README.md b/plugins/linguist-backend/README.md new file mode 100644 index 0000000000..d3c39a5fe7 --- /dev/null +++ b/plugins/linguist-backend/README.md @@ -0,0 +1,94 @@ +# Linguist Backend + +Welcome to the Linguist backend plugin! This plugin provides data for the Linguist frontend features. + +## Setup + +The following sections will help you get the Linguist Backend plugin setup and running. + +### Up and Running + +Here's how to get the backend up and running: + +1. First we need to add the `@backstage/plugin-linguist-backend` package to your backend: + + ```sh + # From the Backstage root directory + cd packages/backend + yarn add @backstage/plugin-linguist-backend + ``` + +2. Then we will create a new file named `packages/backend/src/plugins/linguist.ts`, and add the + following to it: + + ```ts + import { TaskScheduleDefinition } from '@backstage/backend-tasks'; + import { createRouter } from '@backstage/plugin-linguist-backend'; + import { Router } from 'express'; + import type { PluginEnvironment } from '../types'; + + export default async function createPlugin( + env: PluginEnvironment, + ): Promise { + const schedule: TaskScheduleDefinition = { + frequency: { hours: 24 }, + timeout: { minutes: 30 }, + initialDelay: { seconds: 90 }, + }; + + return createRouter({ + logger: env.logger, + config: env.config, + reader: env.reader, + discovery: env.discovery, + database: env.database, + scheduler: env.scheduler, + schedule: schedule, + }); + } + ``` + +3. Next we wire this into the overall backend router, edit `packages/backend/src/index.ts`: + + ```ts + import linguist from './plugins/linguist'; + // ... + async function main() { + // ... + // Add this line under the other lines that follow the useHotMemoize pattern + const linguistEnv = useHotMemoize(module, () => createEnv('linguist')); + // ... + // Insert this line under the other lines that add their routers to apiRouter in the same way + apiRouter.use('/linguist', await linguist(linguistEnv)); + ``` + +4. Now run `yarn start-backend` from the repo root +5. Finally open `http://localhost:7007/api/linguist/health` in a browser and it should return `{"status":"ok"}` + +## Scheduling + +The Linguist backend can be configured to generate the language breakdown for all the entities with the linguist annotation. This is done by passing a `TaskScheduleDefinition` to the `createRouter` function like in Step 2 of the [Up and Running](#up-and-running) documentation. + +Here's another example of the `TaskScheduleDefinition` that will run the language breakdown processing every 12 hours: + +```ts +const schedule: TaskScheduleDefinition = { + frequency: { hours: 12 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 10 }, +}; +``` + +The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the following configuration to your `app-config.yaml`: + +```yaml +linguist: + age: 15 # Days +``` + +With the configuration setup like this if the language breakdown is older than 15 days it will get regenerated. It's recommended that if you choose to use this configuration to set it to a large value - 30, 90, or 180 - as this data generally does not change drastically. + +## Links + +- [Frontend part of the plugin](../linguist/README.md) +- [The Backstage homepage](https://backstage.io) diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md new file mode 100644 index 0000000000..26656416df --- /dev/null +++ b/plugins/linguist-backend/api-report.md @@ -0,0 +1,86 @@ +## API Report File for "@backstage/plugin-linguist-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Config } from '@backstage/config'; +import { EntitiesOverview } from '@backstage/plugin-linguist-common'; +import { EntityResults } from '@backstage/plugin-linguist-common'; +import express from 'express'; +import { Knex } from 'knex'; +import { Languages } from '@backstage/plugin-linguist-common'; +import { Logger } from 'winston'; +import { PluginDatabaseManager } from '@backstage/backend-common'; +import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { PluginTaskScheduler } from '@backstage/backend-tasks'; +import { ProcessedEntity } from '@backstage/plugin-linguist-common'; +import { TaskScheduleDefinition } from '@backstage/backend-tasks'; +import { UrlReader } from '@backstage/backend-common'; + +// @public (undocumented) +export function createRouter(options: RouterOptions): Promise; + +// @public (undocumented) +export class LinguistBackendApi { + constructor( + config: Config, + logger: Logger, + store: LinguistBackendStore, + urlReader: UrlReader, + discovery: PluginEndpointDiscovery, + ); + // (undocumented) + getEntitiesOverview(): Promise; + // (undocumented) + getEntityLanguages(entityRef: string): Promise; + // (undocumented) + processEntities(): Promise; + // (undocumented) + processEntity(entityRef: string, url: string): Promise; +} + +// @public (undocumented) +export class LinguistBackendDatabase implements LinguistBackendStore { + constructor(db: Knex); + // (undocumented) + static create(knex: Knex): Promise; + // (undocumented) + getEntityResults(entityRef: string): Promise; + // (undocumented) + getProcessedEntities(): Promise; + // (undocumented) + insertEntityResults(entityLanguages: EntityResults): Promise; +} + +// @public (undocumented) +export interface LinguistBackendStore { + // (undocumented) + getEntityResults(entityRef: string): Promise; + // (undocumented) + getProcessedEntities(): Promise; + // (undocumented) + insertEntityResults(entityLanguages: EntityResults): Promise; +} + +// @public (undocumented) +export interface RouterOptions { + // (undocumented) + config: Config; + // (undocumented) + database: PluginDatabaseManager; + // (undocumented) + discovery: PluginEndpointDiscovery; + // (undocumented) + linguistBackendApi?: LinguistBackendApi; + // (undocumented) + logger: Logger; + // (undocumented) + reader: UrlReader; + // (undocumented) + schedule?: TaskScheduleDefinition; + // (undocumented) + scheduler?: PluginTaskScheduler; +} + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/linguist-backend/config.d.ts b/plugins/linguist-backend/config.d.ts new file mode 100644 index 0000000000..8e0133c90b --- /dev/null +++ b/plugins/linguist-backend/config.d.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 interface Config { + /** Configuration options for the linguist-backend plugin */ + linguist?: { + /** + * The age of an entity's languages before a refresh occurs, + * an age of 30 would mean the languages would be regenerated after 30 days. + * The default is 0 meaning languages won't be refreshed once generated. + */ + age: number; + }; +} diff --git a/plugins/linguist-backend/migrations/20221115_init.js b/plugins/linguist-backend/migrations/20221115_init.js new file mode 100644 index 0000000000..9eb0a03a90 --- /dev/null +++ b/plugins/linguist-backend/migrations/20221115_init.js @@ -0,0 +1,67 @@ +/* + * 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) { + // Note for the reader: the knex increments types automatically make it a + // primary column, whether you like it or not. That's why the id column is + // not marked as primary as one might have expected; it's only used for + // lookups by ID. Because, SQLite and MySQL don't return RETURNING on + // inserts ... so we want a manually generated key for lookups (an uuid), + // and also an index for ordering guarantees :) + await knex.schema.createTable('entity_result', table => { + table.comment('Table containing results from running Linguist'); + table + .bigIncrements('index') + .notNullable() + .comment('An insert counter to ensure ordering'); + table.uuid('id').notNullable().comment('The ID of the Linguist result'); + table + .text('entity_ref') + .unique() + .notNullable() + .comment('The entity ref that this Linguist result applies to'); + table + .text('languages') + .notNullable() + .comment('The results json as a string'); + table + .dateTime('created_at') + .defaultTo(knex.fn.now()) + .notNullable() + .comment('The timestamp when this entry was created'); + table + .dateTime('processed_date') + .defaultTo(knex.fn.now()) + .notNullable() + .comment('The timestamp when this entity was processed'); + table.index('index', 'entity_result_index_idx'); + table.index('entity_ref', 'entity_result_entity_ref_idx'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('entity_result', table => { + table.dropIndex([], 'entity_result_index_idx'); + table.dropIndex([], 'entity_result_entity_ref_idx'); + }); + await knex.schema.dropTable('entity_result'); +}; diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json new file mode 100644 index 0000000000..b79a97decd --- /dev/null +++ b/plugins/linguist-backend/package.json @@ -0,0 +1,57 @@ +{ + "name": "@backstage/plugin-linguist-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": "workspace:^", + "@backstage/backend-tasks": "workspace:^", + "@backstage/catalog-client": "workspace:^", + "@backstage/catalog-model": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/plugin-auth-node": "workspace:^", + "@backstage/plugin-linguist-common": "workspace:^", + "@types/express": "*", + "express": "^4.18.1", + "express-promise-router": "^4.1.0", + "fs-extra": "^10.0.0", + "knex": "^2.0.0", + "linguist-js": "^2.5.3", + "luxon": "^2.0.2", + "node-fetch": "^2.6.7", + "uuid": "^8.3.2", + "winston": "^3.2.1", + "yn": "^4.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@types/supertest": "^2.0.8", + "msw": "^0.49.0", + "supertest": "^6.2.4" + }, + "files": [ + "dist", + "config.d.ts", + "migrations/**/*.{js,d.ts}" + ], + "configSchema": "config.d.ts" +} diff --git a/plugins/linguist-backend/src/api/LinguistBackendApi.ts b/plugins/linguist-backend/src/api/LinguistBackendApi.ts new file mode 100644 index 0000000000..fdabea6d6c --- /dev/null +++ b/plugins/linguist-backend/src/api/LinguistBackendApi.ts @@ -0,0 +1,173 @@ +/* + * 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 { + EntitiesOverview, + EntityResults, + Language, + Languages, +} from '@backstage/plugin-linguist-common'; +import { + CATALOG_FILTER_EXISTS, + CatalogClient, + GetEntitiesRequest, +} from '@backstage/catalog-client'; +import { PluginEndpointDiscovery, UrlReader } from '@backstage/backend-common'; + +import { Config } from '@backstage/config'; +import { DateTime } from 'luxon'; +import { LINGUIST_ANNOTATION } from '@backstage/plugin-linguist-common'; +import { LinguistBackendStore } from '../db'; +import { Logger } from 'winston'; +import fs from 'fs-extra'; +import linguist from 'linguist-js'; +import { stringifyEntityRef } from '@backstage/catalog-model'; +import { assertError } from '@backstage/errors'; + +/** @public */ +export class LinguistBackendApi { + public constructor( + private readonly config: Config, + private readonly logger: Logger, + private readonly store: LinguistBackendStore, + private readonly urlReader: UrlReader, + private readonly discovery: PluginEndpointDiscovery, + ) {} + + public async getEntityLanguages(entityRef: string): Promise { + this.logger?.debug(`Getting languages for entity "${entityRef}"`); + + return this.store.getEntityResults(entityRef); + } + + public async processEntity(entityRef: string, url: string): Promise { + this.logger?.info( + `Processing languages for entity ${entityRef} from ${url}`, + ); + + const readTreeResponse = await this.urlReader.readTree(url); + const dir = await readTreeResponse.dir(); + + const results = await linguist(dir); + + try { + const totalBytes = results.languages.bytes; + const langResults = results.languages.results; + + const breakdown: Language[] = []; + for (const key in langResults) { + if (Object.prototype.hasOwnProperty.call(langResults, key)) { + const lang: Language = { + name: key, + percentage: +((langResults[key].bytes / totalBytes) * 100).toFixed( + 2, + ), + bytes: langResults[key].bytes, + type: langResults[key].type, + color: langResults[key].color, + }; + breakdown.push(lang); + } + } + + const languages: Languages = { + languageCount: results.languages.count, + totalBytes: totalBytes, + processedDate: new Date().toISOString(), + breakdown: breakdown, + }; + + const entityResults: EntityResults = { + entityRef: entityRef, + results: languages, + }; + + return await this.store.insertEntityResults(entityResults); + } finally { + this.logger?.info(`Cleaning up files from ${dir}`); + await fs.remove(dir); + } + } + + public async processEntities() { + this.logger?.info('Processing applicable entities through Linguist'); + + const eo = await this.getEntitiesOverview(); + this.logger?.info( + `Entities overview: Entity: ${eo.entityCount}, Processed: ${eo.processedCount}, Pending: ${eo.pendingCount}, Stale ${eo.staleCount}`, + ); + + const entities = eo.filteredEntities; + for (const key in entities) { + if (Object.prototype.hasOwnProperty.call(entities, key)) { + const entityRef = stringifyEntityRef(entities[key]); + + const url = + entities[key].metadata.annotations?.[LINGUIST_ANNOTATION] ?? ''; + + try { + await this.processEntity(entityRef, url); + } catch (e) { + assertError(e); + this.logger.error( + `Unable to process "${entityRef}" using "${url}", ${e.message}`, + ); + } + } + } + } + + public async getEntitiesOverview(): Promise { + this.logger?.debug('Getting pending entities'); + const age = this.config.getOptionalNumber('linguist.age') ?? 0; + const catalogApi = new CatalogClient({ discoveryApi: this.discovery }); + const request: GetEntitiesRequest = { + filter: { + kind: ['API', 'Component', 'Template'], + [`metadata.annotations.${LINGUIST_ANNOTATION}`]: CATALOG_FILTER_EXISTS, + }, + fields: ['kind', 'metadata'], + }; + + const response = await catalogApi.getEntities(request); + const entities = response.items; + + const processedEntities = await this.store.getProcessedEntities(); + + const staleEntities = processedEntities.filter(pe => { + if (age === 0) return false; + const staleDate = DateTime.now().minus({ days: age }); + return DateTime.fromJSDate(pe.processed_date) >= staleDate; + }); + + const filteredEntities = entities.filter(en => { + return processedEntities.every(pe => { + const entityRef = stringifyEntityRef(en); + return pe.entityRef !== entityRef; + }); + }); + + const entitiesOverview: EntitiesOverview = { + entityCount: entities.length, + processedCount: processedEntities.length, + staleCount: staleEntities.length, + pendingCount: filteredEntities.length, + filteredEntities: filteredEntities, + }; + + return entitiesOverview; + } +} diff --git a/plugins/linguist-backend/src/api/index.ts b/plugins/linguist-backend/src/api/index.ts new file mode 100644 index 0000000000..a88fa051d4 --- /dev/null +++ b/plugins/linguist-backend/src/api/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 { LinguistBackendApi } from './LinguistBackendApi'; diff --git a/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts b/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts new file mode 100644 index 0000000000..8faa5c3ff0 --- /dev/null +++ b/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts @@ -0,0 +1,103 @@ +/* + * 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 { Knex } from 'knex'; +import { v4 as uuid } from 'uuid'; +import { + EntityResults, + Languages, + ProcessedEntity, +} from '@backstage/plugin-linguist-common'; + +export type RawDbEntityResultRow = { + id: string; + entity_ref: string; + languages: string; + processed_date: Date; +}; + +/** @public */ +export interface LinguistBackendStore { + insertEntityResults(entityLanguages: EntityResults): Promise; + getEntityResults(entityRef: string): Promise; + getProcessedEntities(): Promise; +} + +const migrationsDir = resolvePackagePath( + '@backstage/plugin-linguist-backend', + 'migrations', +); + +/** @public */ +export class LinguistBackendDatabase implements LinguistBackendStore { + static async create(knex: Knex): Promise { + await knex.migrate.latest({ + directory: migrationsDir, + }); + return new LinguistBackendDatabase(knex); + } + + constructor(private readonly db: Knex) {} + + async insertEntityResults(entityLanguages: EntityResults): Promise { + const entityLanguageId = uuid(); + const entityRef = entityLanguages.entityRef; + + const [result] = await this.db('entity_result') + .insert({ + id: entityLanguageId, + entity_ref: entityRef, + languages: JSON.stringify(entityLanguages.results), + processed_date: new Date(entityLanguages.results.processedDate), + }) + .onConflict('entity_ref') + .merge(['languages', 'processed_date']) + .returning('id'); + + return result.id; + } + + async getEntityResults(entityRef: string): Promise { + const entityResults = await this.db('entity_result') + .where({ entity_ref: entityRef }) + .first(); + + if (!entityResults) { + const emptyResults: Languages = { + languageCount: 0, + totalBytes: 0, + processedDate: 'undefined', + breakdown: [], + }; + return emptyResults; + } + + try { + return JSON.parse(entityResults.languages); + } catch (error) { + throw new Error(`Failed to parse languages for '${entityRef}', ${error}`); + } + } + + async getProcessedEntities(): Promise { + const entityResults = await this.db( + 'entity_result', + ).select('entity_ref', 'processed_date'); + + return entityResults; + } +} diff --git a/plugins/linguist-backend/src/db/index.ts b/plugins/linguist-backend/src/db/index.ts new file mode 100644 index 0000000000..c8ec15da68 --- /dev/null +++ b/plugins/linguist-backend/src/db/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 { LinguistBackendDatabase } from './LinguistBackendDatabase'; +export type { LinguistBackendStore } from './LinguistBackendDatabase'; diff --git a/plugins/linguist-backend/src/index.ts b/plugins/linguist-backend/src/index.ts new file mode 100644 index 0000000000..da1e0ffb00 --- /dev/null +++ b/plugins/linguist-backend/src/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 * from './service/router'; +export { LinguistBackendApi } from './api'; +export { LinguistBackendDatabase } from './db'; +export type { LinguistBackendStore } from './db'; diff --git a/plugins/linguist-backend/src/run.ts b/plugins/linguist-backend/src/run.ts new file mode 100644 index 0000000000..d945aa13f0 --- /dev/null +++ b/plugins/linguist-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/linguist-backend/src/service/router.test.ts b/plugins/linguist-backend/src/service/router.test.ts new file mode 100644 index 0000000000..0e20987a43 --- /dev/null +++ b/plugins/linguist-backend/src/service/router.test.ts @@ -0,0 +1,83 @@ +/* + * 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, + PluginDatabaseManager, + PluginEndpointDiscovery, + UrlReaders, +} from '@backstage/backend-common'; +import express from 'express'; +import request from 'supertest'; +import { ConfigReader } from '@backstage/config'; +import { createRouter } from './router'; +import { LinguistBackendApi } from '../api'; + +function createDatabase(): PluginDatabaseManager { + return DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { + client: 'better-sqlite3', + connection: ':memory:', + }, + }, + }), + ).forPlugin('code-coverage'); +} + +const testDiscovery: jest.Mocked = { + getBaseUrl: jest + .fn() + .mockResolvedValue('http://localhost:7007/api/code-coverage'), + getExternalBaseUrl: jest.fn(), +}; + +const mockUrlReader = UrlReaders.default({ + logger: getVoidLogger(), + config: new ConfigReader({}), +}); + +describe('createRouter', () => { + let linguistBackendApi: jest.Mocked; + let app: express.Express; + + beforeAll(async () => { + const router = await createRouter({ + linguistBackendApi, + config: new ConfigReader({}), + discovery: testDiscovery, + database: createDatabase(), + reader: mockUrlReader, + logger: getVoidLogger(), + }); + app = express().use(router); + }); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + describe('GET /health', () => { + it('returns ok', async () => { + const response = await request(app).get('/health'); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ status: 'ok' }); + }); + }); +}); diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts new file mode 100644 index 0000000000..091b7f408d --- /dev/null +++ b/plugins/linguist-backend/src/service/router.ts @@ -0,0 +1,108 @@ +/* + * 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, + PluginEndpointDiscovery, + UrlReader, +} from '@backstage/backend-common'; +import { Config } from '@backstage/config'; +import express from 'express'; +import Router from 'express-promise-router'; +import { Logger } from 'winston'; +import { LinguistBackendApi } from '../api'; +import { LinguistBackendDatabase } from '../db'; +import { + PluginTaskScheduler, + TaskScheduleDefinition, +} from '@backstage/backend-tasks'; + +/** @public */ +export interface RouterOptions { + linguistBackendApi?: LinguistBackendApi; + config: Config; + logger: Logger; + reader: UrlReader; + database: PluginDatabaseManager; + discovery: PluginEndpointDiscovery; + scheduler?: PluginTaskScheduler; + schedule?: TaskScheduleDefinition; +} + +/** @public */ +export async function createRouter( + options: RouterOptions, +): Promise { + const { config, logger, reader, database, discovery, scheduler, schedule } = + options; + + const linguistBackendStore = await LinguistBackendDatabase.create( + await database.getClient(), + ); + + const linguistBackendApi = + options.linguistBackendApi || + new LinguistBackendApi( + config, + logger, + linguistBackendStore, + reader, + discovery, + ); + + if (scheduler && schedule) { + logger.info( + `Scheduling processing of entities with: ${JSON.stringify(schedule)}`, + ); + await scheduler.scheduleTask({ + id: 'linguist_process_entities', + frequency: schedule.frequency, + timeout: schedule.timeout, + initialDelay: schedule.initialDelay, + scope: schedule.scope, + fn: async () => { + await linguistBackendApi.processEntities(); + }, + }); + } + + const router = Router(); + router.use(express.json()); + + router.get('/health', (_, response) => { + response.send({ status: 'ok' }); + }); + + /** + * /entity-languages?entity=component:default/my-component + */ + router.get('/entity-languages', async (req, res) => { + const { entityRef: entityRef } = req.query; + + if (!entityRef) { + throw new Error('No entityRef was provided'); + } + + const entityLanguages = await linguistBackendApi.getEntityLanguages( + entityRef as string, + ); + res.status(200).json(entityLanguages); + }); + + router.use(errorHandler()); + return router; +} diff --git a/plugins/linguist-backend/src/service/standaloneServer.ts b/plugins/linguist-backend/src/service/standaloneServer.ts new file mode 100644 index 0000000000..5578c20e95 --- /dev/null +++ b/plugins/linguist-backend/src/service/standaloneServer.ts @@ -0,0 +1,76 @@ +/* + * 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, + loadBackendConfig, + SingleHostDiscovery, + UrlReaders, + useHotMemoize, +} from '@backstage/backend-common'; +import { Server } from 'http'; +import { Logger } from 'winston'; +import { createRouter } from './router'; +import knexFactory from 'knex'; + +export interface ServerOptions { + port: number; + enableCors: boolean; + logger: Logger; +} + +export async function startStandaloneServer( + options: ServerOptions, +): Promise { + const logger = options.logger.child({ service: 'linguist-backend' }); + const config = await loadBackendConfig({ logger, argv: process.argv }); + const db = useHotMemoize(module, () => { + const knex = knexFactory({ + client: 'sqlite3', + connection: ':memory:', + useNullAsDefault: true, + }); + + knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { + resource.run('PRAGMA foreign_keys = ON', () => {}); + }); + + return knex; + }); + + logger.debug('Starting application server...'); + const router = await createRouter({ + database: { getClient: async () => db }, + config, + discovery: SingleHostDiscovery.fromConfig(config), + reader: UrlReaders.default({ logger, config }), + logger, + }); + + let service = createServiceBuilder(module) + .setPort(options.port) + .addRouter('/linguist', 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/linguist-backend/src/setupTests.ts b/plugins/linguist-backend/src/setupTests.ts new file mode 100644 index 0000000000..813cdeaae3 --- /dev/null +++ b/plugins/linguist-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/linguist-common/.eslintrc.js b/plugins/linguist-common/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/linguist-common/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/linguist-common/README.md b/plugins/linguist-common/README.md new file mode 100644 index 0000000000..9408f7fcc5 --- /dev/null +++ b/plugins/linguist-common/README.md @@ -0,0 +1,3 @@ +# Linguist Common + +Common types, permissions, and constants for the Linguist plugin. diff --git a/plugins/linguist-common/api-report.md b/plugins/linguist-common/api-report.md new file mode 100644 index 0000000000..a9eceb3839 --- /dev/null +++ b/plugins/linguist-common/api-report.md @@ -0,0 +1,50 @@ +## API Report File for "@backstage/plugin-linguist-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Entity } from '@backstage/catalog-model'; + +// @public (undocumented) +export type EntitiesOverview = { + entityCount: number; + processedCount: number; + pendingCount: number; + staleCount: number; + filteredEntities: Entity[]; +}; + +// @public (undocumented) +export type EntityResults = { + entityRef: string; + results: Languages; +}; + +// @public (undocumented) +export type Language = { + name: string; + percentage: number; + bytes: number; + type: string; + color?: `#${string}`; +}; + +// @public (undocumented) +export type Languages = { + languageCount: number; + totalBytes: number; + processedDate: string; + breakdown: Language[]; +}; + +// @public (undocumented) +export const LINGUIST_ANNOTATION = 'backstage.io/linguist'; + +// @public (undocumented) +export type ProcessedEntity = { + entityRef: string; + processed_date: Date; +}; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/linguist-common/package.json b/plugins/linguist-common/package.json new file mode 100644 index 0000000000..eddc114a67 --- /dev/null +++ b/plugins/linguist-common/package.json @@ -0,0 +1,35 @@ +{ + "name": "@backstage/plugin-linguist-common", + "description": "Common functionalities for the linguist 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/catalog-model": "workspace:^", + "@backstage/plugin-permission-common": "workspace:^" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/linguist-common/src/constants.ts b/plugins/linguist-common/src/constants.ts new file mode 100644 index 0000000000..55b3d21d02 --- /dev/null +++ b/plugins/linguist-common/src/constants.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. + */ + +/** @public */ +export const LINGUIST_ANNOTATION = 'backstage.io/linguist'; diff --git a/plugins/linguist-common/src/index.ts b/plugins/linguist-common/src/index.ts new file mode 100644 index 0000000000..88fe08c714 --- /dev/null +++ b/plugins/linguist-common/src/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 './types'; +export * from './constants'; diff --git a/plugins/linguist-common/src/setupTests.ts b/plugins/linguist-common/src/setupTests.ts new file mode 100644 index 0000000000..8b9b6bd586 --- /dev/null +++ b/plugins/linguist-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/linguist-common/src/types.ts b/plugins/linguist-common/src/types.ts new file mode 100644 index 0000000000..01222492b6 --- /dev/null +++ b/plugins/linguist-common/src/types.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 { Entity } from '@backstage/catalog-model'; + +/** @public */ +export type EntityResults = { + entityRef: string; + results: Languages; +}; + +/** @public */ +export type Languages = { + languageCount: number; + totalBytes: number; + processedDate: string; + breakdown: Language[]; +}; + +/** @public */ +export type Language = { + name: string; + percentage: number; + bytes: number; + type: string; + color?: `#${string}`; +}; + +/** @public */ +export type ProcessedEntity = { + entityRef: string; + processed_date: Date; +}; + +/** @public */ +export type EntitiesOverview = { + entityCount: number; + processedCount: number; + pendingCount: number; + staleCount: number; + filteredEntities: Entity[]; +}; diff --git a/plugins/linguist/.eslintrc.js b/plugins/linguist/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/linguist/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/linguist/README.md b/plugins/linguist/README.md new file mode 100644 index 0000000000..d5ca2199dd --- /dev/null +++ b/plugins/linguist/README.md @@ -0,0 +1,88 @@ +# Linguist + +Welcome to the Linguist plugin! + +## Features + +The Linguist plugin consists of a card that will give you the breakdown of the languages used by the configured Entity in the Catalog. + +When there is no Linguist data yet the card will be empty: + +![Example of empty Linguist card](./docs/linguist-no-data.png) + +Clicking on the refresh icon will generate the language breakdown: + +![Example of Linguist card with data](./docs/linguist-with-data.png) + +Here's an example where the permissions are hiding the refresh button: + +![Example of Linguist card without the refresh button](./docs/linguist-no-refresh.png) + +## Setup + +The following sections will help you get the Linguist plugin setup and running. + +### Backend + +You need to setup the [Linguist backend plugin](../linguist-backend/README.md) before you move forward with any of the following steps if you haven't already. + +### Entity Annotation + +To be able to use the Linguist plugin you need to add the following annotation to any entities you want to use it with: + +```yaml +backstage.io/linguist: https://url.to/your/srouce/code +``` + +Linguist uses the `UrlReader` to pull down the files before it scans them to determine the languages, this means you can pull files from all the supported providers - GitHub, GitLab, Bitbucket, Azure, Google GCS, AWS S3, etc. + +Here's what that will look like in action using the Backstage repo as an example: + +```yaml +# Example catalog-info.yaml entity definition file +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + # ... + annotations: + backstage.io/linguist: https://github.com/backstage/backstage +spec: + type: service + # ... +``` + +### Frontend + +To setup the Linguist Card frontend you'll need to do the following steps: + +1. First we need to add the `@backstage/plugin-linguist` package to your frontend app: + + ```sh + # From your Backstage root directory + yarn add --cwd packages/app @backstage/plugin-linguist + ``` + +2. Second we need to add the `EntityLinguistCard` extension to the entity page in your app: + + ```tsx + // In packages/app/src/components/catalog/EntityPage.tsx + import { isLinguistAvailable, EntityLinguistCard } from '@backstage/plugin-linguist'; + + // For example in the Overview section + const overviewContent = ( + + // ... + + + + + + + + // ... + + ``` + +**Notes:** + +- The `if` prop is optional on the `EntitySwitch.Case`, you can remove it if you always want to see the tab even if the entity being viewed does not have the needed annotation diff --git a/plugins/linguist/api-report.md b/plugins/linguist/api-report.md new file mode 100644 index 0000000000..469b3b93c0 --- /dev/null +++ b/plugins/linguist/api-report.md @@ -0,0 +1,21 @@ +## API Report File for "@backstage/plugin-linguist" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { Entity } from '@backstage/catalog-model'; + +// @public (undocumented) +export const EntityLinguistCard: () => JSX.Element; + +// @public (undocumented) +export const isLinguistAvailable: (entity: Entity) => boolean; + +// @public (undocumented) +export const linguistPlugin: BackstagePlugin<{}, {}, {}>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/linguist/dev/index.tsx b/plugins/linguist/dev/index.tsx new file mode 100644 index 0000000000..bb6fb64b52 --- /dev/null +++ b/plugins/linguist/dev/index.tsx @@ -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 React from 'react'; +import { createDevApp } from '@backstage/dev-utils'; +import { linguistPlugin, EntityLinguistCard } from '../src/plugin'; + +createDevApp() + .registerPlugin(linguistPlugin) + .addPage({ + element: , + title: 'Root Page', + path: '/linguist', + }) + .render(); diff --git a/plugins/linguist/docs/linguist-no-data.png b/plugins/linguist/docs/linguist-no-data.png new file mode 100644 index 0000000000000000000000000000000000000000..208b8df5d54f73c71a3ae070587c46d0e853a788 GIT binary patch literal 12616 zcmeHtbx_n@_%A7`B8`NIO1gAO?h-1Eum~&-f*@TIOCus7sC2I=-AH$%fOI1*Af3{2 z53ld5c<(1Sl&$xQu@t9}Nxdvdlv%6*M$V7-$#bUIO1Q zNSe0M(9reGBqfz)BqiyU?W|4AER506nBQ8y5#^AyC2jE>l3Pl_3%F1C@`@p=S>BZ< zDLi6H-@vHF-4cWh5^1k>Ee>~{@h-o?CU!pMi>puuu2--8IOy;44wXYjXU@95Y`2Hm zD=N~Z+nT4wWMcN-?~J`pz1#Vf!&#?`clP~T*mYh}^DBOhVZ9Bdk84Y{NFP|c#_P03 z1zF1OON>mgS#*eDi+CPo>8jpM9FP|O2p=!9L+$%DX5H(Xb~FgR^8jyMD4u!qZDS8{ z5*gAYRia_2A;(oE2u~dUD4EP7*{3gq>}2`Uf~(WFSMot6a*o^$%wb#AQp$M5`d+qQ zew@YV+cHXB3gf#QDf8wwQ=jBa^v72OO8Th2ASI1vjuauyv(Ee#<145$vS-`I92Gce zTHUtlyA`|djY$-9<-hiNyi=Q4DwK177BJqZe5OCfF+MfwEiq9tdDWuQhWTiH`rAGh z9n>f$X{$&Ju>7&HhKz}V0vao5$0%jsWUNIRapJ<3M~Sk z5t~#QivHgh${%-U?dH&;F)PXo1E2Z7uSa$CpQ&NLdx8G0;a)K1P*y9B#}}Ux`c&ck zHQfU|O01vhGrNXl7Zw4NA^$A-|7Nm7xSTR;MCN$^>P7mX-t5O0dPeVE}o+FhkS{JE^&zB&FE2S|T7cpEgn z^qX$?38i(_X6C)f zvEM@bM|?W0&}@kgi4_&gOjcZ3%#cjc^f8wI#QLkpO=xy+28<{s_fGOsV9*ZDAF+cL z^bu+>+Bg^jYxb?ozNixTyvb0Aw{jdz`Ic_Hi^^Z}6k^aP>c1wsr*`3~cPa@d?z0L8 zp2mywcV9#IMTPt*&%2;(_`C@~xBAFps2*P&AA(DXQ9i&%s{vALf+@-L2e zkgB6kzva4?b&*~LCP0&ew8_iA#^1uY1f%V-*ZWWZ&lfZm0yL$var6AOU)pP&xJ$1R zk1iSpv=68^pU&GDgNx&TyaMDu*!iY@QO2=~fTqR34nnpI%!fVziPNR`a-l(NO!I0S$@lPb6%5Fg7T#j`t&zA6o2tW25YTs zHl$9;g@H)6zGvNIuW~DtdZ`+wEJ@}c^XQLQP`22C=tL0lth^f6j=SwFoP~GNZQHxz zFRB>yGDb7nt4KPGB*SMfrxs52zfdGzl>cbYF zzBWjaD1^Hqs%kbG2&TPp=w6K}iT><2sPjTM@V(5B`+fFcAt`js?o{ou<{fs5u8~sf z$^3))xKhE1r%CSQR+XzIZsS7B*(8ifZd=Eq1jX7$qXlqQKjd0DlgMTh$@FW1iB|&5 zbjRO3j#j7pl*C`hu~+;^Ht@zKe^@z}r`koR?FV^j_}ARUDw59%3}H8jg!4e|8b{D(QnB0>Vwlcf*_6>XTiO1 z_Ko4Hid5niQ$7R@1+8?{Q52d_-sUePB3q1(_h&;P&l8LzH5;TUbVyC&EKA6j?+wZ@ zC6L~KeSN@C)SKXF<6Z#T%1jVPNPDwA_mK`h>x}=1xRUsZ!|;fDJ#5rhOf4rZL)Uv`;5<7UJ-T1t6t-`#9%J_AUagR`elK1h$C3t@@`z0_*s1EpRnppN3TriRrYObZ(O0<0Y;>1KIt^+UOpyvv_g_w zwbce?!+{7Eb$pZ>DwbUYh8m#L^h5T6GPGM#pd{S%?KCp@q4@EJq~LZ3Pu~NB373V} z<27_{8}-8wtJ&8AAvwkemlE>3C(Pw_7F5W8WIj-@^`~=XelrQwy>_5V7noDQ5zUdJ z@M_UCu$|XBGjzz60-Iq2{}joW=DFpJ-CskcoNCnd-1*K3TW^JmaL3!Vu}r_Dw)$LI z-_zhQq~kOSbB{}|1f z;Lv+)sg-lppT_QC^wUI_nGzb`K=-BI`vTD26l(f<%&+Dww1AT?by5@p6Mc}p9Qzda zEO*OwK3!lT-sH5zMnRv)oM&HCO!nDHJJlGzp%mXgNHWYCsmHlN)4ILU(?p^~17uQZ z)2ARXXO!6~es*lLl#y0qV=yMiQO(&U!1EUM&=X1*oW;N#haoaKbpz4vYT58 zII3)d_T-D8L_338)^p2vciT!oR8oy^{s|;Z;+Pfa)qGJ+cyoJU*=l}R_$jP+- zja0SG2=kL4A40brL&XkFo#!IdxAyMtEDv#bCbf`Wlj?o8v)Ov1wF@`=2i?OUlA7-Z zeq@hL9g_o&z1aT*bl!OAv!60KP!`{2dZwJLo!DKu){G(rryTPNdR%6V8x`qXeN;MQ zff=#h%E9*U$Ke4t z$CsNEj;N+oa{O{9>V^B>xWEnb7t|!sjmD>f>mU*stXJ<{83?T}LKXy86)JD$lS-3K+F7H7c4s3f$gDSU6W z)O8=ibz_uV%$5bsf*;vZw@|Ceu2#3q-1TVoN_P&Cb%7)i$HyGD4UvV`a}W96>I+QE zwcDHY^hA*@#ym|7Fv=JX8Cg;kKiLsf#R(IQz93mS6y*+S)L2EJp?bx$J+o!!gcHp^ zY#7jR$5T-O2PLC#Uw~_ft_<&5iS+F5^aIn~n+$u*)Pmd7%$BlVbHwh!q~xmS2ImI15-!{cw;}C)7g)&)4aJr)B{!^`4 zb<6L4b9hZQU(PMBtng9fYk7qPVsG5Z<;L*I?-3m0DRPJusr-^|34*yBYS$;5c&ENK z9n%0eYO7W8brU=Dn3F_Dwxg%>=r#W+b50wR#b@=h3)WtQ!O|@={@uB&%Vi;f!m}(N z?qtyvWDy-npZZDHJg0b+*HCEQuv@Z}4TAtdPg&UrA8B6vq{=28heO-w5C7pbYL@oK zqzHA#7?|nn@yg!KMWOpd>WM#+)#Y($9hBpBkv-BBmw`ug3aTP6HDBl3x|5G(`DF?i z%@s_XD;?Xi0%9#cx}|eOxU?of#3J`4LnPzg2X1M6e_Xu7pk ztW4TDYTZ^OTK!ifIo~1>xZFP&A14agy#_hO^I^}k6G_`hkU7ZJd>tDXYsj=6+Dt$(o7i94Dp|`js_2n7zRO- z1tMG!w@qCZA0}h_p?TwB;?nQ?sHMg-a>zl7;ey8-joXcVc5r!ld?-Qp+38-b8{c@> zKXDZJRyB~G+PyB?A;Nvz1u_VB#m%qqL3wpiu=)8(KPi)5C)|`^u6Al8?=m`sk4jzZ z!ne;3d1L39!aQ(zab~G8Gx9bolCtP5_1&@Nxm3Gj*0s>OCx6NXN+g!)s@Y&a8@2FO zU#WSd4mz1Wf{0Q}CEhXH;*%9pPCCxRzvKCRXu}Ikc!jXA?TI}18)6c)@X(){mc;{G z>m;M>M}|F(SA_3cCf0JxpdZ}fip+?u8gzXPe6&|&ZyQ@4O=UyMo&(igMQ7-;nz;^< znY2-=Xl@d{f6|ubX0L7EGDx5(FjWyhqWRdX}4Q+9VB@{n#o!;ddwg%-hNp+ z=^_05vb;+QTOzu0?}pl+Jd+7;m>6zs#*C`0 zH|ri< zJV4a@w-o_i^S%QQZ$-RxxlqXb&!qpu)Bj&oYA0i!5TvKMCOoAVH5eVcLRY0msqkqBSU^vampW42xAXb}EZ4`=;^RH-NMxRtF#yBXZrxe<2hK03hMB zEid@Xe$I{RQxxhz{dYD4j4~D&@v|AbzZNuo4xkhh4%l|y9~b9^!3QjLplPnc5Ep1az7Yi5Kg6 zkqPNCV4sZa0)K%^CKLdi+9l>ayGWCA7}%$Rw$)!a&{uYVBdy#qJ^hO&MzGKSzZi<* z!S>jn_CH4voaS$eM*hc4&ime0cs}O|z&S|7@5x@h(`(atZ{Y<9avs4HJ!;fITKK!f zjw}uy=p3Fd=ha?0J6ZQ^1j%All2elVE?(`)s`d8X+)$L~)PIl{{7!dTW{!}{2e2`5 zBHWasAzh>&Ks$<>J-5!GqB0QB`WP>7R3#RDE-+HzH=(y7r{uys|7AeU_Cg zlC$s(>V1wf#e@1~8dPTM%4>A)J3SgbXG688Wb=v0wJWq)y`3UZDuB8+P(6)*v^X2M z4B%a#{BsoU3u9dN%z{qwJLqe)O|bK;_MP{himWmO-R(_o&K4aSQajia`K4;SzR*%E z*m(j-5a)4n=(m^}$DUo(D+?JE7>zRuxtH2g_{4+MRMs1mvbW@Ud!!6vj3dpWkCk}7 z@=k*|YZZM=%A?|D3fEpQ{8xrWN+_+0#(~%Y96D$EY{2vafo)4iylp} zEQ5kuc+^%a{x(w5Dcn4-nqLnH+`L~jp@eiE;h&;oK6|~vZc(d zmtcGJ-F&Zhma_6%syudj9zdRp?sQ8wE~X{X4fQxKDtR8N?tc$cYM4N-)0RxQE(1KH z>ToFwGe?A@YD2JEUeTF4s#C@MloBglEY8R|(m>9(zKSeB`tYY?WuA21Q!7yA=zY5wS4Yc0^H>5AoC z0&0tV7z#-_*3Fk0ZL=^T1Bv{8IrJQxv}&`x9b?=N#$-JM-ro)VOsQ7|k?LYyyV|-vF|RuuxyFZtpzXZxwHFUCyBZ ztJj!HL}hOEM-Bnl;CfCC*sHTn+1t$W+!>c$0O~o5+j1B9ICTHRI(S}{BY1jTX`S*k&T+4F8KUc}+O^qrKe;>Vm;XNSvq zt!l?~YamA~Xs6rjOpUX;PUrIdZIMf}`qpQ6=mDhs`#bN)YctinsYkDmyd&+17g_=x z+E~)CPHW&5HRn*0ML{!pf!l10_!-Z${&Z)K?IV+a^LOt^jLSE$dc;rbFs~8<^YqAu z?yimrtkfK>dDr<%VJDz`0wEE$tU;v{uI4L>5;ibtFSJ*VaQ3uB*CozAc^>SFX(BY` zo5m-ks`A%>pNQgTyT?&`Z1<21!5ZXnO$%tDk(UHfvqnsql300)&Ga}xwQihl_=~^5 zCfA@(470xhD%pd+r>tS$BLZ!>s(%h@xfsU{$iG0|d_l*DX(gIs3cJ$1v%sYg6{Qj6`nI zz=iN!aXmb?<0hM?BD_++r8%$6aL*M3B-8&3QL zq3jQvJjdm9h4)U_@~Vit6rd3*$Tc0GpbsHJtVGI*HVt?O8Z?ZI56$FtMV_GImVgJQ zUJvS5%Zgo=U6^vrNQn&GyR=8V2N${$;gLNAP;)4e=m1=`dGgE7)cfMextRjhiQ%Y7 z+K{ewH(4AS8z{}5Jy4{Ux_tnu5gxOLG0U~FVILkROgpWaMwPry_(6Y|Ik=I+Eo`69%!lN({%0d8@)tuuGy0a8lc(x-4fPrpPrY{w#;e}j+ zDcSGdc}A*Tnys*~d9EELdJke;FBNc{8jg*Vl5MEgmWUQrh;RQ*3|XjcD7pyhOYmNj z1&NXHJRnb#Q+d>`9io-ZR`Z4R4w#8t-B`&)PP1Kx1-TVx{jPW^yiiv8w5IHh+Ps`* zkSYs7Szwl2JWrN(i{m+x-LX7X@2h1Irj`!KgXFfe=BHR}JZB*w+_Ep-yPmZ<_i;pZ zLuHWo-2w}NjjX0Iq^6Y{nK{wGO)a3(hJoq@Wzm*5Cb zndR5af@y!XZEF{!79c78!rHJY_FYi3U2>C?%M)O%CfZTOx=pK}n2rwkkF89?e4AD^ zMiP+%NPXotjCGa41RimA0!?MQt|$cw;vw}}M}WM~yBIL7Rdea6i#U&n$A_J$%s53% z{-m}lyO|T1H!>VeY#fWtOy(J-WufgHhRv38H@$7><7Cdtd&wHBrdQWC*P(V_Fv6q# z@1lk7(Rxa9$_CW>k6=daJKf1)tFgPXrgVBgB^)~@CA&Ezy!cA9no-5%Ff&1up;&Kq zb4B(*X}Dv65m)NgGIFCHXI4zJJD#7#*!ziD<7I)4$;w|iRNe4hXh*}@KoeGkVceGE zPS{zaHVoGpO$)>+{to%OtNOmxp%s0cX46G`i8*AG_rR64NY(5jfWOdH>A0g6v z)m!jozQVI;xAv|_i=q+c6$`!F3Rw&ZJVl@ z@=^QsR4$XbJ-UcP!+Y>$HILUu6}elhY}E^UzBm+L#4LHvF*#{5rE#_(5OZ@!hX&g! zdQTm`e#pA3L$O#Qv|7~HVk_$q^L?*c*uy>B%t zH{K!X``#<7rvHwGD0NWNzNns0-|Q~CpW!_WoE7OM7fDeJNb6uJxEj#rnxdbk!6knL zcTMT7ze>j2;;3wvd?v0`oS{#ynz_=O32m2>4aQ7P76rLSs@jL@-oQul&E{s7?oV}$ zHurNN+oZ9!ctvO_gZwR(MFJ^kdA%gAmtIDxGiV84ofRuwQ!8L-ABG@uoV#A2%|)yZ zhP++FM);Xl%LaH^%Lfcbg{RZ-D8ArgEn?&x5Q4Y}rc~MJ#HWd*Y~IecRw`%g%0?On zAw#+NzlE|Cx1PtHR_o;m^E8WgRYX*-cb8V>S^M7V52TM0<2`!8k7S#fS-F9;XUqaE zJrPW8FOQPAU~?=Hwg-ouZe5M9vdxWY*dDf%?70=!vL(b^4Ndu{T7>f87Of}^5Z+^N zzopa{lM%#}v*=&<5_X#7zIan-$@!hIX*bI4#_k-RXrF$R6AzoPv0Hn#idhSPV!mp< zakq%hV&JFH6n9k{<%x(O*iwg2^F37?c(y*t?Vgm>!G5YCjn#X7s-_h)-3+br9&;qj zaOB;RTV5ZrQO9!k3fzH8&NLAZ(1g~7S7n28nhVV^ssEkI*HeqI3cbjMl&ZP6g>pIf z7l)fUmOpCI!mjNZ^IP4H6bK_G#iTL0d&^V)MglR!u;WUU3bL)Z*t`rJEf@~fIjrnD ztJ&);?ps!KYvMv4%Xccvi=^vI`0%<&Y<_ZO-`4jXp=Y_;*(L8@bZjykjc~&==el|f zk=;{2)M_&4-{n-SdGxJ>uKl?4iP4l{lpx*1VX|DhHagXF`_#9%W_n2fD%TVqADtN! zNbrg4+GoxyK7n#6Qd!tKkE1=JQ7_u~@;VZmEzAc*ic<`w)Y(`Y;Z|nF`tmqAN-R?> ziE)7(N+&L(o#7=S(H5sQj3(un`7(Iwenx+TnuwKodxGuj#o;0^B4uuS z@`x?jfVA$Bx(&f2&8P61Xcj`P3I>DbY=nbkGWEz6;T2^Tf)6<#n!T9z;kjl8<(n{wL&mP6GG#ntp`CD*Wo-1z5G0n6 z_SN-)T-AHO@K*0c_U;`R(Rd(x&HfCf7w1^ zOS9@>CGDv*scbY6@I*A8M;NNBy%OOFhqlnh+ql8hhI)y^+EF8;&d00yu5N{6yj zaPxvsahpcG<8)g0L$cBoEDOh*0VZ^`Nh`Jgj)V0pybf25fiQPKX| z^)>Z1Ckz>kD;2n@@YfVNN>u97rCk=OWtq8bw6!_vh$|UY_NyYK^r7-{olUsMiT$zp zCh~-}AFwQn84-all&~!Jp^o*NwK(CoV2UYCVk6m3o43|T*0k32=t}yzL(EDn8pvxT z1CNrpGs6*;Vx4l!T%N+wio$n%3I{PVi(cpbDy?^Jd+Uyb{YWyQWUhR6X^}gKTq%?7 z@*w+I)y;|C>#ECAm?GY3M^uxadJ>ydT@hsIA7|ihg%hKjre9G$_x)W`;qv$RZi3x%zb<%ZUU9QiyZ*u67( zJ4AsKN=bXjSFs;iNM%=-$26pOov+~F}p_j|r~gH5~< zJUr7q3{vJdjo|Y5aN;SkJLxG$bdX+$*6ew4FWFYRgkSi>S7v2%qW+yvjeJHoUn{tn z921QDIWH-wXBDuZCC8_0aMLj#G4yK`eB|?5iwr(uU|#Bwief=TQIbdrC?UKBht5l6 z-`q}-sMhP1Sd`|G?(gkr#CJ<;Prjm=uCVIn{d0K^bp@jYYXH5NiT2%^D&dp~zLALl zwHAp^QS=kly0?ab6@CnzRb>%jg5=kK|xnB zSRTt1$niZe<-wgnqger$&NAmUtp4IQzC#9Dfh+`_D8?Lg(w`0HQQQZZWaHoG zMPmMgIsYjwx+BrfuU&GB*5lxOl~Teg|Y{ZM<@65XJ9H&wd+Q;@17(SM@~bZ|arQNedP(oRdMlWihZM zu_Um>-4Ay%SkPvi-C1di%0ftp)NF|r-(aA25Z?xkFKVPRDiI@t@72(Z5@dnKh^VPP zkSTL+%IdF+k@)?p^v$fr@gFkjUtyLkOcg(Avb>0GL%nl}OzoeS<$m`1ix_a+paPI| zwqnt!i%fMmKO88f@TU5U@LW=Gds5c2>sMy?ugJ&Gq4ZU0{Y!tbnGL}E6)I!)e_bIg z1xUUl@>=x8!vWGCvcTSQ`**c3s!8`MI7k@R#WJ~YHt~NYweAc((2#{un8>=~{K~wH Mw4zk5guc)J0^%y>`2YX_ literal 0 HcmV?d00001 diff --git a/plugins/linguist/docs/linguist-no-refresh.png b/plugins/linguist/docs/linguist-no-refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..a3b4e4fde7fa9a38fb1f4e810a14e800c31b0837 GIT binary patch literal 15731 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 literal 0 HcmV?d00001 diff --git a/plugins/linguist/docs/linguist-with-data.png b/plugins/linguist/docs/linguist-with-data.png new file mode 100644 index 0000000000000000000000000000000000000000..e673f994fab4d1db32b0a1cfb1c06bad657efee3 GIT binary patch literal 22018 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 + id: 'plugin.linguist.service', +}); + +export interface LinguistApi { + getLanguages(entityRef: string): Promise; +} diff --git a/plugins/linguist/src/api/LinguistClient.ts b/plugins/linguist/src/api/LinguistClient.ts new file mode 100644 index 0000000000..3e327ff21e --- /dev/null +++ b/plugins/linguist/src/api/LinguistClient.ts @@ -0,0 +1,59 @@ +/* + * 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, IdentityApi } from '@backstage/core-plugin-api'; +import { ResponseError } from '@backstage/errors'; +import { Languages } from '@backstage/plugin-linguist-common'; +import { LinguistApi } from './LinguistApi'; + +export class LinguistClient implements LinguistApi { + private readonly discoveryApi: DiscoveryApi; + private readonly identityApi: IdentityApi; + + public constructor(options: { + discoveryApi: DiscoveryApi; + identityApi: IdentityApi; + }) { + this.discoveryApi = options.discoveryApi; + this.identityApi = options.identityApi; + } + + public async getLanguages(entityRef: string): Promise { + const queryString = new URLSearchParams(); + queryString.append('entityRef', entityRef); + + const urlSegment = `entity-languages?${queryString}`; + + const items = await this.get(urlSegment); + return items; + } + + private async get(path: string): Promise { + const baseUrl = `${await this.discoveryApi.getBaseUrl('linguist')}/`; + const url = new URL(path, baseUrl); + + const { token } = await this.identityApi.getCredentials(); + const response = await fetch(url.toString(), { + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }); + + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + + return response.json() as Promise; + } +} diff --git a/plugins/linguist/src/api/index.ts b/plugins/linguist/src/api/index.ts new file mode 100644 index 0000000000..ca60b60d53 --- /dev/null +++ b/plugins/linguist/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 './LinguistApi'; +export * from './LinguistClient'; diff --git a/plugins/linguist/src/components/LinguistCard/LinguistCard.tsx b/plugins/linguist/src/components/LinguistCard/LinguistCard.tsx new file mode 100644 index 0000000000..6014487d30 --- /dev/null +++ b/plugins/linguist/src/components/LinguistCard/LinguistCard.tsx @@ -0,0 +1,153 @@ +/* + * 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 { + Box, + Chip, + Tooltip, + Typography, + makeStyles, + Grid, + useTheme, +} from '@material-ui/core'; +import { InfoCard, Progress } from '@backstage/core-components'; +import Alert from '@material-ui/lab/Alert'; +import { DateTime } from 'luxon'; +import React from 'react'; +import slugify from 'slugify'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import { useLanguages } from '../../hooks'; + +const useStyles = makeStyles(theme => ({ + infoCard: { + marginBottom: theme.spacing(3), + }, + barContainer: { + height: theme.spacing(2), + marginBottom: theme.spacing(3), + borderRadius: '4px', + backgroundColor: 'transparent', + overflow: 'hidden', + }, + bar: { + height: '100%', + position: 'relative', + }, + languageDot: { + width: '10px', + height: '10px', + borderRadius: '50%', + marginRight: theme.spacing(1), + display: 'inline-block', + }, + label: { + color: 'inherit', + }, +})); + +export const LinguistCard = () => { + const classes = useStyles(); + const theme = useTheme(); + const { entity } = useEntity(); + const { items, loading, error } = useLanguages(entity); + let barWidth = 0; + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + + if (items && items.languageCount === 0 && items.totalBytes === 0) { + return ( + + + + + There is currently no language data for this entity. + + + + + ); + } + + const breakdown = items?.breakdown.sort((a, b) => + a.percentage < b.percentage ? 1 : -1, + ); + const processedDate = items?.processedDate; + + return breakdown && processedDate ? ( + + + {breakdown.map((language, index: number) => { + barWidth = barWidth + language.percentage; + return ( + + + + ); + })} + + + + {breakdown.map(languages => ( + + + {languages.name} - {languages.percentage}% + + } + variant="outlined" + key={slugify(languages.name, { lower: true })} + /> + ))} + + + + ) : ( + <> + ); +}; diff --git a/plugins/linguist/src/components/LinguistCard/index.ts b/plugins/linguist/src/components/LinguistCard/index.ts new file mode 100644 index 0000000000..aefae143fd --- /dev/null +++ b/plugins/linguist/src/components/LinguistCard/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 { LinguistCard } from './LinguistCard'; diff --git a/plugins/linguist/src/hooks/index.ts b/plugins/linguist/src/hooks/index.ts new file mode 100644 index 0000000000..6f8913cf35 --- /dev/null +++ b/plugins/linguist/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 './useLanguages'; diff --git a/plugins/linguist/src/hooks/useLanguages.ts b/plugins/linguist/src/hooks/useLanguages.ts new file mode 100644 index 0000000000..3e99243e94 --- /dev/null +++ b/plugins/linguist/src/hooks/useLanguages.ts @@ -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. + */ + +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { linguistApiRef } from '../api'; +import { useApi } from '@backstage/core-plugin-api'; +import useAsync from 'react-use/lib/useAsync'; + +import { Languages } from '@backstage/plugin-linguist-common'; + +export function useLanguages(entity: Entity): { + items?: Languages; + loading: boolean; + error?: Error; +} { + const entityRef = stringifyEntityRef(entity); + + const api = useApi(linguistApiRef); + const { value, loading, error } = useAsync(() => { + return api.getLanguages(entityRef); + }, [api, entityRef]); + + return { + items: value, + loading, + error, + }; +} diff --git a/plugins/linguist/src/index.ts b/plugins/linguist/src/index.ts new file mode 100644 index 0000000000..ce9cd98cbd --- /dev/null +++ b/plugins/linguist/src/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 { + linguistPlugin, + isLinguistAvailable, + EntityLinguistCard, +} from './plugin'; diff --git a/plugins/linguist/src/plugin.test.ts b/plugins/linguist/src/plugin.test.ts new file mode 100644 index 0000000000..d2a1016a22 --- /dev/null +++ b/plugins/linguist/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 { linguistPlugin } from './plugin'; + +describe('linguist', () => { + it('should export plugin', () => { + expect(linguistPlugin).toBeDefined(); + }); +}); diff --git a/plugins/linguist/src/plugin.ts b/plugins/linguist/src/plugin.ts new file mode 100644 index 0000000000..917a13ca9a --- /dev/null +++ b/plugins/linguist/src/plugin.ts @@ -0,0 +1,53 @@ +/* + * 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, + discoveryApiRef, + identityApiRef, +} from '@backstage/core-plugin-api'; +import { linguistApiRef, LinguistClient } from './api'; +import { LINGUIST_ANNOTATION } from '@backstage/plugin-linguist-common'; +import { Entity } from '@backstage/catalog-model'; + +/** @public */ +export const isLinguistAvailable = (entity: Entity) => + Boolean(entity.metadata.annotations?.[LINGUIST_ANNOTATION]); + +/** @public */ +export const linguistPlugin = createPlugin({ + id: 'linguist', + apis: [ + createApiFactory({ + api: linguistApiRef, + deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef }, + factory: ({ discoveryApi, identityApi }) => + new LinguistClient({ discoveryApi, identityApi }), + }), + ], +}); + +/** @public */ +export const EntityLinguistCard = linguistPlugin.provide( + createComponentExtension({ + name: 'EntityLinguistCard', + component: { + lazy: () => import('./components/LinguistCard').then(m => m.LinguistCard), + }, + }), +); diff --git a/plugins/linguist/src/setupTests.ts b/plugins/linguist/src/setupTests.ts new file mode 100644 index 0000000000..2b5b615b19 --- /dev/null +++ b/plugins/linguist/src/setupTests.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. + */ + +import '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/yarn.lock b/yarn.lock index 345c28a8b5..9697e098ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6895,6 +6895,78 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-linguist-backend@workspace:^, @backstage/plugin-linguist-backend@workspace:plugins/linguist-backend": + version: 0.0.0-use.local + resolution: "@backstage/plugin-linguist-backend@workspace:plugins/linguist-backend" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-tasks": "workspace:^" + "@backstage/catalog-client": "workspace:^" + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" + "@backstage/plugin-linguist-common": "workspace:^" + "@types/express": "*" + "@types/supertest": ^2.0.8 + express: ^4.18.1 + express-promise-router: ^4.1.0 + fs-extra: ^10.0.0 + knex: ^2.0.0 + linguist-js: ^2.5.3 + luxon: ^2.0.2 + msw: ^0.49.0 + node-fetch: ^2.6.7 + supertest: ^6.2.4 + uuid: ^8.3.2 + winston: ^3.2.1 + yn: ^4.0.0 + languageName: unknown + linkType: soft + +"@backstage/plugin-linguist-common@workspace:^, @backstage/plugin-linguist-common@workspace:plugins/linguist-common": + version: 0.0.0-use.local + resolution: "@backstage/plugin-linguist-common@workspace:plugins/linguist-common" + dependencies: + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/plugin-permission-common": "workspace:^" + languageName: unknown + linkType: soft + +"@backstage/plugin-linguist@workspace:^, @backstage/plugin-linguist@workspace:plugins/linguist": + version: 0.0.0-use.local + resolution: "@backstage/plugin-linguist@workspace:plugins/linguist" + dependencies: + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-catalog-react": "workspace:^" + "@backstage/plugin-linguist-common": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@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/user-event": ^14.0.0 + "@types/node": "*" + cross-fetch: ^3.1.5 + luxon: ^2.0.2 + msw: ^0.49.0 + react-use: ^17.2.4 + slugify: ^1.6.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + languageName: unknown + linkType: soft + "@backstage/plugin-microsoft-calendar@workspace:^, @backstage/plugin-microsoft-calendar@workspace:plugins/microsoft-calendar": version: 0.0.0-use.local resolution: "@backstage/plugin-microsoft-calendar@workspace:plugins/microsoft-calendar" @@ -11244,7 +11316,7 @@ __metadata: languageName: node linkType: hard -"@material-ui/core@npm:^4.11.0, @material-ui/core@npm:^4.11.3, @material-ui/core@npm:^4.12.1, @material-ui/core@npm:^4.12.2, @material-ui/core@npm:^4.12.4": +"@material-ui/core@npm:^4.11.0, @material-ui/core@npm:^4.11.3, @material-ui/core@npm:^4.12.1, @material-ui/core@npm:^4.12.2, @material-ui/core@npm:^4.12.4, @material-ui/core@npm:^4.9.13": version: 4.12.4 resolution: "@material-ui/core@npm:4.12.4" dependencies: @@ -17580,10 +17652,10 @@ __metadata: languageName: node linkType: hard -"binary-extensions@npm:^2.0.0": - version: 2.0.0 - resolution: "binary-extensions@npm:2.0.0" - checksum: 554f65d3378cf71c3185c17dec3ca58334b8ff6ae242db3107284765ce33b2af19efd20c11faec41907a40534929e34b3a98e7d391c61e4211b45732dccb1115 +"binary-extensions@npm:^2.0.0, binary-extensions@npm:^2.2.0": + version: 2.2.0 + resolution: "binary-extensions@npm:2.2.0" + checksum: ccd267956c58d2315f5d3ea6757cf09863c5fc703e50fbeb13a7dc849b812ef76e3cf9ca8f35a0c48498776a7478d7b4a0418e1e2b8cb9cb9731f2922aaad7f8 languageName: node linkType: hard @@ -18943,7 +19015,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:*, commander@npm:^9.1.0, commander@npm:^9.4.1": +"commander@npm:*, commander@npm:^9.1.0, commander@npm:^9.4.1, commander@npm:^9.5.0": version: 9.5.0 resolution: "commander@npm:9.5.0" checksum: c7a3e27aa59e913b54a1bafd366b88650bc41d6651f0cbe258d4ff09d43d6a7394232a4dadd0bf518b3e696fdf595db1028a0d82c785b88bd61f8a440cecfade @@ -22227,6 +22299,8 @@ __metadata: "@backstage/plugin-kafka": "workspace:^" "@backstage/plugin-kubernetes": "workspace:^" "@backstage/plugin-lighthouse": "workspace:^" + "@backstage/plugin-linguist": "workspace:^" + "@backstage/plugin-linguist-common": "workspace:^" "@backstage/plugin-microsoft-calendar": "workspace:^" "@backstage/plugin-newrelic": "workspace:^" "@backstage/plugin-newrelic-dashboard": "workspace:^" @@ -22326,6 +22400,7 @@ __metadata: "@backstage/plugin-kafka-backend": "workspace:^" "@backstage/plugin-kubernetes-backend": "workspace:^" "@backstage/plugin-lighthouse-backend": "workspace:^" + "@backstage/plugin-linguist-backend": "workspace:^" "@backstage/plugin-permission-backend": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" @@ -24806,10 +24881,10 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.1.4, ignore@npm:^5.2.0": - version: 5.2.0 - resolution: "ignore@npm:5.2.0" - checksum: 6b1f926792d614f64c6c83da3a1f9c83f6196c2839aa41e1e32dd7b8d174cef2e329d75caabb62cb61ce9dc432f75e67d07d122a037312db7caa73166a1bdb77 +"ignore@npm:^5.1.4, ignore@npm:^5.2.0, ignore@npm:^5.2.4": + version: 5.2.4 + resolution: "ignore@npm:5.2.4" + checksum: 3d4c309c6006e2621659311783eaea7ebcd41fe4ca1d78c91c473157ad6666a57a2df790fe0d07a12300d9aac2888204d7be8d59f9aaf665b1c7fcdb432517ef languageName: node linkType: hard @@ -25826,7 +25901,7 @@ __metadata: languageName: node linkType: hard -"isbinaryfile@npm:^4.0.10, isbinaryfile@npm:^4.0.8": +"isbinaryfile@npm:^4.0.10, isbinaryfile@npm:^4.0.8, isbinaryfile@npm:^4.0.8 <5": version: 4.0.10 resolution: "isbinaryfile@npm:4.0.10" checksum: a6b28db7e23ac7a77d3707567cac81356ea18bd602a4f21f424f862a31d0e7ab4f250759c98a559ece35ffe4d99f0d339f1ab884ffa9795172f632ab8f88e686 @@ -27699,6 +27774,25 @@ __metadata: languageName: node linkType: hard +"linguist-js@npm:^2.5.3": + version: 2.5.4 + resolution: "linguist-js@npm:2.5.4" + dependencies: + binary-extensions: ^2.2.0 + commander: ^9.5.0 + common-path-prefix: ^3.0.0 + cross-fetch: ^3.1.5 + ignore: ^5.2.4 + isbinaryfile: ^4.0.8 <5 + js-yaml: ^4.1.0 + node-cache: ^5.1.2 + bin: + linguist: bin/index.js + linguist-js: bin/index.js + checksum: 92ebfc45f0f17a056153068f7e939a3e6755307d3696673597e824011d83b698063241aa7d082a7f9059416efce85a49056f0a31b3158c25f79e273e2f51e309 + languageName: node + linkType: hard + "linkify-it@npm:^3.0.1": version: 3.0.2 resolution: "linkify-it@npm:3.0.2" @@ -28244,6 +28338,13 @@ __metadata: languageName: node linkType: hard +"luxon@npm:^2.0.2": + version: 2.5.2 + resolution: "luxon@npm:2.5.2" + checksum: d8b671ffd2ff0b438af862ac11082a81b3aedd9f8b6a4ca636f944224f8dd381125cd4d274ca0a8aedcaf2cfca0fc2ca96fe4cc1b16a28b7af701afb95c0bff8 + languageName: node + linkType: hard + "luxon@npm:^3.0.0, luxon@npm:^3.2.1": version: 3.2.1 resolution: "luxon@npm:3.2.1" @@ -35075,6 +35176,13 @@ __metadata: languageName: node linkType: hard +"slugify@npm:^1.6.4": + version: 1.6.5 + resolution: "slugify@npm:1.6.5" + checksum: a955a1b600201030f4c1daa9bb74a17d4402a0693fc40978bbd17e44e64fd72dad3bac4037422aa8aed55b5170edd57f3f4cd8f59ba331f5cf0f10f1a7795609 + languageName: node + linkType: hard + "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0" From bb1cfedc3399b4c7ab4ef23cd3f51b8a18ce0084 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Wed, 8 Feb 2023 15:55:50 -0600 Subject: [PATCH 387/423] Refactor age to use HumanDuration Signed-off-by: Andre Wanlin --- packages/backend/src/plugins/linguist.ts | 1 + plugins/linguist-backend/README.md | 18 +++++++++---- plugins/linguist-backend/api-report.md | 4 +++ plugins/linguist-backend/config.d.ts | 27 ------------------- plugins/linguist-backend/package.json | 5 ++-- .../src/api/LinguistBackendApi.ts | 6 +++-- .../linguist-backend/src/service/router.ts | 15 +++++++++-- yarn.lock | 1 + 8 files changed, 38 insertions(+), 39 deletions(-) delete mode 100644 plugins/linguist-backend/config.d.ts diff --git a/packages/backend/src/plugins/linguist.ts b/packages/backend/src/plugins/linguist.ts index d8e56f658b..85bf3a72ec 100644 --- a/packages/backend/src/plugins/linguist.ts +++ b/packages/backend/src/plugins/linguist.ts @@ -36,5 +36,6 @@ export default async function createPlugin( database: env.database, scheduler: env.scheduler, schedule: schedule, + age: { days: 30 }, }); } diff --git a/plugins/linguist-backend/README.md b/plugins/linguist-backend/README.md index d3c39a5fe7..0ad585dedd 100644 --- a/plugins/linguist-backend/README.md +++ b/plugins/linguist-backend/README.md @@ -79,14 +79,22 @@ const schedule: TaskScheduleDefinition = { }; ``` -The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the following configuration to your `app-config.yaml`: +The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the `age` in your `packages/backend/src/plugins/linguist.ts`: -```yaml -linguist: - age: 15 # Days +```diff + return createRouter({ + logger: env.logger, + config: env.config, + reader: env.reader, + discovery: env.discovery, + database: env.database, + scheduler: env.scheduler, + schedule: schedule, ++ age: { days: 15 }, + }); ``` -With the configuration setup like this if the language breakdown is older than 15 days it will get regenerated. It's recommended that if you choose to use this configuration to set it to a large value - 30, 90, or 180 - as this data generally does not change drastically. +With the `age` setup like this if the language breakdown is older than 15 days it will get regenerated. It's recommended that if you choose to use this configuration to set it to a large value - 30, 90, or 180 - as this data generally does not change drastically. ## Links diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md index 26656416df..3524c02611 100644 --- a/plugins/linguist-backend/api-report.md +++ b/plugins/linguist-backend/api-report.md @@ -7,6 +7,7 @@ import { Config } from '@backstage/config'; import { EntitiesOverview } from '@backstage/plugin-linguist-common'; import { EntityResults } from '@backstage/plugin-linguist-common'; import express from 'express'; +import { HumanDuration } from '@backstage/types'; import { Knex } from 'knex'; import { Languages } from '@backstage/plugin-linguist-common'; import { Logger } from 'winston'; @@ -28,6 +29,7 @@ export class LinguistBackendApi { store: LinguistBackendStore, urlReader: UrlReader, discovery: PluginEndpointDiscovery, + age?: HumanDuration | undefined, ); // (undocumented) getEntitiesOverview(): Promise; @@ -64,6 +66,8 @@ export interface LinguistBackendStore { // @public (undocumented) export interface RouterOptions { + // (undocumented) + age?: HumanDuration; // (undocumented) config: Config; // (undocumented) diff --git a/plugins/linguist-backend/config.d.ts b/plugins/linguist-backend/config.d.ts deleted file mode 100644 index 8e0133c90b..0000000000 --- a/plugins/linguist-backend/config.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 interface Config { - /** Configuration options for the linguist-backend plugin */ - linguist?: { - /** - * The age of an entity's languages before a refresh occurs, - * an age of 30 would mean the languages would be regenerated after 30 days. - * The default is 0 meaning languages won't be refreshed once generated. - */ - age: number; - }; -} diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json index b79a97decd..b1bf7be071 100644 --- a/plugins/linguist-backend/package.json +++ b/plugins/linguist-backend/package.json @@ -30,6 +30,7 @@ "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-linguist-common": "workspace:^", + "@backstage/types": "workspace:^", "@types/express": "*", "express": "^4.18.1", "express-promise-router": "^4.1.0", @@ -50,8 +51,6 @@ }, "files": [ "dist", - "config.d.ts", "migrations/**/*.{js,d.ts}" - ], - "configSchema": "config.d.ts" + ] } diff --git a/plugins/linguist-backend/src/api/LinguistBackendApi.ts b/plugins/linguist-backend/src/api/LinguistBackendApi.ts index fdabea6d6c..816d731d7f 100644 --- a/plugins/linguist-backend/src/api/LinguistBackendApi.ts +++ b/plugins/linguist-backend/src/api/LinguistBackendApi.ts @@ -36,6 +36,7 @@ import fs from 'fs-extra'; import linguist from 'linguist-js'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { assertError } from '@backstage/errors'; +import { HumanDuration } from '@backstage/types'; /** @public */ export class LinguistBackendApi { @@ -45,6 +46,7 @@ export class LinguistBackendApi { private readonly store: LinguistBackendStore, private readonly urlReader: UrlReader, private readonly discovery: PluginEndpointDiscovery, + private readonly age?: HumanDuration, ) {} public async getEntityLanguages(entityRef: string): Promise { @@ -148,8 +150,8 @@ export class LinguistBackendApi { const processedEntities = await this.store.getProcessedEntities(); const staleEntities = processedEntities.filter(pe => { - if (age === 0) return false; - const staleDate = DateTime.now().minus({ days: age }); + if (age === undefined) return false; + const staleDate = DateTime.now().minus(this.age as HumanDuration); return DateTime.fromJSDate(pe.processed_date) >= staleDate; }); diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts index 091b7f408d..122cb939e3 100644 --- a/plugins/linguist-backend/src/service/router.ts +++ b/plugins/linguist-backend/src/service/router.ts @@ -30,6 +30,7 @@ import { PluginTaskScheduler, TaskScheduleDefinition, } from '@backstage/backend-tasks'; +import { HumanDuration } from '@backstage/types'; /** @public */ export interface RouterOptions { @@ -41,14 +42,23 @@ export interface RouterOptions { discovery: PluginEndpointDiscovery; scheduler?: PluginTaskScheduler; schedule?: TaskScheduleDefinition; + age?: HumanDuration; } /** @public */ export async function createRouter( options: RouterOptions, ): Promise { - const { config, logger, reader, database, discovery, scheduler, schedule } = - options; + const { + config, + logger, + reader, + database, + discovery, + scheduler, + schedule, + age, + } = options; const linguistBackendStore = await LinguistBackendDatabase.create( await database.getClient(), @@ -62,6 +72,7 @@ export async function createRouter( linguistBackendStore, reader, discovery, + age, ); if (scheduler && schedule) { diff --git a/yarn.lock b/yarn.lock index 9697e098ce..9dd67caa8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6908,6 +6908,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-linguist-common": "workspace:^" + "@backstage/types": "workspace:^" "@types/express": "*" "@types/supertest": ^2.0.8 express: ^4.18.1 From d327896ecbb5524f3c413dcdfe46c5ceadc8daa1 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Wed, 8 Feb 2023 17:08:51 -0600 Subject: [PATCH 388/423] Refactored createRouter args Signed-off-by: Andre Wanlin --- packages/backend/src/plugins/linguist.ts | 11 +------- plugins/linguist-backend/README.md | 25 +++-------------- plugins/linguist-backend/api-report.md | 15 ++++++++--- .../src/service/router.test.ts | 26 ++++++++++++------ .../linguist-backend/src/service/router.ts | 27 +++++++++---------- .../src/service/standaloneServer.ts | 24 ++++++++++++----- 6 files changed, 64 insertions(+), 64 deletions(-) diff --git a/packages/backend/src/plugins/linguist.ts b/packages/backend/src/plugins/linguist.ts index 85bf3a72ec..948ca7fbb5 100644 --- a/packages/backend/src/plugins/linguist.ts +++ b/packages/backend/src/plugins/linguist.ts @@ -28,14 +28,5 @@ export default async function createPlugin( initialDelay: { seconds: 15 }, }; - return createRouter({ - logger: env.logger, - config: env.config, - reader: env.reader, - discovery: env.discovery, - database: env.database, - scheduler: env.scheduler, - schedule: schedule, - age: { days: 30 }, - }); + return createRouter({ schedule: schedule, age: { days: 30 } }, { ...env }); } diff --git a/plugins/linguist-backend/README.md b/plugins/linguist-backend/README.md index 0ad585dedd..c42112b694 100644 --- a/plugins/linguist-backend/README.md +++ b/plugins/linguist-backend/README.md @@ -36,15 +36,7 @@ Here's how to get the backend up and running: initialDelay: { seconds: 90 }, }; - return createRouter({ - logger: env.logger, - config: env.config, - reader: env.reader, - discovery: env.discovery, - database: env.database, - scheduler: env.scheduler, - schedule: schedule, - }); + return createRouter({ schedule: schedule }, { ...env }); } ``` @@ -79,19 +71,10 @@ const schedule: TaskScheduleDefinition = { }; ``` -The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the `age` in your `packages/backend/src/plugins/linguist.ts`: +The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the `age` (as a `HumanDuration`) in your `packages/backend/src/plugins/linguist.ts` when you call `createRouter`: -```diff - return createRouter({ - logger: env.logger, - config: env.config, - reader: env.reader, - discovery: env.discovery, - database: env.database, - scheduler: env.scheduler, - schedule: schedule, -+ age: { days: 15 }, - }); +```ts +return createRouter({ schedule: schedule, age: { days: 30 } }, { ...env }); ``` With the `age` setup like this if the language breakdown is older than 15 days it will get regenerated. It's recommended that if you choose to use this configuration to set it to a large value - 30, 90, or 180 - as this data generally does not change drastically. diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md index 3524c02611..3fd2823815 100644 --- a/plugins/linguist-backend/api-report.md +++ b/plugins/linguist-backend/api-report.md @@ -19,7 +19,10 @@ import { TaskScheduleDefinition } from '@backstage/backend-tasks'; import { UrlReader } from '@backstage/backend-common'; // @public (undocumented) -export function createRouter(options: RouterOptions): Promise; +export function createRouter( + pluginOptions: PluginOptions, + routerOptions: RouterOptions, +): Promise; // @public (undocumented) export class LinguistBackendApi { @@ -65,9 +68,15 @@ export interface LinguistBackendStore { } // @public (undocumented) -export interface RouterOptions { +export interface PluginOptions { // (undocumented) age?: HumanDuration; + // (undocumented) + schedule?: TaskScheduleDefinition; +} + +// @public (undocumented) +export interface RouterOptions { // (undocumented) config: Config; // (undocumented) @@ -81,8 +90,6 @@ export interface RouterOptions { // (undocumented) reader: UrlReader; // (undocumented) - schedule?: TaskScheduleDefinition; - // (undocumented) scheduler?: PluginTaskScheduler; } diff --git a/plugins/linguist-backend/src/service/router.test.ts b/plugins/linguist-backend/src/service/router.test.ts index 0e20987a43..1de162c97a 100644 --- a/plugins/linguist-backend/src/service/router.test.ts +++ b/plugins/linguist-backend/src/service/router.test.ts @@ -26,6 +26,7 @@ import request from 'supertest'; import { ConfigReader } from '@backstage/config'; import { createRouter } from './router'; import { LinguistBackendApi } from '../api'; +import { TaskScheduleDefinition } from '@backstage/backend-tasks'; function createDatabase(): PluginDatabaseManager { return DatabaseManager.fromConfig( @@ -52,19 +53,28 @@ const mockUrlReader = UrlReaders.default({ config: new ConfigReader({}), }); +const schedule: TaskScheduleDefinition = { + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 15 }, +}; + describe('createRouter', () => { let linguistBackendApi: jest.Mocked; let app: express.Express; beforeAll(async () => { - const router = await createRouter({ - linguistBackendApi, - config: new ConfigReader({}), - discovery: testDiscovery, - database: createDatabase(), - reader: mockUrlReader, - logger: getVoidLogger(), - }); + const router = await createRouter( + { schedule: schedule, age: { days: 30 } }, + { + linguistBackendApi, + config: new ConfigReader({}), + discovery: testDiscovery, + database: createDatabase(), + reader: mockUrlReader, + logger: getVoidLogger(), + }, + ); app = express().use(router); }); diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts index 122cb939e3..8cf426f2b3 100644 --- a/plugins/linguist-backend/src/service/router.ts +++ b/plugins/linguist-backend/src/service/router.ts @@ -32,6 +32,12 @@ import { } from '@backstage/backend-tasks'; import { HumanDuration } from '@backstage/types'; +/** @public */ +export interface PluginOptions { + schedule?: TaskScheduleDefinition; + age?: HumanDuration; +} + /** @public */ export interface RouterOptions { linguistBackendApi?: LinguistBackendApi; @@ -41,31 +47,24 @@ export interface RouterOptions { database: PluginDatabaseManager; discovery: PluginEndpointDiscovery; scheduler?: PluginTaskScheduler; - schedule?: TaskScheduleDefinition; - age?: HumanDuration; } /** @public */ export async function createRouter( - options: RouterOptions, + pluginOptions: PluginOptions, + routerOptions: RouterOptions, ): Promise { - const { - config, - logger, - reader, - database, - discovery, - scheduler, - schedule, - age, - } = options; + const { schedule, age } = pluginOptions; + + const { config, logger, reader, database, discovery, scheduler } = + routerOptions; const linguistBackendStore = await LinguistBackendDatabase.create( await database.getClient(), ); const linguistBackendApi = - options.linguistBackendApi || + routerOptions.linguistBackendApi || new LinguistBackendApi( config, logger, diff --git a/plugins/linguist-backend/src/service/standaloneServer.ts b/plugins/linguist-backend/src/service/standaloneServer.ts index 5578c20e95..874806e788 100644 --- a/plugins/linguist-backend/src/service/standaloneServer.ts +++ b/plugins/linguist-backend/src/service/standaloneServer.ts @@ -25,6 +25,7 @@ import { Server } from 'http'; import { Logger } from 'winston'; import { createRouter } from './router'; import knexFactory from 'knex'; +import { TaskScheduleDefinition } from '@backstage/backend-tasks'; export interface ServerOptions { port: number; @@ -51,14 +52,23 @@ export async function startStandaloneServer( return knex; }); + const schedule: TaskScheduleDefinition = { + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 15 }, + }; + logger.debug('Starting application server...'); - const router = await createRouter({ - database: { getClient: async () => db }, - config, - discovery: SingleHostDiscovery.fromConfig(config), - reader: UrlReaders.default({ logger, config }), - logger, - }); + const router = await createRouter( + { schedule: schedule, age: { days: 30 } }, + { + database: { getClient: async () => db }, + config, + discovery: SingleHostDiscovery.fromConfig(config), + reader: UrlReaders.default({ logger, config }), + logger, + }, + ); let service = createServiceBuilder(module) .setPort(options.port) From 54f08f8bd9671bb87bf5b0932856bc1fd6dc25c5 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Thu, 9 Feb 2023 14:58:01 -0600 Subject: [PATCH 389/423] Refactored processing Signed-off-by: Andre Wanlin --- packages/backend/src/plugins/linguist.ts | 10 +- plugins/linguist-backend/README.md | 33 +++-- plugins/linguist-backend/api-report.md | 24 ++- .../migrations/20221115_init.js | 6 +- .../src/api/LinguistBackendApi.ts | 140 +++++++++++------- .../src/db/LinguistBackendDatabase.ts | 56 ++++++- .../src/service/router.test.ts | 3 +- .../linguist-backend/src/service/router.ts | 12 +- .../src/service/standaloneServer.ts | 3 +- plugins/linguist-common/api-report.md | 6 +- plugins/linguist-common/package.json | 4 - plugins/linguist-common/src/types.ts | 5 +- yarn.lock | 2 - 13 files changed, 199 insertions(+), 105 deletions(-) diff --git a/packages/backend/src/plugins/linguist.ts b/packages/backend/src/plugins/linguist.ts index 948ca7fbb5..2c8713a7e3 100644 --- a/packages/backend/src/plugins/linguist.ts +++ b/packages/backend/src/plugins/linguist.ts @@ -28,5 +28,13 @@ export default async function createPlugin( initialDelay: { seconds: 15 }, }; - return createRouter({ schedule: schedule, age: { days: 30 } }, { ...env }); + return createRouter( + { + schedule: schedule, + age: { days: 30 }, + batchSize: 2, + useSourceLocation: false, + }, + { ...env }, + ); } diff --git a/plugins/linguist-backend/README.md b/plugins/linguist-backend/README.md index c42112b694..cd63f5db03 100644 --- a/plugins/linguist-backend/README.md +++ b/plugins/linguist-backend/README.md @@ -31,8 +31,8 @@ Here's how to get the backend up and running: env: PluginEnvironment, ): Promise { const schedule: TaskScheduleDefinition = { - frequency: { hours: 24 }, - timeout: { minutes: 30 }, + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, initialDelay: { seconds: 90 }, }; @@ -57,20 +57,18 @@ Here's how to get the backend up and running: 4. Now run `yarn start-backend` from the repo root 5. Finally open `http://localhost:7007/api/linguist/health` in a browser and it should return `{"status":"ok"}` -## Scheduling +## Batch Size -The Linguist backend can be configured to generate the language breakdown for all the entities with the linguist annotation. This is done by passing a `TaskScheduleDefinition` to the `createRouter` function like in Step 2 of the [Up and Running](#up-and-running) documentation. - -Here's another example of the `TaskScheduleDefinition` that will run the language breakdown processing every 12 hours: +The Linguist backend is setup to process entities by acting as a queue where it will pull down all the applicable entities from the Catalog and add them to it's database (saving just the `entityRef`). Then it will grab the `n` oldest entities that have not been processed to determine their languages and process them. To control the batch size simply provide that to the `createRouter` function in your `packages/backend/src/plugins/linguist.ts` like this: ```ts -const schedule: TaskScheduleDefinition = { - frequency: { hours: 12 }, - timeout: { minutes: 15 }, - initialDelay: { seconds: 10 }, -}; +return createRouter({ schedule: schedule, batchSize: 40 }, { ...env }); ``` +**Note:** The default batch size is 20 + +## Refresh + The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the `age` (as a `HumanDuration`) in your `packages/backend/src/plugins/linguist.ts` when you call `createRouter`: ```ts @@ -79,6 +77,19 @@ return createRouter({ schedule: schedule, age: { days: 30 } }, { ...env }); With the `age` setup like this if the language breakdown is older than 15 days it will get regenerated. It's recommended that if you choose to use this configuration to set it to a large value - 30, 90, or 180 - as this data generally does not change drastically. +## Use Source Location + +You may wish to use the `backstage.io/source-location` annotation over using the `backstage.io/linguist` as you may not be able to quickly add that annotation to your Entities. To do this you'll just need to set the `useSourceLocation` boolean to `true` in your `packages/backend/src/plugins/linguist.ts` when you call `createRouter`: + +```ts +return createRouter( + { schedule: schedule, useSourceLocation: true }, + { ...env }, +); +``` + +**Note:** This has the potential to cause a lot of processing, be very thoughtful about this before hand + ## Links - [Frontend part of the plugin](../linguist/README.md) diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md index 3fd2823815..484998b099 100644 --- a/plugins/linguist-backend/api-report.md +++ b/plugins/linguist-backend/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { Config } from '@backstage/config'; import { EntitiesOverview } from '@backstage/plugin-linguist-common'; import { EntityResults } from '@backstage/plugin-linguist-common'; import express from 'express'; @@ -27,12 +26,13 @@ export function createRouter( // @public (undocumented) export class LinguistBackendApi { constructor( - config: Config, logger: Logger, store: LinguistBackendStore, urlReader: UrlReader, discovery: PluginEndpointDiscovery, - age?: HumanDuration | undefined, + age?: HumanDuration, + batchSize?: number, + useSourceLocation?: boolean, ); // (undocumented) getEntitiesOverview(): Promise; @@ -52,9 +52,13 @@ export class LinguistBackendDatabase implements LinguistBackendStore { // (undocumented) getEntityResults(entityRef: string): Promise; // (undocumented) - getProcessedEntities(): Promise; + getProcessedEntities(): Promise; + // (undocumented) + getUnprocessedEntities(): Promise; // (undocumented) insertEntityResults(entityLanguages: EntityResults): Promise; + // (undocumented) + insertNewEntity(entityRef: string): Promise; } // @public (undocumented) @@ -62,9 +66,13 @@ export interface LinguistBackendStore { // (undocumented) getEntityResults(entityRef: string): Promise; // (undocumented) - getProcessedEntities(): Promise; + getProcessedEntities(): Promise; + // (undocumented) + getUnprocessedEntities(): Promise; // (undocumented) insertEntityResults(entityLanguages: EntityResults): Promise; + // (undocumented) + insertNewEntity(entityRef: string): Promise; } // @public (undocumented) @@ -72,13 +80,15 @@ export interface PluginOptions { // (undocumented) age?: HumanDuration; // (undocumented) + batchSize?: number; + // (undocumented) schedule?: TaskScheduleDefinition; + // (undocumented) + useSourceLocation?: boolean; } // @public (undocumented) export interface RouterOptions { - // (undocumented) - config: Config; // (undocumented) database: PluginDatabaseManager; // (undocumented) diff --git a/plugins/linguist-backend/migrations/20221115_init.js b/plugins/linguist-backend/migrations/20221115_init.js index 9eb0a03a90..3bcf99e08b 100644 --- a/plugins/linguist-backend/migrations/20221115_init.js +++ b/plugins/linguist-backend/migrations/20221115_init.js @@ -36,10 +36,7 @@ exports.up = async function up(knex) { .unique() .notNullable() .comment('The entity ref that this Linguist result applies to'); - table - .text('languages') - .notNullable() - .comment('The results json as a string'); + table.text('languages').comment('The results json as a string'); table .dateTime('created_at') .defaultTo(knex.fn.now()) @@ -48,7 +45,6 @@ exports.up = async function up(knex) { table .dateTime('processed_date') .defaultTo(knex.fn.now()) - .notNullable() .comment('The timestamp when this entity was processed'); table.index('index', 'entity_result_index_idx'); table.index('entity_ref', 'entity_result_entity_ref_idx'); diff --git a/plugins/linguist-backend/src/api/LinguistBackendApi.ts b/plugins/linguist-backend/src/api/LinguistBackendApi.ts index 816d731d7f..a5bbc5e639 100644 --- a/plugins/linguist-backend/src/api/LinguistBackendApi.ts +++ b/plugins/linguist-backend/src/api/LinguistBackendApi.ts @@ -27,27 +27,48 @@ import { } from '@backstage/catalog-client'; import { PluginEndpointDiscovery, UrlReader } from '@backstage/backend-common'; -import { Config } from '@backstage/config'; import { DateTime } from 'luxon'; import { LINGUIST_ANNOTATION } from '@backstage/plugin-linguist-common'; import { LinguistBackendStore } from '../db'; import { Logger } from 'winston'; import fs from 'fs-extra'; import linguist from 'linguist-js'; -import { stringifyEntityRef } from '@backstage/catalog-model'; +import { + ANNOTATION_SOURCE_LOCATION, + stringifyEntityRef, +} from '@backstage/catalog-model'; import { assertError } from '@backstage/errors'; import { HumanDuration } from '@backstage/types'; /** @public */ export class LinguistBackendApi { + private readonly logger: Logger; + private readonly store: LinguistBackendStore; + private readonly urlReader: UrlReader; + private readonly discovery: PluginEndpointDiscovery; + private readonly catalogClient: CatalogClient; + private readonly age?: HumanDuration; + private readonly batchSize?: number; + private readonly useSourceLocation?: boolean; public constructor( - private readonly config: Config, - private readonly logger: Logger, - private readonly store: LinguistBackendStore, - private readonly urlReader: UrlReader, - private readonly discovery: PluginEndpointDiscovery, - private readonly age?: HumanDuration, - ) {} + logger: Logger, + store: LinguistBackendStore, + urlReader: UrlReader, + discovery: PluginEndpointDiscovery, + age?: HumanDuration, + batchSize?: number, + useSourceLocation?: boolean, + ) { + this.logger = logger; + this.store = store; + this.urlReader = urlReader; + this.discovery = discovery; + this.catalogClient = new CatalogClient({ discoveryApi: this.discovery }); + + this.batchSize = batchSize; + this.age = age; + this.useSourceLocation = useSourceLocation; + } public async getEntityLanguages(entityRef: string): Promise { this.logger?.debug(`Getting languages for entity "${entityRef}"`); @@ -105,65 +126,59 @@ export class LinguistBackendApi { } public async processEntities() { + this.logger?.info('Updating list of entities'); + + await this.addNewEntities(); + this.logger?.info('Processing applicable entities through Linguist'); - const eo = await this.getEntitiesOverview(); + const entitiesOverview = await this.getEntitiesOverview(); this.logger?.info( - `Entities overview: Entity: ${eo.entityCount}, Processed: ${eo.processedCount}, Pending: ${eo.pendingCount}, Stale ${eo.staleCount}`, + `Entities overview: Entity: ${entitiesOverview.entityCount}, Processed: ${entitiesOverview.processedCount}, Pending: ${entitiesOverview.pendingCount}, Stale ${entitiesOverview.staleCount}`, ); - const entities = eo.filteredEntities; - for (const key in entities) { - if (Object.prototype.hasOwnProperty.call(entities, key)) { - const entityRef = stringifyEntityRef(entities[key]); + const entities = entitiesOverview.filteredEntities.slice( + this.batchSize ?? 20, + ); + entities.forEach(async entityRef => { + const entity = await this.catalogClient.getEntityByRef(entityRef); + const annotationKey = this.useSourceLocation + ? ANNOTATION_SOURCE_LOCATION + : LINGUIST_ANNOTATION; - const url = - entities[key].metadata.annotations?.[LINGUIST_ANNOTATION] ?? ''; - - try { - await this.processEntity(entityRef, url); - } catch (e) { - assertError(e); - this.logger.error( - `Unable to process "${entityRef}" using "${url}", ${e.message}`, - ); - } + let url = entity?.metadata.annotations?.[annotationKey] ?? ''; + if (url.startsWith('url:')) { + url = url.slice(4); } - } + + try { + await this.processEntity(entityRef, url); + } catch (error) { + assertError(error); + this.logger.error( + `Unable to process "${entityRef}" using "${url}", message: ${error.message}, stack: ${error.stack}`, + ); + } + }); } public async getEntitiesOverview(): Promise { this.logger?.debug('Getting pending entities'); - const age = this.config.getOptionalNumber('linguist.age') ?? 0; - const catalogApi = new CatalogClient({ discoveryApi: this.discovery }); - const request: GetEntitiesRequest = { - filter: { - kind: ['API', 'Component', 'Template'], - [`metadata.annotations.${LINGUIST_ANNOTATION}`]: CATALOG_FILTER_EXISTS, - }, - fields: ['kind', 'metadata'], - }; - - const response = await catalogApi.getEntities(request); - const entities = response.items; const processedEntities = await this.store.getProcessedEntities(); + const staleEntities = processedEntities + .filter(pe => { + if (this.age === undefined) return false; + const staleDate = DateTime.now().minus(this.age as HumanDuration); + return DateTime.fromJSDate(pe.processedDate) <= staleDate; + }) + .map(pe => pe.entityRef); - const staleEntities = processedEntities.filter(pe => { - if (age === undefined) return false; - const staleDate = DateTime.now().minus(this.age as HumanDuration); - return DateTime.fromJSDate(pe.processed_date) >= staleDate; - }); - - const filteredEntities = entities.filter(en => { - return processedEntities.every(pe => { - const entityRef = stringifyEntityRef(en); - return pe.entityRef !== entityRef; - }); - }); + const unprocessedEntities = await this.store.getUnprocessedEntities(); + const filteredEntities = staleEntities.concat(unprocessedEntities); const entitiesOverview: EntitiesOverview = { - entityCount: entities.length, + entityCount: unprocessedEntities.length, processedCount: processedEntities.length, staleCount: staleEntities.length, pendingCount: filteredEntities.length, @@ -172,4 +187,25 @@ export class LinguistBackendApi { return entitiesOverview; } + + private async addNewEntities() { + const annotationKey = this.useSourceLocation + ? ANNOTATION_SOURCE_LOCATION + : LINGUIST_ANNOTATION; + const request: GetEntitiesRequest = { + filter: { + kind: ['API', 'Component', 'Template'], + [`metadata.annotations.${annotationKey}`]: CATALOG_FILTER_EXISTS, + }, + fields: ['kind', 'metadata'], + }; + + const response = await this.catalogClient.getEntities(request); + const entities = response.items; + + entities.forEach(entity => { + const entityRef = stringifyEntityRef(entity); + this.store.insertNewEntity(entityRef); + }); + } } diff --git a/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts b/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts index 8faa5c3ff0..cf93374800 100644 --- a/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts +++ b/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts @@ -33,8 +33,10 @@ export type RawDbEntityResultRow = { /** @public */ export interface LinguistBackendStore { insertEntityResults(entityLanguages: EntityResults): Promise; + insertNewEntity(entityRef: string): Promise; getEntityResults(entityRef: string): Promise; - getProcessedEntities(): Promise; + getProcessedEntities(): Promise; + getUnprocessedEntities(): Promise; } const migrationsDir = resolvePackagePath( @@ -71,8 +73,21 @@ export class LinguistBackendDatabase implements LinguistBackendStore { return result.id; } + async insertNewEntity(entityRef: string): Promise { + const entityLanguageId = uuid(); + + await this.db('entity_result') + .insert({ + id: entityLanguageId, + entity_ref: entityRef, + }) + .onConflict('entity_ref') + .ignore(); // If the entity_ref is in the table already then we don't want to add it again + } + async getEntityResults(entityRef: string): Promise { const entityResults = await this.db('entity_result') + .whereNotNull('languages') .where({ entity_ref: entityRef }) .first(); @@ -93,11 +108,40 @@ export class LinguistBackendDatabase implements LinguistBackendStore { } } - async getProcessedEntities(): Promise { - const entityResults = await this.db( - 'entity_result', - ).select('entity_ref', 'processed_date'); + async getProcessedEntities(): Promise { + const rawEntities = await this.db('entity_result') + .whereNotNull('processed_date') + .whereNotNull('languages'); - return entityResults; + if (!rawEntities) { + return []; + } + + const processedEntities = rawEntities.map(rawEntity => { + const processEntity = { + entityRef: rawEntity.entity_ref, + processedDate: rawEntity.processed_date, + }; + + return processEntity; + }); + + return processedEntities; + } + + async getUnprocessedEntities(): Promise { + const rawEntities = await this.db('entity_result') + .whereNull('languages') + .orderBy('created_at', 'asc'); + + if (!rawEntities) { + return []; + } + + const unprocessedEntities = rawEntities.map(rawEntity => { + return rawEntity.entity_ref; + }); + + return unprocessedEntities; } } diff --git a/plugins/linguist-backend/src/service/router.test.ts b/plugins/linguist-backend/src/service/router.test.ts index 1de162c97a..34f16f4b21 100644 --- a/plugins/linguist-backend/src/service/router.test.ts +++ b/plugins/linguist-backend/src/service/router.test.ts @@ -65,10 +65,9 @@ describe('createRouter', () => { beforeAll(async () => { const router = await createRouter( - { schedule: schedule, age: { days: 30 } }, + { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, { linguistBackendApi, - config: new ConfigReader({}), discovery: testDiscovery, database: createDatabase(), reader: mockUrlReader, diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts index 8cf426f2b3..e3aeec604e 100644 --- a/plugins/linguist-backend/src/service/router.ts +++ b/plugins/linguist-backend/src/service/router.ts @@ -20,7 +20,6 @@ import { PluginEndpointDiscovery, UrlReader, } from '@backstage/backend-common'; -import { Config } from '@backstage/config'; import express from 'express'; import Router from 'express-promise-router'; import { Logger } from 'winston'; @@ -36,12 +35,13 @@ import { HumanDuration } from '@backstage/types'; export interface PluginOptions { schedule?: TaskScheduleDefinition; age?: HumanDuration; + batchSize?: number; + useSourceLocation?: boolean; } /** @public */ export interface RouterOptions { linguistBackendApi?: LinguistBackendApi; - config: Config; logger: Logger; reader: UrlReader; database: PluginDatabaseManager; @@ -54,10 +54,9 @@ export async function createRouter( pluginOptions: PluginOptions, routerOptions: RouterOptions, ): Promise { - const { schedule, age } = pluginOptions; + const { schedule, age, batchSize, useSourceLocation } = pluginOptions; - const { config, logger, reader, database, discovery, scheduler } = - routerOptions; + const { logger, reader, database, discovery, scheduler } = routerOptions; const linguistBackendStore = await LinguistBackendDatabase.create( await database.getClient(), @@ -66,12 +65,13 @@ export async function createRouter( const linguistBackendApi = routerOptions.linguistBackendApi || new LinguistBackendApi( - config, logger, linguistBackendStore, reader, discovery, age, + batchSize, + useSourceLocation, ); if (scheduler && schedule) { diff --git a/plugins/linguist-backend/src/service/standaloneServer.ts b/plugins/linguist-backend/src/service/standaloneServer.ts index 874806e788..828c83630a 100644 --- a/plugins/linguist-backend/src/service/standaloneServer.ts +++ b/plugins/linguist-backend/src/service/standaloneServer.ts @@ -60,10 +60,9 @@ export async function startStandaloneServer( logger.debug('Starting application server...'); const router = await createRouter( - { schedule: schedule, age: { days: 30 } }, + { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, { database: { getClient: async () => db }, - config, discovery: SingleHostDiscovery.fromConfig(config), reader: UrlReaders.default({ logger, config }), logger, diff --git a/plugins/linguist-common/api-report.md b/plugins/linguist-common/api-report.md index a9eceb3839..954bef7904 100644 --- a/plugins/linguist-common/api-report.md +++ b/plugins/linguist-common/api-report.md @@ -3,15 +3,13 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { Entity } from '@backstage/catalog-model'; - // @public (undocumented) export type EntitiesOverview = { entityCount: number; processedCount: number; pendingCount: number; staleCount: number; - filteredEntities: Entity[]; + filteredEntities: string[]; }; // @public (undocumented) @@ -43,7 +41,7 @@ export const LINGUIST_ANNOTATION = 'backstage.io/linguist'; // @public (undocumented) export type ProcessedEntity = { entityRef: string; - processed_date: Date; + processedDate: Date; }; // (No @packageDocumentation comment for this package) diff --git a/plugins/linguist-common/package.json b/plugins/linguist-common/package.json index eddc114a67..116f785216 100644 --- a/plugins/linguist-common/package.json +++ b/plugins/linguist-common/package.json @@ -22,10 +22,6 @@ "prepack": "backstage-cli package prepack", "postpack": "backstage-cli package postpack" }, - "dependencies": { - "@backstage/catalog-model": "workspace:^", - "@backstage/plugin-permission-common": "workspace:^" - }, "devDependencies": { "@backstage/cli": "workspace:^" }, diff --git a/plugins/linguist-common/src/types.ts b/plugins/linguist-common/src/types.ts index 01222492b6..28a25ed059 100644 --- a/plugins/linguist-common/src/types.ts +++ b/plugins/linguist-common/src/types.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; /** @public */ export type EntityResults = { @@ -41,7 +40,7 @@ export type Language = { /** @public */ export type ProcessedEntity = { entityRef: string; - processed_date: Date; + processedDate: Date; }; /** @public */ @@ -50,5 +49,5 @@ export type EntitiesOverview = { processedCount: number; pendingCount: number; staleCount: number; - filteredEntities: Entity[]; + filteredEntities: string[]; }; diff --git a/yarn.lock b/yarn.lock index 9dd67caa8b..4120623904 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6930,9 +6930,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-linguist-common@workspace:plugins/linguist-common" dependencies: - "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" - "@backstage/plugin-permission-common": "workspace:^" languageName: unknown linkType: soft From 672eade89960801ea392167c86a6d5f664ec1277 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 11 Feb 2023 14:57:08 -0600 Subject: [PATCH 390/423] Organized backend API Signed-off-by: Andre Wanlin --- .../src/api/LinguistBackendApi.ts | 177 +++++++++--------- 1 file changed, 92 insertions(+), 85 deletions(-) diff --git a/plugins/linguist-backend/src/api/LinguistBackendApi.ts b/plugins/linguist-backend/src/api/LinguistBackendApi.ts index a5bbc5e639..34d04b02f9 100644 --- a/plugins/linguist-backend/src/api/LinguistBackendApi.ts +++ b/plugins/linguist-backend/src/api/LinguistBackendApi.ts @@ -76,7 +76,98 @@ export class LinguistBackendApi { return this.store.getEntityResults(entityRef); } - public async processEntity(entityRef: string, url: string): Promise { + public async processEntities() { + this.logger?.info('Updating list of entities'); + + await this.addNewEntities(); + + this.logger?.info('Processing applicable entities through Linguist'); + + await this.generateEntitiesLanguages(); + } + + private async addNewEntities() { + const annotationKey = this.useSourceLocation + ? ANNOTATION_SOURCE_LOCATION + : LINGUIST_ANNOTATION; + const request: GetEntitiesRequest = { + filter: { + kind: ['API', 'Component', 'Template'], + [`metadata.annotations.${annotationKey}`]: CATALOG_FILTER_EXISTS, + }, + fields: ['kind', 'metadata'], + }; + + const response = await this.catalogClient.getEntities(request); + const entities = response.items; + + entities.forEach(entity => { + const entityRef = stringifyEntityRef(entity); + this.store.insertNewEntity(entityRef); + }); + } + + private async generateEntitiesLanguages() { + const entitiesOverview = await this.getEntitiesOverview(); + this.logger?.info( + `Entities overview: Entity: ${entitiesOverview.entityCount}, Processed: ${entitiesOverview.processedCount}, Pending: ${entitiesOverview.pendingCount}, Stale ${entitiesOverview.staleCount}`, + ); + + const entities = entitiesOverview.filteredEntities.slice( + this.batchSize ?? 20, + ); + entities.forEach(async entityRef => { + const entity = await this.catalogClient.getEntityByRef(entityRef); + const annotationKey = this.useSourceLocation + ? ANNOTATION_SOURCE_LOCATION + : LINGUIST_ANNOTATION; + + let url = entity?.metadata.annotations?.[annotationKey] ?? ''; + if (url.startsWith('url:')) { + url = url.slice(4); + } + + try { + await this.generateEntityLanguages(entityRef, url); + } catch (error) { + assertError(error); + this.logger.error( + `Unable to process "${entityRef}" using "${url}", message: ${error.message}, stack: ${error.stack}`, + ); + } + }); + } + + private async getEntitiesOverview(): Promise { + this.logger?.debug('Getting pending entities'); + + const processedEntities = await this.store.getProcessedEntities(); + const staleEntities = processedEntities + .filter(pe => { + if (this.age === undefined) return false; + const staleDate = DateTime.now().minus(this.age as HumanDuration); + return DateTime.fromJSDate(pe.processedDate) <= staleDate; + }) + .map(pe => pe.entityRef); + + const unprocessedEntities = await this.store.getUnprocessedEntities(); + const filteredEntities = staleEntities.concat(unprocessedEntities); + + const entitiesOverview: EntitiesOverview = { + entityCount: unprocessedEntities.length, + processedCount: processedEntities.length, + staleCount: staleEntities.length, + pendingCount: filteredEntities.length, + filteredEntities: filteredEntities, + }; + + return entitiesOverview; + } + + private async generateEntityLanguages( + entityRef: string, + url: string, + ): Promise { this.logger?.info( `Processing languages for entity ${entityRef} from ${url}`, ); @@ -124,88 +215,4 @@ export class LinguistBackendApi { await fs.remove(dir); } } - - public async processEntities() { - this.logger?.info('Updating list of entities'); - - await this.addNewEntities(); - - this.logger?.info('Processing applicable entities through Linguist'); - - const entitiesOverview = await this.getEntitiesOverview(); - this.logger?.info( - `Entities overview: Entity: ${entitiesOverview.entityCount}, Processed: ${entitiesOverview.processedCount}, Pending: ${entitiesOverview.pendingCount}, Stale ${entitiesOverview.staleCount}`, - ); - - const entities = entitiesOverview.filteredEntities.slice( - this.batchSize ?? 20, - ); - entities.forEach(async entityRef => { - const entity = await this.catalogClient.getEntityByRef(entityRef); - const annotationKey = this.useSourceLocation - ? ANNOTATION_SOURCE_LOCATION - : LINGUIST_ANNOTATION; - - let url = entity?.metadata.annotations?.[annotationKey] ?? ''; - if (url.startsWith('url:')) { - url = url.slice(4); - } - - try { - await this.processEntity(entityRef, url); - } catch (error) { - assertError(error); - this.logger.error( - `Unable to process "${entityRef}" using "${url}", message: ${error.message}, stack: ${error.stack}`, - ); - } - }); - } - - public async getEntitiesOverview(): Promise { - this.logger?.debug('Getting pending entities'); - - const processedEntities = await this.store.getProcessedEntities(); - const staleEntities = processedEntities - .filter(pe => { - if (this.age === undefined) return false; - const staleDate = DateTime.now().minus(this.age as HumanDuration); - return DateTime.fromJSDate(pe.processedDate) <= staleDate; - }) - .map(pe => pe.entityRef); - - const unprocessedEntities = await this.store.getUnprocessedEntities(); - const filteredEntities = staleEntities.concat(unprocessedEntities); - - const entitiesOverview: EntitiesOverview = { - entityCount: unprocessedEntities.length, - processedCount: processedEntities.length, - staleCount: staleEntities.length, - pendingCount: filteredEntities.length, - filteredEntities: filteredEntities, - }; - - return entitiesOverview; - } - - private async addNewEntities() { - const annotationKey = this.useSourceLocation - ? ANNOTATION_SOURCE_LOCATION - : LINGUIST_ANNOTATION; - const request: GetEntitiesRequest = { - filter: { - kind: ['API', 'Component', 'Template'], - [`metadata.annotations.${annotationKey}`]: CATALOG_FILTER_EXISTS, - }, - fields: ['kind', 'metadata'], - }; - - const response = await this.catalogClient.getEntities(request); - const entities = response.items; - - entities.forEach(entity => { - const entityRef = stringifyEntityRef(entity); - this.store.insertNewEntity(entityRef); - }); - } } From 027d58f938e85f7e4b37c721643642e483ba76b4 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 11 Feb 2023 15:02:12 -0600 Subject: [PATCH 391/423] Fixed ordering Signed-off-by: Andre Wanlin --- packages/app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app/package.json b/packages/app/package.json index 8c26254268..f27afa2ff9 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -41,9 +41,9 @@ "@backstage/plugin-kafka": "workspace:^", "@backstage/plugin-kubernetes": "workspace:^", "@backstage/plugin-lighthouse": "workspace:^", - "@backstage/plugin-microsoft-calendar": "workspace:^", "@backstage/plugin-linguist": "workspace:^", "@backstage/plugin-linguist-common": "workspace:^", + "@backstage/plugin-microsoft-calendar": "workspace:^", "@backstage/plugin-newrelic": "workspace:^", "@backstage/plugin-newrelic-dashboard": "workspace:^", "@backstage/plugin-org": "workspace:^", From a021b247991bfe8a74c6934396e60fa89bbe57fe Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 11 Feb 2023 15:05:30 -0600 Subject: [PATCH 392/423] Updated API Report Signed-off-by: Andre Wanlin --- plugins/linguist-backend/api-report.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md index 484998b099..c11296b0b3 100644 --- a/plugins/linguist-backend/api-report.md +++ b/plugins/linguist-backend/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { EntitiesOverview } from '@backstage/plugin-linguist-common'; import { EntityResults } from '@backstage/plugin-linguist-common'; import express from 'express'; import { HumanDuration } from '@backstage/types'; @@ -35,13 +34,9 @@ export class LinguistBackendApi { useSourceLocation?: boolean, ); // (undocumented) - getEntitiesOverview(): Promise; - // (undocumented) getEntityLanguages(entityRef: string): Promise; // (undocumented) processEntities(): Promise; - // (undocumented) - processEntity(entityRef: string, url: string): Promise; } // @public (undocumented) From 0a1f04170cfada36020728234182657dc0d6506c Mon Sep 17 00:00:00 2001 From: Charlie Chiang Date: Sun, 12 Feb 2023 21:13:48 +0800 Subject: [PATCH 393/423] Add kubevela to plugin marketplace Signed-off-by: Charlie Chiang --- microsite/data/plugins/kubevela.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 microsite/data/plugins/kubevela.yaml diff --git a/microsite/data/plugins/kubevela.yaml b/microsite/data/plugins/kubevela.yaml new file mode 100644 index 0000000000..524a046025 --- /dev/null +++ b/microsite/data/plugins/kubevela.yaml @@ -0,0 +1,15 @@ +--- +title: KubeVela +author: Charlie Chiang +authorUrl: https://github.com/charlie0129 +category: App Delivery +description: KubeVela is a modern software delivery platform that makes deploying and operating applications across today's hybrid, multi-cloud environments easier, faster and more reliable. +documentation: https://github.com/kubevela-contrib/backstage-plugin-kubevela +iconUrl: https://kubevela.io/img/logo.svg +npmPackageName: '@oamdev/plugin-kubevela-backend' +tags: + - cd + - delivery + - multi-cluster + - deployment as code +addedDate: '2023-02-12' From b6a43bcdc0c734a92380cb796ac8f26300e2463b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 12 Feb 2023 22:38:56 +0100 Subject: [PATCH 394/423] exit prerelease Signed-off-by: Patrik Oldsberg --- .changeset/pre.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/pre.json b/.changeset/pre.json index 9b28c37a30..01c51bcc4b 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -1,5 +1,5 @@ { - "mode": "pre", + "mode": "exit", "tag": "next", "initialVersions": { "example-app": "0.2.79", From 2be83af0a876b7f9695926558091f5115159380b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Klimczak?= Date: Mon, 13 Feb 2023 08:00:03 +0100 Subject: [PATCH 395/423] typo: typo in imported package name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bartłomiej Klimczak --- docs/plugins/url-reader.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/plugins/url-reader.md b/docs/plugins/url-reader.md index 595c87ab94..fa9c341543 100644 --- a/docs/plugins/url-reader.md +++ b/docs/plugins/url-reader.md @@ -40,7 +40,7 @@ i.e.`packages/backend/src/index.ts`. ```ts // File: packages/backend/src/index.ts -import { URLReaders } from '@backstage/backend-common'; +import { UrlReaders } from '@backstage/backend-common'; function makeCreateEnv(config: Config) { // .... From 33d042bcaf0b6dc4c045ab63e655c51203871170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Sun, 12 Feb 2023 12:13:16 +0100 Subject: [PATCH 396/423] simplify MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../deleteWithEagerPruningOfChildren.ts | 273 ++++++++++-------- 1 file changed, 145 insertions(+), 128 deletions(-) diff --git a/plugins/catalog-backend/src/database/operations/provider/deleteWithEagerPruningOfChildren.ts b/plugins/catalog-backend/src/database/operations/provider/deleteWithEagerPruningOfChildren.ts index c600825d6f..33da37bc55 100644 --- a/plugins/catalog-backend/src/database/operations/provider/deleteWithEagerPruningOfChildren.ts +++ b/plugins/catalog-backend/src/database/operations/provider/deleteWithEagerPruningOfChildren.ts @@ -16,7 +16,7 @@ import { Knex } from 'knex'; import lodash from 'lodash'; -import { DbRefreshStateReferencesRow, DbRefreshStateRow } from '../../tables'; +import { DbRefreshStateReferencesRow } from '../../tables'; /** * Given a number of entity refs originally created by a given entity provider @@ -36,135 +36,152 @@ export async function deleteWithEagerPruningOfChildren(options: { // limits for the number of permitted bindings on a precompiled statement let removedCount = 0; for (const refs of lodash.chunk(entityRefs, 1000)) { - /* - WITH RECURSIVE - -- All the nodes that can be reached downwards from our root - descendants(entity_ref) AS ( - SELECT target_entity_ref - FROM refresh_state_references - WHERE source_key = "R1" AND target_entity_ref IN [...refs] - UNION - SELECT target_entity_ref - FROM descendants - JOIN refresh_state_references ON source_entity_ref = descendants.entity_ref - ), - -- All the individual relations that can be reached upwards from each descendant - ancestors(source_key, source_entity_ref, target_entity_ref, subject) AS ( - SELECT source_key, source_entity_ref, target_entity_ref, descendants.entity_ref - FROM descendants - JOIN refresh_state_references ON refresh_state_references.target_entity_ref = descendants.entity_ref - UNION - SELECT - refresh_state_references.source_key, - refresh_state_references.source_entity_ref, - refresh_state_references.target_entity_ref, - ancestors.subject - FROM ancestors - JOIN refresh_state_references ON refresh_state_references.target_entity_ref = ancestors.source_entity_ref - ) - -- Start out with all of the descendants - SELECT descendants.entity_ref - FROM descendants - -- Exclude those who seem to have a root relation somewhere upwards that's not part of our own deletion - WHERE NOT EXISTS ( - SELECT * FROM ancestors - WHERE ancestors.subject = descendants.entity_ref - AND ancestors.source_key IS NOT NULL - AND (ancestors.source_key != "R1" OR ancestors.target_entity_ref NOT IN [...refs]) - ) - */ - removedCount += await tx('refresh_state') - .whereIn('entity_ref', function orphanedEntityRefs(orphans) { - return ( - orphans - // All the nodes that can be reached downwards from our root - .withRecursive( - 'descendants', - ['entity_ref'], - function descendants(outer) { - return outer - .select({ entity_ref: 'target_entity_ref' }) - .from('refresh_state_references') - .where('source_key', '=', sourceKey) - .whereIn('target_entity_ref', refs) - .union(function recursive(inner) { - return inner - .select({ - entity_ref: - 'refresh_state_references.target_entity_ref', - }) - .from('descendants') - .join('refresh_state_references', { - 'descendants.entity_ref': - 'refresh_state_references.source_entity_ref', - }); - }); - }, - ) - // All the relations that can be reached upwards from each descendant - .withRecursive( - 'ancestors', - [ - 'source_key', - 'source_entity_ref', - 'target_entity_ref', - 'subject', - ], - function ancestors(outer) { - return outer - .select({ - source_key: 'refresh_state_references.source_key', - source_entity_ref: - 'refresh_state_references.source_entity_ref', - target_entity_ref: - 'refresh_state_references.target_entity_ref', - subject: 'descendants.entity_ref', - }) + removedCount += await tx + .delete() + .from('refresh_state') + .whereIn('entity_ref', orphans => + orphans + // First find all nodes that can be reached downwards from the roots + // (deletion targets), including the roots themselves, by traversing + // down the refresh_state_references table. Note that this query + // starts with a condition that source_key = our source key, and + // target_entity_ref is one of the deletion targets. This has two + // effects: it won't match attempts at deleting something that didn't + // originate from us in the first place, and also won't match non-root + // entities (source_key would be null for those). + // + // KeyA - R1 - R2 Legend: + // \ ----------------------------------------- + // R3 Key* Source key + // / R* Entity ref + // KeyA - R4 - R5 lines Individual references; sources to + // / the left and targets to the right + // KeyB --- R6 + // + // The scenario is that KeyA wants to delete R1. + // + // The query starts with the KeyA-R1 reference, and then traverses + // down to also find R2 and R3. It uses union instead of union all, + // because it wants to find the set of unique descendants even if + // the tree has unexpected loops etc. + .withRecursive('descendants', ['entity_ref'], initial => + initial + .select('target_entity_ref') + .from('refresh_state_references') + .where('source_key', '=', sourceKey) + .whereIn('target_entity_ref', refs) + .union(recursive => + recursive + .select('refresh_state_references.target_entity_ref') .from('descendants') - .join('refresh_state_references', { - 'refresh_state_references.target_entity_ref': - 'descendants.entity_ref', - }) - .union(function recursive(inner) { - return inner - .select({ - source_key: 'refresh_state_references.source_key', - source_entity_ref: - 'refresh_state_references.source_entity_ref', - target_entity_ref: - 'refresh_state_references.target_entity_ref', - subject: 'ancestors.subject', - }) - .from('ancestors') - .join('refresh_state_references', { - 'refresh_state_references.target_entity_ref': - 'ancestors.source_entity_ref', - }); - }); - }, - ) - // Start out with all of the descendants - .select('descendants.entity_ref') - .from('descendants') - // Exclude those who seem to have a root relation somewhere upwards that's not part of our own deletion - .whereNotExists(function otherAncestors(outer) { - outer - .from('ancestors') - .where( - 'ancestors.subject', - '=', - tx.ref('descendants.entity_ref'), + .join( + 'refresh_state_references', + 'descendants.entity_ref', + 'refresh_state_references.source_entity_ref', + ), + ), + ) + // Then for each descendant, traverse all the way back upwards through + // the refresh_state_references table to get an exhaustive list of all + // references that are part of keeping that particular descendant + // alive. + // + // Continuing the scenario from above, starting from R3, it goes + // upwards to find every pair along every relation line. + // + // Top branch: R2-R3, R1-R2, KeyA-R1 + // Middle branch: R5-R3, R4-R5, KeyA-R4 + // Bottom branch: R6-R5, KeyB-R6 + // + // Note that this all applied to the subject R3. The exact same thing + // will be done starting from each other descendant (R2 and R1). They + // only have one and two references to find, respectively. + // + // This query also uses union instead of union all, to get the set of + // distinct relations even if the tree has unexpected loops etc. + .withRecursive( + 'ancestors', + ['source_key', 'source_entity_ref', 'target_entity_ref', 'subject'], + initial => + initial + .select( + 'refresh_state_references.source_key', + 'refresh_state_references.source_entity_ref', + 'refresh_state_references.target_entity_ref', + 'descendants.entity_ref', ) - .whereNotNull('ancestors.source_key') - .andWhere(function differentRoot(inner) { - inner - .where('ancestors.source_key', '!=', sourceKey) - .orWhereNotIn('ancestors.target_entity_ref', refs); - }); - }) - ); - }) - .delete(); + .from('descendants') + .join( + 'refresh_state_references', + 'refresh_state_references.target_entity_ref', + 'descendants.entity_ref', + ) + .union(recursive => + recursive + .select( + 'refresh_state_references.source_key', + 'refresh_state_references.source_entity_ref', + 'refresh_state_references.target_entity_ref', + 'ancestors.subject', + ) + .from('ancestors') + .join( + 'refresh_state_references', + 'refresh_state_references.target_entity_ref', + 'ancestors.source_entity_ref', + ), + ), + ) + // Finally, from that list of ancestor relations per descendant, pick + // out the ones that are roots (have a source_key). Specifically, find + // ones that seem to be be either (1) from another source, or (2) + // aren't part of the deletion targets. Those are markers that tell us + // that the corresponding descendant should be kept alive and NOT + // subject to eager deletion, because there's "something else" (not + // targeted for deletion) that has references down through the tree to + // it. + // + // Continuing the scenario from above, for R3 we have + // + // KeyA-R1, KeyA-R4, KeyB-R6 + // + // This tells us that R3 should be kept alive for two reasons: it's + // referenced by a node that isn't being deleted (R4), and also by + // another source (KeyB). What about R1 and R2? They both have + // + // KeyA-R1 + // + // So those should be deleted, since they are definitely only being + // kept alive by something that's about to be deleted. + // + // Final shape of the tree: + // + // R3 + // / + // KeyA - R4 - R5 + // / + // KeyB --- R6 + .with('retained', ['entity_ref'], notPartOfDeletion => + notPartOfDeletion + .select('subject') + .from('ancestors') + .whereNotNull('ancestors.source_key') + .where(foreignKeyOrRef => + foreignKeyOrRef + .where('ancestors.source_key', '!=', sourceKey) + .orWhereNotIn('ancestors.target_entity_ref', refs), + ), + ) + // Return all descendants minus the retained ones + .select('descendants.entity_ref') + .from('descendants') + .leftOuterJoin( + 'retained', + 'retained.entity_ref', + 'descendants.entity_ref', + ) + .whereNull('retained.entity_ref'), + ); // Delete the references that originate only from this entity provider. Note // that there may be more than one entity provider making a "claim" for a From 0c1d0229aa6530dc7bf2fdaf18380c75e2a27a71 Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Mon, 13 Feb 2023 13:46:03 +0100 Subject: [PATCH 397/423] remove not needed test dependencies Signed-off-by: Katharina Sick --- plugins/auth-backend/package.json | 2 -- .../src/providers/bitbucketServer/provider.test.ts | 5 ++--- plugins/auth-backend/src/setupTests.ts | 3 +-- yarn.lock | 4 +--- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 91fb5bed5b..a95465dbad 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -78,7 +78,6 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "@testing-library/jest-dom": "^5.16.5", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", @@ -90,7 +89,6 @@ "@types/passport-saml": "^1.1.3", "@types/passport-strategy": "^0.2.35", "@types/xml2js": "^0.4.7", - "cross-fetch": "^3.1.5", "msw": "^0.49.0", "supertest": "^6.1.3" }, diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts index 3934cafd36..1a661b82bc 100644 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts @@ -15,7 +15,7 @@ */ import * as helpers from '../../lib/passport/PassportStrategyHelper'; -import { makeProfileInfo } from '../../lib/passport/PassportStrategyHelper'; +import { makeProfileInfo } from '../../lib/passport'; import { AuthResolverContext } from '../types'; import { bitbucketServer, @@ -24,10 +24,9 @@ import { } from './provider'; import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/test-utils'; -import { fetch } from 'cross-fetch'; import { rest } from 'msw'; -global.fetch = fetch; +global.fetch = require('node-fetch'); jest.mock('../../lib/passport/PassportStrategyHelper', () => { return { diff --git a/plugins/auth-backend/src/setupTests.ts b/plugins/auth-backend/src/setupTests.ts index c1d649f2ad..d3232290a7 100644 --- a/plugins/auth-backend/src/setupTests.ts +++ b/plugins/auth-backend/src/setupTests.ts @@ -14,5 +14,4 @@ * limitations under the License. */ -import '@testing-library/jest-dom'; -import 'cross-fetch/polyfill'; +export {}; diff --git a/yarn.lock b/yarn.lock index 7bfbb5ea1f..1621cdc5b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4537,7 +4537,6 @@ __metadata: "@backstage/types": "workspace:^" "@davidzemon/passport-okta-oauth": ^0.0.5 "@google-cloud/firestore": ^6.0.0 - "@testing-library/jest-dom": ^5.16.5 "@types/body-parser": ^1.19.0 "@types/cookie-parser": ^1.4.2 "@types/express": ^4.17.6 @@ -4554,7 +4553,6 @@ __metadata: compression: ^1.7.4 cookie-parser: ^1.4.5 cors: ^2.8.5 - cross-fetch: ^3.1.5 express: ^4.17.1 express-promise-router: ^4.1.0 express-session: ^1.17.1 @@ -13580,7 +13578,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/jest-dom@npm:^5.10.1, @testing-library/jest-dom@npm:^5.16.4, @testing-library/jest-dom@npm:^5.16.5": +"@testing-library/jest-dom@npm:^5.10.1, @testing-library/jest-dom@npm:^5.16.4": version: 5.16.5 resolution: "@testing-library/jest-dom@npm:5.16.5" dependencies: From 006f84dc86d8cb18d8cef8b6600a41711724807a Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Mon, 13 Feb 2023 14:50:03 +0100 Subject: [PATCH 398/423] Updated the 'Debugging Jest Tests' section Signed-off-by: bnechyporenko --- docs/local-dev/cli-build-system.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index ba65bedb9f..bef0ef9d97 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -597,7 +597,11 @@ If you also want to enable source maps when debugging tests, you can do so by se ### Debugging Jest Tests -To configure the debugging of your tests in IntelliJ, you have to: +For your productivity working with unit tests it's quite essential to have your debugging configured in IDE. It will help you to identify the root cause of the issue faster. + +Each of IDE has own way to set it up. We started with giving an example how to configure it in Intellij IDEA. In a near future we might also add the information for VS Code. + +#### Intellij IDEA 1. Update Jest configuration template by: From a8c0c0383e013a8a50b84678eab28baa475a87a6 Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Mon, 13 Feb 2023 15:28:27 +0100 Subject: [PATCH 399/423] Updated the 'Debugging Jest Tests' section Signed-off-by: bnechyporenko --- docs/local-dev/cli-build-system.md | 39 +++++++++++++----------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index bef0ef9d97..ec0f3273fb 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -556,7 +556,22 @@ The overrides in a single `package.json` may for example look like this: }, ``` -If you want to configure editor integration for tests we recommend executing the bundled configuration directly with Jest rather than running through the Yarn test script. For example, with the Jest extension for VS Code the configuration would look something like this: +### Debugging Jest Tests + +For your productivity working with unit tests it's quite essential to have your debugging configured in IDE. It will help you to identify the root cause of the issue faster. + +#### Intellij IDEA + +1. Update Jest configuration template by: + +- Click on "Edit Configurations" on top panel +- In the modal dialog click on link "Edit configuration templates..." located in the bottom left corner. +- In "Jest package" you have to point to relative path of jest module (it will be suggested by IntelliJ), i.e. ~/proj/backstage/node_modules/jest +- In "Jest config" point to your jest configuration file, use absolute path for that, i.e. `--config /Users/user/proj/backstage/packages/cli/config/jest.js --runInBand` + +2. Now you can run any tests by clicking on green arrow located on `describe` or `it`. + +#### VS Code ```jsonc { @@ -571,7 +586,7 @@ If you want to configure editor integration for tests we recommend executing the } ``` -If you also want to enable source maps when debugging tests, you can do so by setting the `ENABLE_SOURCE_MAPS` environment variable. For example, a complete launch configuration for VS Code debugging may look like this: +A complete launch configuration for VS Code debugging may look like this: ```json { @@ -583,9 +598,6 @@ If you also want to enable source maps when debugging tests, you can do so by se "disableOptimisticBPs": true, "program": "${workspaceFolder}/node_modules/.bin/jest", "cwd": "${workspaceFolder}", - "env": { - "ENABLE_SOURCE_MAPS": "true" - }, "args": [ "--config", "node_modules/@backstage/cli/config/jest.js", @@ -595,23 +607,6 @@ If you also want to enable source maps when debugging tests, you can do so by se } ``` -### Debugging Jest Tests - -For your productivity working with unit tests it's quite essential to have your debugging configured in IDE. It will help you to identify the root cause of the issue faster. - -Each of IDE has own way to set it up. We started with giving an example how to configure it in Intellij IDEA. In a near future we might also add the information for VS Code. - -#### Intellij IDEA - -1. Update Jest configuration template by: - -- Click on "Edit Configurations" on top panel -- In the modal dialog click on link "Edit configuration templates..." located in the bottom left corner. -- In "Jest package" you have to point to relative path of jest module (it will be suggested by IntelliJ), i.e. ~/proj/backstage/node_modules/jest -- In "Jest config" point to your jest configuration file, use absolute path for that, i.e. `--config /Users/user/proj/backstage/packages/cli/config/jest.js --runInBand` - -2. Now you can run any tests by clicking on green arrow located on `describe` or `it`. - ## Publishing Package publishing is an optional part of the Backstage build system and not From 08b7ac6f07d4d50f5c65ff9cf24b618a1c669377 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 13 Feb 2023 16:02:09 +0100 Subject: [PATCH 400/423] microsite: add fold to last two blog posts Signed-off-by: Patrik Oldsberg --- microsite/blog/2023-01-31-incremental-entity-provider.md | 4 +++- microsite/blog/2023-02-06-whats-ahead-in-2023.md | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/microsite/blog/2023-01-31-incremental-entity-provider.md b/microsite/blog/2023-01-31-incremental-entity-provider.md index c14c3fc15d..fd273af208 100644 --- a/microsite/blog/2023-01-31-incremental-entity-provider.md +++ b/microsite/blog/2023-01-31-incremental-entity-provider.md @@ -4,10 +4,12 @@ author: Paul Cowan & Taras Mankovski authorURL: https://frontside.com/ --- -At the heart of [Backstage](https://backstage.io/) is the [Backstage Software Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview), which is a data store that allows an organization to centralize and visualize its many software services and components. Backstage inspects and transforms an organization's disparate software services and parts into a centralized data store. +At the heart of [Backstage](https://backstage.io/) is the [Backstage Software Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview), which is a data store that allows an organization to centralize and visualize its many software services and components. Backstage inspects and transforms an organization's disparate software services and parts into a centralized data store. This blog post introduces the concept of incremental entity providers, which allow Backstage to scale ingestion to even larger datasets. ![catalog pipeline](assets/2023-01-31/catalog-pipeline.png) + + A common use case is for an organization to want to surface ownership and metadata about repositories. Backstage provides a mechanism for discovering and transforming repository information into a standard data structure and persisting it into the Backstage [Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview). This process is known as ingestion, where all data is transformed into a standard Backstage data structure known as an entity. Entities in the Catalog’s data store are accessible to the Backstage App via the REST API. Data is transformed into entities via what is known as the ingestion and processing loop, which can be thought of as an [extract, transform and load (ETL) pipeline](https://en.wikipedia.org/wiki/Extract,_transform,_load), where raw data such as GitHub repositories are loaded from GitHub, transformed into entities and outputted to the Catalog. diff --git a/microsite/blog/2023-02-06-whats-ahead-in-2023.md b/microsite/blog/2023-02-06-whats-ahead-in-2023.md index a9f06d9ea0..f989973ca0 100644 --- a/microsite/blog/2023-02-06-whats-ahead-in-2023.md +++ b/microsite/blog/2023-02-06-whats-ahead-in-2023.md @@ -10,6 +10,8 @@ authorURL: https://github.com/leemills83 Okay, everyone. Time to move on from all the 2022 reflections, Top 10 lists, and Wrapped(s), and turn our gaze in the other direction — towards 2023. As the Backstage team moves into the new year, we find ourselves asking those perennial questions: How can we continue to grow and enhance the Backstage community? How can we improve the experience for those adopting Backstage? How can we give the best support to Backstage contributors? + + Well, we don’t have all the answers, but we do have some. So we wanted to share more on three ongoing initiatives aimed at moving the needle forward for these three distinct, yet interrelated, questions. - Grow your influence by climbing the contribution ladder From dfbe698743d83672e4d0092d46e77a451a676cfa Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Mon, 13 Feb 2023 09:38:48 -0500 Subject: [PATCH 401/423] chore(review): address comments Signed-off-by: Phil Kuang --- .github/CODEOWNERS | 2 ++ plugins/entity-feedback-backend/package.json | 2 +- .../src/service/DatabaseHandler.ts | 9 +++++--- plugins/entity-feedback-common/api-report.md | 23 +++++++++---------- plugins/entity-feedback-common/package.json | 2 +- plugins/entity-feedback-common/src/index.ts | 2 +- plugins/entity-feedback/api-report.md | 14 +++++++---- plugins/entity-feedback/package.json | 2 +- .../src/api/EntityFeedbackApi.ts | 8 ++++--- .../src/api/EntityFeedbackClient.ts | 6 ++--- .../FeedbackResponseTable.tsx | 4 ++-- 11 files changed, 42 insertions(+), 32 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bb6f8da19b..d4d5f91a0d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -37,6 +37,8 @@ yarn.lock @backstage/maintainers @back /plugins/code-coverage-backend @backstage/maintainers @alde @nissayeva /plugins/cost-insights @backstage/maintainers @backstage/silver-lining /plugins/cost-insights-* @backstage/maintainers @backstage/silver-lining +/plugins/entity-feedback @backstage/maintainers @kuangp +/plugins/entity-feedback-* @backstage/maintainers @kuangp /plugins/events-backend @backstage/maintainers @pjungermann /plugins/events-backend-module-aws-sqs @backstage/maintainers @pjungermann /plugins/events-backend-module-azure @backstage/maintainers @pjungermann diff --git a/plugins/entity-feedback-backend/package.json b/plugins/entity-feedback-backend/package.json index 487d5f5d5e..7fbc7b9f7e 100644 --- a/plugins/entity-feedback-backend/package.json +++ b/plugins/entity-feedback-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback-backend", - "version": "0.1.0", + "version": "0.0.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback-backend/src/service/DatabaseHandler.ts b/plugins/entity-feedback-backend/src/service/DatabaseHandler.ts index aeeaffd694..9b81cd94bb 100644 --- a/plugins/entity-feedback-backend/src/service/DatabaseHandler.ts +++ b/plugins/entity-feedback-backend/src/service/DatabaseHandler.ts @@ -15,7 +15,10 @@ */ import { resolvePackagePath } from '@backstage/backend-common'; -import { Rating, Response } from '@backstage/plugin-entity-feedback-common'; +import { + FeedbackResponse, + Rating, +} from '@backstage/plugin-entity-feedback-common'; import { Knex } from 'knex'; const migrationsDir = resolvePackagePath( @@ -119,7 +122,7 @@ export class DatabaseHandler { ).map(rating => ({ userRef: rating.user_ref, rating: rating.rating })); } - async recordResponse(response: Response) { + async recordResponse(response: FeedbackResponse) { await this.database('responses').insert({ entity_ref: response.entityRef, response: response.response, @@ -131,7 +134,7 @@ export class DatabaseHandler { async getResponses( entityRef: string, - ): Promise[]> { + ): Promise[]> { return ( await this.database('responses') .where('entity_ref', entityRef) diff --git a/plugins/entity-feedback-common/api-report.md b/plugins/entity-feedback-common/api-report.md index 35da32c1da..118e6c78f2 100644 --- a/plugins/entity-feedback-common/api-report.md +++ b/plugins/entity-feedback-common/api-report.md @@ -16,17 +16,7 @@ export interface EntityRatingsData { } // @public (undocumented) -export interface Rating { - // (undocumented) - entityRef: string; - // (undocumented) - rating: string; - // (undocumented) - userRef: string; -} - -// @public (undocumented) -interface Response_2 { +export interface FeedbackResponse { // (undocumented) comments?: string; // (undocumented) @@ -38,5 +28,14 @@ interface Response_2 { // (undocumented) userRef: string; } -export { Response_2 as Response }; + +// @public (undocumented) +export interface Rating { + // (undocumented) + entityRef: string; + // (undocumented) + rating: string; + // (undocumented) + userRef: string; +} ``` diff --git a/plugins/entity-feedback-common/package.json b/plugins/entity-feedback-common/package.json index 45a5a2b131..6316b72943 100644 --- a/plugins/entity-feedback-common/package.json +++ b/plugins/entity-feedback-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-entity-feedback-common", "description": "Common functionalities for the entity-feedback plugin", - "version": "0.1.0", + "version": "0.0.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback-common/src/index.ts b/plugins/entity-feedback-common/src/index.ts index f19fcdd648..eea289a899 100644 --- a/plugins/entity-feedback-common/src/index.ts +++ b/plugins/entity-feedback-common/src/index.ts @@ -32,7 +32,7 @@ export interface Rating { /** * @public */ -export interface Response { +export interface FeedbackResponse { entityRef: string; response?: string; comments?: string; diff --git a/plugins/entity-feedback/api-report.md b/plugins/entity-feedback/api-report.md index 399e84e674..06b0166b0d 100644 --- a/plugins/entity-feedback/api-report.md +++ b/plugins/entity-feedback/api-report.md @@ -10,10 +10,10 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { EntityRatingsData } from '@backstage/plugin-entity-feedback-common'; +import { FeedbackResponse } from '@backstage/plugin-entity-feedback-common'; import { FetchApi } from '@backstage/core-plugin-api'; import { Rating } from '@backstage/plugin-entity-feedback-common'; import { ReactNode } from 'react'; -import { Response as Response_2 } from '@backstage/plugin-entity-feedback-common'; import { RouteRef } from '@backstage/core-plugin-api'; // @public (undocumented) @@ -25,13 +25,15 @@ export interface EntityFeedbackApi { // (undocumented) getRatings(entityRef: string): Promise[]>; // (undocumented) - getResponses(entityRef: string): Promise[]>; + getResponses( + entityRef: string, + ): Promise[]>; // (undocumented) recordRating(entityRef: string, rating: string): Promise; // (undocumented) recordResponse( entityRef: string, - response: Omit, + response: Omit, ): Promise; } @@ -48,13 +50,15 @@ export class EntityFeedbackClient implements EntityFeedbackApi { // (undocumented) getRatings(entityRef: string): Promise[]>; // (undocumented) - getResponses(entityRef: string): Promise[]>; + getResponses( + entityRef: string, + ): Promise[]>; // (undocumented) recordRating(entityRef: string, rating: string): Promise; // (undocumented) recordResponse( entityRef: string, - response: Omit, + response: Omit, ): Promise; } diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index 6d71b04cc2..f8560a9237 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback", - "version": "0.1.0", + "version": "0.0.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback/src/api/EntityFeedbackApi.ts b/plugins/entity-feedback/src/api/EntityFeedbackApi.ts index f8f6b4fccc..d2f1a46f55 100644 --- a/plugins/entity-feedback/src/api/EntityFeedbackApi.ts +++ b/plugins/entity-feedback/src/api/EntityFeedbackApi.ts @@ -17,8 +17,8 @@ import { createApiRef } from '@backstage/core-plugin-api'; import { EntityRatingsData, + FeedbackResponse, Rating, - Response, } from '@backstage/plugin-entity-feedback-common'; /** @@ -42,8 +42,10 @@ export interface EntityFeedbackApi { recordResponse( entityRef: string, - response: Omit, + response: Omit, ): Promise; - getResponses(entityRef: string): Promise[]>; + getResponses( + entityRef: string, + ): Promise[]>; } diff --git a/plugins/entity-feedback/src/api/EntityFeedbackClient.ts b/plugins/entity-feedback/src/api/EntityFeedbackClient.ts index 43d3cbe95a..34856473c8 100644 --- a/plugins/entity-feedback/src/api/EntityFeedbackClient.ts +++ b/plugins/entity-feedback/src/api/EntityFeedbackClient.ts @@ -18,8 +18,8 @@ import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'; import { ResponseError } from '@backstage/errors'; import { EntityRatingsData, + FeedbackResponse, Rating, - Response, } from '@backstage/plugin-entity-feedback-common'; import { EntityFeedbackApi } from './EntityFeedbackApi'; @@ -99,7 +99,7 @@ export class EntityFeedbackClient implements EntityFeedbackApi { async recordResponse( entityRef: string, - response: Omit, + response: Omit, ) { const baseUrl = await this.discoveryApi.getBaseUrl('entity-feedback'); const resp = await this.fetchApi.fetch( @@ -118,7 +118,7 @@ export class EntityFeedbackClient implements EntityFeedbackApi { async getResponses( entityRef: string, - ): Promise[]> { + ): Promise[]> { const baseUrl = await this.discoveryApi.getBaseUrl('entity-feedback'); const resp = await this.fetchApi.fetch( `${baseUrl}/responses/${encodeURIComponent(entityRef)}`, diff --git a/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.tsx b/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.tsx index 2bc03b8537..ba954c7747 100644 --- a/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.tsx +++ b/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.tsx @@ -18,7 +18,7 @@ import { parseEntityRef } from '@backstage/catalog-model'; import { ErrorPanel, Table } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; import { humanizeEntityRef } from '@backstage/plugin-catalog-react'; -import { Response } from '@backstage/plugin-entity-feedback-common'; +import { FeedbackResponse } from '@backstage/plugin-entity-feedback-common'; import { BackstageTheme } from '@backstage/theme'; import { Chip, makeStyles } from '@material-ui/core'; import CheckIcon from '@material-ui/icons/Check'; @@ -27,7 +27,7 @@ import useAsync from 'react-use/lib/useAsync'; import { entityFeedbackApiRef } from '../../api'; -type ResponseRow = Omit; +type ResponseRow = Omit; const useStyles = makeStyles(theme => ({ consentCheck: { From 0303587bcefb28694bd9d43d2fb6e8af2796ef7d Mon Sep 17 00:00:00 2001 From: Justin De Burgo <57914589+jpdeburgo@users.noreply.github.com> Date: Mon, 13 Feb 2023 09:21:44 -0600 Subject: [PATCH 402/423] Update .changeset/famous-squids-wonder.md Co-authored-by: Patrik Oldsberg Signed-off-by: Justin De Burgo <57914589+jpdeburgo@users.noreply.github.com> --- .changeset/famous-squids-wonder.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/famous-squids-wonder.md b/.changeset/famous-squids-wonder.md index 11ca76ddc1..5b027e9a63 100644 --- a/.changeset/famous-squids-wonder.md +++ b/.changeset/famous-squids-wonder.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog-backend': patch --- -Adding dot option to mini match used in catalog rules to allow for catalog imports with hidden folders +Location rule target patterns now also match hidden files, i.e. path components with a leading dot. From 1fad33684e4f6aac04b3865b924a19e16a110b5a Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Mon, 13 Feb 2023 16:31:49 +0100 Subject: [PATCH 403/423] use node-fetch Signed-off-by: Katharina Sick --- plugins/auth-backend/package.json | 2 +- .../bitbucketServer/provider.test.ts | 2 - .../src/providers/bitbucketServer/provider.ts | 3 +- yarn.lock | 49 ++++++++++++++++--- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index a95465dbad..67a532e6fd 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -59,7 +59,7 @@ "minimatch": "^5.0.0", "morgan": "^1.10.0", "node-cache": "^5.1.2", - "node-fetch": "^2.6.7", + "node-fetch": "^3.3.0", "openid-client": "^5.2.1", "passport": "^0.6.0", "passport-auth0": "^1.4.3", diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts index 1a661b82bc..fc48cdbe8b 100644 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts @@ -26,8 +26,6 @@ import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/test-utils'; import { rest } from 'msw'; -global.fetch = require('node-fetch'); - jest.mock('../../lib/passport/PassportStrategyHelper', () => { return { ...jest.requireActual('../../lib/passport/PassportStrategyHelper'), diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts index cd082ee953..fb8dd3d5b8 100644 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts @@ -42,6 +42,7 @@ import express from 'express'; import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; import { Profile as PassportProfile } from 'passport'; import { commonByEmailResolver } from '../resolvers'; +import fetch from 'node-fetch'; type PrivateInfo = { refreshToken: string; @@ -215,7 +216,7 @@ export class BitbucketServerAuthProvider implements OAuthHandlers { throw new Error(`Failed to retrieve the user '${username}'`); } - const user = await userResponse.json(); + const user = (await userResponse.json()) as any; const passportProfile = { provider: 'bitbucketServer', diff --git a/yarn.lock b/yarn.lock index 1621cdc5b1..232efe185c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4567,7 +4567,7 @@ __metadata: morgan: ^1.10.0 msw: ^0.49.0 node-cache: ^5.1.2 - node-fetch: ^2.6.7 + node-fetch: ^3.3.0 openid-client: ^5.2.1 passport: ^0.6.0 passport-auth0: ^1.4.3 @@ -20160,6 +20160,13 @@ __metadata: languageName: node linkType: hard +"data-uri-to-buffer@npm:^4.0.0": + version: 4.0.1 + resolution: "data-uri-to-buffer@npm:4.0.1" + checksum: 0d0790b67ffec5302f204c2ccca4494f70b4e2d940fea3d36b09f0bb2b8539c2e86690429eb1f1dc4bcc9e4df0644193073e63d9ee48ac9fce79ec1506e4aa4c + languageName: node + linkType: hard + "data-urls@npm:^2.0.0": version: 2.0.0 resolution: "data-urls@npm:2.0.0" @@ -22814,6 +22821,16 @@ __metadata: languageName: node linkType: hard +"fetch-blob@npm:^3.1.2, fetch-blob@npm:^3.1.4": + version: 3.2.0 + resolution: "fetch-blob@npm:3.2.0" + dependencies: + node-domexception: ^1.0.0 + web-streams-polyfill: ^3.0.3 + checksum: f19bc28a2a0b9626e69fd7cf3a05798706db7f6c7548da657cbf5026a570945f5eeaedff52007ea35c8bcd3d237c58a20bf1543bc568ab2422411d762dd3d5bf + languageName: node + linkType: hard + "figures@npm:^3.0.0, figures@npm:^3.2.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -23204,6 +23221,15 @@ __metadata: languageName: node linkType: hard +"formdata-polyfill@npm:^4.0.10": + version: 4.0.10 + resolution: "formdata-polyfill@npm:4.0.10" + dependencies: + fetch-blob: ^3.1.2 + checksum: 82a34df292afadd82b43d4a740ce387bc08541e0a534358425193017bf9fb3567875dc5f69564984b1da979979b70703aa73dee715a17b6c229752ae736dd9db + languageName: node + linkType: hard + "formidable@npm:^2.0.1": version: 2.1.2 resolution: "formidable@npm:2.1.2" @@ -29791,7 +29817,7 @@ __metadata: languageName: node linkType: hard -"node-domexception@npm:1.0.0": +"node-domexception@npm:1.0.0, node-domexception@npm:^1.0.0": version: 1.0.0 resolution: "node-domexception@npm:1.0.0" checksum: ee1d37dd2a4eb26a8a92cd6b64dfc29caec72bff5e1ed9aba80c294f57a31ba4895a60fd48347cf17dd6e766da0ae87d75657dfd1f384ebfa60462c2283f5c7f @@ -29836,6 +29862,17 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^3.3.0": + version: 3.3.0 + resolution: "node-fetch@npm:3.3.0" + dependencies: + data-uri-to-buffer: ^4.0.0 + fetch-blob: ^3.1.4 + formdata-polyfill: ^4.0.10 + checksum: e9936908d2783d3c48a038e187f8062de294d75ef43ec8ab812d7cbd682be2b67605868758d2e9cad6103706dcfe4a9d21d78f6df984e8edf10e7a5ce2e665f8 + languageName: node + linkType: hard + "node-forge@npm:^1, node-forge@npm:^1.3.1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -38005,10 +38042,10 @@ __metadata: languageName: node linkType: hard -"web-streams-polyfill@npm:^3.2.0": - version: 3.2.0 - resolution: "web-streams-polyfill@npm:3.2.0" - checksum: e23ad0649392fa0159dbfc6bb27474c308c3f332d9078cfef3c06c154165bef18732c5814126147c6c712f604216ddc950c171c854e3821f020e0d2d721a5958 +"web-streams-polyfill@npm:^3.0.3, web-streams-polyfill@npm:^3.2.0": + version: 3.2.1 + resolution: "web-streams-polyfill@npm:3.2.1" + checksum: b119c78574b6d65935e35098c2afdcd752b84268e18746606af149e3c424e15621b6f1ff0b42b2676dc012fc4f0d313f964b41a4b5031e525faa03997457da02 languageName: node linkType: hard From 02ac23ea90cf369af8c2eda9b721dd311236e3a8 Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Mon, 13 Feb 2023 16:34:37 +0100 Subject: [PATCH 404/423] reset node-fetch version Signed-off-by: Katharina Sick --- plugins/auth-backend/package.json | 2 +- yarn.lock | 43 +++---------------------------- 2 files changed, 4 insertions(+), 41 deletions(-) diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 67a532e6fd..a95465dbad 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -59,7 +59,7 @@ "minimatch": "^5.0.0", "morgan": "^1.10.0", "node-cache": "^5.1.2", - "node-fetch": "^3.3.0", + "node-fetch": "^2.6.7", "openid-client": "^5.2.1", "passport": "^0.6.0", "passport-auth0": "^1.4.3", diff --git a/yarn.lock b/yarn.lock index 232efe185c..4f9bfd99af 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4567,7 +4567,7 @@ __metadata: morgan: ^1.10.0 msw: ^0.49.0 node-cache: ^5.1.2 - node-fetch: ^3.3.0 + node-fetch: ^2.6.7 openid-client: ^5.2.1 passport: ^0.6.0 passport-auth0: ^1.4.3 @@ -20160,13 +20160,6 @@ __metadata: languageName: node linkType: hard -"data-uri-to-buffer@npm:^4.0.0": - version: 4.0.1 - resolution: "data-uri-to-buffer@npm:4.0.1" - checksum: 0d0790b67ffec5302f204c2ccca4494f70b4e2d940fea3d36b09f0bb2b8539c2e86690429eb1f1dc4bcc9e4df0644193073e63d9ee48ac9fce79ec1506e4aa4c - languageName: node - linkType: hard - "data-urls@npm:^2.0.0": version: 2.0.0 resolution: "data-urls@npm:2.0.0" @@ -22821,16 +22814,6 @@ __metadata: languageName: node linkType: hard -"fetch-blob@npm:^3.1.2, fetch-blob@npm:^3.1.4": - version: 3.2.0 - resolution: "fetch-blob@npm:3.2.0" - dependencies: - node-domexception: ^1.0.0 - web-streams-polyfill: ^3.0.3 - checksum: f19bc28a2a0b9626e69fd7cf3a05798706db7f6c7548da657cbf5026a570945f5eeaedff52007ea35c8bcd3d237c58a20bf1543bc568ab2422411d762dd3d5bf - languageName: node - linkType: hard - "figures@npm:^3.0.0, figures@npm:^3.2.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -23221,15 +23204,6 @@ __metadata: languageName: node linkType: hard -"formdata-polyfill@npm:^4.0.10": - version: 4.0.10 - resolution: "formdata-polyfill@npm:4.0.10" - dependencies: - fetch-blob: ^3.1.2 - checksum: 82a34df292afadd82b43d4a740ce387bc08541e0a534358425193017bf9fb3567875dc5f69564984b1da979979b70703aa73dee715a17b6c229752ae736dd9db - languageName: node - linkType: hard - "formidable@npm:^2.0.1": version: 2.1.2 resolution: "formidable@npm:2.1.2" @@ -29817,7 +29791,7 @@ __metadata: languageName: node linkType: hard -"node-domexception@npm:1.0.0, node-domexception@npm:^1.0.0": +"node-domexception@npm:1.0.0": version: 1.0.0 resolution: "node-domexception@npm:1.0.0" checksum: ee1d37dd2a4eb26a8a92cd6b64dfc29caec72bff5e1ed9aba80c294f57a31ba4895a60fd48347cf17dd6e766da0ae87d75657dfd1f384ebfa60462c2283f5c7f @@ -29862,17 +29836,6 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^3.3.0": - version: 3.3.0 - resolution: "node-fetch@npm:3.3.0" - dependencies: - data-uri-to-buffer: ^4.0.0 - fetch-blob: ^3.1.4 - formdata-polyfill: ^4.0.10 - checksum: e9936908d2783d3c48a038e187f8062de294d75ef43ec8ab812d7cbd682be2b67605868758d2e9cad6103706dcfe4a9d21d78f6df984e8edf10e7a5ce2e665f8 - languageName: node - linkType: hard - "node-forge@npm:^1, node-forge@npm:^1.3.1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -38042,7 +38005,7 @@ __metadata: languageName: node linkType: hard -"web-streams-polyfill@npm:^3.0.3, web-streams-polyfill@npm:^3.2.0": +"web-streams-polyfill@npm:^3.2.0": version: 3.2.1 resolution: "web-streams-polyfill@npm:3.2.1" checksum: b119c78574b6d65935e35098c2afdcd752b84268e18746606af149e3c424e15621b6f1ff0b42b2676dc012fc4f0d313f964b41a4b5031e525faa03997457da02 From c51efce2a0e0f6cef6c4994ca361c8a75a6fd118 Mon Sep 17 00:00:00 2001 From: Jan Van Bruggen Date: Thu, 9 Feb 2023 13:34:03 -0700 Subject: [PATCH 405/423] Update docs to always use `yarn add --cwd` for app & backend Some commands currently error, and others are simply formatted inconsistently. This format seems to work and be the most popular/common, so I applied it to all similar occurrences. Signed-off-by: Jan Van Bruggen --- .changeset/empty-games-cheer.md | 22 +++++++++++++++++++ .../configure-app-with-plugins.md | 3 ++- docs/integrations/aws-s3/discovery.md | 2 +- docs/integrations/gerrit/discovery.md | 2 +- docs/integrations/gitlab/discovery.md | 2 +- docs/permissions/getting-started.md | 3 ++- docs/permissions/plugin-authors/01-setup.md | 7 +++--- docs/plugins/backend-plugin.md | 2 +- .../tutorials/configuring-plugin-databases.md | 2 +- packages/backend-test-utils/README.md | 2 +- plugins/adr-backend/README.md | 5 ++--- plugins/allure/README.md | 11 ++-------- plugins/analytics-module-ga/README.md | 7 +++++- .../api-docs-module-protoc-gen-doc/README.md | 5 +++-- plugins/azure-devops-backend/README.md | 5 ++--- plugins/azure-sites-backend/README.md | 2 +- plugins/azure-sites/README.md | 5 +++-- .../README.md | 2 +- plugins/catalog-graph/README.md | 5 +++-- plugins/code-coverage-backend/README.md | 5 ++++- plugins/code-coverage/README.md | 5 ++++- plugins/home/README.md | 2 +- plugins/ilert/README.md | 2 +- .../lighthouse/src/components/Intro/index.tsx | 4 ++-- plugins/microsoft-calendar/README.md | 2 +- plugins/shortcuts/README.md | 3 ++- plugins/xcmetrics/README.md | 5 ++--- 27 files changed, 76 insertions(+), 46 deletions(-) create mode 100644 .changeset/empty-games-cheer.md diff --git a/.changeset/empty-games-cheer.md b/.changeset/empty-games-cheer.md new file mode 100644 index 0000000000..d17e97f752 --- /dev/null +++ b/.changeset/empty-games-cheer.md @@ -0,0 +1,22 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +'@backstage/plugin-api-docs-module-protoc-gen-doc': patch +'@backstage/plugin-code-coverage-backend': patch +'@backstage/plugin-azure-devops-backend': patch +'@backstage/backend-test-utils': patch +'@backstage/plugin-analytics-module-ga': patch +'@backstage/plugin-azure-sites-backend': patch +'@backstage/plugin-microsoft-calendar': patch +'@backstage/plugin-catalog-graph': patch +'@backstage/plugin-code-coverage': patch +'@backstage/plugin-adr-backend': patch +'@backstage/plugin-azure-sites': patch +'@backstage/plugin-lighthouse': patch +'@backstage/plugin-shortcuts': patch +'@backstage/plugin-xcmetrics': patch +'@backstage/plugin-allure': patch +'@backstage/plugin-ilert': patch +'@backstage/plugin-home': patch +--- + +Update docs to always use `yarn add --cwd` for app & backend diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md index ebe98f9ddc..835da0cd49 100644 --- a/docs/getting-started/configure-app-with-plugins.md +++ b/docs/getting-started/configure-app-with-plugins.md @@ -22,7 +22,8 @@ to an entity in the software catalog. 1. Add the plugin's npm package to the repo: ```bash - yarn workspace app add @backstage/plugin-circleci + # From your Backstage root directory + yarn add --cwd packages/app @backstage/plugin-circleci ``` Note the plugin is added to the `app` package, rather than the root diff --git a/docs/integrations/aws-s3/discovery.md b/docs/integrations/aws-s3/discovery.md index 748aeb2392..4a2b953bc9 100644 --- a/docs/integrations/aws-s3/discovery.md +++ b/docs/integrations/aws-s3/discovery.md @@ -63,7 +63,7 @@ As this provider is not one of the default providers, you will first need to ins the AWS catalog plugin: ```bash -# From the Backstage root directory +# From your Backstage root directory yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-aws ``` diff --git a/docs/integrations/gerrit/discovery.md b/docs/integrations/gerrit/discovery.md index 7ed05d2b3b..5d822effb5 100644 --- a/docs/integrations/gerrit/discovery.md +++ b/docs/integrations/gerrit/discovery.md @@ -17,7 +17,7 @@ As this provider is not one of the default providers, you will first need to ins the Gerrit provider plugin: ```bash -# From the Backstage root directory +# From your Backstage root directory yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-gerrit ``` diff --git a/docs/integrations/gitlab/discovery.md b/docs/integrations/gitlab/discovery.md index 51c34b67ac..3d554ce6b2 100644 --- a/docs/integrations/gitlab/discovery.md +++ b/docs/integrations/gitlab/discovery.md @@ -36,7 +36,7 @@ As this provider is not one of the default providers, you will first need to ins the gitlab catalog plugin: ```bash -# From the Backstage root directory +# From your Backstage root directory yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-gitlab ``` diff --git a/docs/permissions/getting-started.md b/docs/permissions/getting-started.md index d2c467ff08..e71601b703 100644 --- a/docs/permissions/getting-started.md +++ b/docs/permissions/getting-started.md @@ -47,7 +47,8 @@ The permissions framework uses a new `permission-backend` plugin to accept autho 1. Add `@backstage/plugin-permission-backend` as a dependency of your Backstage backend: ```bash -$ yarn workspace backend add @backstage/plugin-permission-backend +# From your Backstage root directory +$ yarn add --cwd packages/backend @backstage/plugin-permission-backend ``` 2. Add the following to a new file, `packages/backend/src/plugins/permission.ts`. This adds the permission-backend router, and configures it with a policy which allows everything. diff --git a/docs/permissions/plugin-authors/01-setup.md b/docs/permissions/plugin-authors/01-setup.md index a38b81e679..c368505849 100644 --- a/docs/permissions/plugin-authors/01-setup.md +++ b/docs/permissions/plugin-authors/01-setup.md @@ -39,9 +39,10 @@ The source code is available here: 2. Add these packages as dependencies for your Backstage app: - ``` - $ yarn workspace backend add @internal/plugin-todo-list-backend @internal/plugin-todo-list-common - $ yarn workspace app add @internal/plugin-todo-list + ```sh + # From your Backstage root directory + $ yarn add --cwd packages/backend @internal/plugin-todo-list-backend @internal/plugin-todo-list-common + $ yarn add --cwd packages/app @internal/plugin-todo-list ``` 3. Include the backend and frontend plugin in your application: diff --git a/docs/plugins/backend-plugin.md b/docs/plugins/backend-plugin.md index 517779d161..c4414c8e55 100644 --- a/docs/plugins/backend-plugin.md +++ b/docs/plugins/backend-plugin.md @@ -66,7 +66,7 @@ To actually attach and run the plugin router, you will make some modifications to your backend. ```bash -# From the Backstage root directory +# From your Backstage root directory yarn add --cwd packages/backend @internal/plugin-carmen-backend@^0.1.1 # Change this to match the plugin's package.json ``` diff --git a/docs/tutorials/configuring-plugin-databases.md b/docs/tutorials/configuring-plugin-databases.md index ed550f1801..34e62c285a 100644 --- a/docs/tutorials/configuring-plugin-databases.md +++ b/docs/tutorials/configuring-plugin-databases.md @@ -37,7 +37,7 @@ package. If you intend to use both PostgreSQL and SQLite, you can install both of them. ```bash -# From the Backstage root directory +# From your Backstage root directory # install pg if you need PostgreSQL yarn add --cwd packages/backend pg diff --git a/packages/backend-test-utils/README.md b/packages/backend-test-utils/README.md index 38756fa5d7..7ccf4e2798 100644 --- a/packages/backend-test-utils/README.md +++ b/packages/backend-test-utils/README.md @@ -7,7 +7,7 @@ Test helpers library for Backstage backends. Add the library as a `devDependency` to your backend package: ```sh -# From the Backstage root directory, go to your backend package, or to a backend plugin +# From your Backstage root directory, go to your backend package, or to a backend plugin cd plugins/my-plugin-backend yarn add --dev @backstage/backend-test-utils ``` diff --git a/plugins/adr-backend/README.md b/plugins/adr-backend/README.md index b751a3b56d..29fead7c84 100644 --- a/plugins/adr-backend/README.md +++ b/plugins/adr-backend/README.md @@ -19,9 +19,8 @@ Here's how to get the backend up and running: 1. First we need to add the `@backstage/plugin-adr-backend` package to your backend: ```sh -# From the Backstage root directory -cd packages/backend -yarn add @backstage/plugin-adr-backend +# From your Backstage root directory +yarn add --cwd packages/backend @backstage/plugin-adr-backend ``` 2. Then we will create a new file named `packages/backend/src/plugins/adr.ts`, and add the diff --git a/plugins/allure/README.md b/plugins/allure/README.md index b9a8435a34..3a1137fc39 100644 --- a/plugins/allure/README.md +++ b/plugins/allure/README.md @@ -4,16 +4,9 @@ Welcome to the Backstage Allure plugin. This plugin add an entity service page t ## Install -Run the below command from the `app` package directory. - ```shell -yarn add @backstage/plugin-allure -``` - -alternatively, you can execute below command from the root directory of your Backstage app. - -```shell -yarn workspace app add @backstage/plugin-allure +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-allure ``` ## Configure diff --git a/plugins/analytics-module-ga/README.md b/plugins/analytics-module-ga/README.md index c2d79aa45d..d6e2642e2b 100644 --- a/plugins/analytics-module-ga/README.md +++ b/plugins/analytics-module-ga/README.md @@ -9,7 +9,12 @@ This plugin contains no other functionality. ## Installation 1. Install the plugin package in your Backstage app: - `cd packages/app && yarn add @backstage/plugin-analytics-module-ga` + +```sh +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-analytics-module-ga +``` + 2. Wire up the API implementation to your App: ```tsx diff --git a/plugins/api-docs-module-protoc-gen-doc/README.md b/plugins/api-docs-module-protoc-gen-doc/README.md index 4d90cd74c2..a921fafc0b 100644 --- a/plugins/api-docs-module-protoc-gen-doc/README.md +++ b/plugins/api-docs-module-protoc-gen-doc/README.md @@ -6,8 +6,9 @@ This package contains ApiDefinitionWidgets for the following projects: ## Setup -``` -yarn add @backstage/plugin-api-docs-module-protoc-gen-doc +```sh +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-api-docs-module-protoc-gen-doc ``` ## Add the GrpcDocsApiWidget to your apis diff --git a/plugins/azure-devops-backend/README.md b/plugins/azure-devops-backend/README.md index 301ae5b2b9..ba2a847c0a 100644 --- a/plugins/azure-devops-backend/README.md +++ b/plugins/azure-devops-backend/README.md @@ -30,9 +30,8 @@ Here's how to get the backend up and running: 1. First we need to add the `@backstage/plugin-azure-devops-backend` package to your backend: ```sh - # From the Backstage root directory - cd packages/backend - yarn add @backstage/plugin-azure-devops-backend + # From your Backstage root directory + yarn add --cwd packages/backend @backstage/plugin-azure-devops-backend ``` 2. Then we will create a new file named `packages/backend/src/plugins/azure-devops.ts`, and add the diff --git a/plugins/azure-sites-backend/README.md b/plugins/azure-sites-backend/README.md index 5f19267499..0d44b9a4e4 100644 --- a/plugins/azure-sites-backend/README.md +++ b/plugins/azure-sites-backend/README.md @@ -36,7 +36,7 @@ Here's how to get the backend plugin up and running: 1. First we need to add the `@backstage/plugin-azure-sites-backend` package to your backend: ```sh - # From the Backstage root directory + # From your Backstage root directory yarn add --cwd packages/backend @backstage/plugin-azure-sites-backend ``` diff --git a/plugins/azure-sites/README.md b/plugins/azure-sites/README.md index f240dab140..57bf84ccc5 100644 --- a/plugins/azure-sites/README.md +++ b/plugins/azure-sites/README.md @@ -44,10 +44,11 @@ azure.com/microsoft-web-sites: func-testapp ### Install the component -1. Install the plugin in the `packages/app` directory +1. Install the plugin ```sh -yarn add @backstage/plugin-azure-sites +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-azure-sites ``` 2. Add widget component to your Backstage instance: diff --git a/plugins/catalog-backend-module-incremental-ingestion/README.md b/plugins/catalog-backend-module-incremental-ingestion/README.md index aa23b8dfc1..7fe36eeec7 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/README.md +++ b/plugins/catalog-backend-module-incremental-ingestion/README.md @@ -41,7 +41,7 @@ The Incremental Entity Provider backend is designed for data sources that provid ## Installation -1. Install `@backstage/plugin-catalog-backend-module-incremental-ingestion` with `yarn workspace backend add @backstage/plugin-catalog-backend-module-incremental-ingestion` +1. Install `@backstage/plugin-catalog-backend-module-incremental-ingestion` with `yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-incremental-ingestion` from the Backstage root directory. 2. In your catalog.ts, import `IncrementalCatalogBuilder` from `@backstage/plugin-catalog-backend-module-incremental-ingestion` and instantiate it with `await IncrementalCatalogBuilder.create(env, builder)`. You have to pass `builder` into `IncrementalCatalogBuilder.create` function because `IncrementalCatalogBuilder` will convert an `IncrementalEntityProvider` into an `EntityProvider` and call `builder.addEntityProvider`. ```ts diff --git a/plugins/catalog-graph/README.md b/plugins/catalog-graph/README.md index 33dee92935..f723523716 100644 --- a/plugins/catalog-graph/README.md +++ b/plugins/catalog-graph/README.md @@ -24,9 +24,10 @@ The plugin comes with these features: To use the catalog graph plugin, you have to add some things to your Backstage app: -1. Add a dependency to your `packages/app/package.json`, run: +1. Add a dependency to your `packages/app/package.json`: ```sh - yarn add @backstage/plugin-catalog-graph + # From your Backstage root directory + yarn add --cwd packages/app @backstage/plugin-catalog-graph ``` 2. Add the `CatalogGraphPage` to your `packages/app/src/App.tsx`: diff --git a/plugins/code-coverage-backend/README.md b/plugins/code-coverage-backend/README.md index ae6021b07c..802e538125 100644 --- a/plugins/code-coverage-backend/README.md +++ b/plugins/code-coverage-backend/README.md @@ -4,7 +4,10 @@ This is the backend part of the `code-coverage` plugin. It takes care of process ## Installation -`yarn workspace backend add @backstage/plugin-code-coverage-backend` +```sh +# From your Backstage root directory +yarn add --cwd packages/backend @backstage/plugin-code-coverage-backend +``` First create a `codecoverage.ts` file here: `packages/backend/src/plugins`. Now add the following as its content: diff --git a/plugins/code-coverage/README.md b/plugins/code-coverage/README.md index ce793a78d3..d4daa6ec00 100644 --- a/plugins/code-coverage/README.md +++ b/plugins/code-coverage/README.md @@ -4,7 +4,10 @@ This is the frontend part of the code-coverage plugin. It displays code coverage ## Installation -`yarn workspace app add @backstage/plugin-code-coverage` +```sh +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-code-coverage +``` Finally you need to import and render the code coverage entity, in `packages/app/src/components/catalog/EntityPage.tsx` add the following: diff --git a/plugins/home/README.md b/plugins/home/README.md index 0cd307b706..1fdface722 100644 --- a/plugins/home/README.md +++ b/plugins/home/README.md @@ -9,7 +9,7 @@ For App Integrators, the system is designed to be composable to give total freed If you have a standalone app (you didn't clone this repo), then do ```bash -# From the Backstage repository root +# From your Backstage root directory yarn add --cwd packages/app @backstage/plugin-home ``` diff --git a/plugins/ilert/README.md b/plugins/ilert/README.md index c704108126..814baea507 100644 --- a/plugins/ilert/README.md +++ b/plugins/ilert/README.md @@ -26,7 +26,7 @@ In detail this plugin provides: Install the plugin: ```bash -# From the Backstage repository root +# From your Backstage root directory yarn add --cwd packages/app @backstage/plugin-ilert ``` diff --git a/plugins/lighthouse/src/components/Intro/index.tsx b/plugins/lighthouse/src/components/Intro/index.tsx index 57609476b8..69fcf21cf3 100644 --- a/plugins/lighthouse/src/components/Intro/index.tsx +++ b/plugins/lighthouse/src/components/Intro/index.tsx @@ -50,8 +50,8 @@ with the environment variable \`LAS_CORS\` set to \`true\`._ When you have an instance running that Backstage can hook into, first install the plugin into your app: \`\`\`sh -cd packages/app -yarn add @backstage/plugin-lighthouse +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-lighthouse \`\`\` Modify your app routes in \`App.tsx\` to include the \`LighthousePage\` component exported from the plugin, for example: diff --git a/plugins/microsoft-calendar/README.md b/plugins/microsoft-calendar/README.md index 73a66b15f5..219a7cf2dc 100644 --- a/plugins/microsoft-calendar/README.md +++ b/plugins/microsoft-calendar/README.md @@ -25,7 +25,7 @@ The following sections will help you set up the Microsoft calendar plugin. 1. Install the plugin by running this command ```bash -# From the Backstage repository root +# From your Backstage root directory yarn add --cwd packages/app @backstage/plugin-microsoft-calendar ``` diff --git a/plugins/shortcuts/README.md b/plugins/shortcuts/README.md index d7f8f19aec..cd79901656 100644 --- a/plugins/shortcuts/README.md +++ b/plugins/shortcuts/README.md @@ -7,7 +7,8 @@ The shortcuts plugin allows a user to have easy access to pages within a Backsta ### Install the package: ```bash -yarn add @backstage/plugin-shortcuts +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-shortcuts ``` ### Register plugin: diff --git a/plugins/xcmetrics/README.md b/plugins/xcmetrics/README.md index a3bb93d2af..7c003722a0 100644 --- a/plugins/xcmetrics/README.md +++ b/plugins/xcmetrics/README.md @@ -7,10 +7,9 @@ With this plugin, you can view data from XCMetrics directly in Backstage. ## Getting started -From `packages/app`: - ```bash -yarn add @backstage/plugin-xcmetrics +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-xcmetrics ``` In `packages/app/src/App.tsx`, add the following: From 79c6b9aa0e1982da010c1bdd2c2969c395ac76fc Mon Sep 17 00:00:00 2001 From: bogdannechyporenko Date: Mon, 13 Feb 2023 19:18:20 +0100 Subject: [PATCH 406/423] Added Intellij to a Vale vocabulary Signed-off-by: bogdannechyporenko --- .github/vale/Vocab/Backstage/accept.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index e6380a17f0..a488ad8f87 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -160,6 +160,7 @@ indexable inlined inlinehilite integrator's +Intellij interop JaCoCo JavaScript From 67ed63552446b512d549e911e13cd7d36eb36186 Mon Sep 17 00:00:00 2001 From: Christopher Kruse Date: Mon, 13 Feb 2023 10:28:03 -0800 Subject: [PATCH 407/423] fix: use `NotFoundError` for missing team in org Per [PR comment][1], better to use the provided error type that more closely matches the error encountered. [1]: https://github.com/backstage/backstage/pull/16059#discussion_r1103873709 Signed-off-by: Christopher Kruse --- .../src/scaffolder/actions/builtin/github/helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts index dc8c4cd856..75c8f25d8b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts @@ -15,7 +15,7 @@ */ import { Config } from '@backstage/config'; -import { assertError, InputError } from '@backstage/errors'; +import { assertError, InputError, NotFoundError } from '@backstage/errors'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, @@ -370,7 +370,7 @@ async function validateAccessTeam(client: Octokit, access: string) { if (e.response.data.message === 'Not Found') { const message = `Received 'Not Found' from the API; one of org: ${org} or team: ${team_slug} was not found within GitHub.`; - throw new Error(message, { cause: e }); + throw new NotFoundError(message); } } } From f52b9828fa73d56a1bb7ec2849619e51a3fc29ad Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Mon, 13 Feb 2023 21:13:31 -0500 Subject: [PATCH 408/423] fix: Missing headers Signed-off-by: Adam Harvey --- docs/features/software-catalog/system-model.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/features/software-catalog/system-model.md b/docs/features/software-catalog/system-model.md index 16ad48abcf..a9b89ef4f4 100644 --- a/docs/features/software-catalog/system-model.md +++ b/docs/features/software-catalog/system-model.md @@ -63,7 +63,7 @@ BigTable databases, Pub/Sub topics, S3 buckets or CDNs. Modelling them together with components and systems will better allow us to visualize resource footprint, and create tooling around them. -##Organizational Entities +## Organizational Entities ### User @@ -120,7 +120,7 @@ product or use-case, share the same entity types in their APIs, and integrate well with each other. Other domains could be “Content Ingestion”, “Ads” or “Search”. -##Other +## Other ### Location From 7bd24b919c15ad103f5b15303c47c9869caac9f6 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Mon, 13 Feb 2023 21:20:50 -0500 Subject: [PATCH 409/423] chore: Link on page reference to diagram Signed-off-by: Adam Harvey --- docs/features/software-catalog/system-model.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/features/software-catalog/system-model.md b/docs/features/software-catalog/system-model.md index a9b89ef4f4..af359bb18a 100644 --- a/docs/features/software-catalog/system-model.md +++ b/docs/features/software-catalog/system-model.md @@ -128,7 +128,8 @@ A location is a marker that references other places to look for catalog data. ### Type -The type field in the system has no set meaning. It is up to the user to assign their own types and use them as desired, such as for link validation or creating custom UI components. Some common pre-defined types are depicted in the ecosystem modeling diagram. +The type field in the system has no set meaning. It is up to the user to assign their own types and use them as desired, such as for link validation or creating custom UI components. Some common pre-defined types are depicted in the +[ecosystem modeling diagram](#ecosystem-modeling). ### Template From b16a9c59f5de06b27854c79abcd713c3d5cb7183 Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Tue, 14 Feb 2023 08:40:29 +0100 Subject: [PATCH 410/423] Renamed Intellij to IntelliJ Signed-off-by: bnechyporenko --- .github/vale/Vocab/Backstage/accept.txt | 1 - docs/local-dev/cli-build-system.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index a488ad8f87..e6380a17f0 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -160,7 +160,6 @@ indexable inlined inlinehilite integrator's -Intellij interop JaCoCo JavaScript diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index ec0f3273fb..424b5f2c0c 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -560,7 +560,7 @@ The overrides in a single `package.json` may for example look like this: For your productivity working with unit tests it's quite essential to have your debugging configured in IDE. It will help you to identify the root cause of the issue faster. -#### Intellij IDEA +#### IntelliJ IDEA 1. Update Jest configuration template by: From 4bdd6bcb3c2cb1a87c2955862815d6e62c225373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 14 Feb 2023 10:21:48 +0100 Subject: [PATCH 411/423] Prefer Link over plain anchors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/tidy-kids-hide.md | 7 +++++++ .../DagTableComponent/DagTableComponent.tsx | 16 +++++++++------- .../AzureSitesOverviewTable.tsx | 5 ++--- .../lighthouse/src/components/Intro/index.tsx | 6 +++--- 4 files changed, 21 insertions(+), 13 deletions(-) create mode 100644 .changeset/tidy-kids-hide.md diff --git a/.changeset/tidy-kids-hide.md b/.changeset/tidy-kids-hide.md new file mode 100644 index 0000000000..194497d05c --- /dev/null +++ b/.changeset/tidy-kids-hide.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-apache-airflow': patch +'@backstage/plugin-azure-sites': patch +'@backstage/plugin-lighthouse': patch +--- + +Prefer Link over plain anchors diff --git a/plugins/apache-airflow/src/components/DagTableComponent/DagTableComponent.tsx b/plugins/apache-airflow/src/components/DagTableComponent/DagTableComponent.tsx index 2660e9380e..2cd136c7fa 100644 --- a/plugins/apache-airflow/src/components/DagTableComponent/DagTableComponent.tsx +++ b/plugins/apache-airflow/src/components/DagTableComponent/DagTableComponent.tsx @@ -15,6 +15,7 @@ */ import { + Link, Progress, StatusError, StatusOK, @@ -144,13 +145,14 @@ export const DenseTable = ({ dags, rowClick }: DenseTableProps) => { { title: 'Link', field: 'dagUrl', - render: (row: Partial) => ( - - - - - - ), + render: (row: Partial) => + !row.dagUrl ? null : ( + + + + + + ), width: '5%', disableClick: true, hidden: hiddenColumns.some(field => field === 'dagUrl'), diff --git a/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx b/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx index dc059b2f15..5b67fe844a 100644 --- a/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx +++ b/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx @@ -164,9 +164,8 @@ const ActionButtons = ({ )} diff --git a/plugins/lighthouse/src/components/Intro/index.tsx b/plugins/lighthouse/src/components/Intro/index.tsx index 57609476b8..519b0a3f21 100644 --- a/plugins/lighthouse/src/components/Intro/index.tsx +++ b/plugins/lighthouse/src/components/Intro/index.tsx @@ -22,6 +22,7 @@ import LighthouseSupportButton from '../SupportButton'; import { ContentHeader, InfoCard, + Link, MarkdownContent, } from '@backstage/core-components'; @@ -108,10 +109,9 @@ function GettingStartedCard() { From 17b573e4be9c2277b4f83d9a03a21ba73773e93f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 14 Feb 2023 10:51:23 +0100 Subject: [PATCH 412/423] backend-test-utils: mark backend system utils as stable Signed-off-by: Patrik Oldsberg --- .changeset/silent-roses-join.md | 5 +++++ packages/backend-test-utils/api-report.md | 8 ++++---- .../backend-test-utils/src/next/services/mockServices.ts | 2 +- .../backend-test-utils/src/next/wiring/TestBackend.ts | 6 +++--- 4 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 .changeset/silent-roses-join.md diff --git a/.changeset/silent-roses-join.md b/.changeset/silent-roses-join.md new file mode 100644 index 0000000000..5794c8701c --- /dev/null +++ b/.changeset/silent-roses-join.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +The new backend system testing utilities have now been marked as stable API. diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index 0b3d7dd843..c13d1bb859 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -28,7 +28,7 @@ import { UrlReaderService } from '@backstage/backend-plugin-api'; // @public (undocumented) export function isDockerDisabledForTests(): boolean; -// @alpha (undocumented) +// @public (undocumented) export namespace mockServices { // (undocumented) export namespace cache { @@ -126,7 +126,7 @@ export function setupRequestMockHandlers(worker: { resetHandlers: () => void; }): void; -// @alpha (undocumented) +// @public (undocumented) export function startTestBackend< TServices extends any[], TExtensionPoints extends any[], @@ -134,12 +134,12 @@ export function startTestBackend< options: TestBackendOptions, ): Promise; -// @alpha (undocumented) +// @public (undocumented) export interface TestBackend extends Backend { readonly server: ExtendedHttpServer; } -// @alpha (undocumented) +// @public (undocumented) export interface TestBackendOptions< TServices extends any[], TExtensionPoints extends any[], diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index 2e97cc63fb..8a3125214c 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -58,7 +58,7 @@ function simpleFactory< } /** - * @alpha + * @public */ export namespace mockServices { export function config(options?: config.Options): ConfigService { diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.ts index bbda9854d4..66bbb62193 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.ts @@ -36,7 +36,7 @@ import { mockServices } from '../services'; import { ConfigReader } from '@backstage/config'; import express from 'express'; -/** @alpha */ +/** @public */ export interface TestBackendOptions< TServices extends any[], TExtensionPoints extends any[], @@ -60,7 +60,7 @@ export interface TestBackendOptions< features?: BackendFeature[]; } -/** @alpha */ +/** @public */ export interface TestBackend extends Backend { /** * Provides access to the underling HTTP server for use with utilities @@ -89,7 +89,7 @@ const defaultServiceFactories = [ const backendInstancesToCleanUp = new Array(); -/** @alpha */ +/** @public */ export async function startTestBackend< TServices extends any[], TExtensionPoints extends any[], From d4ba79253b70945b6c2c054c3f2195e0c608f891 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 14 Feb 2023 10:52:40 +0100 Subject: [PATCH 413/423] docs/local-dev: codeblock Signed-off-by: Patrik Oldsberg --- docs/local-dev/cli-build-system.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index 424b5f2c0c..cf8ac626b9 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -566,7 +566,7 @@ For your productivity working with unit tests it's quite essential to have your - Click on "Edit Configurations" on top panel - In the modal dialog click on link "Edit configuration templates..." located in the bottom left corner. -- In "Jest package" you have to point to relative path of jest module (it will be suggested by IntelliJ), i.e. ~/proj/backstage/node_modules/jest +- In "Jest package" you have to point to relative path of jest module (it will be suggested by IntelliJ), i.e. `~/proj/backstage/node_modules/jest` - In "Jest config" point to your jest configuration file, use absolute path for that, i.e. `--config /Users/user/proj/backstage/packages/cli/config/jest.js --runInBand` 2. Now you can run any tests by clicking on green arrow located on `describe` or `it`. From d746d81bdd1fa37b5ac0c6e39410a228e0535676 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho Date: Wed, 8 Feb 2023 15:10:41 +0100 Subject: [PATCH 414/423] renaming(getMkDocsYml): Renamed to getMkdocsYml Suggested by kmatyukhin on https://github.com/backstage/backstage/pull/15417 Signed-off-by: Renan Mendes Carvalho Co-authored-by: Konstantin Matyukhin --- .../techdocs-cli/src/commands/generate/generate.ts | 4 ++-- packages/techdocs-cli/src/commands/serve/mkdocs.ts | 4 ++-- packages/techdocs-cli/src/commands/serve/serve.ts | 4 ++-- plugins/techdocs-node/api-report.md | 2 +- .../src/stages/generate/helpers.test.ts | 12 ++++++------ plugins/techdocs-node/src/stages/generate/helpers.ts | 2 +- plugins/techdocs-node/src/stages/generate/index.ts | 2 +- .../techdocs-node/src/stages/generate/techdocs.ts | 4 ++-- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/techdocs-cli/src/commands/generate/generate.ts b/packages/techdocs-cli/src/commands/generate/generate.ts index 8445dd9ec6..db58ea4faf 100644 --- a/packages/techdocs-cli/src/commands/generate/generate.ts +++ b/packages/techdocs-cli/src/commands/generate/generate.ts @@ -21,7 +21,7 @@ import Docker from 'dockerode'; import { TechdocsGenerator, ParsedLocationAnnotation, - getMkDocsYml, + getMkdocsYml, } from '@backstage/plugin-techdocs-node'; import { ContainerRunner, @@ -55,7 +55,7 @@ export default async function generate(opts: OptionValues) { await fs.ensureDir(outputDir); - const { path: mkDocsYmlPath, configIsTemporary } = await getMkDocsYml( + const { path: mkDocsYmlPath, configIsTemporary } = await getMkdocsYml( sourceDir, ); diff --git a/packages/techdocs-cli/src/commands/serve/mkdocs.ts b/packages/techdocs-cli/src/commands/serve/mkdocs.ts index 1a471cf1a6..50aa94e346 100644 --- a/packages/techdocs-cli/src/commands/serve/mkdocs.ts +++ b/packages/techdocs-cli/src/commands/serve/mkdocs.ts @@ -19,7 +19,7 @@ import openBrowser from 'react-dev-utils/openBrowser'; import { createLogger } from '../../lib/utility'; import { runMkdocsServer } from '../../lib/mkdocsServer'; import { LogFunc, waitForSignal } from '../../lib/run'; -import { getMkDocsYml } from '@backstage/plugin-techdocs-node'; +import { getMkdocsYml } from '@backstage/plugin-techdocs-node'; import fs from 'fs-extra'; export default async function serveMkdocs(opts: OptionValues) { @@ -29,7 +29,7 @@ export default async function serveMkdocs(opts: OptionValues) { const localAddr = `http://127.0.0.1:${opts.port}`; const expectedDevAddr = opts.docker ? dockerAddr : localAddr; - const { path: mkDocsYmlPath, configIsTemporary } = await getMkDocsYml( + const { path: mkDocsYmlPath, configIsTemporary } = await getMkdocsYml( './', opts.siteName, ); diff --git a/packages/techdocs-cli/src/commands/serve/serve.ts b/packages/techdocs-cli/src/commands/serve/serve.ts index 48e48d4f66..bf67606481 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -22,7 +22,7 @@ import HTTPServer from '../../lib/httpServer'; import { runMkdocsServer } from '../../lib/mkdocsServer'; import { LogFunc, waitForSignal } from '../../lib/run'; import { createLogger } from '../../lib/utility'; -import { getMkDocsYml } from '@backstage/plugin-techdocs-node'; +import { getMkdocsYml } from '@backstage/plugin-techdocs-node'; import fs from 'fs-extra'; function findPreviewBundlePath(): string { @@ -66,7 +66,7 @@ export default async function serve(opts: OptionValues) { ? mkdocsDockerAddr : mkdocsLocalAddr; - const { path: mkDocsYmlPath, configIsTemporary } = await getMkDocsYml( + const { path: mkDocsYmlPath, configIsTemporary } = await getMkdocsYml( './', opts.siteName, ); diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index ce5bd1ae09..314a46a405 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -89,7 +89,7 @@ export const getLocationForEntity: ( ) => ParsedLocationAnnotation; // @public -export const getMkDocsYml: ( +export const getMkdocsYml: ( inputDir: string, siteOptions?: { name?: string; diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index e635542a7c..aad7706ab1 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -25,7 +25,7 @@ import { ParsedLocationAnnotation } from '../../helpers'; import { createOrUpdateMetadata, getGeneratorKey, - getMkDocsYml, + getMkdocsYml, getRepoUrlFromLocationAnnotation, patchIndexPreBuild, storeEtagMetadata, @@ -517,7 +517,7 @@ describe('helpers', () => { }); }); - describe('getMkDocsYml', () => { + describe('getMkdocsYml', () => { const inputDir = resolvePath(__filename, '../__fixtures__/'); const siteOptions = { name: mockEntity.metadata.title, @@ -530,7 +530,7 @@ describe('helpers', () => { path: mkdocsPath, content, configIsTemporary, - } = await getMkDocsYml(inputDir, siteOptions); + } = await getMkdocsYml(inputDir, siteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); @@ -544,7 +544,7 @@ describe('helpers', () => { path: mkdocsPath, content, configIsTemporary, - } = await getMkDocsYml(inputDir, siteOptions); + } = await getMkdocsYml(inputDir, siteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); expect(configIsTemporary).toBe(false); @@ -562,7 +562,7 @@ describe('helpers', () => { path: mkdocsPath, content, configIsTemporary, - } = await getMkDocsYml(inputDir, defaultSiteOptions); + } = await getMkdocsYml(inputDir, defaultSiteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsDefaultYml.toString()); @@ -571,7 +571,7 @@ describe('helpers', () => { it('throws when neither .yml nor .yaml nor default file is present', async () => { const invalidInputDir = resolvePath(__filename); - await expect(getMkDocsYml(invalidInputDir, siteOptions)).rejects.toThrow( + await expect(getMkdocsYml(invalidInputDir, siteOptions)).rejects.toThrow( /Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml or default for validation/, ); }); diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index 27c24ea66e..e16293f906 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -193,7 +193,7 @@ export const generateMkdocsYml = async ( * @param siteOptions - options for the site: `name` property will be used in mkdocs.yml for the * required `site_name` property, default value is "Documentation Site" */ -export const getMkDocsYml = async ( +export const getMkdocsYml = async ( inputDir: string, siteOptions?: { name?: string }, ): Promise<{ path: string; content: string; configIsTemporary: boolean }> => { diff --git a/plugins/techdocs-node/src/stages/generate/index.ts b/plugins/techdocs-node/src/stages/generate/index.ts index fa36486a0f..3bd42643c1 100644 --- a/plugins/techdocs-node/src/stages/generate/index.ts +++ b/plugins/techdocs-node/src/stages/generate/index.ts @@ -15,7 +15,7 @@ */ export { TechdocsGenerator } from './techdocs'; export { Generators } from './generators'; -export { getMkDocsYml } from './helpers'; +export { getMkdocsYml } from './helpers'; export type { GeneratorBase, GeneratorOptions, diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index 93285b7468..b71148060e 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -24,7 +24,7 @@ import { } from '@backstage/integration'; import { createOrUpdateMetadata, - getMkDocsYml, + getMkdocsYml, patchIndexPreBuild, runCommand, storeEtagMetadata, @@ -100,7 +100,7 @@ export class TechdocsGenerator implements GeneratorBase { } = options; // Do some updates to mkdocs.yml before generating docs e.g. adding repo_url - const { path: mkdocsYmlPath, content } = await getMkDocsYml( + const { path: mkdocsYmlPath, content } = await getMkdocsYml( inputDir, siteOptions, ); From c5d51ad7d4106e4f44d5179c24be2f6464b77f81 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho Date: Wed, 8 Feb 2023 15:46:10 +0100 Subject: [PATCH 415/423] renaming(mkDocs): To mkdocs Suggested by kmatyukhin on https://github.com/backstage/backstage/pull/15417 Signed-off-by: Renan Mendes Carvalho Co-authored-by: Konstantin Matyukhin --- .../techdocs-cli/cypress/e2e/mkdocs_serve.cy.js | 4 ++-- .../techdocs-cli/src/commands/generate/generate.ts | 4 ++-- packages/techdocs-cli/src/commands/serve/mkdocs.ts | 4 ++-- packages/techdocs-cli/src/commands/serve/serve.ts | 4 ++-- plugins/techdocs-node/api-report.md | 14 ++++++++++++++ .../src/stages/generate/helpers.test.ts | 2 +- plugins/techdocs-node/src/stages/generate/index.ts | 7 +++++++ .../{mkDocsPatchers.ts => mkdocsPatchers.ts} | 0 .../techdocs-node/src/stages/generate/techdocs.ts | 2 +- 9 files changed, 31 insertions(+), 10 deletions(-) rename plugins/techdocs-node/src/stages/generate/{mkDocsPatchers.ts => mkdocsPatchers.ts} (100%) diff --git a/packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js b/packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js index d9da6caeca..d5417e615f 100644 --- a/packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js +++ b/packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js @@ -16,7 +16,7 @@ /// describe('TechDocs Live Preview - MkDocs Serve', () => { it('successfully serves documentation', () => { - cy.visit(Cypress.env('mkDocsBaseUrl')); + cy.visit(Cypress.env('mkdocsBaseUrl')); cy.contains('hello mock docs'); }); @@ -41,7 +41,7 @@ describe('TechDocs Live Preview - MkDocs Serve', () => { }); it('matchImage - MkDocs Page', () => { - cy.visit(Cypress.env('mkDocsBaseUrl')).then(() => { + cy.visit(Cypress.env('mkdocsBaseUrl')).then(() => { cy.document().matchImage(); }); }); diff --git a/packages/techdocs-cli/src/commands/generate/generate.ts b/packages/techdocs-cli/src/commands/generate/generate.ts index db58ea4faf..b8ad466bb3 100644 --- a/packages/techdocs-cli/src/commands/generate/generate.ts +++ b/packages/techdocs-cli/src/commands/generate/generate.ts @@ -55,7 +55,7 @@ export default async function generate(opts: OptionValues) { await fs.ensureDir(outputDir); - const { path: mkDocsYmlPath, configIsTemporary } = await getMkdocsYml( + const { path: mkdocsYmlPath, configIsTemporary } = await getMkdocsYml( sourceDir, ); @@ -116,7 +116,7 @@ export default async function generate(opts: OptionValues) { if (configIsTemporary) { process.on('exit', async () => { - fs.rmSync(mkDocsYmlPath, {}); + fs.rmSync(mkdocsYmlPath, {}); }); } diff --git a/packages/techdocs-cli/src/commands/serve/mkdocs.ts b/packages/techdocs-cli/src/commands/serve/mkdocs.ts index 50aa94e346..c061d4474f 100644 --- a/packages/techdocs-cli/src/commands/serve/mkdocs.ts +++ b/packages/techdocs-cli/src/commands/serve/mkdocs.ts @@ -29,7 +29,7 @@ export default async function serveMkdocs(opts: OptionValues) { const localAddr = `http://127.0.0.1:${opts.port}`; const expectedDevAddr = opts.docker ? dockerAddr : localAddr; - const { path: mkDocsYmlPath, configIsTemporary } = await getMkdocsYml( + const { path: mkdocsYmlPath, configIsTemporary } = await getMkdocsYml( './', opts.siteName, ); @@ -81,7 +81,7 @@ export default async function serveMkdocs(opts: OptionValues) { if (configIsTemporary) { process.on('exit', async () => { - fs.rmSync(mkDocsYmlPath, {}); + fs.rmSync(mkdocsYmlPath, {}); }); } } diff --git a/packages/techdocs-cli/src/commands/serve/serve.ts b/packages/techdocs-cli/src/commands/serve/serve.ts index bf67606481..9cfc24b629 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -66,7 +66,7 @@ export default async function serve(opts: OptionValues) { ? mkdocsDockerAddr : mkdocsLocalAddr; - const { path: mkDocsYmlPath, configIsTemporary } = await getMkdocsYml( + const { path: mkdocsYmlPath, configIsTemporary } = await getMkdocsYml( './', opts.siteName, ); @@ -150,7 +150,7 @@ export default async function serve(opts: OptionValues) { if (configIsTemporary) { process.on('exit', async () => { - fs.rmSync(mkDocsYmlPath, {}); + fs.rmSync(mkdocsYmlPath, {}); }); } } diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index 314a46a405..11ff53514b 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -88,6 +88,20 @@ export const getLocationForEntity: ( scmIntegration: ScmIntegrationRegistry, ) => ParsedLocationAnnotation; +// @public @deprecated (undocumented) +export const getMkDocsYml: ( + inputDir: string, + siteOptions?: + | { + name?: string | undefined; + } + | undefined, +) => Promise<{ + path: string; + content: string; + configIsTemporary: boolean; +}>; + // @public export const getMkdocsYml: ( inputDir: string, diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index aad7706ab1..b24d85430b 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -34,7 +34,7 @@ import { import { patchMkdocsYmlPreBuild, pathMkdocsYmlWithTechdocsPlugin, -} from './mkDocsPatchers'; +} from './mkdocsPatchers'; import yaml from 'js-yaml'; const mockEntity = { diff --git a/plugins/techdocs-node/src/stages/generate/index.ts b/plugins/techdocs-node/src/stages/generate/index.ts index 3bd42643c1..aaf27026c2 100644 --- a/plugins/techdocs-node/src/stages/generate/index.ts +++ b/plugins/techdocs-node/src/stages/generate/index.ts @@ -23,3 +23,10 @@ export type { GeneratorRunOptions, SupportedGeneratorKey, } from './types'; +import { getMkdocsYml } from './helpers'; +/** + * @public + * @deprecated + * Deprecated in favor of getMkdocsYml (lowercase 'd') + */ +export const getMkDocsYml = getMkdocsYml; diff --git a/plugins/techdocs-node/src/stages/generate/mkDocsPatchers.ts b/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts similarity index 100% rename from plugins/techdocs-node/src/stages/generate/mkDocsPatchers.ts rename to plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index b71148060e..2f88e1a8ad 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -34,7 +34,7 @@ import { import { patchMkdocsYmlPreBuild, pathMkdocsYmlWithTechdocsPlugin, -} from './mkDocsPatchers'; +} from './mkdocsPatchers'; import { GeneratorBase, GeneratorConfig, From dd1e37649fefd548e11d8fa103189b2a4e983f4a Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho Date: Fri, 10 Feb 2023 14:40:14 +0100 Subject: [PATCH 416/423] changeset(@techdocs/cli@,@backstage/plugin-techdocs-node) Signed-off-by: Renan Mendes Carvalho --- .changeset/cool-radios-hope.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/cool-radios-hope.md diff --git a/.changeset/cool-radios-hope.md b/.changeset/cool-radios-hope.md new file mode 100644 index 0000000000..4a66925d05 --- /dev/null +++ b/.changeset/cool-radios-hope.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-techdocs-node': minor +'@techdocs/cli': patch +--- + +Deprecated getMkDocsYml in favor of getMkdocsYml (lowercase 'd') From 869d658d2eaa527418ea4f6dab9aa7d1b0a55811 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 14 Feb 2023 10:38:02 +0100 Subject: [PATCH 417/423] e2e-test: ignore AWS SDK v2 deprecation message Signed-off-by: Patrik Oldsberg --- packages/e2e-test/src/commands/run.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/e2e-test/src/commands/run.ts b/packages/e2e-test/src/commands/run.ts index 254198ebb4..b3fb8d9a3c 100644 --- a/packages/e2e-test/src/commands/run.ts +++ b/packages/e2e-test/src/commands/run.ts @@ -490,6 +490,17 @@ async function testBackendStart(appDir: string, ...args: string[]) { !l.includes('Update this package.json to use a subpath') && !l.includes( '(Use `node --trace-deprecation ...` to show where the warning was created)', + ) && + // These 4 are all for the AWS SDK v2 deprecation + !l.includes( + 'The AWS SDK for JavaScript (v2) will be put into maintenance mode', + ) && + !l.includes( + 'Please migrate your code to use AWS SDK for JavaScript', + ) && + !l.includes('check the migration guide at https://a.co/7PzMCcy') && + !l.includes( + '(Use `node --trace-warnings ...` to show where the warning was created)', ), ).length !== 0 ); From 725383f69de0f181c6907950ac83a63f6c9017b6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 14 Feb 2023 13:55:45 +0100 Subject: [PATCH 418/423] backend-*: updated READMEs Signed-off-by: Patrik Oldsberg --- .changeset/pretty-icons-glow.md | 8 ++++++++ packages/backend-app-api/README.md | 3 ++- packages/backend-defaults/README.md | 5 +++-- packages/backend-dev-utils/README.md | 21 ++++++++++++++++++--- packages/backend-plugin-api/README.md | 9 +++++---- 5 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 .changeset/pretty-icons-glow.md diff --git a/.changeset/pretty-icons-glow.md b/.changeset/pretty-icons-glow.md new file mode 100644 index 0000000000..6023e47307 --- /dev/null +++ b/.changeset/pretty-icons-glow.md @@ -0,0 +1,8 @@ +--- +'@backstage/backend-plugin-api': patch +'@backstage/backend-dev-utils': patch +'@backstage/backend-defaults': patch +'@backstage/backend-app-api': patch +--- + +Tweaked messaging in the README. diff --git a/packages/backend-app-api/README.md b/packages/backend-app-api/README.md index ee608ceb43..44705cde52 100644 --- a/packages/backend-app-api/README.md +++ b/packages/backend-app-api/README.md @@ -1,6 +1,6 @@ # @backstage/backend-app-api -**This package is HIGHLY EXPERIMENTAL, do not use this for production** +**This package is EXPERIMENTAL, we recommend against using it for production deployments** This package provides the core API used by Backstage backend apps. @@ -17,3 +17,4 @@ yarn add --cwd packages/backend @backstage/backend-app-api - [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) - [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) +- [Backstage Backend System](https://backstage.io/docs/backend-system/) diff --git a/packages/backend-defaults/README.md b/packages/backend-defaults/README.md index 3128159f7c..826994da23 100644 --- a/packages/backend-defaults/README.md +++ b/packages/backend-defaults/README.md @@ -1,8 +1,8 @@ # @backstage/backend-defaults -**This package is HIGHLY EXPERIMENTAL, do not use this for production** +**This package is EXPERIMENTAL, we recommend against using it for production deployments** -This package provides the core API used by Backstage backend apps. +This package provides the default implementations and setup for a standard Backstage backend app. ## Installation @@ -17,3 +17,4 @@ yarn add --cwd packages/backend @backstage/backend-defaults - [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) - [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) +- [Backstage Backend System](https://backstage.io/docs/backend-system/) diff --git a/packages/backend-dev-utils/README.md b/packages/backend-dev-utils/README.md index 8acce94cf0..c60f5a4ad7 100644 --- a/packages/backend-dev-utils/README.md +++ b/packages/backend-dev-utils/README.md @@ -1,5 +1,20 @@ -# backend-dev-utils +# @backstage/backend-dev-utils -Welcome to the backend-dev-utils package! +**This package is EXPERIMENTAL, but we encourage use of it to add support for the new backend system in your own plugins** -_This package is experimental._ +This package helps set up local development environments for Backstage backend packages. + +## Installation + +Add the library to your backend plugin or module package: + +```bash +# From your Backstage root directory +yarn add --cwd plugins/-backend @backstage/backend-dev-utils +``` + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) +- [Backstage Backend System](https://backstage.io/docs/backend-system/) diff --git a/packages/backend-plugin-api/README.md b/packages/backend-plugin-api/README.md index 364655dd60..02b19a0c40 100644 --- a/packages/backend-plugin-api/README.md +++ b/packages/backend-plugin-api/README.md @@ -1,19 +1,20 @@ # @backstage/backend-plugin-api -**This package is HIGHLY EXPERIMENTAL, do not use this for production** +**This package is EXPERIMENTAL, but we encourage use of it to add support for the new backend system in your own plugins** -This package provides the core API used by Backstage backend plugins. +This package provides the core API used by Backstage backend plugins and modules. ## Installation -Add the library to your backend plugin package: +Add the library to your backend plugin or module package: ```bash # From your Backstage root directory -yarn add --cwd plugin/-backend @backstage/backend-plugin-api +yarn add --cwd plugins/-backend @backstage/backend-plugin-api ``` ## Documentation - [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) - [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) +- [Backstage Backend System](https://backstage.io/docs/backend-system/) From 14916877dd267a7dd0488bd30e350bb84bfa941c Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 17:27:16 +0100 Subject: [PATCH 419/423] docs: added some documentation about how to test the alpha version of the scaffolder Signed-off-by: blam --- .../testing-scaffolder-alpha.md | 234 ++++++++++++++++++ microsite/sidebars.json | 1 + 2 files changed, 235 insertions(+) create mode 100644 docs/features/software-templates/testing-scaffolder-alpha.md diff --git a/docs/features/software-templates/testing-scaffolder-alpha.md b/docs/features/software-templates/testing-scaffolder-alpha.md new file mode 100644 index 0000000000..68a4c5486d --- /dev/null +++ b/docs/features/software-templates/testing-scaffolder-alpha.md @@ -0,0 +1,234 @@ +--- +id: testing-scaffolder-alpha +title: 'Experimental: Testing out the `alpha` Scaffolder plugin' +# prettier-ignore +description: Docs on the upcoming breaking release for the scaffolder plugin +--- + +## What's `scaffolder/next`? + +The `alpha` version, or as you might have seen referred to in other places the `scaffolder/next` release, is a new version of the `scaffolder` plugin that will be the first breaking change to the plugin, so you can also think of it as `@backstage/plugin-scaffolder@2.0.0`. +Its mostly a rewrite of a lot of the frontend components and pages that had very limited test coverage, which made adding new features to the `scaffolder` plugin quite hard, and we were lacking in confidence when making changes. + +There is of course some other things that have changed when re-writing this, which are essentially what has caused some breaking changes. +Now, this is not like previous scaffolder changes where you would have to change all of your templates as this is only the frontend plugin that is going to have breaking changes. You can read more about the [breaking changes](#breaking-changes) below. + +## What's new? + +First off, the main dependency that we have for the frontend which is responsible for rendering the `JSONSchema` into `material-ui` components is [react-jsonschema-form](https://github.com/rjsf-team/react-jsonschema-form). +This dependency in the current verison of the plugin is 3.x.x, which is now 2 major versions out of date. Long story short, `v4` of this plugin contained some bug fixes, and new features but we we're unable to upragde due to some issues with having support for `material-ui@v4`, so we had to wait for `v5` to be released, and because of the `FieldExtensions` and how they are very tightly coupled to the `react-jsonschema-form` library, we also wanted to make sure that this release was stable before getting people to migrate their `Field Extensions`. + +With that in mind, this release has `v5` of `react-jsonschema-form`, and with that comes all the new features and bugfixes in `v4` that we were waiting for - one of the main ones being the ability to use `if / then else` syntax in the `template.yaml` definitions! 🎉 + +We've also rebuilt how validation works in the `scaffolder` components, which now means that we've opened the ability to have `async` validation functions in your `Field Extensions`. + +Some of the pages have gotten a little bit of an overhaul in terms of UI based on some research and feedback from the community and internally. + +- The `TemplateList` page has gotten some new `Card` components which show a little more information than the previous version with a little `material-ui` standards. +- The `WizardPage` has recieved some new updates with the stepper now running horizontally, and the `Review` step being a dedicated step in the stepper. +- The `OngoingTask` page now does not show the logs by default, and instead has a much cleaner interface for tracking the ongoing steps and the pipeline of actions that are currently showing. + - You can also now provide your own `OutputsComponent` which can be used to render the outputs from an ongoing / completed task in a way that suits your templates the best. For instance, if your template produces `Pull Requests`, it could be useful to render these in an interactive way where you can see the statuses of each of these `Pull Requests` in the `Ongoing Task` page. + +There's also a lot of bug fixes, and other things, but these are the main ones that we wanted to highlight. + +## How do I test out the `alpha` version? + +With the release of `v1.12.0` it's now possible to run the `scaffolder/next` plugin and it be a drop in replacement for the current version that you use today. This means that you can start using the new code, and start testing it out. Once we have collected enough feedback, and squashed any bugs that might block us from releasing is, it will be promoted from the `/alpha` exports and replace the existing code leading to breaking changes if you haven't already made these changes part of this testing pilot. Those that have chosen to opt into this testing pilot means that once we promote it from the `/alpha` exports, you will need to update your code to point to the original exports from the `scaffolder` plugin, just like the code is today but with the [breaking changes](#breaking-changes) that you already made to your `Custom Field Extensions`. + +It's also worth calling out that if you do test this out, and find some issues or something not working out as expected, feel free to raise an issue in the [repo](https://github.com/backstage/backstage) or reach out to us on Discord! + +### Make the required changes to `App.tsx` + +The `ScaffolderPage` router has a completely different export for the `scaffolder/next` work, so you will want to change any import from the old `ScaffolderPage` to the new `NextScaffolderPage` + +```diff +- import { ScaffolderPage } from '@backstage/plugin-scaffolder'; ++ import { NextScaffolderPage } from '@backstage/plugin-scaffolder/alpha'; + +``` + +And this API should be the exact same as the previous Router, so you should be able to make a change like the following futher down in this file: + +```diff + + entity?.metadata?.tags?.includes('recommended') ?? false, + }, + ]} + /> + } + > + + + ... other extensions + + + + ... other layouts + + +``` + +### Make the required changes to your `CustomFieldExtensions` + +There's differently named function for creating field extensions part of the `/alpha` exports as these are the ones that can contain breaking changes because of the breaking changes that have been applied in `react-jsonschema-form`. + +Let's take the following example: + +```ts +export const EntityNamePickerFieldExtension = scaffolderPlugin.provide( + createScaffolderFieldExtension({ + component: EntityNamePicker, + name: 'EntityNamePicker', + validation: entityNamePickerValidation, + schema: EntityNamePickerSchema, + }), +); +``` + +References for `createScaffolderFieldExtension` have an `/alpha` version of `createNextScaffolderFieldExtension`, which should be used instead. + +```diff +-import { createScaffolderFieldExtension } from '@backstage/plugin-scaffolder'; ++import { createNextScaffolderFieldExtension } from '@backstage/plugin-scaffolder/alpha'; + +export const EntityNamePickerFieldExtension = scaffolderPlugin.provide( +- createScaffolderFieldExtension({ ++ createNextScaffolderFieldExtension({ + component: EntityNamePicker, + name: 'EntityNamePicker', + validation: entityNamePickerValidation, + }), +); +``` + +Once you've done this you will find that you will have two squiggly lines under the properties that are passed in. One for the component and one for the validation (if provided.) + +Let's take the following code for the `EntityNamePicker` component: + +```ts +export const EntityNamePicker = ( + props: FieldExtensionComponentProps, +) => { + const { + onChange, + required, + schema: { title = 'Name', description = 'Unique name of the component' }, + rawErrors, + formData, + uiSchema: { 'ui:autofocus': autoFocus }, + idSchema, + placeholder, + } = props; + ... +} +``` + +There's another `/alpha` export that's you need to replace `FieldExtensionComponentProps` with which is the `NextFieldExtensionComponentProps`. + +```diff +- import { FieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react'; ++ import { NextFieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react/alpha'; + +export const EntityNamePicker = ( +- props: FieldExtensionComponentProps, ++ props: NextFieldExtensionComponentProps, +) => { + const { + onChange, + required, + schema: { title = 'Name', description = 'Unique name of the component' }, + rawErrors, + formData, +- uiSchema: { 'ui:autofocus': autoFocus }, ++ uiSchema: { 'ui:autofocus': autoFocus } = {}, + idSchema, + placeholder, + } = props; + ... +} +``` + +You'll notice that there's an additional change here, which is that we're now defaulting the `uiSchema` to an empty object. This is because the `uiSchema` is now optional, and if you don't provide it, it will be `undefined` instead of an empty object. There's more around this in the [breaking changes](#breaking-changes) section. + +To fix the previous validation error, you will need to change the import for the `FieldValidation` type that is used in the `validation` function. + +Let's take the following example of the validation function: + +```ts +import { FieldValidation } from '@rjsf/utils'; +import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; + +export const entityNamePickerValidation = ( + value: string, + validation: FieldValidation, +) => { + if (!KubernetesValidatorFunctions.isValidObjectName(value)) { + validation.addError( + 'Must start and end with an alphanumeric character, and contain only alphanumeric characters, hyphens, underscores, and periods. Maximum length is 63 characters.', + ); + } +}; +``` + +You will need to change the import for `FieldValidation` to point at the new `react-jsonschema-form` dependency. + +> Note: you will proabably need to install this dependency too, by using `yarn add @rjsf/utils` in the package where you define these validation functions, this could also be in the `packages/app` folder, so you can install it there if needed. + +```diff +- import { FieldValidation } from '@rjsf/core'; ++ import { FieldValidation } from '@rjsf/utils; +import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; + +export const entityNamePickerValidation = ( + value: string, + validation: FieldValidation, +) => { +``` + +## Breaking Changes + +Once we fully release the code that is in the `/alpha` exports right now onto the current API and release v2.0.0 of `@backstage/plugin-scaffolder` the breaking changes will be as follows: + +### `uiSchema` is now optional + +Later releases of `react-jsonschema-form` have made the `uiSchema` optional, and if you don't provide it, it will be `undefined` instead of an empty object. This means that you will need to make sure that you're defaulting the `uiSchema` to an empty object if you're using it in your code. + +```diff + const { + onChange, + required, + schema: { title = 'Name', description = 'Unique name of the component' }, + rawErrors, + formData, +- uiSchema: { 'ui:autofocus': autoFocus }, ++ uiSchema: { 'ui:autofocus': autoFocus } = {}, + idSchema, + placeholder, + } = props; +``` + +### `formData` can also be `undefined` + +If you were using the `formData` and assuming that it was set to an empty object when building `Field Extensions` that return objects, then this will be `undefined` now due to a change in the `react-jsonschema-form` library. + +```diff + const { + onChange, + required, + schema: { title = 'Name', description = 'Unique name of the component' }, + rawErrors, +- formData, ++ formData = {}, // or mayube some other default value that you would prefer + uiSchema: { 'ui:autofocus': autoFocus } = {}, + idSchema, + placeholder, + } = props; +``` diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 6baeb20e8b..fea976a5d6 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -104,6 +104,7 @@ "features/software-templates/writing-custom-actions", "features/software-templates/writing-custom-field-extensions", "features/software-templates/writing-custom-step-layouts", + "features/software-templates/testing-scaffolder-alpah", "features/software-templates/migrating-from-v1beta2-to-v1beta3" ] }, From be4474135a4a76287aaf458834ffdf735b136a63 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 17:37:32 +0100 Subject: [PATCH 420/423] chore: make vale and @kuangp happy :D Signed-off-by: blam --- .github/vale/Vocab/Backstage/accept.txt | 1 + .../software-templates/testing-scaffolder-alpha.md | 10 +++++----- microsite/sidebars.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index e6380a17f0..08e325c38b 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -33,6 +33,7 @@ Blackbox bool boolean Brex +bugfixes builtins callout CDNs diff --git a/docs/features/software-templates/testing-scaffolder-alpha.md b/docs/features/software-templates/testing-scaffolder-alpha.md index 68a4c5486d..b8b63330d1 100644 --- a/docs/features/software-templates/testing-scaffolder-alpha.md +++ b/docs/features/software-templates/testing-scaffolder-alpha.md @@ -16,16 +16,16 @@ Now, this is not like previous scaffolder changes where you would have to change ## What's new? First off, the main dependency that we have for the frontend which is responsible for rendering the `JSONSchema` into `material-ui` components is [react-jsonschema-form](https://github.com/rjsf-team/react-jsonschema-form). -This dependency in the current verison of the plugin is 3.x.x, which is now 2 major versions out of date. Long story short, `v4` of this plugin contained some bug fixes, and new features but we we're unable to upragde due to some issues with having support for `material-ui@v4`, so we had to wait for `v5` to be released, and because of the `FieldExtensions` and how they are very tightly coupled to the `react-jsonschema-form` library, we also wanted to make sure that this release was stable before getting people to migrate their `Field Extensions`. +This dependency in the current version of the plugin is 3.x.x, which is now 2 major versions out of date. Long story short, `v4` of this plugin contained some bug fixes, and new features but we we're unable to upgrade due to some issues with having support for `material-ui@v4`, so we had to wait for `v5` to be released, and because of the `FieldExtensions` and how they are very tightly coupled to the `react-jsonschema-form` library, we also wanted to make sure that this release was stable before getting people to migrate their `Field Extensions`. -With that in mind, this release has `v5` of `react-jsonschema-form`, and with that comes all the new features and bugfixes in `v4` that we were waiting for - one of the main ones being the ability to use `if / then else` syntax in the `template.yaml` definitions! 🎉 +With that in mind, this release has `v5` of `react-jsonschema-form`, and with that comes all the new features and bugfixes in `v4` that we were waiting for - one of the main ones being the ability to use `if / then / else` syntax in the `template.yaml` definitions! 🎉 We've also rebuilt how validation works in the `scaffolder` components, which now means that we've opened the ability to have `async` validation functions in your `Field Extensions`. Some of the pages have gotten a little bit of an overhaul in terms of UI based on some research and feedback from the community and internally. - The `TemplateList` page has gotten some new `Card` components which show a little more information than the previous version with a little `material-ui` standards. -- The `WizardPage` has recieved some new updates with the stepper now running horizontally, and the `Review` step being a dedicated step in the stepper. +- The `WizardPage` has received some new updates with the stepper now running horizontally, and the `Review` step being a dedicated step in the stepper. - The `OngoingTask` page now does not show the logs by default, and instead has a much cleaner interface for tracking the ongoing steps and the pipeline of actions that are currently showing. - You can also now provide your own `OutputsComponent` which can be used to render the outputs from an ongoing / completed task in a way that suits your templates the best. For instance, if your template produces `Pull Requests`, it could be useful to render these in an interactive way where you can see the statuses of each of these `Pull Requests` in the `Ongoing Task` page. @@ -47,7 +47,7 @@ The `ScaffolderPage` router has a completely different export for the `scaffolde ``` -And this API should be the exact same as the previous Router, so you should be able to make a change like the following futher down in this file: +And this API should be the exact same as the previous Router, so you should be able to make a change like the following further down in this file: ```diff Note: you will proabably need to install this dependency too, by using `yarn add @rjsf/utils` in the package where you define these validation functions, this could also be in the `packages/app` folder, so you can install it there if needed. +> Note: you will probably need to install this dependency too, by using `yarn add @rjsf/utils` in the package where you define these validation functions, this could also be in the `packages/app` folder, so you can install it there if needed. ```diff - import { FieldValidation } from '@rjsf/core'; diff --git a/microsite/sidebars.json b/microsite/sidebars.json index fea976a5d6..b7e2068aca 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -104,7 +104,7 @@ "features/software-templates/writing-custom-actions", "features/software-templates/writing-custom-field-extensions", "features/software-templates/writing-custom-step-layouts", - "features/software-templates/testing-scaffolder-alpah", + "features/software-templates/testing-scaffolder-alpha", "features/software-templates/migrating-from-v1beta2-to-v1beta3" ] }, From e900342bb6bdc4240d7395d6b6902683567c1d7d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 14 Feb 2023 10:02:15 +0100 Subject: [PATCH 421/423] Apply suggestions from code review Co-authored-by: Phil Kuang Signed-off-by: Patrik Oldsberg --- .../features/software-templates/testing-scaffolder-alpha.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/features/software-templates/testing-scaffolder-alpha.md b/docs/features/software-templates/testing-scaffolder-alpha.md index b8b63330d1..d10c7e7a0f 100644 --- a/docs/features/software-templates/testing-scaffolder-alpha.md +++ b/docs/features/software-templates/testing-scaffolder-alpha.md @@ -33,7 +33,7 @@ There's also a lot of bug fixes, and other things, but these are the main ones t ## How do I test out the `alpha` version? -With the release of `v1.12.0` it's now possible to run the `scaffolder/next` plugin and it be a drop in replacement for the current version that you use today. This means that you can start using the new code, and start testing it out. Once we have collected enough feedback, and squashed any bugs that might block us from releasing is, it will be promoted from the `/alpha` exports and replace the existing code leading to breaking changes if you haven't already made these changes part of this testing pilot. Those that have chosen to opt into this testing pilot means that once we promote it from the `/alpha` exports, you will need to update your code to point to the original exports from the `scaffolder` plugin, just like the code is today but with the [breaking changes](#breaking-changes) that you already made to your `Custom Field Extensions`. +With the release of `v1.12.0` it's now possible to run the `scaffolder/next` plugin and it be a drop in replacement for the current version that you use today. This means that you can start using the new code, and start testing it out. Once we have collected enough feedback, and squashed any bugs that might block us from releasing, it will be promoted from the `/alpha` exports and replace the existing code leading to breaking changes if you haven't already made these changes as part of this testing pilot. Those that have chosen to opt into this testing pilot means that once we promote it from the `/alpha` exports, you will need to update your code to point to the original exports from the `scaffolder` plugin, just like the code is today but with the [breaking changes](#breaking-changes) that you already made to your `Custom Field Extensions`. It's also worth calling out that if you do test this out, and find some issues or something not working out as expected, feel free to raise an issue in the [repo](https://github.com/backstage/backstage) or reach out to us on Discord! @@ -131,7 +131,7 @@ export const EntityNamePicker = ( } ``` -There's another `/alpha` export that's you need to replace `FieldExtensionComponentProps` with which is the `NextFieldExtensionComponentProps`. +There's another `/alpha` export that you need to replace `FieldExtensionComponentProps` with which is the `NextFieldExtensionComponentProps`. ```diff - import { FieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react'; @@ -226,7 +226,7 @@ If you were using the `formData` and assuming that it was set to an empty object schema: { title = 'Name', description = 'Unique name of the component' }, rawErrors, - formData, -+ formData = {}, // or mayube some other default value that you would prefer ++ formData = {}, // or maybe some other default value that you would prefer uiSchema: { 'ui:autofocus': autoFocus } = {}, idSchema, placeholder, From 4226e75198f01258e930d9db4d0acdf3bffd7a74 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:00:45 +0000 Subject: [PATCH 422/423] chore(deps): update dependency lint-staged to v13.1.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 af1a8fd1b0..ac66cab7ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27871,8 +27871,8 @@ __metadata: linkType: hard "lint-staged@npm:^13.0.0": - version: 13.1.1 - resolution: "lint-staged@npm:13.1.1" + version: 13.1.2 + resolution: "lint-staged@npm:13.1.2" dependencies: cli-truncate: ^3.1.0 colorette: ^2.0.19 @@ -27889,7 +27889,7 @@ __metadata: yaml: ^2.1.3 bin: lint-staged: bin/lint-staged.js - checksum: 8e5093c7e982a2f6d6449927a40156a812644479df1d2760aee8bf05df3a314e022d8f7e275e57fd61769ee57e3cf7b062ed3c6e4934a63848300b877e269daa + checksum: f854ad5c88542b8f06e27f3b4046927a4f3d4a451a04e079526559d819a325762268f65bd2df7156bcc0cb5f531f621c42cdb824b403f537c78305adc9e56a54 languageName: node linkType: hard From 71c0aee2598883a0fa0ec479a4d591ca6ab42a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 14 Feb 2023 14:07:07 +0100 Subject: [PATCH 423/423] update the alpha warning blurbs in backend docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- docs/backend-system/architecture/01-index.md | 2 +- docs/backend-system/architecture/02-backends.md | 2 +- docs/backend-system/architecture/03-services.md | 2 +- docs/backend-system/architecture/04-plugins.md | 2 +- docs/backend-system/architecture/05-extension-points.md | 2 +- docs/backend-system/architecture/06-modules.md | 2 +- docs/backend-system/architecture/07-naming-patterns.md | 2 +- docs/backend-system/building-backends/01-index.md | 2 +- docs/backend-system/building-backends/08-migrating.md | 2 +- docs/backend-system/building-plugins-and-modules/01-index.md | 2 +- .../backend-system/building-plugins-and-modules/02-testing.md | 2 +- .../building-plugins-and-modules/08-migrating.md | 2 +- docs/backend-system/core-services/01-index.md | 2 +- docs/backend-system/index.md | 4 ++-- docs/plugins/new-backend-system.md | 4 ++-- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/backend-system/architecture/01-index.md b/docs/backend-system/architecture/01-index.md index a9f08c7907..76953f7009 100644 --- a/docs/backend-system/architecture/01-index.md +++ b/docs/backend-system/architecture/01-index.md @@ -6,7 +6,7 @@ sidebar_label: System Architecture description: The structure and architecture of the new Backend System and its component parts --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** ## Building Blocks diff --git a/docs/backend-system/architecture/02-backends.md b/docs/backend-system/architecture/02-backends.md index 53670aba12..b6079d71b4 100644 --- a/docs/backend-system/architecture/02-backends.md +++ b/docs/backend-system/architecture/02-backends.md @@ -6,7 +6,7 @@ sidebar_label: Backend description: Backend instances --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** ## The Backend Instance diff --git a/docs/backend-system/architecture/03-services.md b/docs/backend-system/architecture/03-services.md index 875cb3aaea..8a86d90efb 100644 --- a/docs/backend-system/architecture/03-services.md +++ b/docs/backend-system/architecture/03-services.md @@ -6,7 +6,7 @@ sidebar_label: Services description: Services for backend plugins --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** Backend services provide shared functionality available to all backend plugins and modules. They are made available through service references that embed a type that represents the service interface, similar to how [Utility APIs](../../api/utility-apis.md) work in the Backstage frontend system. To use a service in your plugin or module you request an implementation of that service using the service reference. diff --git a/docs/backend-system/architecture/04-plugins.md b/docs/backend-system/architecture/04-plugins.md index e73f086c43..04271b17da 100644 --- a/docs/backend-system/architecture/04-plugins.md +++ b/docs/backend-system/architecture/04-plugins.md @@ -6,7 +6,7 @@ sidebar_label: Plugins description: Backend plugins --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** Plugins provide the actual base features of a Backstage backend. Each plugin operates completely independently of all other plugins and they only communicate with each other through network calls. This means that there is a strong degree of isolation between plugins, and that each plugin can be considered a separate microservice. While a default Backstage project has all plugins installed within a single backend, it is also possible to split this setup into multiple backends, with each backend housing one or more plugins. diff --git a/docs/backend-system/architecture/05-extension-points.md b/docs/backend-system/architecture/05-extension-points.md index 278c565472..6d320037ba 100644 --- a/docs/backend-system/architecture/05-extension-points.md +++ b/docs/backend-system/architecture/05-extension-points.md @@ -6,7 +6,7 @@ sidebar_label: Extension Points description: Extension points of backend plugins --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** While plugins are able to accept options for lightweight forms of customization and extension, you quickly hit a limit where you need something more powerful to allow users to extend your plugin. For this purpose, the backend system provides a mechanism for plugins to provide extension points, which can be used to expose deeper customizations for your plugin. Extension points are used by modules, which are installed in the backend adjacent to plugins. Modules are covered more in-depth in the [next section](./06-modules.md). diff --git a/docs/backend-system/architecture/06-modules.md b/docs/backend-system/architecture/06-modules.md index 2f359eaa75..53aae9e38d 100644 --- a/docs/backend-system/architecture/06-modules.md +++ b/docs/backend-system/architecture/06-modules.md @@ -6,7 +6,7 @@ sidebar_label: Modules description: Modules for backend plugins --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** Backend modules are used to extend [plugins](./04-plugins.md) with additional features or change existing behavior. They must always be installed in the same backend instance as the plugin that they extend, and may only extend a single plugin. Modules interact with their target plugin using the [extension points](./05-extension-points.md) registered by the plugin, while also being able to depend on the [services](./03-services.md) of that plugin. diff --git a/docs/backend-system/architecture/07-naming-patterns.md b/docs/backend-system/architecture/07-naming-patterns.md index b62e049f08..b541cc09ba 100644 --- a/docs/backend-system/architecture/07-naming-patterns.md +++ b/docs/backend-system/architecture/07-naming-patterns.md @@ -6,7 +6,7 @@ sidebar_label: Naming Patterns description: Naming patterns in the backend system --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** These are the naming patterns to adhere to within the backend system. They help us keep exports consistent across packages and make it easier to understand the usage and intent of exports. diff --git a/docs/backend-system/building-backends/01-index.md b/docs/backend-system/building-backends/01-index.md index bda2aa7eaa..65c536afdd 100644 --- a/docs/backend-system/building-backends/01-index.md +++ b/docs/backend-system/building-backends/01-index.md @@ -6,7 +6,7 @@ sidebar_label: Overview description: Building backends using the new backend system --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** > NOTE: If you have an existing backend that is not yet using the new backend > system, see [migrating](./08-migrating.md). diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index e503d627ef..567476532f 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -6,7 +6,7 @@ sidebar_label: Migration Guide description: How to migrate existing backends to the new backend system --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. As such, it is not considered stable, and it is not recommended to migrate production backends to the new backend system until it has a stable release.** ## Overview diff --git a/docs/backend-system/building-plugins-and-modules/01-index.md b/docs/backend-system/building-plugins-and-modules/01-index.md index cae5052d04..18cbabfe5d 100644 --- a/docs/backend-system/building-plugins-and-modules/01-index.md +++ b/docs/backend-system/building-plugins-and-modules/01-index.md @@ -6,7 +6,7 @@ sidebar_label: Overview description: Building backend plugins and modules using the new backend system --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** > NOTE: If you have an existing backend and/or backend plugins that are not yet > using the new backend system, see [migrating](./08-migrating.md). diff --git a/docs/backend-system/building-plugins-and-modules/02-testing.md b/docs/backend-system/building-plugins-and-modules/02-testing.md index 37c5698512..7f93fab45b 100644 --- a/docs/backend-system/building-plugins-and-modules/02-testing.md +++ b/docs/backend-system/building-plugins-and-modules/02-testing.md @@ -6,7 +6,7 @@ sidebar_label: Testing description: Learn how to test your backend plugins and modules --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** Utilities for testing backend plugins and modules are available in `@backstage/backend-test-utils`. This section describes those facilities. diff --git a/docs/backend-system/building-plugins-and-modules/08-migrating.md b/docs/backend-system/building-plugins-and-modules/08-migrating.md index 687f4c1d5e..cf5aa8106f 100644 --- a/docs/backend-system/building-plugins-and-modules/08-migrating.md +++ b/docs/backend-system/building-plugins-and-modules/08-migrating.md @@ -6,7 +6,7 @@ sidebar_label: Migration Guide description: How to migrate existing backend plugins to the new backend system --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** Migrating an existing backend plugin to the new backend system is fairly straightforward. The process is similar across the majority of plugins which just return a `Router` that is then wired up in the `index.ts` file of your backend. The primary thing that we need to do is to make sure that the dependencies that are required by the plugin are available, and then registering the router with the HTTP router service. diff --git a/docs/backend-system/core-services/01-index.md b/docs/backend-system/core-services/01-index.md index b6682c2708..6448943e3a 100644 --- a/docs/backend-system/core-services/01-index.md +++ b/docs/backend-system/core-services/01-index.md @@ -6,7 +6,7 @@ sidebar_label: Core Services description: Core backend service APIs --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** The default backend provides several [core services](https://github.com/backstage/backstage/blob/master/packages/backend-plugin-api/src/services/definitions/coreServices.ts) out of the box which includes access to configuration, logging, URL Readers, databases and more. diff --git a/docs/backend-system/index.md b/docs/backend-system/index.md index de598167ae..d2d7c8e69e 100644 --- a/docs/backend-system/index.md +++ b/docs/backend-system/index.md @@ -6,10 +6,10 @@ sidebar_label: Overview description: The Backend System --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** ## Status -The new backend system is under active development, and only a small number of plugins have been migrated so far. It is possible to try it out, but it is not recommended to use this new system in production yet. +The new backend system is in alpha, and only a small number of plugins have been migrated so far. It is possible to try it out, but it is not recommended to use this new system in production yet. You can find an example backend setup in [the `backend-next` package](https://github.com/backstage/backstage/tree/master/packages/backend-next). diff --git a/docs/plugins/new-backend-system.md b/docs/plugins/new-backend-system.md index 785d364ae2..2ff061a60b 100644 --- a/docs/plugins/new-backend-system.md +++ b/docs/plugins/new-backend-system.md @@ -4,11 +4,11 @@ title: New Backend System description: Details of the upcoming backend system --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** ## Status -The new backend system is under active development, and only a small number of plugins have been migrated so far. It is possible to try it out, but it is not recommended to use this new system in production yet. +The new backend system is in alpha, and only a small number of plugins have been migrated so far. It is possible to try it out, but it is not recommended to use this new system in production yet. You can find an example backend setup in [the backend-next package](https://github.com/backstage/backstage/tree/master/packages/backend-next).