From 49776f84799241af6b0ba31f84217d4e59044a36 Mon Sep 17 00:00:00 2001 From: Phil Gore Date: Fri, 10 Sep 2021 16:18:54 -0500 Subject: [PATCH 01/26] commit client changes for searchStreaming generator Signed-off-by: Phil Gore --- .../src/ldap/client.ts | 56 +++++++++++++++++++ .../src/ldap/read.ts | 25 ++++++--- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts index a99fc3846e..6dae1839ce 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts @@ -109,6 +109,62 @@ export class LdapClient { } } + /** + * Performs an LDAP search operation, calls a function on each entry to limit memory usage + * + * @param dn The fully qualified base DN to search within + * @param options The search options + */ + *searchStreaming(dn: string, options: SearchOptions) { + let queuesize = 25; + if (options) { + if ( + options.paged && + typeof options.paged === 'object' && + typeof options.paged.pageSize === 'number' && + options.paged.pageSize > 0 + ) { + queuesize = options.paged.pageSize; + } + } + const queue: SearchEntry[] = new Array(queuesize); + let done = false; + try { + this.client.search(dn, options, (err, res) => { + if (err) { + throw new Error(errorString(err)); + } + + res.on('searchReference', () => { + throw new Error('Unable to handle referral'); + }); + + res.on('searchEntry', entry => { + queue.push(entry); + }); + + res.on('error', e => { + throw new Error(errorString(e)); + }); + + res.on('end', r => { + if (!r) { + throw new Error('Null response'); + } else if (r.status !== 0) { + throw new Error(`Got status ${r.status}: ${r.errorMessage}`); + } else { + done = true; + } + }); + }); + } catch (e) { + throw new Error(`LDAP search at DN "${dn}" failed, ${e.message}`); + } + while (!done && queue.length > 0) { + yield queue.pop(); + } + } + /** * Get the Server Vendor. * Currently only detects Microsoft Active Directory Servers. diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.ts index f3ee09d32d..96a9966628 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.ts @@ -107,16 +107,19 @@ export async function readLdapUsers( const transformer = opts?.transformer ?? defaultUserTransformer; - const entries = await client.search(dn, options); + const entries = client.searchStreaming(dn, options); + for (const entry of entries) { + if (!entry) { + continue; + } - for (const user of entries) { - const entity = await transformer(vendor, config, user); + const entity = await transformer(vendor, config, entry); if (!entity) { continue; } - mapReferencesAttr(user, vendor, map.memberOf, (myDn, vs) => { + mapReferencesAttr(entry, vendor, map.memberOf, (myDn, vs) => { ensureItems(userMemberOf, myDn, vs); }); @@ -210,19 +213,23 @@ export async function readLdapGroups( const transformer = opts?.transformer ?? defaultGroupTransformer; - const entries = await client.search(dn, options); + const entries = client.searchStreaming(dn, options); - for (const group of entries) { - const entity = await transformer(vendor, config, group); + for (const entry of entries) { + if (!entry) { + continue; + } + + const entity = await transformer(vendor, config, entry); if (!entity) { continue; } - mapReferencesAttr(group, vendor, map.memberOf, (myDn, vs) => { + mapReferencesAttr(entry, vendor, map.memberOf, (myDn, vs) => { ensureItems(groupMemberOf, myDn, vs); }); - mapReferencesAttr(group, vendor, map.members, (myDn, vs) => { + mapReferencesAttr(entry, vendor, map.members, (myDn, vs) => { ensureItems(groupMember, myDn, vs); }); From ebd2ddf4a27a990f25e1977c72cd4fbdbf403a00 Mon Sep 17 00:00:00 2001 From: Phil Gore Date: Sat, 11 Sep 2021 12:59:34 -0500 Subject: [PATCH 02/26] figuring out why the tests list this as not a function Signed-off-by: Phil Gore --- .../src/ldap/client.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts index 6dae1839ce..d859c5e08b 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts @@ -110,13 +110,16 @@ export class LdapClient { } /** - * Performs an LDAP search operation, calls a function on each entry to limit memory usage + * Performs an LDAP search operation, creates a generator to limit memory usage * * @param dn The fully qualified base DN to search within * @param options The search options */ - *searchStreaming(dn: string, options: SearchOptions) { - let queuesize = 25; + *searchStreaming( + dn: string, + options: SearchOptions, + ): IterableIterator { + let queueSize = 25; if (options) { if ( options.paged && @@ -124,10 +127,10 @@ export class LdapClient { typeof options.paged.pageSize === 'number' && options.paged.pageSize > 0 ) { - queuesize = options.paged.pageSize; + queueSize = options.paged.pageSize; } } - const queue: SearchEntry[] = new Array(queuesize); + const queue: SearchEntry[] = new Array(queueSize); let done = false; try { this.client.search(dn, options, (err, res) => { @@ -161,7 +164,11 @@ export class LdapClient { throw new Error(`LDAP search at DN "${dn}" failed, ${e.message}`); } while (!done && queue.length > 0) { - yield queue.pop(); + const res = queue.pop(); + if (!res) { + continue; + } + yield res; } } From 211698b3f10a21c70e64662b56d22ae1460b9374 Mon Sep 17 00:00:00 2001 From: Phil Gore Date: Tue, 14 Sep 2021 11:02:13 -0500 Subject: [PATCH 03/26] mock implementation for new func and passing tests Signed-off-by: Phil Gore --- .../src/ldap/client.ts | 82 +++---- .../src/ldap/read.test.ts | 209 ++++++++++-------- .../src/ldap/read.ts | 25 +-- 3 files changed, 163 insertions(+), 153 deletions(-) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts index d859c5e08b..eddd4291d1 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts @@ -24,6 +24,10 @@ import { LdapVendor, } from './vendors'; +export interface SearchCallback { + (entry: SearchEntry): void; +} + /** * Basic wrapper for the ldapjs library. * @@ -110,66 +114,50 @@ export class LdapClient { } /** - * Performs an LDAP search operation, creates a generator to limit memory usage + * Performs an LDAP search operation, calls a function on each entry to limit memory usage * * @param dn The fully qualified base DN to search within * @param options The search options + * @param f The callback to call on each search entry */ - *searchStreaming( + async searchStreaming( dn: string, options: SearchOptions, - ): IterableIterator { - let queueSize = 25; - if (options) { - if ( - options.paged && - typeof options.paged === 'object' && - typeof options.paged.pageSize === 'number' && - options.paged.pageSize > 0 - ) { - queueSize = options.paged.pageSize; - } - } - const queue: SearchEntry[] = new Array(queueSize); - let done = false; + f: SearchCallback, + ): Promise { try { - this.client.search(dn, options, (err, res) => { - if (err) { - throw new Error(errorString(err)); - } - - res.on('searchReference', () => { - throw new Error('Unable to handle referral'); - }); - - res.on('searchEntry', entry => { - queue.push(entry); - }); - - res.on('error', e => { - throw new Error(errorString(e)); - }); - - res.on('end', r => { - if (!r) { - throw new Error('Null response'); - } else if (r.status !== 0) { - throw new Error(`Got status ${r.status}: ${r.errorMessage}`); - } else { - done = true; + return await new Promise((resolve, reject) => { + this.client.search(dn, options, (err, res) => { + if (err) { + reject(new Error(errorString(err))); } + + res.on('searchReference', () => { + reject(new Error('Unable to handle referral')); + }); + + res.on('searchEntry', async entry => { + await f(entry); + }); + + res.on('error', e => { + reject(new Error(errorString(e))); + }); + + res.on('end', r => { + if (!r) { + throw new Error('Null response'); + } else if (r.status !== 0) { + throw new Error(`Got status ${r.status}: ${r.errorMessage}`); + } else { + resolve(); + } + }); }); }); } catch (e) { throw new Error(`LDAP search at DN "${dn}" failed, ${e.message}`); } - while (!done && queue.length > 0) { - const res = queue.pop(); - if (!res) { - continue; - } - yield res; - } } /** diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts index b357b6b408..3615d8b2ad 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts @@ -67,7 +67,7 @@ function searchEntry( describe('readLdapUsers', () => { const client: jest.Mocked = { - search: jest.fn(), + searchStreaming: jest.fn(), getVendor: jest.fn(), } as any; @@ -75,18 +75,25 @@ describe('readLdapUsers', () => { it('transfers all attributes from a default ldap vendor', async () => { client.getVendor.mockResolvedValue(DefaultLdapVendor); - client.search.mockResolvedValue([ - searchEntry({ - uid: ['uid-value'], - description: ['description-value'], - cn: ['cn-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - entryDN: ['dn-value'], - entryUUID: ['uuid-value'], - }), - ]); + client.searchStreaming.mockImplementation( + async (_dn, _opts, fn): Promise => { + return await new Promise((resolve, _reject) => { + fn( + searchEntry({ + uid: ['uid-value'], + description: ['description-value'], + cn: ['cn-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + entryDN: ['dn-value'], + entryUUID: ['uuid-value'], + }), + ); + resolve(); + }); + }, + ); const config: UserConfig = { dn: 'ddd', options: {}, @@ -129,37 +136,45 @@ describe('readLdapUsers', () => { it('transfers all attributes from Microsoft Active Directory', async () => { client.getVendor.mockResolvedValue(ActiveDirectoryVendor); - client.search.mockResolvedValue([ - searchEntry({ - uid: ['uid-value'], - description: ['description-value'], - cn: ['cn-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - distinguishedName: ['dn-value'], - objectGUID: [ - Buffer.from([ - 68, - 2, - 125, - 190, - 209, - 0, - 94, - 73, - 133, - 33, - 230, - 174, - 234, - 195, - 160, - 152, - ]), - ], - }), - ]); + client.searchStreaming.mockImplementation( + async (_dn, _opts, fn): Promise => { + return await new Promise((resolve, _reject) => { + fn( + searchEntry({ + uid: ['uid-value'], + description: ['description-value'], + cn: ['cn-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + distinguishedName: ['dn-value'], + objectGUID: [ + Buffer.from([ + 68, + 2, + 125, + 190, + 209, + 0, + 94, + 73, + 133, + 33, + 230, + 174, + 234, + 195, + 160, + 152, + ]), + ], + }), + ); + resolve(); + }); + }, + ); + const config: UserConfig = { dn: 'ddd', options: {}, @@ -203,7 +218,7 @@ describe('readLdapUsers', () => { describe('readLdapGroups', () => { const client: jest.Mocked = { - search: jest.fn(), + searchStreaming: jest.fn(), getVendor: jest.fn(), } as any; @@ -211,19 +226,26 @@ describe('readLdapGroups', () => { it('transfers all attributes from a default ldap vendor', async () => { client.getVendor.mockResolvedValue(DefaultLdapVendor); - client.search.mockResolvedValue([ - searchEntry({ - cn: ['cn-value'], - description: ['description-value'], - tt: ['type-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - member: ['e', 'f', 'g'], - entryDN: ['dn-value'], - entryUUID: ['uuid-value'], - }), - ]); + client.searchStreaming.mockImplementation( + async (_dn, _opts, fn): Promise => { + return await new Promise((resolve, _reject) => { + fn( + searchEntry({ + cn: ['cn-value'], + description: ['description-value'], + tt: ['type-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + member: ['e', 'f', 'g'], + entryDN: ['dn-value'], + entryUUID: ['uuid-value'], + }), + ); + resolve(); + }); + }, + ); const config: GroupConfig = { dn: 'ddd', options: {}, @@ -274,38 +296,45 @@ describe('readLdapGroups', () => { }); it('transfers all attributes from Microsoft Active Directory', async () => { client.getVendor.mockResolvedValue(ActiveDirectoryVendor); - client.search.mockResolvedValue([ - searchEntry({ - cn: ['cn-value'], - description: ['description-value'], - tt: ['type-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - member: ['e', 'f', 'g'], - distinguishedName: ['dn-value'], - objectGUID: [ - Buffer.from([ - 68, - 2, - 125, - 190, - 209, - 0, - 94, - 73, - 133, - 33, - 230, - 174, - 234, - 195, - 160, - 152, - ]), - ], - }), - ]); + client.searchStreaming.mockImplementation( + async (_dn, _opts, fn): Promise => { + return await new Promise((resolve, _reject) => { + fn( + searchEntry({ + cn: ['cn-value'], + description: ['description-value'], + tt: ['type-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + member: ['e', 'f', 'g'], + distinguishedName: ['dn-value'], + objectGUID: [ + Buffer.from([ + 68, + 2, + 125, + 190, + 209, + 0, + 94, + 73, + 133, + 33, + 230, + 174, + 234, + 195, + 160, + 152, + ]), + ], + }), + ); + resolve(); + }); + }, + ); const config: GroupConfig = { dn: 'ddd', options: {}, diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.ts index 96a9966628..37e69c5bcf 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.ts @@ -107,24 +107,19 @@ export async function readLdapUsers( const transformer = opts?.transformer ?? defaultUserTransformer; - const entries = client.searchStreaming(dn, options); - for (const entry of entries) { - if (!entry) { - continue; - } - - const entity = await transformer(vendor, config, entry); + await client.searchStreaming(dn, options, async user => { + const entity = await transformer(vendor, config, user); if (!entity) { - continue; + return; } - mapReferencesAttr(entry, vendor, map.memberOf, (myDn, vs) => { + mapReferencesAttr(user, vendor, map.memberOf, (myDn, vs) => { ensureItems(userMemberOf, myDn, vs); }); entities.push(entity); - } + }); return { users: entities, userMemberOf }; } @@ -213,17 +208,15 @@ export async function readLdapGroups( const transformer = opts?.transformer ?? defaultGroupTransformer; - const entries = client.searchStreaming(dn, options); - - for (const entry of entries) { + await client.searchStreaming(dn, options, async entry => { if (!entry) { - continue; + return; } const entity = await transformer(vendor, config, entry); if (!entity) { - continue; + return; } mapReferencesAttr(entry, vendor, map.memberOf, (myDn, vs) => { @@ -234,7 +227,7 @@ export async function readLdapGroups( }); groups.push(entity); - } + }); return { groups, From 8b016ce67bda539223847b045d0eb3b4ca8dbc6e Mon Sep 17 00:00:00 2001 From: Phil Gore Date: Tue, 14 Sep 2021 11:12:33 -0500 Subject: [PATCH 04/26] adding changeset Signed-off-by: Phil Gore --- .changeset/proud-adults-bathe.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/proud-adults-bathe.md diff --git a/.changeset/proud-adults-bathe.md b/.changeset/proud-adults-bathe.md new file mode 100644 index 0000000000..86b8cfecb3 --- /dev/null +++ b/.changeset/proud-adults-bathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-ldap': minor +--- + +Alters LDAP processor to handle one SearchEntry at a time From 287d055a9d9486ecbe5569b55f8b7fc000a94e94 Mon Sep 17 00:00:00 2001 From: Phil Gore Date: Tue, 14 Sep 2021 13:14:00 -0500 Subject: [PATCH 05/26] prettifying test, updating api-report and test cases Signed-off-by: Phil Gore callback without promise and adjust test cases Signed-off-by: Phil Gore prettifying test Signed-off-by: Phil Gore updating api-report Signed-off-by: Phil Gore --- .../catalog-backend-module-ldap/api-report.md | 9 + .../src/ldap/client.ts | 4 +- .../src/ldap/read.test.ts | 184 +++++++----------- 3 files changed, 79 insertions(+), 118 deletions(-) diff --git a/plugins/catalog-backend-module-ldap/api-report.md b/plugins/catalog-backend-module-ldap/api-report.md index 35f647ec70..91f70eaa21 100644 --- a/plugins/catalog-backend-module-ldap/api-report.md +++ b/plugins/catalog-backend-module-ldap/api-report.md @@ -103,6 +103,15 @@ export class LdapClient { // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen search(dn: string, options: SearchOptions): Promise; + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen + // Warning: (ae-forgotten-export) The symbol "SearchCallback" needs to be exported by the entry point index.d.ts + searchStreaming( + dn: string, + options: SearchOptions, + f: SearchCallback, + ): Promise; } // Warning: (ae-missing-release-tag) "LdapOrgEntityProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts index a36a96b638..048aa40dc1 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts @@ -147,8 +147,8 @@ export class LdapClient { reject(new Error('Unable to handle referral')); }); - res.on('searchEntry', async entry => { - await f(entry); + res.on('searchEntry', entry => { + f(entry); }); res.on('error', e => { diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts index 5674c041ab..c4f203c5db 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts @@ -75,25 +75,20 @@ describe('readLdapUsers', () => { it('transfers all attributes from a default ldap vendor', async () => { client.getVendor.mockResolvedValue(DefaultLdapVendor); - client.searchStreaming.mockImplementation( - async (_dn, _opts, fn): Promise => { - return await new Promise((resolve, _reject) => { - fn( - searchEntry({ - uid: ['uid-value'], - description: ['description-value'], - cn: ['cn-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - entryDN: ['dn-value'], - entryUUID: ['uuid-value'], - }), - ); - resolve(); - }); - }, - ); + client.searchStreaming.mockImplementation(async (_dn, _opts, fn) => { + await fn( + searchEntry({ + uid: ['uid-value'], + description: ['description-value'], + cn: ['cn-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + entryDN: ['dn-value'], + entryUUID: ['uuid-value'], + }), + ); + }); const config: UserConfig = { dn: 'ddd', options: {}, @@ -136,44 +131,25 @@ describe('readLdapUsers', () => { it('transfers all attributes from Microsoft Active Directory', async () => { client.getVendor.mockResolvedValue(ActiveDirectoryVendor); - client.searchStreaming.mockImplementation( - async (_dn, _opts, fn): Promise => { - return await new Promise((resolve, _reject) => { - fn( - searchEntry({ - uid: ['uid-value'], - description: ['description-value'], - cn: ['cn-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - distinguishedName: ['dn-value'], - objectGUID: [ - Buffer.from([ - 68, - 2, - 125, - 190, - 209, - 0, - 94, - 73, - 133, - 33, - 230, - 174, - 234, - 195, - 160, - 152, - ]), - ], - }), - ); - resolve(); - }); - }, - ); + client.searchStreaming.mockImplementation(async (_dn, _opts, fn) => { + await fn( + searchEntry({ + uid: ['uid-value'], + description: ['description-value'], + cn: ['cn-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + distinguishedName: ['dn-value'], + objectGUID: [ + Buffer.from([ + 68, 2, 125, 190, 209, 0, 94, 73, 133, 33, 230, 174, 234, 195, 160, + 152, + ]), + ], + }), + ); + }); const config: UserConfig = { dn: 'ddd', options: {}, @@ -225,26 +201,21 @@ describe('readLdapGroups', () => { it('transfers all attributes from a default ldap vendor', async () => { client.getVendor.mockResolvedValue(DefaultLdapVendor); - client.searchStreaming.mockImplementation( - async (_dn, _opts, fn): Promise => { - return await new Promise((resolve, _reject) => { - fn( - searchEntry({ - cn: ['cn-value'], - description: ['description-value'], - tt: ['type-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - member: ['e', 'f', 'g'], - entryDN: ['dn-value'], - entryUUID: ['uuid-value'], - }), - ); - resolve(); - }); - }, - ); + client.searchStreaming.mockImplementation(async (_dn, _opts, fn) => { + await fn( + searchEntry({ + cn: ['cn-value'], + description: ['description-value'], + tt: ['type-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + member: ['e', 'f', 'g'], + entryDN: ['dn-value'], + entryUUID: ['uuid-value'], + }), + ); + }); const config: GroupConfig = { dn: 'ddd', options: {}, @@ -295,45 +266,26 @@ describe('readLdapGroups', () => { }); it('transfers all attributes from Microsoft Active Directory', async () => { client.getVendor.mockResolvedValue(ActiveDirectoryVendor); - client.searchStreaming.mockImplementation( - async (_dn, _opts, fn): Promise => { - return await new Promise((resolve, _reject) => { - fn( - searchEntry({ - cn: ['cn-value'], - description: ['description-value'], - tt: ['type-value'], - mail: ['mail-value'], - avatarUrl: ['avatarUrl-value'], - memberOf: ['x', 'y', 'z'], - member: ['e', 'f', 'g'], - distinguishedName: ['dn-value'], - objectGUID: [ - Buffer.from([ - 68, - 2, - 125, - 190, - 209, - 0, - 94, - 73, - 133, - 33, - 230, - 174, - 234, - 195, - 160, - 152, - ]), - ], - }), - ); - resolve(); - }); - }, - ); + client.searchStreaming.mockImplementation(async (_dn, _opts, fn) => { + await fn( + searchEntry({ + cn: ['cn-value'], + description: ['description-value'], + tt: ['type-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + member: ['e', 'f', 'g'], + distinguishedName: ['dn-value'], + objectGUID: [ + Buffer.from([ + 68, 2, 125, 190, 209, 0, 94, 73, 133, 33, 230, 174, 234, 195, 160, + 152, + ]), + ], + }), + ); + }); const config: GroupConfig = { dn: 'ddd', options: {}, From ea048ce7a02e7d7650a420604930245f6e842555 Mon Sep 17 00:00:00 2001 From: "@pawelmitka" Date: Wed, 15 Sep 2021 12:09:32 +0200 Subject: [PATCH 06/26] feat(scaffolder-backend): Yeoman Generator module Added a new Scaffolder Backend Yeoman module to allow for integration with Yeoman Generators. At the moment the only action added is 'run' to execute installed Yeoman Generator. The Yeoman Generator can be either added as a dependency in `package.json` of a service that uses this plugin or installed in an environment using `npm install -g https://github.com/org/generator-name.git` Tests for `yeomanRun.ts` were not added because 'yeoman'environment' module is exported in a way that does not allow partial mocking while '@types/yeoman-environment' does not support Yeoman 3.x, yet. I also tested it E2E. Signed-off-by: @pawelmitka --- .../.eslintrc.js | 3 + .../README.md | 156 +++++ .../api-report.md | 14 + .../package.json | 34 + .../src/actions/index.ts | 16 + .../src/actions/run/index.ts | 16 + .../src/actions/run/yeoman.test.ts | 70 ++ .../src/actions/run/yeoman.ts | 67 ++ .../src/actions/run/yeomanRun.ts | 36 ++ .../src/index.ts | 16 + yarn.lock | 608 +++++++++++++++++- 11 files changed, 1024 insertions(+), 12 deletions(-) create mode 100644 plugins/scaffolder-backend-module-yeoman/.eslintrc.js create mode 100644 plugins/scaffolder-backend-module-yeoman/README.md create mode 100644 plugins/scaffolder-backend-module-yeoman/api-report.md create mode 100644 plugins/scaffolder-backend-module-yeoman/package.json create mode 100644 plugins/scaffolder-backend-module-yeoman/src/actions/index.ts create mode 100644 plugins/scaffolder-backend-module-yeoman/src/actions/run/index.ts create mode 100644 plugins/scaffolder-backend-module-yeoman/src/actions/run/yeoman.test.ts create mode 100644 plugins/scaffolder-backend-module-yeoman/src/actions/run/yeoman.ts create mode 100644 plugins/scaffolder-backend-module-yeoman/src/actions/run/yeomanRun.ts create mode 100644 plugins/scaffolder-backend-module-yeoman/src/index.ts diff --git a/plugins/scaffolder-backend-module-yeoman/.eslintrc.js b/plugins/scaffolder-backend-module-yeoman/.eslintrc.js new file mode 100644 index 0000000000..16a033dbc6 --- /dev/null +++ b/plugins/scaffolder-backend-module-yeoman/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint.backend')], +}; diff --git a/plugins/scaffolder-backend-module-yeoman/README.md b/plugins/scaffolder-backend-module-yeoman/README.md new file mode 100644 index 0000000000..bacbb87648 --- /dev/null +++ b/plugins/scaffolder-backend-module-yeoman/README.md @@ -0,0 +1,156 @@ +# scaffolder-backend-module-yeoman + +Welcome to the `run:yeoman` action for the `scaffolder-backend`. + +## Getting started + +You need to configure the action in your backend: + +## From your Backstage root directory + +``` +cd packages/backend +yarn add @backstage/plugin-scaffolder-backend-module-yeoman +``` + +Configure the action: +(you can check the [docs](https://backstage.io/docs/features/software-templates/writing-custom-actions#registering-custom-actions) to see all options): + +```typescript +// packages/backend/src/plugins/scaffolder.ts + +const actions = [ + createRunYeomanAction(), + ...createBuiltInActions({ + containerRunner, + integrations, + config, + catalogClient, + reader, + }), +]; + +return await createRouter({ + containerRunner, + logger, + config, + database, + catalogClient, + reader, + actions, +}); +``` + +After that you can use the action in your template: + +```yaml +apiVersion: backstage.io/v1beta2 +kind: Template +metadata: + name: yeoman-demo + title: Yeoman Test + description: Cookiecutter example +spec: + owner: backstage/techdocs-core + type: service + + parameters: + - title: Fill in some steps + required: + - name + - owner + properties: + name: + title: Name + type: string + description: Unique name of the component + ui:autofocus: true + ui:options: + rows: 5 + owner: + title: Owner + type: string + description: Owner of the component + ui:field: OwnerPicker + ui:options: + allowedKinds: + - Group + system: + title: System + type: string + description: System of the component + ui:field: EntityPicker + ui:options: + allowedKinds: + - System + defaultKind: System + + - title: Choose a location + required: + - repoUrl + - dryRun + properties: + repoUrl: + title: Repository Location + type: string + ui:field: RepoUrlPicker + ui:options: + allowedHosts: + - github.com + dryRun: + title: Only perform a dry run, don't publish anything + type: boolean + default: false + + steps: + - id: yeoman + name: Yeoman + action: run:yeoman + input: + namespace: 'org:codeowners' + options: + codeowners: '@{{ parameters.owner }}' + + - id: publish + if: '{{ not parameters.dryRun }}' + name: Publish + action: publish:github + input: + allowedHosts: ['github.com'] + description: 'This is {{ parameters.name }}' + repoUrl: '{{ parameters.repoUrl }}' + + - id: register + if: '{{ not parameters.dryRun }}' + name: Register + action: catalog:register + input: + repoContentsUrl: '{{ steps.publish.output.repoContentsUrl }}' + catalogInfoPath: '/catalog-info.yaml' + + - name: Results + if: '{{ parameters.dryRun }}' + action: debug:log + input: + listWorkspace: true + + output: + links: + - title: Repository + url: '{{ steps.publish.output.remoteUrl }}' + - title: Open in catalog + icon: 'catalog' + entityRef: '{{ steps.register.output.entityRef }}' +``` + +You can also visit the `/create/actions` route in your Backstage application to find out more about the parameters this action accepts when it's installed to configure how you like. + +### Yeoman Generators setup + +Yeoman generator should be installed a dependency of your `backstage/packages/backend` in `package.json` + +```package.json +"generator-name": "^1.2.3" +``` + +Alternatively it can be installed globally in the environment using, e.g.: `npm install -g generator-name`. diff --git a/plugins/scaffolder-backend-module-yeoman/api-report.md b/plugins/scaffolder-backend-module-yeoman/api-report.md new file mode 100644 index 0000000000..1f38d3945c --- /dev/null +++ b/plugins/scaffolder-backend-module-yeoman/api-report.md @@ -0,0 +1,14 @@ +## API Report File for "@backstage/plugin-scaffolder-backend-module-yeoman" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { TemplateAction } from '@backstage/plugin-scaffolder-backend'; + +// Warning: (ae-missing-release-tag) "createRunYeomanAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function createRunYeomanAction(): TemplateAction; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json new file mode 100644 index 0000000000..195aac6fc1 --- /dev/null +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -0,0 +1,34 @@ +{ + "name": "@backstage/plugin-scaffolder-backend-module-yeoman", + "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" + }, + "scripts": { + "start": "backstage-cli backend:dev", + "build": "backstage-cli backend:build", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "prepack": "backstage-cli prepack", + "postpack": "backstage-cli postpack", + "clean": "backstage-cli clean" + }, + "dependencies": { + "@backstage/config": "^0.1.8", + "@backstage/plugin-scaffolder-backend": "^0.15.2", + "winston": "^3.2.1", + "yeoman-environment": "^3.6.0" + }, + "devDependencies": { + "@backstage/backend-common": "^0.9.2", + "@types/jest": "^26.0.7" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/scaffolder-backend-module-yeoman/src/actions/index.ts b/plugins/scaffolder-backend-module-yeoman/src/actions/index.ts new file mode 100644 index 0000000000..61bfea8510 --- /dev/null +++ b/plugins/scaffolder-backend-module-yeoman/src/actions/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 * from './run'; diff --git a/plugins/scaffolder-backend-module-yeoman/src/actions/run/index.ts b/plugins/scaffolder-backend-module-yeoman/src/actions/run/index.ts new file mode 100644 index 0000000000..52d3f3ac92 --- /dev/null +++ b/plugins/scaffolder-backend-module-yeoman/src/actions/run/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 { createRunYeomanAction } from './yeoman'; diff --git a/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeoman.test.ts b/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeoman.test.ts new file mode 100644 index 0000000000..6e61ae77c4 --- /dev/null +++ b/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeoman.test.ts @@ -0,0 +1,70 @@ +/* + * 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 { yeomanRun } from './yeomanRun'; + +jest.mock('./yeomanRun'); + +import { getVoidLogger } from '@backstage/backend-common'; +import os from 'os'; +import { PassThrough } from 'stream'; +import { createRunYeomanAction } from './yeoman'; +import type { ActionContext } from '@backstage/plugin-scaffolder-backend'; +import { JsonObject } from '@backstage/config'; + +describe('run:yeoman', () => { + const mockTmpDir = os.tmpdir(); + + let mockContext: ActionContext<{ + namespace: string; + args?: string[]; + options?: JsonObject; + }>; + + const action = createRunYeomanAction(); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + it('should call yeomanRun with the correct variables', async () => { + const namespace = 'whatever:app'; + const args = ['aa', 'bb']; + const options = { + code: 'owner', + }; + mockContext = { + input: { + namespace, + args, + options, + }, + workspacePath: mockTmpDir, + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), + }; + + await action.handler(mockContext); + expect(yeomanRun).toHaveBeenCalledWith( + mockTmpDir, + namespace, + args, + options, + ); + }); +}); diff --git a/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeoman.ts b/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeoman.ts new file mode 100644 index 0000000000..c8bd49f3d3 --- /dev/null +++ b/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeoman.ts @@ -0,0 +1,67 @@ +/* + * 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 { JsonObject } from '@backstage/config'; +import { createTemplateAction } from '@backstage/plugin-scaffolder-backend'; +import { yeomanRun } from './yeomanRun'; + +export function createRunYeomanAction() { + return createTemplateAction<{ + namespace: string; + args?: string[]; + options?: JsonObject; + }>({ + id: 'run:yeoman', + description: 'Runs Yeoman on an installed Yeoman generator', + schema: { + input: { + type: 'object', + required: ['namespace'], + properties: { + namespace: { + title: 'Generator Namespace', + description: 'Yeoman generator namespace, e.g: node:app', + type: 'string', + }, + args: { + title: 'Generator Arguments', + description: 'Arguments to pass on to Yeoman for templating', + type: 'array', + items: { + type: 'string', + }, + }, + options: { + title: 'Generator Options', + description: 'Options to pass on to Yeoman for templating', + type: 'object', + }, + }, + }, + }, + async handler(ctx) { + ctx.logger.info( + `Templating using Yeoman generator: ${ctx.input.namespace}`, + ); + await yeomanRun( + ctx.workspacePath, + ctx.input.namespace, + ctx.input.args, + ctx.input.options, + ); + }, + }); +} diff --git a/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeomanRun.ts b/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeomanRun.ts new file mode 100644 index 0000000000..ff11634f81 --- /dev/null +++ b/plugins/scaffolder-backend-module-yeoman/src/actions/run/yeomanRun.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { JsonObject } from '@backstage/config'; + +/* + * This module should use '@types/yeoman-environment' eventually as soon as '@types/yeoman-environment' supports + * the latest version of Yeoman -> 3.x. Then it will be possible to test this module with jest. + */ + +export async function yeomanRun( + workspace: string, + namespace: string, + args?: string[], + opts?: JsonObject, +) { + const yeoman = require('yeoman-environment'); + const generator = yeoman.lookupGenerator(namespace); + const env = yeoman.createEnv(undefined, { cwd: workspace }); + env.register(generator, namespace); + const yeomanArgs = [namespace, ...(args ?? [])]; + await env.run(yeomanArgs, opts); +} diff --git a/plugins/scaffolder-backend-module-yeoman/src/index.ts b/plugins/scaffolder-backend-module-yeoman/src/index.ts new file mode 100644 index 0000000000..4f06b14a86 --- /dev/null +++ b/plugins/scaffolder-backend-module-yeoman/src/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 * from './actions'; diff --git a/yarn.lock b/yarn.lock index 4c75abd9e3..4fa2b23e42 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2855,6 +2855,11 @@ dependencies: yaml-ast-parser "0.0.43" +"@gar/promisify@^1.0.1": + version "1.1.2" + resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210" + integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw== + "@gitbeaker/core@^30.2.0", "@gitbeaker/core@^30.3.0": version "30.3.0" resolved "https://registry.npmjs.org/@gitbeaker/core/-/core-30.3.0.tgz#d005891d47cfacb41d4a3cc8bf3ee8c68c53d378" @@ -4663,11 +4668,56 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" +"@npmcli/arborist@^2.2.2": + version "2.8.3" + resolved "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.8.3.tgz#5569e7d2038f6893abc81f9c879f497b506e6980" + integrity sha512-miFcxbZjmQqeFTeRSLLh+lc/gxIKDO5L4PVCp+dp+kmcwJmYsEJmF7YvHR2yi3jF+fxgvLf3CCFzboPIXAuabg== + dependencies: + "@npmcli/installed-package-contents" "^1.0.7" + "@npmcli/map-workspaces" "^1.0.2" + "@npmcli/metavuln-calculator" "^1.1.0" + "@npmcli/move-file" "^1.1.0" + "@npmcli/name-from-folder" "^1.0.1" + "@npmcli/node-gyp" "^1.0.1" + "@npmcli/package-json" "^1.0.1" + "@npmcli/run-script" "^1.8.2" + bin-links "^2.2.1" + cacache "^15.0.3" + common-ancestor-path "^1.0.1" + json-parse-even-better-errors "^2.3.1" + json-stringify-nice "^1.1.4" + mkdirp "^1.0.4" + mkdirp-infer-owner "^2.0.0" + npm-install-checks "^4.0.0" + npm-package-arg "^8.1.5" + npm-pick-manifest "^6.1.0" + npm-registry-fetch "^11.0.0" + pacote "^11.3.5" + parse-conflict-json "^1.1.1" + proc-log "^1.0.0" + promise-all-reject-late "^1.0.0" + promise-call-limit "^1.0.1" + read-package-json-fast "^2.0.2" + readdir-scoped-modules "^1.1.0" + rimraf "^3.0.2" + semver "^7.3.5" + ssri "^8.0.1" + treeverse "^1.0.4" + walk-up-path "^1.0.0" + "@npmcli/ci-detect@^1.0.0": version "1.3.0" resolved "https://registry.npmjs.org/@npmcli/ci-detect/-/ci-detect-1.3.0.tgz#6c1d2c625fb6ef1b9dea85ad0a5afcbef85ef22a" integrity sha512-oN3y7FAROHhrAt7Rr7PnTSwrHrZVRTS2ZbyxeQwSSYD0ifwM3YNgQqbaRmjcWoPyq77MjchusjJDspbzMmip1Q== +"@npmcli/fs@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@npmcli/fs/-/fs-1.0.0.tgz#589612cfad3a6ea0feafcb901d29c63fd52db09f" + integrity sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ== + dependencies: + "@gar/promisify" "^1.0.1" + semver "^7.3.5" + "@npmcli/git@^2.0.1": version "2.0.6" resolved "https://registry.npmjs.org/@npmcli/git/-/git-2.0.6.tgz#47b97e96b2eede3f38379262fa3bdfa6eae57bf2" @@ -4683,7 +4733,21 @@ unique-filename "^1.1.1" which "^2.0.2" -"@npmcli/installed-package-contents@^1.0.6": +"@npmcli/git@^2.1.0": + version "2.1.0" + resolved "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz#2fbd77e147530247d37f325930d457b3ebe894f6" + integrity sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw== + dependencies: + "@npmcli/promise-spawn" "^1.3.2" + lru-cache "^6.0.0" + mkdirp "^1.0.4" + npm-pick-manifest "^6.1.1" + promise-inflight "^1.0.1" + promise-retry "^2.0.1" + semver "^7.3.5" + which "^2.0.2" + +"@npmcli/installed-package-contents@^1.0.6", "@npmcli/installed-package-contents@^1.0.7": version "1.0.7" resolved "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz#ab7408c6147911b970a8abe261ce512232a3f4fa" integrity sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw== @@ -4691,6 +4755,25 @@ npm-bundled "^1.1.1" npm-normalize-package-bin "^1.0.1" +"@npmcli/map-workspaces@^1.0.2": + version "1.0.4" + resolved "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-1.0.4.tgz#915708b55afa25e20bc2c14a766c124c2c5d4cab" + integrity sha512-wVR8QxhyXsFcD/cORtJwGQodeeaDf0OxcHie8ema4VgFeqwYkFsDPnSrIRSytX8xR6nKPAH89WnwTcaU608b/Q== + dependencies: + "@npmcli/name-from-folder" "^1.0.1" + glob "^7.1.6" + minimatch "^3.0.4" + read-package-json-fast "^2.0.1" + +"@npmcli/metavuln-calculator@^1.1.0": + version "1.1.1" + resolved "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-1.1.1.tgz#2f95ff3c6d88b366dd70de1c3f304267c631b458" + integrity sha512-9xe+ZZ1iGVaUovBVFI9h3qW+UuECUzhvZPxK9RaEA2mjU26o5D0JloGYWwLYvQELJNmBdQB6rrpuN8jni6LwzQ== + dependencies: + cacache "^15.0.5" + pacote "^11.1.11" + semver "^7.3.2" + "@npmcli/move-file@^1.0.1": version "1.0.1" resolved "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz#de103070dac0f48ce49cf6693c23af59c0f70464" @@ -4698,11 +4781,31 @@ dependencies: mkdirp "^1.0.4" -"@npmcli/node-gyp@^1.0.2": +"@npmcli/move-file@^1.1.0": + version "1.1.2" + resolved "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" + integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== + dependencies: + mkdirp "^1.0.4" + rimraf "^3.0.2" + +"@npmcli/name-from-folder@^1.0.1": + version "1.0.1" + resolved "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz#77ecd0a4fcb772ba6fe927e2e2e155fbec2e6b1a" + integrity sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA== + +"@npmcli/node-gyp@^1.0.1", "@npmcli/node-gyp@^1.0.2": version "1.0.2" resolved "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.2.tgz#3cdc1f30e9736dbc417373ed803b42b1a0a29ede" integrity sha512-yrJUe6reVMpktcvagumoqD9r08fH1iRo01gn1u0zoCApa9lnZGEigVKUd2hzsCId4gdtkZZIVscLhNxMECKgRg== +"@npmcli/package-json@^1.0.1": + version "1.0.1" + resolved "https://registry.npmjs.org/@npmcli/package-json/-/package-json-1.0.1.tgz#1ed42f00febe5293c3502fd0ef785647355f6e89" + integrity sha512-y6jnu76E9C23osz8gEMBayZmaZ69vFOIk8vR1FJL/wbEJ54+9aVG9rLTjQKSXfgYZEr50nw1txBBFfBZZe+bYg== + dependencies: + json-parse-even-better-errors "^2.3.1" + "@npmcli/promise-spawn@^1.1.0", "@npmcli/promise-spawn@^1.2.0", "@npmcli/promise-spawn@^1.3.2": version "1.3.2" resolved "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz#42d4e56a8e9274fba180dabc0aea6e38f29274f5" @@ -6560,6 +6663,11 @@ resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== +"@types/expect@^1.20.4": + version "1.20.4" + resolved "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz#8288e51737bf7e3ab5d7c77bfa695883745264e5" + integrity sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg== + "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18", "@types/express-serve-static-core@^4.17.21": version "4.17.24" resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz#ea41f93bf7e0d59cd5a76665068ed6aab6815c07" @@ -6996,6 +7104,11 @@ resolved "https://registry.npmjs.org/@types/node/-/node-12.12.58.tgz#46dae9b2b9ee5992818c8f7cee01ff4ce03ab44c" integrity sha512-Be46CNIHWAagEfINOjmriSxuv7IVcqbGe+sDSg2SYCEz/0CRBy7LRASGfRbD8KZkqoePU73Wsx3UvOSFcq/9hA== +"@types/node@^15.6.1": + version "15.14.9" + resolved "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz#bc43c990c3c9be7281868bbc7b8fdd6e2b57adfa" + integrity sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A== + "@types/normalize-package-data@^2.4.0": version "2.4.0" resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" @@ -7501,6 +7614,14 @@ resolved "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f" integrity sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ== +"@types/vinyl@^2.0.4": + version "2.0.6" + resolved "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz#b2d134603557a7c3d2b5d3dc23863ea2b5eb29b0" + integrity sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g== + dependencies: + "@types/expect" "^1.20.4" + "@types/node" "*" + "@types/webpack-dev-server@^3.11.5": version "3.11.5" resolved "https://registry.npmjs.org/@types/webpack-dev-server/-/webpack-dev-server-3.11.5.tgz#f4a254a3dd0667c8ee4af90d42afdb4ad1d607f3" @@ -8131,6 +8252,13 @@ agent-base@6: dependencies: debug "4" +agent-base@^6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + agentkeepalive@^4.1.3, agentkeepalive@^4.1.4: version "4.1.4" resolved "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz#d928028a4862cb11718e55227872e842a44c945b" @@ -8587,6 +8715,14 @@ archiver@^5.0.2, archiver@^5.3.0: tar-stream "^2.2.0" zip-stream "^4.1.0" +are-we-there-yet@^1.1.5: + version "1.1.7" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" + integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" @@ -8834,6 +8970,11 @@ async-retry@^1.2.1, async-retry@^1.3.1: dependencies: retry "0.12.0" +async@0.9.x: + version "0.9.2" + resolved "https://registry.npmjs.org/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= + async@^2.6.2: version "2.6.3" resolved "https://registry.npmjs.org/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" @@ -9396,6 +9537,18 @@ bignumber.js@^9.0.0: resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== +bin-links@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/bin-links/-/bin-links-2.2.1.tgz#347d9dbb48f7d60e6c11fe68b77a424bee14d61b" + integrity sha512-wFzVTqavpgCCYAh8SVBdnZdiQMxTkGR+T3b14CNpBXIBe2neJWaMGAZ55XWWHELJJ89dscuq0VCBqcVaIOgCMg== + dependencies: + cmd-shim "^4.0.1" + mkdirp "^1.0.3" + npm-normalize-package-bin "^1.0.0" + read-cmd-shim "^2.0.0" + rimraf "^3.0.0" + write-file-atomic "^3.0.3" + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -9419,6 +9572,11 @@ binary@~0.3.0: buffers "~0.1.1" chainsaw "~0.1.0" +binaryextensions@^4.15.0, binaryextensions@^4.16.0: + version "4.18.0" + resolved "https://registry.npmjs.org/binaryextensions/-/binaryextensions-4.18.0.tgz#22aeada2d14de062c60e8ca59a504a5636a76ceb" + integrity sha512-PQu3Kyv9dM4FnwB7XGj1+HucW+ShvJzJqjuw1JkKVs1mWdwOKVcRjOi+pV9X52A0tNvrPCsPkbFFQb+wE1EAXw== + bindings@^1.5.0: version "1.5.0" resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" @@ -9815,6 +9973,30 @@ cacache@^12.0.2: unique-filename "^1.1.1" y18n "^4.0.0" +cacache@^15.0.3, cacache@^15.2.0: + version "15.3.0" + resolved "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" + integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== + dependencies: + "@npmcli/fs" "^1.0.0" + "@npmcli/move-file" "^1.0.1" + chownr "^2.0.0" + fs-minipass "^2.0.0" + glob "^7.1.4" + infer-owner "^1.0.4" + lru-cache "^6.0.0" + minipass "^3.1.1" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^1.0.3" + p-map "^4.0.0" + promise-inflight "^1.0.1" + rimraf "^3.0.2" + ssri "^8.0.1" + tar "^6.0.2" + unique-filename "^1.1.1" + cacache@^15.0.5: version "15.0.5" resolved "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz#69162833da29170d6732334643c60e005f5f17d0" @@ -10344,6 +10526,13 @@ cli-table3@0.6.0, cli-table3@~0.6.0: optionalDependencies: colors "^1.1.2" +cli-table@^0.3.1: + version "0.3.6" + resolved "https://registry.npmjs.org/cli-table/-/cli-table-0.3.6.tgz#e9d6aa859c7fe636981fd3787378c2a20bce92fc" + integrity sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ== + dependencies: + colors "1.0.3" + cli-truncate@2.1.0, cli-truncate@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" @@ -10401,6 +10590,11 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +clone-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= + clone-deep@^0.2.4: version "0.2.4" resolved "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz#4e73dd09e9fb971cc38670c5dced9c1896481cc6" @@ -10428,7 +10622,12 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" -clone@2.x: +clone-stats@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= + +clone@2.x, clone@^2.1.1: version "2.1.2" resolved "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= @@ -10438,12 +10637,21 @@ clone@^1.0.2: resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= +cloneable-readable@^1.0.0: + version "1.1.3" + resolved "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz#120a00cb053bfb63a222e709f9683ea2e11d8cec" + integrity sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ== + dependencies: + inherits "^2.0.1" + process-nextick-args "^2.0.0" + readable-stream "^2.3.5" + clsx@^1.0.1, clsx@^1.0.2, clsx@^1.0.4, clsx@^1.1.0: version "1.1.1" resolved "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== -cmd-shim@^4.1.0: +cmd-shim@^4.0.1, cmd-shim@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/cmd-shim/-/cmd-shim-4.1.0.tgz#b3a904a6743e9fede4148c6f3800bf2a08135bdd" integrity sha512-lb9L7EM4I/ZRVuljLPEtUJOP+xiQVknZ4ZMpMgEp4JzNldPb27HU03hi6K1/6CoIuit/Zm/LQXySErFeXxDprw== @@ -10586,6 +10794,11 @@ colorette@^1.2.1, colorette@^1.2.2: resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== +colors@1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= + colors@^1.1.2, colors@^1.2.1: version "1.4.0" resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" @@ -10629,6 +10842,11 @@ command-exists@^1.2.9: resolved "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== +commander@7.1.0: + version "7.1.0" + resolved "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz#f2eaecf131f10e36e07d894698226e36ae0eb5ff" + integrity sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg== + commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, commander@^2.7.1, commander@~2.20.3: version "2.20.3" resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -10654,6 +10872,11 @@ commander@^7.1.0, commander@^7.2.0: resolved "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== +common-ancestor-path@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7" + integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w== + common-tags@1.8.0, common-tags@^1.8.0: version "1.8.0" resolved "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" @@ -11856,6 +12079,11 @@ dateformat@^3.0.0, dateformat@^3.0.3: resolved "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== +dateformat@^4.5.0: + version "4.5.1" + resolved "https://registry.npmjs.org/dateformat/-/dateformat-4.5.1.tgz#c20e7a9ca77d147906b6dc2261a8be0a5bd2173c" + integrity sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q== + dayjs@^1.10.4, dayjs@^1.9.4: version "1.10.4" resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2" @@ -12557,6 +12785,13 @@ ee-first@1.1.1: resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= +ejs@^3.1.6: + version "3.1.6" + resolved "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a" + integrity sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw== + dependencies: + jake "^10.6.1" + elastic-builder@^2.16.0: version "2.16.0" resolved "https://registry.npmjs.org/elastic-builder/-/elastic-builder-2.16.0.tgz#684757ab9e6a4214653d23d84cec5ab8d185892f" @@ -12754,6 +12989,11 @@ error-stack-parser@^2.0.6: dependencies: stackframe "^1.1.1" +error@^10.4.0: + version "10.4.0" + resolved "https://registry.npmjs.org/error/-/error-10.4.0.tgz#6fcf0fd64bceb1e750f8ed9a3dd880f00e46a487" + integrity sha512-YxIFEJuhgcICugOUvRx5th0UM+ActZ9sjY0QJmeVwsQdvosZ7kYzc9QqS0Da3R5iUmgU5meGIxh0xBeZpMVeLw== + es-abstract@^1.17.0, es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2: version "1.18.0" resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz#ab80b359eecb7ede4c298000390bc5ac3ec7b5a4" @@ -13793,6 +14033,13 @@ filefy@0.1.10: resolved "https://registry.npmjs.org/filefy/-/filefy-0.1.10.tgz#174677c8e2fa5bc39a3af0ed6fb492f16b8fbf42" integrity sha512-VgoRVOOY1WkTpWH+KBy8zcU1G7uQTVsXqhWEgzryB9A5hg2aqCyZ6aQ/5PSzlqM5+6cnVrX6oYV0XqD3HZSnmQ== +filelist@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b" + integrity sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ== + dependencies: + minimatch "^3.0.4" + filesize@6.1.0: version "6.1.0" resolved "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz#e81bdaa780e2451d714d71c0d7a4f3238d37ad00" @@ -13911,6 +14158,13 @@ find-yarn-workspace-root2@1.2.16: micromatch "^4.0.2" pkg-dir "^4.2.0" +first-chunk-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz#1bdecdb8e083c0664b91945581577a43a9f31d70" + integrity sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA= + dependencies: + readable-stream "^2.0.2" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -14954,6 +15208,11 @@ graphql@^15.3.0, graphql@^15.4.0: resolved "https://registry.npmjs.org/graphql/-/graphql-15.5.1.tgz#f2f84415d8985e7b84731e7f3536f8bb9d383aad" integrity sha512-FeTRX67T3LoE3LWAxxOlW2K3Bz+rMYAC18rRguK4wgXaTZMiJwSUwDmPFo3UadAKbzirKIg5Qy+sNJXbpPRnQw== +grouped-queue@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/grouped-queue/-/grouped-queue-2.0.0.tgz#a2c6713f2171e45db2c300a3a9d7c119d694dac8" + integrity sha512-/PiFUa7WIsl48dUeCvhIHnwNmAAzlI/eHoJl0vu3nsFA366JleY7Ff8EVTplZu5kO0MIdZjKTTnzItL61ahbnw== + growly@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -15271,6 +15530,13 @@ hosted-git-info@^3.0.6: dependencies: lru-cache "^6.0.0" +hosted-git-info@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961" + integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg== + dependencies: + lru-cache "^6.0.0" + hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" @@ -15859,6 +16125,26 @@ inquirer@^7.0.4, inquirer@^7.3.3: strip-ansi "^6.0.0" through "^2.3.6" +inquirer@^8.0.0: + version "8.1.4" + resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.1.4.tgz#d5734392ecaabad3c276afc1e8ff3406089b9280" + integrity sha512-Wi0b5XDuPSlmdq7MBb89/x2DG/5ApMFrwS7Mook/4bqukKla0gFfVYYdl/2O1pU8AomLe000evbxDgy/pUEodg== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.1" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.21" + mute-stream "0.0.8" + ora "^5.4.1" + run-async "^2.4.0" + rxjs "^7.2.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + inquirer@^8.1.0: version "8.1.1" resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.1.1.tgz#7c53d94c6d03011c7bb2a947f0dca3b98246c26a" @@ -16442,6 +16728,13 @@ is-root@2.1.0: resolved "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== +is-scoped@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-scoped/-/is-scoped-2.1.0.tgz#fef0713772658bdf5bee418608267ddae6d3566d" + integrity sha512-Cv4OpPTHAK9kHYzkzCrof3VJh7H/PrG2MBUMvvJebaaUMbqhm0YAtXnvh0I3Hnj2tMZWwrRROWLSgfJrKqWmlQ== + dependencies: + scoped-regex "^2.0.0" + is-set@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz#d1604afdab1724986d30091575f54945da7e5f43" @@ -16537,7 +16830,7 @@ is-upper-case@^2.0.2: dependencies: tslib "^2.0.3" -is-utf8@^0.2.0: +is-utf8@^0.2.0, is-utf8@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= @@ -16722,6 +17015,16 @@ iterate-value@^1.0.0: es-get-iterator "^1.0.2" iterate-iterator "^1.0.1" +jake@^10.6.1: + version "10.8.2" + resolved "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b" + integrity sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A== + dependencies: + async "0.9.x" + chalk "^2.4.2" + filelist "^1.0.1" + minimatch "^3.0.4" + jenkins@^0.28.1: version "0.28.1" resolved "https://registry.npmjs.org/jenkins/-/jenkins-0.28.1.tgz#f7951798ee5d2bb501a831979b6b5ecc1a922a64" @@ -17402,7 +17705,7 @@ json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== -json-parse-even-better-errors@^2.3.0: +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== @@ -17471,6 +17774,11 @@ json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" +json-stringify-nice@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz#2c937962b80181d3f317dd39aa323e14f5a60a67" + integrity sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw== + json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -17687,6 +17995,16 @@ junk@^3.1.0: resolved "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== +just-diff-apply@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-3.0.0.tgz#a77348d24f0694e378b57293dceb65bdf5a91c4f" + integrity sha512-K2MLc+ZC2DVxX4V61bIKPeMUUfj1YYZ3h0myhchDXOW1cKoPZMnjIoNCqv9bF2n5Oob1PFxuR2gVJxkxz4e58w== + +just-diff@^3.0.1: + version "3.1.1" + resolved "https://registry.npmjs.org/just-diff/-/just-diff-3.1.1.tgz#d50c597c6fd4776495308c63bdee1b6839082647" + integrity sha512-sdMWKjRq8qWZEjDcVA6llnUT8RDEBIfOiGpYFPYa9u+2c39JCsejktSP7mj5eRid5EIvTzIpQ2kDOCw1Nq9BjQ== + just-extend@^4.0.2: version "4.2.1" resolved "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744" @@ -18654,6 +18972,28 @@ make-fetch-happen@^8.0.9: socks-proxy-agent "^5.0.0" ssri "^8.0.0" +make-fetch-happen@^9.0.1: + version "9.1.0" + resolved "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" + integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== + dependencies: + agentkeepalive "^4.1.3" + cacache "^15.2.0" + http-cache-semantics "^4.1.0" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-lambda "^1.0.1" + lru-cache "^6.0.0" + minipass "^3.1.3" + minipass-collect "^1.0.2" + minipass-fetch "^1.3.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.2" + promise-retry "^2.0.1" + socks-proxy-agent "^6.0.0" + ssri "^8.0.0" + makeerror@1.0.x: version "1.0.11" resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -18898,6 +19238,32 @@ media-typer@0.3.0: resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= +"mem-fs-editor@^8.1.2 || ^9.0.0": + version "9.3.0" + resolved "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-9.3.0.tgz#85ce80541b1961d1d9f433e275c7cee9d0a1c9a2" + integrity sha512-QKFbPwGCh1ypmc2H8BUYpbapwT/x2AOCYZQogzSui4rUNes7WVMagQXsirPIfp18EarX0SSY9Fpg426nSjew4Q== + dependencies: + binaryextensions "^4.16.0" + commondir "^1.0.1" + deep-extend "^0.6.0" + ejs "^3.1.6" + globby "^11.0.3" + isbinaryfile "^4.0.8" + minimatch "^3.0.4" + multimatch "^5.0.0" + normalize-path "^3.0.0" + textextensions "^5.13.0" + +"mem-fs@^1.2.0 || ^2.0.0": + version "2.2.1" + resolved "https://registry.npmjs.org/mem-fs/-/mem-fs-2.2.1.tgz#c87bc8a53fb17971b129d4bcd59a9149fb78c5b1" + integrity sha512-yiAivd4xFOH/WXlUi6v/nKopBh1QLzwjFi36NK88cGt/PRXI8WeBASqY+YSjIVWvQTx3hR8zHKDBMV6hWmglNA== + dependencies: + "@types/node" "^15.6.1" + "@types/vinyl" "^2.0.4" + vinyl "^2.0.1" + vinyl-file "^3.0.0" + mem@^8.1.1: version "8.1.1" resolved "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz#cf118b357c65ab7b7e0817bdf00c8062297c0122" @@ -19653,7 +20019,7 @@ needle@^2.2.1, needle@^2.5.0: iconv-lite "^0.4.4" sax "^1.2.4" -negotiator@0.6.2: +negotiator@0.6.2, negotiator@^0.6.2: version "0.6.2" resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== @@ -20026,6 +20392,15 @@ npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.0: semver "^7.0.0" validate-npm-package-name "^3.0.0" +npm-package-arg@^8.1.2, npm-package-arg@^8.1.5: + version "8.1.5" + resolved "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz#3369b2d5fe8fdc674baa7f1786514ddc15466e44" + integrity sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q== + dependencies: + hosted-git-info "^4.0.1" + semver "^7.3.4" + validate-npm-package-name "^3.0.0" + npm-packlist@^1.1.6: version "1.4.8" resolved "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" @@ -20054,6 +20429,28 @@ npm-pick-manifest@^6.0.0: npm-package-arg "^8.0.0" semver "^7.0.0" +npm-pick-manifest@^6.1.0, npm-pick-manifest@^6.1.1: + version "6.1.1" + resolved "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz#7b5484ca2c908565f43b7f27644f36bb816f5148" + integrity sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA== + dependencies: + npm-install-checks "^4.0.0" + npm-normalize-package-bin "^1.0.1" + npm-package-arg "^8.1.2" + semver "^7.3.4" + +npm-registry-fetch@^11.0.0: + version "11.0.0" + resolved "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz#68c1bb810c46542760d62a6a965f85a702d43a76" + integrity sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA== + dependencies: + make-fetch-happen "^9.0.1" + minipass "^3.1.3" + minipass-fetch "^1.3.0" + minipass-json-stream "^1.0.1" + minizlib "^2.0.0" + npm-package-arg "^8.0.0" + npm-registry-fetch@^9.0.0: version "9.0.0" resolved "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-9.0.0.tgz#86f3feb4ce00313bc0b8f1f8f69daae6face1661" @@ -20371,7 +20768,7 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -ora@^5.3.0: +ora@^5.3.0, ora@^5.4.1: version "5.4.1" resolved "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== @@ -20640,6 +21037,31 @@ packet-reader@1.0.0: resolved "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== +pacote@^11.1.11, pacote@^11.3.5: + version "11.3.5" + resolved "https://registry.npmjs.org/pacote/-/pacote-11.3.5.tgz#73cf1fc3772b533f575e39efa96c50be8c3dc9d2" + integrity sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg== + dependencies: + "@npmcli/git" "^2.1.0" + "@npmcli/installed-package-contents" "^1.0.6" + "@npmcli/promise-spawn" "^1.2.0" + "@npmcli/run-script" "^1.8.2" + cacache "^15.0.5" + chownr "^2.0.0" + fs-minipass "^2.1.0" + infer-owner "^1.0.4" + minipass "^3.1.3" + mkdirp "^1.0.3" + npm-package-arg "^8.0.1" + npm-packlist "^2.1.4" + npm-pick-manifest "^6.0.0" + npm-registry-fetch "^11.0.0" + promise-retry "^2.0.1" + read-package-json-fast "^2.0.1" + rimraf "^3.0.2" + ssri "^8.0.1" + tar "^6.1.0" + pacote@^11.2.6: version "11.2.6" resolved "https://registry.npmjs.org/pacote/-/pacote-11.2.6.tgz#c0426e5d5c8d33aeea3461a75e1390f1ba78f953" @@ -20711,6 +21133,15 @@ parse-asn1@^5.0.0: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" +parse-conflict-json@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-1.1.1.tgz#54ec175bde0f2d70abf6be79e0e042290b86701b" + integrity sha512-4gySviBiW5TRl7XHvp1agcS7SOe0KZOjC//71dzZVWJrY9hCrgtvl5v3SyIxCZ4fZF47TxD9nfzmxcx76xmbUw== + dependencies: + json-parse-even-better-errors "^2.3.0" + just-diff "^3.0.1" + just-diff-apply "^3.0.0" + parse-entities@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" @@ -21818,6 +22249,16 @@ preferred-pm@^3.0.0: path-exists "^4.0.0" which-pm "2.0.0" +preferred-pm@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/preferred-pm/-/preferred-pm-3.0.3.tgz#1b6338000371e3edbce52ef2e4f65eb2e73586d6" + integrity sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ== + dependencies: + find-up "^5.0.0" + find-yarn-workspace-root2 "1.2.16" + path-exists "^4.0.0" + which-pm "2.0.0" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -21848,7 +22289,7 @@ prettier@~2.2.1: resolved "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== -pretty-bytes@^5.6.0: +pretty-bytes@^5.3.0, pretty-bytes@^5.6.0: version "5.6.0" resolved "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== @@ -21903,7 +22344,12 @@ private@^0.1.8: resolved "https://registry.npmjs.org/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== -process-nextick-args@~2.0.0: +proc-log@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/proc-log/-/proc-log-1.0.0.tgz#0d927307401f69ed79341e83a0b2c9a13395eb77" + integrity sha512-aCk8AO51s+4JyuYGg3Q/a6gnrlDO09NpVWePtjp7xwphcoQ04x5WAfCyugcsbLooWcMJ87CLkD4+604IckEdhg== + +process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== @@ -21925,6 +22371,16 @@ prom-client@^13.2.0: dependencies: tdigest "^0.1.1" +promise-all-reject-late@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz#f8ebf13483e5ca91ad809ccc2fcf25f26f8643c2" + integrity sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw== + +promise-call-limit@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.1.tgz#4bdee03aeb85674385ca934da7114e9bcd3c6e24" + integrity sha512-3+hgaa19jzCGLuSCbieeRsu5C2joKfYn8pY6JAuXFRVfF4IO+L7UPpFWNTeWT9pM7uhskvbPPd/oEOktCn317Q== + promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" @@ -22842,6 +23298,14 @@ read-package-json-fast@^2.0.1: json-parse-even-better-errors "^2.3.0" npm-normalize-package-bin "^1.0.1" +read-package-json-fast@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz#323ca529630da82cb34b36cc0b996693c98c2b83" + integrity sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ== + dependencies: + json-parse-even-better-errors "^2.3.0" + npm-normalize-package-bin "^1.0.1" + read-package-json@^2.0.0: version "2.1.1" resolved "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.1.tgz#16aa66c59e7d4dad6288f179dd9295fd59bb98f1" @@ -22996,7 +23460,7 @@ readdir-glob@^1.0.0: dependencies: minimatch "^3.0.4" -readdir-scoped-modules@^1.0.0: +readdir-scoped-modules@^1.0.0, readdir-scoped-modules@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309" integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== @@ -23401,6 +23865,11 @@ replace-ext@1.0.0: resolved "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= +replace-ext@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a" + integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw== + replace-in-file@^6.0.0: version "6.1.0" resolved "https://registry.npmjs.org/replace-in-file/-/replace-in-file-6.1.0.tgz#9f9ddd7bb70d6ad231d2ad692e1b646e73d06647" @@ -23811,7 +24280,7 @@ rxjs@^6.6.6: dependencies: tslib "^1.9.0" -rxjs@^7.1.0: +rxjs@^7.1.0, rxjs@^7.2.0: version "7.3.0" resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.3.0.tgz#39fe4f3461dc1e50be1475b2b85a0a88c1e938c6" integrity sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw== @@ -23947,6 +24416,11 @@ schema-utils@^3.1.0: ajv "^6.12.5" ajv-keywords "^3.5.2" +scoped-regex@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/scoped-regex/-/scoped-regex-2.1.0.tgz#7b9be845d81fd9d21d1ec97c61a0b7cf86d2015f" + integrity sha512-g3WxHrqSWCZHGHlSrF51VXFdjImhwvH8ZO/pryFH56Qi0cDsZfylQa/t0jCzVQFNbNvM00HfHjkDPEuarKDSWQ== + screenfull@^5.0.0, screenfull@^5.1.0: version "5.1.0" resolved "https://registry.npmjs.org/screenfull/-/screenfull-5.1.0.tgz#85c13c70f4ead4c1b8a935c70010dfdcd2c0e5c8" @@ -24431,6 +24905,15 @@ socks-proxy-agent@^5.0.0: debug "4" socks "^2.3.3" +socks-proxy-agent@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.0.0.tgz#9f8749cdc05976505fa9f9a958b1818d0e60573b" + integrity sha512-FIgZbQWlnjVEQvMkylz64/rUggGtrKstPnx8OZyYFG0tAFR8CSBtpXxSwbFLHyeXFn/cunFL7MpuSOvDSOPo9g== + dependencies: + agent-base "^6.0.2" + debug "^4.3.1" + socks "^2.6.1" + socks@^2.3.3: version "2.5.1" resolved "https://registry.npmjs.org/socks/-/socks-2.5.1.tgz#7720640b6b5ec9a07d556419203baa3f0596df5f" @@ -24439,6 +24922,14 @@ socks@^2.3.3: ip "^1.1.5" smart-buffer "^4.1.0" +socks@^2.6.1: + version "2.6.1" + resolved "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e" + integrity sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA== + dependencies: + ip "^1.1.5" + smart-buffer "^4.1.0" + sonic-boom@^0.7.5: version "0.7.7" resolved "https://registry.npmjs.org/sonic-boom/-/sonic-boom-0.7.7.tgz#d921de887428208bfa07b0ae32c278de043f350a" @@ -25079,6 +25570,21 @@ strip-ansi@^7.0.0: dependencies: ansi-regex "^6.0.1" +strip-bom-buf@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz#1cb45aaf57530f4caf86c7f75179d2c9a51dd572" + integrity sha1-HLRar1dTD0yvhsf3UXnSyaUd1XI= + dependencies: + is-utf8 "^0.2.1" + +strip-bom-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz#f87db5ef2613f6968aa545abfe1ec728b6a829ca" + integrity sha1-+H217yYT9paKpUWr/h7HKLaoKco= + dependencies: + first-chunk-stream "^2.0.0" + strip-bom "^2.0.0" + strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" @@ -25725,6 +26231,11 @@ text-table@0.2.0, text-table@^0.2.0: resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= +textextensions@^5.12.0, textextensions@^5.13.0: + version "5.14.0" + resolved "https://registry.npmjs.org/textextensions/-/textextensions-5.14.0.tgz#a6ff6aee5faaa751e6157d422c722a2bfd59eedf" + integrity sha512-4cAYwNFNYlIAHBUo7p6zw8POUvWbZor+/R0Tanv+rIhsauEyV9QSrEXL40pI+GfTQxKX8k6Tyw6CmdSDSmASrg== + thenify-all@^1.0.0: version "1.6.0" resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" @@ -25999,6 +26510,11 @@ tree-kill@^1.2.2: resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== +treeverse@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/treeverse/-/treeverse-1.0.4.tgz#a6b0ebf98a1bca6846ddc7ecbc900df08cb9cd5f" + integrity sha512-whw60l7r+8ZU8Tu/Uc2yxtc4ZTZbR/PF3u1IPNKGQ6p8EICLb3Z2lAgoqw9bqYd8IkgnsaOcLzYHFckjqNsf0g== + trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" @@ -26978,6 +27494,29 @@ vfile@^4.0.0: unist-util-stringify-position "^2.0.0" vfile-message "^2.0.0" +vinyl-file@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/vinyl-file/-/vinyl-file-3.0.0.tgz#b104d9e4409ffa325faadd520642d0a3b488b365" + integrity sha1-sQTZ5ECf+jJfqt1SBkLQo7SIs2U= + dependencies: + graceful-fs "^4.1.2" + pify "^2.3.0" + strip-bom-buf "^1.0.0" + strip-bom-stream "^2.0.0" + vinyl "^2.0.1" + +vinyl@^2.0.1: + version "2.2.1" + resolved "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz#23cfb8bbab5ece3803aa2c0a1eb28af7cbba1974" + integrity sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw== + dependencies: + clone "^2.1.1" + clone-buffer "^1.0.0" + clone-stats "^1.0.0" + cloneable-readable "^1.0.0" + remove-trailing-separator "^1.0.1" + replace-ext "^1.0.0" + vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" @@ -27018,6 +27557,11 @@ wait-on@6.0.0: minimist "^1.2.5" rxjs "^7.1.0" +walk-up-path@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/walk-up-path/-/walk-up-path-1.0.0.tgz#d4745e893dd5fd0dbb58dd0a4c6a33d9c9fec53e" + integrity sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg== + walker@^1.0.7, walker@~1.0.5: version "1.0.7" resolved "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" @@ -27864,6 +28408,46 @@ yauzl@^2.10.0: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" +yeoman-environment@^3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-3.6.0.tgz#91267ced0d474c4dec330b83f232e72e796c0730" + integrity sha512-X16N9lhzRdUKFT8MZrpwjLDKsdgAUqh4VPR2wAXeAqjJJaUxYBxCQGFxtZVTf3vbyNuIHXPunwOLtK60bpapbg== + dependencies: + "@npmcli/arborist" "^2.2.2" + are-we-there-yet "^1.1.5" + arrify "^2.0.1" + binaryextensions "^4.15.0" + chalk "^4.1.0" + cli-table "^0.3.1" + commander "7.1.0" + dateformat "^4.5.0" + debug "^4.1.1" + diff "^5.0.0" + error "^10.4.0" + escape-string-regexp "^4.0.0" + execa "^5.0.0" + find-up "^5.0.0" + globby "^11.0.1" + grouped-queue "^2.0.0" + inquirer "^8.0.0" + is-scoped "^2.1.0" + lodash "^4.17.10" + log-symbols "^4.0.0" + mem-fs "^1.2.0 || ^2.0.0" + mem-fs-editor "^8.1.2 || ^9.0.0" + minimatch "^3.0.4" + npmlog "^4.1.2" + p-queue "^6.6.2" + pacote "^11.2.6" + preferred-pm "^3.0.3" + pretty-bytes "^5.3.0" + semver "^7.1.3" + slash "^3.0.0" + strip-ansi "^6.0.0" + text-table "^0.2.0" + textextensions "^5.12.0" + untildify "^4.0.0" + yml-loader@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/yml-loader/-/yml-loader-2.1.0.tgz#b976b8691b537b6d3dc7d92a9a7d34b90de10870" From 65f5317914127e0f38a12a68ce7ebffd722d26ab Mon Sep 17 00:00:00 2001 From: Phil Gore Date: Wed, 15 Sep 2021 10:09:50 -0500 Subject: [PATCH 07/26] LDAP change is just a patch, not minor version Signed-off-by: Phil Gore --- .changeset/proud-adults-bathe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/proud-adults-bathe.md b/.changeset/proud-adults-bathe.md index 86b8cfecb3..a8f15b18a3 100644 --- a/.changeset/proud-adults-bathe.md +++ b/.changeset/proud-adults-bathe.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-catalog-backend-module-ldap': minor +'@backstage/plugin-catalog-backend-module-ldap': patch --- Alters LDAP processor to handle one SearchEntry at a time From be13dfe61a96387afed22969002a19ae48850753 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 16 Sep 2021 12:22:19 +0200 Subject: [PATCH 08/26] Make techdocs context search bar width adjust on smaller screens Signed-off-by: Oliver Sand --- .changeset/techdocs-shy-beans-prove.md | 5 +++++ plugins/techdocs/src/reader/components/Reader.tsx | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 .changeset/techdocs-shy-beans-prove.md diff --git a/.changeset/techdocs-shy-beans-prove.md b/.changeset/techdocs-shy-beans-prove.md new file mode 100644 index 0000000000..5aa9db1da7 --- /dev/null +++ b/.changeset/techdocs-shy-beans-prove.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Make techdocs context search bar width adjust on smaller screens. diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index 5fe395e131..b1205e7dd9 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -64,6 +64,10 @@ const useStyles = makeStyles(theme => ({ marginLeft: '20rem', maxWidth: 'calc(100% - 20rem * 2 - 3rem)', marginTop: theme.spacing(1), + '@media screen and (max-width: 76.1875em)': { + marginLeft: '10rem', + maxWidth: 'calc(100% - 10rem)', + }, }, })); From 690657799e782254940c86ba34a81e988a55db79 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Tue, 22 Jun 2021 13:41:33 +0200 Subject: [PATCH 09/26] Add initial support for customizing the catalog import page Signed-off-by: Oliver Sand --- .changeset/few-penguins-watch.md | 35 ++++++ .../DefaultImportComponentPage.test.tsx | 84 +++++++++++++ .../DefaultImportComponentPage.tsx | 58 +++++++++ .../DefaultImportComponentPage/index.ts | 17 +++ .../src/components/ImportComponentPage.tsx | 115 ------------------ .../ImportComponentPage.test.tsx | 4 +- .../ImportComponentPage.tsx | 31 +++++ .../components/ImportComponentPage/index.ts | 17 +++ .../ImportInfoCard/ImportInfoCard.test.tsx | 51 ++++++++ .../ImportInfoCard/ImportInfoCard.tsx | 79 ++++++++++++ .../src/components/ImportInfoCard/index.ts | 17 +++ .../ImportOptionsContext.tsx | 24 ++++ .../components/ImportOptionsContext/index.ts | 17 +++ .../ImportStepper/ImportStepper.tsx | 8 +- .../src/components/ImportStepper/defaults.tsx | 23 +--- .../catalog-import/src/components/Router.tsx | 5 +- .../catalog-import/src/components/index.ts | 5 +- .../catalog-import/src/components/types.ts | 30 +++++ plugins/catalog-import/src/plugin.ts | 5 +- 19 files changed, 483 insertions(+), 142 deletions(-) create mode 100644 .changeset/few-penguins-watch.md create mode 100644 plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx create mode 100644 plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx create mode 100644 plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts delete mode 100644 plugins/catalog-import/src/components/ImportComponentPage.tsx rename plugins/catalog-import/src/components/{ => ImportComponentPage}/ImportComponentPage.test.tsx (94%) create mode 100644 plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx create mode 100644 plugins/catalog-import/src/components/ImportComponentPage/index.ts create mode 100644 plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx create mode 100644 plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx create mode 100644 plugins/catalog-import/src/components/ImportInfoCard/index.ts create mode 100644 plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx create mode 100644 plugins/catalog-import/src/components/ImportOptionsContext/index.ts create mode 100644 plugins/catalog-import/src/components/types.ts diff --git a/.changeset/few-penguins-watch.md b/.changeset/few-penguins-watch.md new file mode 100644 index 0000000000..1b410f0174 --- /dev/null +++ b/.changeset/few-penguins-watch.md @@ -0,0 +1,35 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Add initial support for customizing the catalog import page. + +It is now possible to pass a custom layout to the import page, as it's already +supported by the search page. If no custom layout is passed, the default layout +is used. + +```typescript +}> + +
+ + + + Start tracking your component in Backstage by adding it to the + software catalog. + + + + + + Hello World + + + + + + + + + +``` diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx new file mode 100644 index 0000000000..5e49872319 --- /dev/null +++ b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx @@ -0,0 +1,84 @@ +/* + * 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 { CatalogClient } from '@backstage/catalog-client'; +import { + ApiProvider, + ApiRegistry, + configApiRef, + ConfigReader, +} from '@backstage/core'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { wrapInTestApp } from '@backstage/test-utils'; +import { act, render } from '@testing-library/react'; +import React from 'react'; +import { catalogImportApiRef, CatalogImportClient } from '../../api'; +import { DefaultImportComponentPage } from './DefaultImportComponentPage'; + +describe('', () => { + const identityApi = { + getUserId: () => { + return 'user'; + }, + getProfile: () => { + return {}; + }, + getIdToken: () => { + return Promise.resolve('token'); + }, + signOut: () => { + return Promise.resolve(); + }, + }; + + let apis: ApiRegistry; + + beforeEach(() => { + apis = ApiRegistry.with( + configApiRef, + new ConfigReader({ integrations: {} }), + ) + .with(catalogApiRef, new CatalogClient({ discoveryApi: {} as any })) + .with( + catalogImportApiRef, + new CatalogImportClient({ + discoveryApi: {} as any, + githubAuthApi: { + getAccessToken: async () => 'token', + }, + identityApi, + scmIntegrationsApi: {} as any, + catalogApi: {} as any, + }), + ); + }); + + it('renders without exploding', async () => { + await act(async () => { + const { getByText } = render( + wrapInTestApp( + + + , + ), + ); + + expect( + getByText('Start tracking your component in Backstage'), + ).toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx new file mode 100644 index 0000000000..b9aad55274 --- /dev/null +++ b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx @@ -0,0 +1,58 @@ +/* + * 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 { + configApiRef, + Content, + ContentHeader, + Header, + Page, + SupportButton, + useApi, +} from '@backstage/core'; +import { Grid } from '@material-ui/core'; +import React from 'react'; +import { ImportInfoCard } from '../ImportInfoCard'; +import { ImportStepper } from '../ImportStepper'; + +export const DefaultImportComponentPage = () => { + const configApi = useApi(configApiRef); + const appTitle = configApi.getOptional('app.title') || 'Backstage'; + + return ( + +
+ + + + Start tracking your component in {appTitle} by adding it to the + software catalog. + + + + + + + + + + + + + + + ); +}; diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts b/plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts new file mode 100644 index 0000000000..f3450413a6 --- /dev/null +++ b/plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { DefaultImportComponentPage } from './DefaultImportComponentPage'; diff --git a/plugins/catalog-import/src/components/ImportComponentPage.tsx b/plugins/catalog-import/src/components/ImportComponentPage.tsx deleted file mode 100644 index bf53af134f..0000000000 --- a/plugins/catalog-import/src/components/ImportComponentPage.tsx +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 { Chip, Grid, Typography } from '@material-ui/core'; -import React from 'react'; -import { ImportStepper } from './ImportStepper'; -import { StepperProviderOpts } from './ImportStepper/defaults'; - -import { configApiRef, useApi } from '@backstage/core-plugin-api'; -import { - Content, - ContentHeader, - Header, - InfoCard, - Page, - SupportButton, -} from '@backstage/core-components'; - -export const ImportComponentPage = (opts: StepperProviderOpts) => { - const configApi = useApi(configApiRef); - const appTitle = configApi.getOptional('app.title') || 'Backstage'; - - const integrations = configApi.getConfig('integrations'); - const hasGithubIntegration = integrations.has('github'); - - return ( - -
- - - - Start tracking your component in {appTitle} by adding it to the - software catalog. - - - - - - - - Enter the URL to your source code repository to add it to{' '} - {appTitle}. - - - Link to an existing entity file - - - Example:{' '} - - https://github.com/backstage/backstage/blob/master/catalog-info.yaml - - - - The wizard analyzes the file, previews the entities, and adds - them to the {appTitle} catalog. - - {hasGithubIntegration && ( - <> - - Link to a repository{' '} - - - - Example: https://github.com/backstage/backstage - - - The wizard discovers all catalog-info.yaml{' '} - files in the repository, previews the entities, and adds - them to the {appTitle} catalog. - - {!opts?.pullRequest?.disable && ( - - If no entities are found, the wizard will prepare a Pull - Request that adds an example{' '} - catalog-info.yaml and prepares the {appTitle}{' '} - catalog to load all entities as soon as the Pull Request - is merged. - - )} - - )} - - - - - - - - - - ); -}; diff --git a/plugins/catalog-import/src/components/ImportComponentPage.test.tsx b/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.test.tsx similarity index 94% rename from plugins/catalog-import/src/components/ImportComponentPage.test.tsx rename to plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.test.tsx index 2e572c8936..4177a6ae64 100644 --- a/plugins/catalog-import/src/components/ImportComponentPage.test.tsx +++ b/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.test.tsx @@ -19,7 +19,7 @@ import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import React from 'react'; -import { catalogImportApiRef, CatalogImportClient } from '../api'; +import { catalogImportApiRef, CatalogImportClient } from '../../api'; import { ImportComponentPage } from './ImportComponentPage'; import { @@ -78,7 +78,7 @@ describe('', () => { ); expect( - await getByText('Start tracking your component in Backstage'), + getByText('Start tracking your component in Backstage'), ).toBeInTheDocument(); }); }); diff --git a/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx b/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx new file mode 100644 index 0000000000..3a89705493 --- /dev/null +++ b/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx @@ -0,0 +1,31 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { useOutlet } from 'react-router'; +import { DefaultImportComponentPage } from '../DefaultImportComponentPage'; +import { ImportOptionsContext } from '../ImportOptionsContext'; +import { ImportOptions } from '../types'; + +export const ImportComponentPage = (opts: ImportOptions) => { + const outlet = useOutlet(); + + return ( + + {outlet || } + + ); +}; diff --git a/plugins/catalog-import/src/components/ImportComponentPage/index.ts b/plugins/catalog-import/src/components/ImportComponentPage/index.ts new file mode 100644 index 0000000000..263ba51a23 --- /dev/null +++ b/plugins/catalog-import/src/components/ImportComponentPage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { ImportComponentPage } from './ImportComponentPage'; diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx new file mode 100644 index 0000000000..899ad18cc3 --- /dev/null +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx @@ -0,0 +1,51 @@ +/* + * 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 { + ApiProvider, + ApiRegistry, + configApiRef, + ConfigReader, +} from '@backstage/core'; +import { wrapInTestApp } from '@backstage/test-utils'; +import { act, render } from '@testing-library/react'; +import React from 'react'; +import { ImportInfoCard } from './ImportInfoCard'; + +describe('', () => { + let apis: ApiRegistry; + + beforeEach(() => { + apis = ApiRegistry.with( + configApiRef, + new ConfigReader({ integrations: {} }), + ); + }); + + it('renders without exploding', async () => { + await act(async () => { + const { getByText } = render( + wrapInTestApp( + + + , + ), + ); + + expect(getByText('Register an existing component')).toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx new file mode 100644 index 0000000000..8fbbe6cc82 --- /dev/null +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx @@ -0,0 +1,79 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ConfigApi, configApiRef, InfoCard, useApi } from '@backstage/core'; +import { Typography } from '@material-ui/core'; +import React from 'react'; +import { useImportOptions } from '../ImportOptionsContext'; + +export const ImportInfoCard = () => { + const configApi = useApi(configApiRef); + const appTitle = configApi.getOptional('app.title') || 'Backstage'; + const opts = useImportOptions(); + + const integrations = configApi.getConfig('integrations'); + const hasGithubIntegration = integrations.has('github'); + + return ( + + + Enter the URL to your source code repository to add it to {appTitle}. + + Link to an existing entity file + + Example:{' '} + + https://github.com/backstage/backstage/blob/master/catalog-info.yaml + + + + The wizard analyzes the file, previews the entities, and adds them to + the {appTitle} catalog. + + {hasGithubIntegration && ( + <> + + Link to a repository{' '} + + + + Example: https://github.com/backstage/backstage + + + The wizard discovers all catalog-info.yaml files in the + repository, previews the entities, and adds them to the {appTitle}{' '} + catalog. + + {!opts?.pullRequest?.disable && ( + + If no entities are found, the wizard will prepare a Pull Request + that adds an example catalog-info.yaml and prepares + the {appTitle} catalog to load all entities as soon as the Pull + Request is merged. + + )} + + )} + + ); +}; diff --git a/plugins/catalog-import/src/components/ImportInfoCard/index.ts b/plugins/catalog-import/src/components/ImportInfoCard/index.ts new file mode 100644 index 0000000000..c82e88f7e8 --- /dev/null +++ b/plugins/catalog-import/src/components/ImportInfoCard/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { ImportInfoCard } from './ImportInfoCard'; diff --git a/plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx b/plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx new file mode 100644 index 0000000000..f22963429b --- /dev/null +++ b/plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx @@ -0,0 +1,24 @@ +/* + * 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 { createContext, useContext } from 'react'; +import { ImportOptions } from '../types'; + +export const ImportOptionsContext = createContext({}); + +export const useImportOptions = (): ImportOptions => { + return useContext(ImportOptionsContext); +}; diff --git a/plugins/catalog-import/src/components/ImportOptionsContext/index.ts b/plugins/catalog-import/src/components/ImportOptionsContext/index.ts new file mode 100644 index 0000000000..42d41718e4 --- /dev/null +++ b/plugins/catalog-import/src/components/ImportOptionsContext/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { ImportOptionsContext, useImportOptions } from './ImportOptionsContext'; diff --git a/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx b/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx index 48ee23e444..a669377b21 100644 --- a/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx +++ b/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx @@ -17,13 +17,14 @@ import { Step, StepContent, Stepper } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import React, { useMemo } from 'react'; +import { useImportOptions } from '../ImportOptionsContext'; +import { ImportOptions } from '../types'; import { ImportFlows, ImportState, useImportState } from '../useImportState'; import { defaultGenerateStepper, defaultStepper, StepConfiguration, StepperProvider, - StepperProviderOpts, } from './defaults'; import { configApiRef, useApi } from '@backstage/core-plugin-api'; @@ -42,18 +43,19 @@ type Props = { defaults: StepperProvider, ) => StepperProvider; variant?: InfoCardVariants; - opts?: StepperProviderOpts; + /// @deprecated Pass import options via ImportOptionsContext instead. + opts?: ImportOptions; }; export const ImportStepper = ({ initialUrl, generateStepper = defaultGenerateStepper, variant, - opts, }: Props) => { const configApi = useApi(configApiRef); const classes = useStyles(); const state = useImportState({ initialUrl }); + const opts = useImportOptions(); const states = useMemo( () => generateStepper(state.activeFlow, defaultStepper), diff --git a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx index 79d859ce32..9afd983da5 100644 --- a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx +++ b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx @@ -35,22 +35,9 @@ import { } from '../StepPrepareCreatePullRequest'; import { StepPrepareSelectLocations } from '../StepPrepareSelectLocations'; import { StepReviewLocation } from '../StepReviewLocation'; +import { ImportOptions, StepperApis } from '../types'; import { ImportFlows, ImportState } from '../useImportState'; -export type StepperProviderOpts = { - pullRequest?: { - disable?: boolean; - preparePullRequest?: (apis: StepperApis) => { - title?: string; - body?: string; - }; - }; -}; - -type StepperApis = { - configApi: ConfigApi; -}; - export type StepConfiguration = { stepLabel: React.ReactElement; content: React.ReactElement; @@ -59,19 +46,19 @@ export type StepConfiguration = { export type StepperProvider = { analyze: ( s: Extract, - opts: { apis: StepperApis; opts?: StepperProviderOpts }, + opts: { apis: StepperApis; opts?: ImportOptions }, ) => StepConfiguration; prepare: ( s: Extract, - opts: { apis: StepperApis; opts?: StepperProviderOpts }, + opts: { apis: StepperApis; opts?: ImportOptions }, ) => StepConfiguration; review: ( s: Extract, - opts: { apis: StepperApis; opts?: StepperProviderOpts }, + opts: { apis: StepperApis; opts?: ImportOptions }, ) => StepConfiguration; finish: ( s: Extract, - opts: { apis: StepperApis; opts?: StepperProviderOpts }, + opts: { apis: StepperApis; opts?: ImportOptions }, ) => StepConfiguration; }; diff --git a/plugins/catalog-import/src/components/Router.tsx b/plugins/catalog-import/src/components/Router.tsx index c8f1ae65a3..05ae51ca01 100644 --- a/plugins/catalog-import/src/components/Router.tsx +++ b/plugins/catalog-import/src/components/Router.tsx @@ -17,9 +17,10 @@ import React from 'react'; import { Route, Routes } from 'react-router-dom'; import { ImportComponentPage } from './ImportComponentPage'; -import { StepperProviderOpts } from './ImportStepper/defaults'; +import { ImportOptions } from './types'; -export const Router = (opts: StepperProviderOpts) => ( +/// @deprecated, use ImportComponentPage instead. +export const Router = (opts: ImportOptions) => ( } /> diff --git a/plugins/catalog-import/src/components/index.ts b/plugins/catalog-import/src/components/index.ts index 9b53200317..81056274f0 100644 --- a/plugins/catalog-import/src/components/index.ts +++ b/plugins/catalog-import/src/components/index.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -export * from './ImportStepper'; +export * from './DefaultImportComponentPage'; export * from './EntityListComponent'; +export * from './ImportInfoCard'; +export * from './ImportOptionsContext'; +export * from './ImportStepper'; export * from './StepInitAnalyzeUrl'; export * from './StepPrepareCreatePullRequest'; diff --git a/plugins/catalog-import/src/components/types.ts b/plugins/catalog-import/src/components/types.ts new file mode 100644 index 0000000000..7cfc8043c7 --- /dev/null +++ b/plugins/catalog-import/src/components/types.ts @@ -0,0 +1,30 @@ +/* + * 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 { ConfigApi } from '@backstage/core-plugin-api'; + +export type ImportOptions = { + pullRequest?: { + disable?: boolean; + preparePullRequest?: ( + apis: StepperApis, + ) => { title?: string; body?: string }; + }; +}; + +export type StepperApis = { + configApi: ConfigApi; +}; diff --git a/plugins/catalog-import/src/plugin.ts b/plugins/catalog-import/src/plugin.ts index 3ab999ac07..075d8a2084 100644 --- a/plugins/catalog-import/src/plugin.ts +++ b/plugins/catalog-import/src/plugin.ts @@ -67,7 +67,10 @@ export const catalogImportPlugin = createPlugin({ export const CatalogImportPage = catalogImportPlugin.provide( createRoutableExtension({ - component: () => import('./components/Router').then(m => m.Router), + component: () => + import('./components/ImportComponentPage').then( + m => m.ImportComponentPage, + ), mountPoint: rootRouteRef, }), ); From e0f228c46f29971c1e78f99b76eb937c2a35209c Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 12 Aug 2021 11:52:37 +0200 Subject: [PATCH 10/26] Migrate my changes to the new core-* apis Signed-off-by: Oliver Sand --- .../DefaultImportComponentPage.test.tsx | 4 ++-- .../DefaultImportComponentPage.tsx | 5 ++--- .../src/components/ImportInfoCard/ImportInfoCard.test.tsx | 4 ++-- .../src/components/ImportInfoCard/ImportInfoCard.tsx | 5 +++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx index 5e49872319..e807559cbf 100644 --- a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx +++ b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx @@ -18,9 +18,9 @@ import { CatalogClient } from '@backstage/catalog-client'; import { ApiProvider, ApiRegistry, - configApiRef, ConfigReader, -} from '@backstage/core'; +} from '@backstage/core-app-api'; +import { configApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx index b9aad55274..d9e9e09335 100644 --- a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx +++ b/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx @@ -15,14 +15,13 @@ */ import { - configApiRef, Content, ContentHeader, Header, Page, SupportButton, - useApi, -} from '@backstage/core'; +} from '@backstage/core-components'; +import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { Grid } from '@material-ui/core'; import React from 'react'; import { ImportInfoCard } from '../ImportInfoCard'; diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx index 899ad18cc3..c2302403d3 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx @@ -17,9 +17,9 @@ import { ApiProvider, ApiRegistry, - configApiRef, ConfigReader, -} from '@backstage/core'; +} from '@backstage/core-app-api'; +import { configApiRef } from '@backstage/core-plugin-api'; import { wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import React from 'react'; diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx index 8fbbe6cc82..282070ad28 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx @@ -14,8 +14,9 @@ * limitations under the License. */ -import { ConfigApi, configApiRef, InfoCard, useApi } from '@backstage/core'; -import { Typography } from '@material-ui/core'; +import { InfoCard } from '@backstage/core-components'; +import { configApiRef, useApi } from '@backstage/core-plugin-api'; +import { Chip, Typography } from '@material-ui/core'; import React from 'react'; import { useImportOptions } from '../ImportOptionsContext'; From befaae417c8f418eef50b496efde6f4a71eb375d Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 12 Aug 2021 12:04:42 +0200 Subject: [PATCH 11/26] Update api-report.md Signed-off-by: Oliver Sand --- plugins/catalog-import/api-report.md | 32 +++++++++++++++---- .../src/components/ImportStepper/defaults.tsx | 1 - 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/plugins/catalog-import/api-report.md b/plugins/catalog-import/api-report.md index 6752f95748..9462894f61 100644 --- a/plugins/catalog-import/api-report.md +++ b/plugins/catalog-import/api-report.md @@ -9,6 +9,7 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { ConfigApi } from '@backstage/core-plugin-api'; +import { Context } from 'react'; import { Controller } from 'react-hook-form'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; @@ -114,11 +115,11 @@ export class CatalogImportClient implements CatalogImportApi { }>; } -// Warning: (ae-forgotten-export) The symbol "StepperProviderOpts" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "ImportOptions" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "CatalogImportPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const CatalogImportPage: (opts: StepperProviderOpts) => JSX.Element; +export const CatalogImportPage: (opts: ImportOptions) => JSX.Element; // Warning: (ae-missing-release-tag) "catalogImportPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -144,6 +145,11 @@ export function defaultGenerateStepper( defaults: StepperProvider, ): StepperProvider; +// Warning: (ae-missing-release-tag) "DefaultImportComponentPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const DefaultImportComponentPage: () => JSX.Element; + // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "EntityListComponent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -155,7 +161,17 @@ export const EntityListComponent: ({ onItemClick, firstListItem, withLinks, -}: Props_2) => JSX.Element; +}: Props) => JSX.Element; + +// Warning: (ae-missing-release-tag) "ImportInfoCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const ImportInfoCard: () => JSX.Element; + +// Warning: (ae-missing-release-tag) "ImportOptionsContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const ImportOptionsContext: Context; // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ImportStepper" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -165,8 +181,7 @@ export const ImportStepper: ({ initialUrl, generateStepper, variant, - opts, -}: Props) => JSX.Element; +}: Props_2) => JSX.Element; // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen @@ -206,7 +221,7 @@ export const PreviewPullRequestComponent: ({ // Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const Router: (opts: StepperProviderOpts) => JSX.Element; +export const Router: (opts: ImportOptions) => JSX.Element; // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen @@ -234,6 +249,11 @@ export const StepPrepareCreatePullRequest: ({ defaultBody, }: Props_8) => JSX.Element; +// Warning: (ae-missing-release-tag) "useImportOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const useImportOptions: () => ImportOptions; + // Warnings were encountered during analysis: // // src/api/CatalogImportApi.d.ts:14:5 - (ae-forgotten-export) The symbol "PartialEntity" needs to be exported by the entry point index.d.ts diff --git a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx index 9afd983da5..d4099c1177 100644 --- a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx +++ b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { ConfigApi } from '@backstage/core-plugin-api'; import { Box, Checkbox, From 1bbb8cee46f69ae25f184bfe889bf6c3919f98f1 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Wed, 18 Aug 2021 09:37:06 +0200 Subject: [PATCH 12/26] Rename ImportComponentPage to ImportPage as it can import all kinds of entities Signed-off-by: Oliver Sand --- plugins/catalog-import/api-report.md | 4 ++-- plugins/catalog-import/dev/index.tsx | 4 ++-- .../DefaultImportPage.test.tsx} | 17 ++++++++--------- .../DefaultImportPage.tsx} | 2 +- .../index.ts | 2 +- .../ImportPage.test.tsx} | 6 +++--- .../ImportPage.tsx} | 6 +++--- .../index.ts | 2 +- .../catalog-import/src/components/Router.tsx | 6 +++--- plugins/catalog-import/src/components/index.ts | 2 +- plugins/catalog-import/src/plugin.ts | 5 +---- 11 files changed, 26 insertions(+), 30 deletions(-) rename plugins/catalog-import/src/components/{ImportComponentPage/ImportComponentPage.test.tsx => DefaultImportPage/DefaultImportPage.test.tsx} (94%) rename plugins/catalog-import/src/components/{DefaultImportComponentPage/DefaultImportComponentPage.tsx => DefaultImportPage/DefaultImportPage.tsx} (97%) rename plugins/catalog-import/src/components/{ImportComponentPage => DefaultImportPage}/index.ts (90%) rename plugins/catalog-import/src/components/{DefaultImportComponentPage/DefaultImportComponentPage.test.tsx => ImportPage/ImportPage.test.tsx} (92%) rename plugins/catalog-import/src/components/{ImportComponentPage/ImportComponentPage.tsx => ImportPage/ImportPage.tsx} (83%) rename plugins/catalog-import/src/components/{DefaultImportComponentPage => ImportPage}/index.ts (88%) diff --git a/plugins/catalog-import/api-report.md b/plugins/catalog-import/api-report.md index 9462894f61..a89654a56e 100644 --- a/plugins/catalog-import/api-report.md +++ b/plugins/catalog-import/api-report.md @@ -145,10 +145,10 @@ export function defaultGenerateStepper( defaults: StepperProvider, ): StepperProvider; -// Warning: (ae-missing-release-tag) "DefaultImportComponentPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-missing-release-tag) "DefaultImportPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const DefaultImportComponentPage: () => JSX.Element; +export const DefaultImportPage: () => JSX.Element; // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "EntityListComponent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/plugins/catalog-import/dev/index.tsx b/plugins/catalog-import/dev/index.tsx index 48d9320ca9..a0cf034782 100644 --- a/plugins/catalog-import/dev/index.tsx +++ b/plugins/catalog-import/dev/index.tsx @@ -29,7 +29,7 @@ import { EntityListComponent, ImportStepper, } from '../src'; -import { ImportComponentPage } from '../src/components/ImportComponentPage'; +import { ImportPage } from '../src/components/ImportPage'; import { Content, Header, InfoCard, Page } from '@backstage/core-components'; const getEntityNames = (url: string): EntityName[] => [ @@ -252,7 +252,7 @@ createDevApp() }) .addPage({ title: 'Catalog Import', - element: , + element: , }) .addPage({ title: 'Catalog Import 2', diff --git a/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.test.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx similarity index 94% rename from plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.test.tsx rename to plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx index 4177a6ae64..3a66c11dde 100644 --- a/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.test.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx @@ -15,21 +15,20 @@ */ import { CatalogClient } from '@backstage/catalog-client'; -import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { wrapInTestApp } from '@backstage/test-utils'; -import { act, render } from '@testing-library/react'; -import React from 'react'; -import { catalogImportApiRef, CatalogImportClient } from '../../api'; -import { ImportComponentPage } from './ImportComponentPage'; - import { ApiProvider, ApiRegistry, ConfigReader, } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { wrapInTestApp } from '@backstage/test-utils'; +import { act, render } from '@testing-library/react'; +import React from 'react'; +import { catalogImportApiRef, CatalogImportClient } from '../../api'; +import { DefaultImportPage } from './DefaultImportPage'; -describe('', () => { +describe('', () => { const identityApi = { getUserId: () => { return 'user'; @@ -72,7 +71,7 @@ describe('', () => { const { getByText } = render( wrapInTestApp( - + , ), ); diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx similarity index 97% rename from plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx rename to plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx index d9e9e09335..8693895ec0 100644 --- a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx @@ -27,7 +27,7 @@ import React from 'react'; import { ImportInfoCard } from '../ImportInfoCard'; import { ImportStepper } from '../ImportStepper'; -export const DefaultImportComponentPage = () => { +export const DefaultImportPage = () => { const configApi = useApi(configApiRef); const appTitle = configApi.getOptional('app.title') || 'Backstage'; diff --git a/plugins/catalog-import/src/components/ImportComponentPage/index.ts b/plugins/catalog-import/src/components/DefaultImportPage/index.ts similarity index 90% rename from plugins/catalog-import/src/components/ImportComponentPage/index.ts rename to plugins/catalog-import/src/components/DefaultImportPage/index.ts index 263ba51a23..5a4d4907e3 100644 --- a/plugins/catalog-import/src/components/ImportComponentPage/index.ts +++ b/plugins/catalog-import/src/components/DefaultImportPage/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { ImportComponentPage } from './ImportComponentPage'; +export { DefaultImportPage } from './DefaultImportPage'; diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx similarity index 92% rename from plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx rename to plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx index e807559cbf..8a481d74c9 100644 --- a/plugins/catalog-import/src/components/DefaultImportComponentPage/DefaultImportComponentPage.test.tsx +++ b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx @@ -26,9 +26,9 @@ import { wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import React from 'react'; import { catalogImportApiRef, CatalogImportClient } from '../../api'; -import { DefaultImportComponentPage } from './DefaultImportComponentPage'; +import { ImportPage } from './ImportPage'; -describe('', () => { +describe('', () => { const identityApi = { getUserId: () => { return 'user'; @@ -71,7 +71,7 @@ describe('', () => { const { getByText } = render( wrapInTestApp( - + , ), ); diff --git a/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx b/plugins/catalog-import/src/components/ImportPage/ImportPage.tsx similarity index 83% rename from plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx rename to plugins/catalog-import/src/components/ImportPage/ImportPage.tsx index 3a89705493..507ea0c5df 100644 --- a/plugins/catalog-import/src/components/ImportComponentPage/ImportComponentPage.tsx +++ b/plugins/catalog-import/src/components/ImportPage/ImportPage.tsx @@ -16,16 +16,16 @@ import React from 'react'; import { useOutlet } from 'react-router'; -import { DefaultImportComponentPage } from '../DefaultImportComponentPage'; +import { DefaultImportPage } from '../DefaultImportPage'; import { ImportOptionsContext } from '../ImportOptionsContext'; import { ImportOptions } from '../types'; -export const ImportComponentPage = (opts: ImportOptions) => { +export const ImportPage = (opts: ImportOptions) => { const outlet = useOutlet(); return ( - {outlet || } + {outlet || } ); }; diff --git a/plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts b/plugins/catalog-import/src/components/ImportPage/index.ts similarity index 88% rename from plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts rename to plugins/catalog-import/src/components/ImportPage/index.ts index f3450413a6..891c5302db 100644 --- a/plugins/catalog-import/src/components/DefaultImportComponentPage/index.ts +++ b/plugins/catalog-import/src/components/ImportPage/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { DefaultImportComponentPage } from './DefaultImportComponentPage'; +export { ImportPage } from './ImportPage'; diff --git a/plugins/catalog-import/src/components/Router.tsx b/plugins/catalog-import/src/components/Router.tsx index 05ae51ca01..3fc9896800 100644 --- a/plugins/catalog-import/src/components/Router.tsx +++ b/plugins/catalog-import/src/components/Router.tsx @@ -16,12 +16,12 @@ import React from 'react'; import { Route, Routes } from 'react-router-dom'; -import { ImportComponentPage } from './ImportComponentPage'; +import { ImportPage } from './ImportPage'; import { ImportOptions } from './types'; -/// @deprecated, use ImportComponentPage instead. +/// @deprecated, use ImportPage instead. export const Router = (opts: ImportOptions) => ( - } /> + } /> ); diff --git a/plugins/catalog-import/src/components/index.ts b/plugins/catalog-import/src/components/index.ts index 81056274f0..d34ecf3bcc 100644 --- a/plugins/catalog-import/src/components/index.ts +++ b/plugins/catalog-import/src/components/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -export * from './DefaultImportComponentPage'; +export * from './DefaultImportPage'; export * from './EntityListComponent'; export * from './ImportInfoCard'; export * from './ImportOptionsContext'; diff --git a/plugins/catalog-import/src/plugin.ts b/plugins/catalog-import/src/plugin.ts index 075d8a2084..2aa4d78f2d 100644 --- a/plugins/catalog-import/src/plugin.ts +++ b/plugins/catalog-import/src/plugin.ts @@ -67,10 +67,7 @@ export const catalogImportPlugin = createPlugin({ export const CatalogImportPage = catalogImportPlugin.provide( createRoutableExtension({ - component: () => - import('./components/ImportComponentPage').then( - m => m.ImportComponentPage, - ), + component: () => import('./components/ImportPage').then(m => m.ImportPage), mountPoint: rootRouteRef, }), ); From 66a9e17035cbd1fae4f01fae0986e4720824c046 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Wed, 18 Aug 2021 14:06:47 +0200 Subject: [PATCH 13/26] Implement customization with an API instead of context Signed-off-by: Oliver Sand --- .changeset/few-penguins-watch.md | 12 ++++- plugins/catalog-import/api-report.md | 30 +++++------ .../src/api/CatalogImportApi.ts | 4 ++ .../src/api/CatalogImportClient.test.ts | 1 + .../src/api/CatalogImportClient.ts | 22 ++++++++ .../DefaultImportPage.test.tsx | 1 + .../ImportInfoCard/ImportInfoCard.test.tsx | 54 ++++++++++++++++++- .../ImportInfoCard/ImportInfoCard.tsx | 9 ++-- .../ImportOptionsContext.tsx | 24 --------- .../components/ImportOptionsContext/index.ts | 17 ------ .../components/ImportPage/ImportPage.test.tsx | 25 +++++++++ .../src/components/ImportPage/ImportPage.tsx | 10 +--- .../ImportStepper/ImportStepper.tsx | 21 +++----- .../src/components/ImportStepper/defaults.tsx | 41 ++++---------- .../catalog-import/src/components/Router.tsx | 27 ---------- .../catalog-import/src/components/index.ts | 1 - .../catalog-import/src/components/types.ts | 13 +---- plugins/catalog-import/src/index.ts | 1 - plugins/catalog-import/src/plugin.ts | 10 ++-- 19 files changed, 160 insertions(+), 163 deletions(-) delete mode 100644 plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx delete mode 100644 plugins/catalog-import/src/components/ImportOptionsContext/index.ts delete mode 100644 plugins/catalog-import/src/components/Router.tsx diff --git a/.changeset/few-penguins-watch.md b/.changeset/few-penguins-watch.md index 1b410f0174..3d7d9fb457 100644 --- a/.changeset/few-penguins-watch.md +++ b/.changeset/few-penguins-watch.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-catalog-import': patch +'@backstage/plugin-catalog-import': minor --- Add initial support for customizing the catalog import page. @@ -33,3 +33,13 @@ is used. ``` + +Previously it was possible to disable and customize the automatic pull request +feature by passing options to `` (`pullRequest.disable` and +`pullRequest.preparePullRequest`). This functionality is moved to the +`CatalogImportApi` which now provides an optional `preparePullRequest()` +function. The function can either be overridden to generate a different content +for the pull request, or removed to disable this feature. + +The export of the long term deprecated legacy `` is removed, migrate to +`` instead. diff --git a/plugins/catalog-import/api-report.md b/plugins/catalog-import/api-report.md index a89654a56e..894a7fab61 100644 --- a/plugins/catalog-import/api-report.md +++ b/plugins/catalog-import/api-report.md @@ -9,7 +9,6 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { ConfigApi } from '@backstage/core-plugin-api'; -import { Context } from 'react'; import { Controller } from 'react-hook-form'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; @@ -69,6 +68,11 @@ export interface CatalogImportApi { // (undocumented) analyzeUrl(url: string): Promise; // (undocumented) + preparePullRequest?(): { + title: string; + body: string; + }; + // (undocumented) submitPullRequest(options: { repositoryUrl: string; fileContent: string; @@ -95,10 +99,16 @@ export class CatalogImportClient implements CatalogImportApi { identityApi: IdentityApi; scmIntegrationsApi: ScmIntegrationRegistry; catalogApi: CatalogApi; + configApi: ConfigApi; }); // (undocumented) analyzeUrl(url: string): Promise; // (undocumented) + preparePullRequest(): { + title: string; + body: string; + }; + // (undocumented) submitPullRequest({ repositoryUrl, fileContent, @@ -115,11 +125,10 @@ export class CatalogImportClient implements CatalogImportApi { }>; } -// Warning: (ae-forgotten-export) The symbol "ImportOptions" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "CatalogImportPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const CatalogImportPage: (opts: ImportOptions) => JSX.Element; +export const CatalogImportPage: () => JSX.Element; // Warning: (ae-missing-release-tag) "catalogImportPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -168,11 +177,6 @@ export const EntityListComponent: ({ // @public (undocumented) export const ImportInfoCard: () => JSX.Element; -// Warning: (ae-missing-release-tag) "ImportOptionsContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const ImportOptionsContext: Context; - // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ImportStepper" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -218,11 +222,6 @@ export const PreviewPullRequestComponent: ({ classes, }: Props_7) => JSX.Element; -// Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const Router: (opts: ImportOptions) => JSX.Element; - // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen @@ -249,11 +248,6 @@ export const StepPrepareCreatePullRequest: ({ defaultBody, }: Props_8) => JSX.Element; -// Warning: (ae-missing-release-tag) "useImportOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const useImportOptions: () => ImportOptions; - // Warnings were encountered during analysis: // // src/api/CatalogImportApi.d.ts:14:5 - (ae-forgotten-export) The symbol "PartialEntity" needs to be exported by the entry point index.d.ts diff --git a/plugins/catalog-import/src/api/CatalogImportApi.ts b/plugins/catalog-import/src/api/CatalogImportApi.ts index 04e98f3d7c..fae4e3d3b3 100644 --- a/plugins/catalog-import/src/api/CatalogImportApi.ts +++ b/plugins/catalog-import/src/api/CatalogImportApi.ts @@ -42,6 +42,10 @@ export type AnalyzeResult = export interface CatalogImportApi { analyzeUrl(url: string): Promise; + preparePullRequest?(): { + title: string; + body: string; + }; submitPullRequest(options: { repositoryUrl: string; fileContent: string; diff --git a/plugins/catalog-import/src/api/CatalogImportClient.test.ts b/plugins/catalog-import/src/api/CatalogImportClient.test.ts index 2936f956e4..99928727fb 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.test.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.test.ts @@ -115,6 +115,7 @@ describe('CatalogImportClient', () => { scmIntegrationsApi, identityApi, catalogApi, + configApi: new ConfigReader({}), }); }); diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index 2497af99d8..12aabf2b7f 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -17,6 +17,7 @@ import { CatalogApi } from '@backstage/catalog-client'; import { EntityName } from '@backstage/catalog-model'; import { + ConfigApi, DiscoveryApi, IdentityApi, OAuthApi, @@ -37,6 +38,7 @@ export class CatalogImportClient implements CatalogImportApi { private readonly githubAuthApi: OAuthApi; private readonly scmIntegrationsApi: ScmIntegrationRegistry; private readonly catalogApi: CatalogApi; + private readonly configApi: ConfigApi; constructor(options: { discoveryApi: DiscoveryApi; @@ -44,12 +46,14 @@ export class CatalogImportClient implements CatalogImportApi { identityApi: IdentityApi; scmIntegrationsApi: ScmIntegrationRegistry; catalogApi: CatalogApi; + configApi: ConfigApi; }) { this.discoveryApi = options.discoveryApi; this.githubAuthApi = options.githubAuthApi; this.identityApi = options.identityApi; this.scmIntegrationsApi = options.scmIntegrationsApi; this.catalogApi = options.catalogApi; + this.configApi = options.configApi; } async analyzeUrl(url: string): Promise { @@ -114,6 +118,24 @@ export class CatalogImportClient implements CatalogImportApi { }; } + preparePullRequest(): { + title: string; + body: string; + } { + const appTitle = + this.configApi.getOptionalString('app.title') ?? 'Backstage'; + const appBaseUrl = this.configApi.getString('app.baseUrl'); + + return { + title: 'Add catalog-info.yaml config file', + body: `This pull request adds a **Backstage entity metadata file** \ +to this repository so that the component can be added to the \ +[${appTitle} software catalog](${appBaseUrl}).\n\nAfter this pull request is merged, \ +the component will become available.\n\nFor more information, read an \ +[overview of the Backstage software catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview).`, + }; + } + async submitPullRequest({ repositoryUrl, fileContent, diff --git a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx index 3a66c11dde..5551a060b6 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx @@ -62,6 +62,7 @@ describe('', () => { identityApi, scmIntegrationsApi: {} as any, catalogApi: {} as any, + configApi: {} as any, }), ); }); diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx index c2302403d3..f03d6b28e8 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx @@ -23,19 +23,35 @@ import { configApiRef } from '@backstage/core-plugin-api'; import { wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import React from 'react'; +import { CatalogImportApi, catalogImportApiRef } from '../../api'; import { ImportInfoCard } from './ImportInfoCard'; describe('', () => { let apis: ApiRegistry; + let catalogImportApi: jest.Mocked; beforeEach(() => { + catalogImportApi = { + analyzeUrl: jest.fn(), + submitPullRequest: jest.fn(), + }; + apis = ApiRegistry.with( configApiRef, - new ConfigReader({ integrations: {} }), - ); + new ConfigReader({ + integrations: { + github: [{ token: 'my-token' }], + }, + }), + ).with(catalogImportApiRef, catalogImportApi); }); it('renders without exploding', async () => { + apis = ApiRegistry.with( + configApiRef, + new ConfigReader({ integrations: {} }), + ).with(catalogImportApiRef, catalogImportApi); + await act(async () => { const { getByText } = render( wrapInTestApp( @@ -48,4 +64,38 @@ describe('', () => { expect(getByText('Register an existing component')).toBeInTheDocument(); }); }); + + it('renders section on GitHub discovery if supported', async () => { + catalogImportApi.preparePullRequest = () => ({ title: '', body: '' }); + + await act(async () => { + const { getByText } = render( + wrapInTestApp( + + + , + ), + ); + + expect(getByText(/The wizard discovers all/)).toBeInTheDocument(); + }); + }); + + it('renders section on pull requests if supported', async () => { + catalogImportApi.preparePullRequest = () => ({ title: '', body: '' }); + + await act(async () => { + const { getByText } = render( + wrapInTestApp( + + + , + ), + ); + + expect( + getByText(/the wizard will prepare a Pull Request/), + ).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx index 282070ad28..2fab223f20 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx @@ -18,12 +18,12 @@ import { InfoCard } from '@backstage/core-components'; import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { Chip, Typography } from '@material-ui/core'; import React from 'react'; -import { useImportOptions } from '../ImportOptionsContext'; +import { catalogImportApiRef } from '../../api'; export const ImportInfoCard = () => { const configApi = useApi(configApiRef); const appTitle = configApi.getOptional('app.title') || 'Backstage'; - const opts = useImportOptions(); + const catalogImportApi = useApi(catalogImportApiRef); const integrations = configApi.getConfig('integrations'); const hasGithubIntegration = integrations.has('github'); @@ -33,8 +33,7 @@ export const ImportInfoCard = () => { title="Register an existing component" deepLink={{ title: 'Learn more about the Software Catalog', - link: - 'https://backstage.io/docs/features/software-catalog/software-catalog-overview', + link: 'https://backstage.io/docs/features/software-catalog/software-catalog-overview', }} > @@ -65,7 +64,7 @@ export const ImportInfoCard = () => { repository, previews the entities, and adds them to the {appTitle}{' '} catalog. - {!opts?.pullRequest?.disable && ( + {catalogImportApi.preparePullRequest && ( If no entities are found, the wizard will prepare a Pull Request that adds an example catalog-info.yaml and prepares diff --git a/plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx b/plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx deleted file mode 100644 index f22963429b..0000000000 --- a/plugins/catalog-import/src/components/ImportOptionsContext/ImportOptionsContext.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 { createContext, useContext } from 'react'; -import { ImportOptions } from '../types'; - -export const ImportOptionsContext = createContext({}); - -export const useImportOptions = (): ImportOptions => { - return useContext(ImportOptionsContext); -}; diff --git a/plugins/catalog-import/src/components/ImportOptionsContext/index.ts b/plugins/catalog-import/src/components/ImportOptionsContext/index.ts deleted file mode 100644 index 42d41718e4..0000000000 --- a/plugins/catalog-import/src/components/ImportOptionsContext/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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 { ImportOptionsContext, useImportOptions } from './ImportOptionsContext'; diff --git a/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx index 8a481d74c9..1e2182005e 100644 --- a/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx +++ b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx @@ -25,9 +25,15 @@ import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { wrapInTestApp } from '@backstage/test-utils'; import { act, render } from '@testing-library/react'; import React from 'react'; +import { useOutlet } from 'react-router'; import { catalogImportApiRef, CatalogImportClient } from '../../api'; import { ImportPage } from './ImportPage'; +jest.mock('react-router', () => ({ + ...jest.requireActual('react-router'), + useOutlet: jest.fn(), +})); + describe('', () => { const identityApi = { getUserId: () => { @@ -62,10 +68,13 @@ describe('', () => { identityApi, scmIntegrationsApi: {} as any, catalogApi: {} as any, + configApi: new ConfigReader({}), }), ); }); + afterEach(() => jest.resetAllMocks()); + it('renders without exploding', async () => { await act(async () => { const { getByText } = render( @@ -81,4 +90,20 @@ describe('', () => { ).toBeInTheDocument(); }); }); + + it('renders with custom children', async () => { + (useOutlet as jest.Mock).mockReturnValue(
Hello World
); + + await act(async () => { + const { getByText } = render( + wrapInTestApp( + + + , + ), + ); + + expect(getByText('Hello World')).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/catalog-import/src/components/ImportPage/ImportPage.tsx b/plugins/catalog-import/src/components/ImportPage/ImportPage.tsx index 507ea0c5df..467bd710f0 100644 --- a/plugins/catalog-import/src/components/ImportPage/ImportPage.tsx +++ b/plugins/catalog-import/src/components/ImportPage/ImportPage.tsx @@ -17,15 +17,9 @@ import React from 'react'; import { useOutlet } from 'react-router'; import { DefaultImportPage } from '../DefaultImportPage'; -import { ImportOptionsContext } from '../ImportOptionsContext'; -import { ImportOptions } from '../types'; -export const ImportPage = (opts: ImportOptions) => { +export const ImportPage = () => { const outlet = useOutlet(); - return ( - - {outlet || } - - ); + return outlet || ; }; diff --git a/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx b/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx index a669377b21..4112775c2d 100644 --- a/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx +++ b/plugins/catalog-import/src/components/ImportStepper/ImportStepper.tsx @@ -14,11 +14,12 @@ * limitations under the License. */ +import { InfoCard, InfoCardVariants } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; import { Step, StepContent, Stepper } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import React, { useMemo } from 'react'; -import { useImportOptions } from '../ImportOptionsContext'; -import { ImportOptions } from '../types'; +import { catalogImportApiRef } from '../../api'; import { ImportFlows, ImportState, useImportState } from '../useImportState'; import { defaultGenerateStepper, @@ -27,9 +28,6 @@ import { StepperProvider, } from './defaults'; -import { configApiRef, useApi } from '@backstage/core-plugin-api'; -import { InfoCard, InfoCardVariants } from '@backstage/core-components'; - const useStyles = makeStyles(() => ({ stepperRoot: { padding: 0, @@ -43,8 +41,6 @@ type Props = { defaults: StepperProvider, ) => StepperProvider; variant?: InfoCardVariants; - /// @deprecated Pass import options via ImportOptionsContext instead. - opts?: ImportOptions; }; export const ImportStepper = ({ @@ -52,10 +48,9 @@ export const ImportStepper = ({ generateStepper = defaultGenerateStepper, variant, }: Props) => { - const configApi = useApi(configApiRef); + const catalogImportApi = useApi(catalogImportApiRef); const classes = useStyles(); const state = useImportState({ initialUrl }); - const opts = useImportOptions(); const states = useMemo( () => generateStepper(state.activeFlow, defaultStepper), @@ -81,25 +76,25 @@ export const ImportStepper = ({ {render( states.analyze( state as Extract, - { apis: { configApi }, opts }, + { apis: { catalogImportApi } }, ), )} {render( states.prepare( state as Extract, - { apis: { configApi }, opts }, + { apis: { catalogImportApi } }, ), )} {render( states.review( state as Extract, - { apis: { configApi }, opts }, + { apis: { catalogImportApi } }, ), )} {render( states.finish( state as Extract, - { apis: { configApi }, opts }, + { apis: { catalogImportApi } }, ), )} diff --git a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx index d4099c1177..72f946af6c 100644 --- a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx +++ b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx @@ -34,7 +34,7 @@ import { } from '../StepPrepareCreatePullRequest'; import { StepPrepareSelectLocations } from '../StepPrepareSelectLocations'; import { StepReviewLocation } from '../StepReviewLocation'; -import { ImportOptions, StepperApis } from '../types'; +import { StepperApis } from '../types'; import { ImportFlows, ImportState } from '../useImportState'; export type StepConfiguration = { @@ -45,41 +45,22 @@ export type StepConfiguration = { export type StepperProvider = { analyze: ( s: Extract, - opts: { apis: StepperApis; opts?: ImportOptions }, + opts: { apis: StepperApis }, ) => StepConfiguration; prepare: ( s: Extract, - opts: { apis: StepperApis; opts?: ImportOptions }, + opts: { apis: StepperApis }, ) => StepConfiguration; review: ( s: Extract, - opts: { apis: StepperApis; opts?: ImportOptions }, + opts: { apis: StepperApis }, ) => StepConfiguration; finish: ( s: Extract, - opts: { apis: StepperApis; opts?: ImportOptions }, + opts: { apis: StepperApis }, ) => StepConfiguration; }; -function defaultPreparePullRequest( - apis: StepperApis, - { title, body }: { title?: string; body?: string } = {}, -) { - const appTitle = apis.configApi.getOptionalString('app.title') ?? 'Backstage'; - const appBaseUrl = apis.configApi.getString('app.baseUrl'); - - return { - title: title ?? 'Add catalog-info.yaml config file', - body: - body ?? - `This pull request adds a **Backstage entity metadata file** \ -to this repository so that the component can be added to the \ -[${appTitle} software catalog](${appBaseUrl}).\n\nAfter this pull request is merged, \ -the component will become available.\n\nFor more information, read an \ -[overview of the Backstage software catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview).`, - }; -} - /** * The default stepper generation function. * @@ -155,12 +136,8 @@ export function defaultGenerateStepper( return defaults.prepare(state, opts); } - const preparePullRequest = - opts?.opts?.pullRequest?.preparePullRequest; - const { title, body } = defaultPreparePullRequest( - opts.apis, - preparePullRequest ? preparePullRequest(opts.apis) : {}, - ); + const { title, body } = + opts.apis.catalogImportApi.preparePullRequest!(); return { stepLabel: Create Pull Request, @@ -285,14 +262,14 @@ export function defaultGenerateStepper( } export const defaultStepper: StepperProvider = { - analyze: (state, { opts }) => ({ + analyze: (state, { apis }) => ({ stepLabel: Select URL, content: ( ), }), diff --git a/plugins/catalog-import/src/components/Router.tsx b/plugins/catalog-import/src/components/Router.tsx deleted file mode 100644 index 3fc9896800..0000000000 --- a/plugins/catalog-import/src/components/Router.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import React from 'react'; -import { Route, Routes } from 'react-router-dom'; -import { ImportPage } from './ImportPage'; -import { ImportOptions } from './types'; - -/// @deprecated, use ImportPage instead. -export const Router = (opts: ImportOptions) => ( - - } /> - -); diff --git a/plugins/catalog-import/src/components/index.ts b/plugins/catalog-import/src/components/index.ts index d34ecf3bcc..886c679d2d 100644 --- a/plugins/catalog-import/src/components/index.ts +++ b/plugins/catalog-import/src/components/index.ts @@ -17,7 +17,6 @@ export * from './DefaultImportPage'; export * from './EntityListComponent'; export * from './ImportInfoCard'; -export * from './ImportOptionsContext'; export * from './ImportStepper'; export * from './StepInitAnalyzeUrl'; export * from './StepPrepareCreatePullRequest'; diff --git a/plugins/catalog-import/src/components/types.ts b/plugins/catalog-import/src/components/types.ts index 7cfc8043c7..baa279ff21 100644 --- a/plugins/catalog-import/src/components/types.ts +++ b/plugins/catalog-import/src/components/types.ts @@ -14,17 +14,8 @@ * limitations under the License. */ -import { ConfigApi } from '@backstage/core-plugin-api'; - -export type ImportOptions = { - pullRequest?: { - disable?: boolean; - preparePullRequest?: ( - apis: StepperApis, - ) => { title?: string; body?: string }; - }; -}; +import { CatalogImportApi } from '../api'; export type StepperApis = { - configApi: ConfigApi; + catalogImportApi: CatalogImportApi; }; diff --git a/plugins/catalog-import/src/index.ts b/plugins/catalog-import/src/index.ts index adee41bdbd..149c3e55c6 100644 --- a/plugins/catalog-import/src/index.ts +++ b/plugins/catalog-import/src/index.ts @@ -25,6 +25,5 @@ export { catalogImportPlugin as plugin, CatalogImportPage, } from './plugin'; -export { Router } from './components/Router'; export * from './components'; export * from './api'; diff --git a/plugins/catalog-import/src/plugin.ts b/plugins/catalog-import/src/plugin.ts index 2aa4d78f2d..d7d6370de3 100644 --- a/plugins/catalog-import/src/plugin.ts +++ b/plugins/catalog-import/src/plugin.ts @@ -14,10 +14,8 @@ * limitations under the License. */ -import { scmIntegrationsApiRef } from '@backstage/integration-react'; -import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { catalogImportApiRef, CatalogImportClient } from './api'; import { + configApiRef, createApiFactory, createPlugin, createRoutableExtension, @@ -26,6 +24,9 @@ import { githubAuthApiRef, identityApiRef, } from '@backstage/core-plugin-api'; +import { scmIntegrationsApiRef } from '@backstage/integration-react'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { catalogImportApiRef, CatalogImportClient } from './api'; export const rootRouteRef = createRouteRef({ path: '', @@ -43,6 +44,7 @@ export const catalogImportPlugin = createPlugin({ identityApi: identityApiRef, scmIntegrationsApi: scmIntegrationsApiRef, catalogApi: catalogApiRef, + configApi: configApiRef, }, factory: ({ discoveryApi, @@ -50,6 +52,7 @@ export const catalogImportPlugin = createPlugin({ identityApi, scmIntegrationsApi, catalogApi, + configApi, }) => new CatalogImportClient({ discoveryApi, @@ -57,6 +60,7 @@ export const catalogImportPlugin = createPlugin({ scmIntegrationsApi, identityApi, catalogApi, + configApi, }), }), ], From 18571288a8f1b254c374766164dd2dec15ef1ff5 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 16 Sep 2021 16:05:11 +0200 Subject: [PATCH 14/26] Make preparePullRequest async Signed-off-by: Oliver Sand --- .../src/api/CatalogImportApi.ts | 6 +- .../src/api/CatalogImportClient.test.ts | 15 +- .../src/api/CatalogImportClient.ts | 4 +- .../ImportInfoCard/ImportInfoCard.test.tsx | 4 +- .../src/components/ImportStepper/defaults.tsx | 5 - .../StepPrepareCreatePullRequest.test.tsx | 53 +++--- .../StepPrepareCreatePullRequest.tsx | 169 ++++++++++-------- 7 files changed, 139 insertions(+), 117 deletions(-) diff --git a/plugins/catalog-import/src/api/CatalogImportApi.ts b/plugins/catalog-import/src/api/CatalogImportApi.ts index fae4e3d3b3..a4645dc7ef 100644 --- a/plugins/catalog-import/src/api/CatalogImportApi.ts +++ b/plugins/catalog-import/src/api/CatalogImportApi.ts @@ -15,8 +15,8 @@ */ import { EntityName } from '@backstage/catalog-model'; -import { PartialEntity } from '../types'; import { createApiRef } from '@backstage/core-plugin-api'; +import { PartialEntity } from '../types'; export const catalogImportApiRef = createApiRef({ id: 'plugin.catalog-import.service', @@ -42,10 +42,10 @@ export type AnalyzeResult = export interface CatalogImportApi { analyzeUrl(url: string): Promise; - preparePullRequest?(): { + preparePullRequest?(): Promise<{ title: string; body: string; - }; + }>; submitPullRequest(options: { repositoryUrl: string; fileContent: string; diff --git a/plugins/catalog-import/src/api/CatalogImportClient.test.ts b/plugins/catalog-import/src/api/CatalogImportClient.test.ts index 99928727fb..0782b44147 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.test.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.test.ts @@ -115,7 +115,11 @@ describe('CatalogImportClient', () => { scmIntegrationsApi, identityApi, catalogApi, - configApi: new ConfigReader({}), + configApi: new ConfigReader({ + app: { + baseUrl: 'https://demo.backstage.io/', + }, + }), }); }); @@ -444,4 +448,13 @@ describe('CatalogImportClient', () => { }); }); }); + + describe('preparePullRequest', () => { + test('should prepare pull request details', async () => { + await expect(catalogImportClient.preparePullRequest()).resolves.toEqual({ + title: 'Add catalog-info.yaml config file', + body: expect.any(String), + }); + }); + }); }); diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index 12aabf2b7f..242f8440d1 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -118,10 +118,10 @@ export class CatalogImportClient implements CatalogImportApi { }; } - preparePullRequest(): { + async preparePullRequest(): Promise<{ title: string; body: string; - } { + }> { const appTitle = this.configApi.getOptionalString('app.title') ?? 'Backstage'; const appBaseUrl = this.configApi.getString('app.baseUrl'); diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx index f03d6b28e8..b33e3c4d36 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx @@ -66,7 +66,7 @@ describe('', () => { }); it('renders section on GitHub discovery if supported', async () => { - catalogImportApi.preparePullRequest = () => ({ title: '', body: '' }); + catalogImportApi.preparePullRequest = async () => ({ title: '', body: '' }); await act(async () => { const { getByText } = render( @@ -82,7 +82,7 @@ describe('', () => { }); it('renders section on pull requests if supported', async () => { - catalogImportApi.preparePullRequest = () => ({ title: '', body: '' }); + catalogImportApi.preparePullRequest = async () => ({ title: '', body: '' }); await act(async () => { const { getByText } = render( diff --git a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx index 72f946af6c..357ed64e14 100644 --- a/plugins/catalog-import/src/components/ImportStepper/defaults.tsx +++ b/plugins/catalog-import/src/components/ImportStepper/defaults.tsx @@ -136,9 +136,6 @@ export function defaultGenerateStepper( return defaults.prepare(state, opts); } - const { title, body } = - opts.apis.catalogImportApi.preparePullRequest!(); - return { stepLabel: Create Pull Request, content: ( @@ -146,8 +143,6 @@ export function defaultGenerateStepper( analyzeResult={state.analyzeResult} onPrepare={state.onPrepare} onGoBack={state.onGoBack} - defaultTitle={title} - defaultBody={body} renderFormFields={({ values, setValue, diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx index 08b8177291..e697b54b19 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx @@ -14,23 +14,25 @@ * limitations under the License. */ +import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { TextField } from '@material-ui/core'; import { act, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; +import { errorApiRef } from '../../../../../packages/core-plugin-api/src'; import { AnalyzeResult, catalogImportApiRef } from '../../api'; import { asInputRef } from '../helpers'; import { generateEntities, StepPrepareCreatePullRequest, } from './StepPrepareCreatePullRequest'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; describe('', () => { const catalogImportApi: jest.Mocked = { analyzeUrl: jest.fn(), submitPullRequest: jest.fn(), + preparePullRequest: jest.fn(), }; const catalogApi: jest.Mocked = { @@ -44,12 +46,16 @@ describe('', () => { removeEntityByUid: jest.fn(), }; + const errorApi: jest.Mocked = { + error$: jest.fn(), + post: jest.fn(), + }; + const Wrapper = ({ children }: { children?: React.ReactNode }) => ( {children} @@ -77,16 +83,19 @@ describe('', () => { beforeEach(() => { jest.resetAllMocks(); + + (catalogImportApi.preparePullRequest! as jest.Mock).mockResolvedValue({ + title: 'My title', + body: 'My **body**', + }); }); it('renders without exploding', async () => { catalogApi.getEntities.mockReturnValue(Promise.resolve({ items: [] })); await act(async () => { - const { getByText } = render( + const { findByText } = render( { @@ -105,8 +114,8 @@ describe('', () => { }, ); - const title = getByText('My title'); - const description = getByText('body', { selector: 'strong' }); + const title = await findByText('My title'); + const description = await findByText('body', { selector: 'strong' }); expect(title).toBeInTheDocument(); expect(title).toBeVisible(); expect(description).toBeInTheDocument(); @@ -124,10 +133,8 @@ describe('', () => { ); await act(async () => { - await render( + render( { @@ -154,11 +161,9 @@ describe('', () => { }, ); - await userEvent.type(await screen.getByLabelText('name'), '-changed'); - await userEvent.type(await screen.getByLabelText('owner'), '-changed'); - await userEvent.click( - await screen.getByRole('button', { name: /Create PR/i }), - ); + userEvent.type(await screen.findByLabelText('name'), '-changed'); + userEvent.type(await screen.findByLabelText('owner'), '-changed'); + userEvent.click(screen.getByRole('button', { name: /Create PR/i })); }); expect(catalogImportApi.submitPullRequest).toBeCalledTimes(1); @@ -212,10 +217,8 @@ spec: ); await act(async () => { - await render( + render( { @@ -234,8 +237,8 @@ spec: }, ); - await userEvent.click( - await screen.getByRole('button', { name: /Create PR/i }), + userEvent.click( + await screen.findByRole('button', { name: /Create PR/i }), ); }); @@ -261,10 +264,8 @@ spec: ); await act(async () => { - await render( + render( void; onGoBack?: () => void; - defaultTitle: string; - defaultBody: string; - renderFormFields: ( props: Pick< UseFormReturn, @@ -99,16 +96,30 @@ export const StepPrepareCreatePullRequest = ({ onPrepare, onGoBack, renderFormFields, - defaultTitle, - defaultBody, }: Props) => { const classes = useStyles(); const catalogApi = useApi(catalogApiRef); - const catalogInfoApi = useApi(catalogImportApiRef); + const catalogImportApi = useApi(catalogImportApiRef); + const errorApi = useApi(errorApiRef); const [submitted, setSubmitted] = useState(false); const [error, setError] = useState(); + const { + loading: prDefaultsLoading, + value: prDefaults, + error: prDefaultsError, + } = useAsync( + () => catalogImportApi.preparePullRequest!(), + [catalogImportApi.preparePullRequest], + ); + + useEffect(() => { + if (prDefaultsError) { + errorApi.post(prDefaultsError); + } + }, [prDefaultsError, errorApi]); + const { loading: groupsLoading, value: groups } = useAsync(async () => { const groupEntities = await catalogApi.getEntities({ filter: { kind: 'group' }, @@ -124,7 +135,7 @@ export const StepPrepareCreatePullRequest = ({ setSubmitted(true); try { - const pr = await catalogInfoApi.submitPullRequest({ + const pr = await catalogImportApi.submitPullRequest({ repositoryUrl: analyzeResult.url, title: data.title, body: data.body, @@ -171,7 +182,7 @@ export const StepPrepareCreatePullRequest = ({ analyzeResult.generatedEntities, analyzeResult.integrationType, analyzeResult.url, - catalogInfoApi, + catalogImportApi, onPrepare, ], ); @@ -184,79 +195,81 @@ export const StepPrepareCreatePullRequest = ({ a Pull Request that creates one.
- - onSubmit={handleResult} - defaultValues={{ - title: defaultTitle, - body: defaultBody, - owner: - (analyzeResult.generatedEntities[0]?.spec?.owner as string) || '', - componentName: - analyzeResult.generatedEntities[0]?.metadata?.name || '', - useCodeowners: false, - }} - render={({ values, formState, register, setValue }) => ( - <> - {renderFormFields({ - values, - formState, - register, - setValue, - groups: groups ?? [], - groupsLoading, - })} + {!prDefaultsLoading && ( + + onSubmit={handleResult} + defaultValues={{ + title: prDefaults?.title ?? '', + body: prDefaults?.body ?? '', + owner: + (analyzeResult.generatedEntities[0]?.spec?.owner as string) || '', + componentName: + analyzeResult.generatedEntities[0]?.metadata?.name || '', + useCodeowners: false, + }} + render={({ values, formState, register, setValue }) => ( + <> + {renderFormFields({ + values, + formState, + register, + setValue, + groups: groups ?? [], + groupsLoading, + })} - - Preview Pull Request - + + Preview Pull Request + - + - - Preview Entities - + + Preview Entities + - - - {error && {error}} - - - {onGoBack && ( - - )} - - Create PR - - - - )} - /> + repositoryUrl={analyzeResult.url} + classes={{ + card: classes.previewCard, + cardContent: classes.previewCardContent, + }} + /> + + {error && {error}} + + + {onGoBack && ( + + )} + + Create PR + + + + )} + /> + )} ); }; From bd44d3adce5922ba9d4d1b339ff19887882e1512 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 16 Sep 2021 16:19:14 +0200 Subject: [PATCH 15/26] Update api report Signed-off-by: Oliver Sand --- plugins/catalog-import/api-report.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/catalog-import/api-report.md b/plugins/catalog-import/api-report.md index 894a7fab61..753244b28f 100644 --- a/plugins/catalog-import/api-report.md +++ b/plugins/catalog-import/api-report.md @@ -68,10 +68,10 @@ export interface CatalogImportApi { // (undocumented) analyzeUrl(url: string): Promise; // (undocumented) - preparePullRequest?(): { + preparePullRequest?(): Promise<{ title: string; body: string; - }; + }>; // (undocumented) submitPullRequest(options: { repositoryUrl: string; @@ -104,10 +104,10 @@ export class CatalogImportClient implements CatalogImportApi { // (undocumented) analyzeUrl(url: string): Promise; // (undocumented) - preparePullRequest(): { + preparePullRequest(): Promise<{ title: string; body: string; - }; + }>; // (undocumented) submitPullRequest({ repositoryUrl, @@ -244,8 +244,6 @@ export const StepPrepareCreatePullRequest: ({ onPrepare, onGoBack, renderFormFields, - defaultTitle, - defaultBody, }: Props_8) => JSX.Element; // Warnings were encountered during analysis: From febddedcb2f0a1e045f15be2ebe3dc1fe0a0f51d Mon Sep 17 00:00:00 2001 From: Tim Hansen Date: Thu, 16 Sep 2021 16:03:51 -0600 Subject: [PATCH 16/26] security: bump lodash to 4.17.21 Signed-off-by: Tim Hansen --- .changeset/spicy-yaks-notice.md | 19 +++++++++++++++++++ package.json | 3 ++- packages/backend-common/package.json | 2 +- packages/catalog-model/package.json | 2 +- packages/cli/package.json | 2 +- packages/config/package.json | 2 +- packages/core-components/package.json | 2 +- .../catalog-backend-module-ldap/package.json | 2 +- .../package.json | 2 +- plugins/catalog-backend/package.json | 2 +- plugins/catalog-react/package.json | 2 +- plugins/circleci/package.json | 2 +- plugins/kafka-backend/package.json | 2 +- plugins/kubernetes-backend/package.json | 2 +- plugins/rollbar-backend/package.json | 2 +- plugins/rollbar/package.json | 2 +- plugins/search-backend-module-pg/package.json | 2 +- yarn.lock | 7 +------ 18 files changed, 37 insertions(+), 22 deletions(-) create mode 100644 .changeset/spicy-yaks-notice.md diff --git a/.changeset/spicy-yaks-notice.md b/.changeset/spicy-yaks-notice.md new file mode 100644 index 0000000000..ae5c3ba1a5 --- /dev/null +++ b/.changeset/spicy-yaks-notice.md @@ -0,0 +1,19 @@ +--- +'@backstage/backend-common': patch +'@backstage/catalog-model': patch +'@backstage/cli': patch +'@backstage/config': patch +'@backstage/core-components': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-catalog-backend-module-ldap': patch +'@backstage/plugin-catalog-backend-module-msgraph': patch +'@backstage/plugin-catalog-react': patch +'@backstage/plugin-circleci': patch +'@backstage/plugin-kafka-backend': patch +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-rollbar': patch +'@backstage/plugin-rollbar-backend': patch +'@backstage/plugin-search-backend-module-pg': patch +--- + +Bump `lodash` to remediate `SNYK-JS-LODASH-590103` security vulnerability diff --git a/package.json b/package.json index d362338370..3f259516b2 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,8 @@ "**/@roadiehq/**/@backstage/plugin-catalog": "*", "**/@roadiehq/**/@backstage/catalog-model": "*", "graphql-language-service-interface": "2.8.2", - "graphql-language-service-parser": "1.9.0" + "graphql-language-service-parser": "1.9.0", + "lodash": "^4.17.21" }, "version": "1.0.0", "dependencies": { diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index f5cfaae27a..77090e13dc 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -55,7 +55,7 @@ "keyv": "^4.0.3", "keyv-memcache": "^1.2.5", "knex": "^0.95.1", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "logform": "^2.1.1", "minimatch": "^3.0.4", "minimist": "^1.2.5", diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 75574b029f..a2fc76c83a 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -36,7 +36,7 @@ "@types/yup": "^0.29.8", "ajv": "^7.0.3", "json-schema": "^0.3.0", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "uuid": "^8.0.0", "yup": "^0.29.3" }, diff --git a/packages/cli/package.json b/packages/cli/package.json index cb2b04aae9..8dabbed89d 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -82,7 +82,7 @@ "jest": "^26.0.1", "jest-css-modules": "^2.1.0", "json-schema": "^0.3.0", - "lodash": "^4.17.19", + "lodash": "^4.17.21", "mini-css-extract-plugin": "^1.4.1", "node-libs-browser": "^2.2.1", "ora": "^5.3.0", diff --git a/packages/config/package.json b/packages/config/package.json index 969bc44045..13b074c620 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "lodash": "^4.17.15" + "lodash": "^4.17.21" }, "devDependencies": { "@types/jest": "^26.0.7", diff --git a/packages/core-components/package.json b/packages/core-components/package.json index cb15e89d4a..7ffff145f5 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -50,7 +50,7 @@ "d3-zoom": "^2.0.0", "dagre": "^0.8.5", "immer": "^9.0.1", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "pluralize": "^8.0.0", "prop-types": "^15.7.2", "qs": "^6.9.4", diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 5909c28a98..2787287b62 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -34,7 +34,7 @@ "@backstage/plugin-catalog-backend": "^0.13.3", "@types/ldapjs": "^2.2.0", "ldapjs": "^2.2.0", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "winston": "^3.2.1" }, "devDependencies": { diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 4209630cc5..397d4fffb3 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -35,7 +35,7 @@ "@backstage/plugin-catalog-backend": "^0.13.5", "@microsoft/microsoft-graph-types": "^1.25.0", "cross-fetch": "^3.0.6", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "p-limit": "^3.0.2", "winston": "^3.2.1", "qs": "^6.9.4" diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 9aba035f78..16f61c2b9a 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -51,7 +51,7 @@ "git-url-parse": "^11.6.0", "glob": "^7.1.6", "knex": "^0.95.1", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "luxon": "^2.0.2", "morgan": "^1.10.0", "p-limit": "^3.0.2", diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 9388ef3670..54d8af11b6 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -41,7 +41,7 @@ "@material-ui/lab": "4.0.0-alpha.57", "@types/react": "*", "jwt-decode": "^3.1.0", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "qs": "^6.9.4", "react": "^16.13.1", "react-router": "6.0.0-beta.0", diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index bdc2946177..bf60f4de8e 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -42,7 +42,7 @@ "@material-ui/lab": "4.0.0-alpha.57", "circleci-api": "^4.0.0", "humanize-duration": "^3.27.0", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "luxon": "^2.0.2", "react": "^16.13.1", "react-dom": "^16.13.1", diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 0952e335cb..0583bccf68 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -40,7 +40,7 @@ "express": "^4.17.1", "express-promise-router": "^4.1.0", "kafkajs": "^1.16.0-beta.6", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "winston": "^3.2.1" }, "devDependencies": { diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index fdba331c07..3154cab61d 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -47,7 +47,7 @@ "express-promise-router": "^4.1.0", "fs-extra": "9.1.0", "helmet": "^4.0.0", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "morgan": "^1.10.0", "stream-buffers": "^3.0.2", "winston": "^3.2.1", diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 75eb7b9773..e6f92d4065 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -42,7 +42,7 @@ "express-promise-router": "^4.1.0", "fs-extra": "9.1.0", "helmet": "^4.0.0", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "morgan": "^1.10.0", "winston": "^3.2.1", "yn": "^4.0.0" diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 49bd185dde..66037f7b8b 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -40,7 +40,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "react": "^16.13.1", "react-dom": "^16.13.1", "react-router": "6.0.0-beta.0", diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 1bd4c9fee5..3dfb1fe307 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -23,7 +23,7 @@ "@backstage/backend-common": "^0.9.1", "@backstage/search-common": "^0.2.0", "@backstage/plugin-search-backend-node": "^0.4.2", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "knex": "^0.95.1" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 82aa7a3da0..4ca7415d32 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18433,12 +18433,7 @@ lodash.without@^4.4.0: resolved "https://registry.npmjs.org/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw= -lodash@4.17.15: - version "4.17.15" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -lodash@4.17.21, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@~4.17.0, lodash@~4.17.15, lodash@~4.17.4: +lodash@4.17.15, lodash@4.17.21, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@~4.17.0, lodash@~4.17.15, lodash@~4.17.4: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== From 552a23507f58d9276d4e267b294f39d198ce2c4b Mon Sep 17 00:00:00 2001 From: Tim Hansen Date: Thu, 16 Sep 2021 19:52:14 -0600 Subject: [PATCH 17/26] Remove root resolution Signed-off-by: Tim Hansen --- package.json | 3 +-- yarn.lock | 7 ++++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 3f259516b2..d362338370 100644 --- a/package.json +++ b/package.json @@ -49,8 +49,7 @@ "**/@roadiehq/**/@backstage/plugin-catalog": "*", "**/@roadiehq/**/@backstage/catalog-model": "*", "graphql-language-service-interface": "2.8.2", - "graphql-language-service-parser": "1.9.0", - "lodash": "^4.17.21" + "graphql-language-service-parser": "1.9.0" }, "version": "1.0.0", "dependencies": { diff --git a/yarn.lock b/yarn.lock index 4ca7415d32..82aa7a3da0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18433,7 +18433,12 @@ lodash.without@^4.4.0: resolved "https://registry.npmjs.org/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw= -lodash@4.17.15, lodash@4.17.21, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@~4.17.0, lodash@~4.17.15, lodash@~4.17.4: +lodash@4.17.15: + version "4.17.15" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +lodash@4.17.21, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@~4.17.0, lodash@~4.17.15, lodash@~4.17.4: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== From a5e881809ab275f53a47f8e844bcef1e6a1a6cba Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Fri, 17 Sep 2021 08:27:43 +0200 Subject: [PATCH 18/26] Fix import Signed-off-by: Oliver Sand --- .../StepPrepareCreatePullRequest.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx index e697b54b19..2212daf0c0 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx @@ -15,12 +15,12 @@ */ import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { errorApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { TextField } from '@material-ui/core'; import { act, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { errorApiRef } from '../../../../../packages/core-plugin-api/src'; import { AnalyzeResult, catalogImportApiRef } from '../../api'; import { asInputRef } from '../helpers'; import { From 86c716c60b35e8fc44799c2dda896a45347ec0ed Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Fri, 17 Sep 2021 08:27:57 +0200 Subject: [PATCH 19/26] Use `renderInTestApp` Signed-off-by: Oliver Sand --- .../DefaultImportPage.test.tsx | 23 +++----- .../ImportInfoCard/ImportInfoCard.test.tsx | 55 +++++++------------ .../components/ImportPage/ImportPage.test.tsx | 39 +++++-------- .../StepInitAnalyzeUrl.test.tsx | 9 ++- 4 files changed, 49 insertions(+), 77 deletions(-) diff --git a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx index 5551a060b6..57376c33f2 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.test.tsx @@ -22,8 +22,7 @@ import { } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { wrapInTestApp } from '@backstage/test-utils'; -import { act, render } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; import { catalogImportApiRef, CatalogImportClient } from '../../api'; import { DefaultImportPage } from './DefaultImportPage'; @@ -68,18 +67,14 @@ describe('', () => { }); it('renders without exploding', async () => { - await act(async () => { - const { getByText } = render( - wrapInTestApp( - - - , - ), - ); + const { getByText } = await renderInTestApp( + + + , + ); - expect( - getByText('Start tracking your component in Backstage'), - ).toBeInTheDocument(); - }); + expect( + getByText('Start tracking your component in Backstage'), + ).toBeInTheDocument(); }); }); diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx index b33e3c4d36..4e0c3694cd 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.test.tsx @@ -20,8 +20,7 @@ import { ConfigReader, } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; -import { wrapInTestApp } from '@backstage/test-utils'; -import { act, render } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; import { CatalogImportApi, catalogImportApiRef } from '../../api'; import { ImportInfoCard } from './ImportInfoCard'; @@ -52,50 +51,38 @@ describe('', () => { new ConfigReader({ integrations: {} }), ).with(catalogImportApiRef, catalogImportApi); - await act(async () => { - const { getByText } = render( - wrapInTestApp( - - - , - ), - ); + const { getByText } = await renderInTestApp( + + + , + ); - expect(getByText('Register an existing component')).toBeInTheDocument(); - }); + expect(getByText('Register an existing component')).toBeInTheDocument(); }); it('renders section on GitHub discovery if supported', async () => { catalogImportApi.preparePullRequest = async () => ({ title: '', body: '' }); - await act(async () => { - const { getByText } = render( - wrapInTestApp( - - - , - ), - ); + const { getByText } = await renderInTestApp( + + + , + ); - expect(getByText(/The wizard discovers all/)).toBeInTheDocument(); - }); + expect(getByText(/The wizard discovers all/)).toBeInTheDocument(); }); it('renders section on pull requests if supported', async () => { catalogImportApi.preparePullRequest = async () => ({ title: '', body: '' }); - await act(async () => { - const { getByText } = render( - wrapInTestApp( - - - , - ), - ); + const { getByText } = await renderInTestApp( + + + , + ); - expect( - getByText(/the wizard will prepare a Pull Request/), - ).toBeInTheDocument(); - }); + expect( + getByText(/the wizard will prepare a Pull Request/), + ).toBeInTheDocument(); }); }); diff --git a/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx index 1e2182005e..fe3c3673f8 100644 --- a/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx +++ b/plugins/catalog-import/src/components/ImportPage/ImportPage.test.tsx @@ -22,8 +22,7 @@ import { } from '@backstage/core-app-api'; import { configApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { wrapInTestApp } from '@backstage/test-utils'; -import { act, render } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; import { useOutlet } from 'react-router'; import { catalogImportApiRef, CatalogImportClient } from '../../api'; @@ -76,34 +75,26 @@ describe('', () => { afterEach(() => jest.resetAllMocks()); it('renders without exploding', async () => { - await act(async () => { - const { getByText } = render( - wrapInTestApp( - - - , - ), - ); + const { getByText } = await renderInTestApp( + + + , + ); - expect( - getByText('Start tracking your component in Backstage'), - ).toBeInTheDocument(); - }); + expect( + getByText('Start tracking your component in Backstage'), + ).toBeInTheDocument(); }); it('renders with custom children', async () => { (useOutlet as jest.Mock).mockReturnValue(
Hello World
); - await act(async () => { - const { getByText } = render( - wrapInTestApp( - - - , - ), - ); + const { getByText } = await renderInTestApp( + + + , + ); - expect(getByText('Hello World')).toBeInTheDocument(); - }); + expect(getByText('Hello World')).toBeInTheDocument(); }); }); diff --git a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx index 9cc9532a3d..ec058dee62 100644 --- a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx +++ b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx @@ -14,15 +14,14 @@ * limitations under the License. */ +import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { errorApiRef } from '@backstage/core-plugin-api'; import { act, render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { AnalyzeResult, catalogImportApiRef } from '../../api/'; import { StepInitAnalyzeUrl } from './StepInitAnalyzeUrl'; -import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; -import { errorApiRef } from '@backstage/core-plugin-api'; - describe('', () => { const catalogImportApi: jest.Mocked = { analyzeUrl: jest.fn(), @@ -313,7 +312,7 @@ describe('', () => { ); await act(async () => { - await userEvent.type( + userEvent.type( getByRole('textbox', { name: /Repository/i }), 'https://my-repository-2', ); @@ -357,7 +356,7 @@ describe('', () => { ); await act(async () => { - await userEvent.type( + userEvent.type( getByRole('textbox', { name: /Repository/i }), 'https://my-repository-2', ); From a92ea2a110190ca098d390bbeedfb288f7d89b60 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Sep 2021 04:12:35 +0000 Subject: [PATCH 20/26] build(deps): bump isomorphic-git from 1.9.2 to 1.10.0 Bumps [isomorphic-git](https://github.com/isomorphic-git/isomorphic-git) from 1.9.2 to 1.10.0. - [Release notes](https://github.com/isomorphic-git/isomorphic-git/releases) - [Changelog](https://github.com/isomorphic-git/isomorphic-git/blob/main/docs/in-the-news.md) - [Commits](https://github.com/isomorphic-git/isomorphic-git/compare/v1.9.2...v1.10.0) --- updated-dependencies: - dependency-name: isomorphic-git dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index a0d4170cb2..0d0a6d460a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16626,9 +16626,9 @@ isomorphic-form-data@^2.0.0: form-data "^2.3.2" isomorphic-git@^1.8.0: - version "1.9.2" - resolved "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.9.2.tgz#0e492dbcd9873070b2a57eef257a45b90020ed72" - integrity sha512-puCXcGgtkDXdMYLZlAEGbpkbmHn/Q4Lsl2uMFwMLOKmmr8Qe7Fe3+c6k2+aHW3rMdJYg9xTv95BJ+PRzR8Ydww== + version "1.10.0" + resolved "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.10.0.tgz#59a4604d1190d1e7fc52172085da25e6a428bc07" + integrity sha512-CijspEYaOQAnsHWXyq8ICZXzLJ/1wYQAa0jdfLcugA/68oNzrxykjGZz8Up7B8huA1VfkFHm4VviExtj/zpViw== dependencies: async-lock "^1.1.0" clean-git-ref "^2.0.1" From aa34ee229ade778361aacbe2eda54eee32bf96b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Sep 2021 04:07:25 +0000 Subject: [PATCH 21/26] build(deps-dev): bump prettier from 2.4.0 to 2.4.1 in /microsite Bumps [prettier](https://github.com/prettier/prettier) from 2.4.0 to 2.4.1. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.4.0...2.4.1) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- microsite/package.json | 2 +- microsite/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/microsite/package.json b/microsite/package.json index b3048612a7..dafab893e2 100644 --- a/microsite/package.json +++ b/microsite/package.json @@ -19,7 +19,7 @@ "@spotify/prettier-config": "^11.0.0", "docusaurus": "^2.0.0-alpha.70", "js-yaml": "^4.1.0", - "prettier": "^2.4.0", + "prettier": "^2.4.1", "yarn-lock-check": "^1.0.5" }, "prettier": "@spotify/prettier-config" diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 2973f364b0..6dfdb022fb 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -5207,10 +5207,10 @@ prepend-http@^2.0.0: resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= -prettier@^2.4.0: - version "2.4.0" - resolved "https://registry.npmjs.org/prettier/-/prettier-2.4.0.tgz#85bdfe0f70c3e777cf13a4ffff39713ca6f64cba" - integrity sha512-DsEPLY1dE5HF3BxCRBmD4uYZ+5DCbvatnolqTqcxEgKVZnL2kUfyu7b8pPQ5+hTBkdhU9SLUmK0/pHb07RE4WQ== +prettier@^2.4.1: + version "2.4.1" + resolved "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz#671e11c89c14a4cfc876ce564106c4a6726c9f5c" + integrity sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA== prismjs@^1.22.0: version "1.23.0" From a8f8446859eb127342dee96e3b827f9d56a37049 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Fri, 17 Sep 2021 10:14:10 +0200 Subject: [PATCH 22/26] Fix build Signed-off-by: Oliver Sand --- .../components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx index ec058dee62..4a72a653ea 100644 --- a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx +++ b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.test.tsx @@ -312,7 +312,7 @@ describe('', () => { ); await act(async () => { - userEvent.type( + await userEvent.type( getByRole('textbox', { name: /Repository/i }), 'https://my-repository-2', ); @@ -356,7 +356,7 @@ describe('', () => { ); await act(async () => { - userEvent.type( + await userEvent.type( getByRole('textbox', { name: /Repository/i }), 'https://my-repository-2', ); From 9dd3ba66fc4000bfdf4c5f4662f14b8210effc65 Mon Sep 17 00:00:00 2001 From: "@pawelmitka" Date: Fri, 17 Sep 2021 13:19:47 +0200 Subject: [PATCH 23/26] chore: make package public Signed-off-by: @pawelmitka --- plugins/scaffolder-backend-module-yeoman/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index 195aac6fc1..eb339b90d5 100644 --- a/plugins/scaffolder-backend-module-yeoman/package.json +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -4,6 +4,7 @@ "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", + "private": false, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", From 28daaaa1ad4eea55a58c79cd6c9099c924e3ca80 Mon Sep 17 00:00:00 2001 From: "@pawelmitka" Date: Fri, 17 Sep 2021 13:27:15 +0200 Subject: [PATCH 24/26] fix: resolve yarn.lock conflict Signed-off-by: @pawelmitka --- yarn.lock | 101 +++++++++++++++++++++--------------------------------- 1 file changed, 39 insertions(+), 62 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4fa2b23e42..d6b4f819b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8416,9 +8416,9 @@ ansi-regex@^4.0.0, ansi-regex@^4.1.0: integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== ansi-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" - integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + version "5.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-regex@^6.0.1: version "6.0.1" @@ -9126,11 +9126,11 @@ axios-cached-dns-resolve@0.5.2: pino-pretty "^2.6.0" axios@^0.21.1: - version "0.21.1" - resolved "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" - integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== + version "0.21.4" + resolved "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== dependencies: - follow-redirects "^1.10.0" + follow-redirects "^1.14.0" axobject-query@^2.2.0: version "2.2.0" @@ -10554,15 +10554,6 @@ cli-width@^3.0.0: resolved "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== -clipboard@^2.0.0: - version "2.0.6" - resolved "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz#52921296eec0fdf77ead1749421b21c968647376" - integrity sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg== - dependencies: - good-listener "^1.2.2" - select "^1.1.2" - tiny-emitter "^2.0.0" - cliui@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" @@ -12084,11 +12075,16 @@ dateformat@^4.5.0: resolved "https://registry.npmjs.org/dateformat/-/dateformat-4.5.1.tgz#c20e7a9ca77d147906b6dc2261a8be0a5bd2173c" integrity sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q== -dayjs@^1.10.4, dayjs@^1.9.4: +dayjs@^1.10.4: version "1.10.4" resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2" integrity sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw== +dayjs@^1.9.4: + version "1.10.7" + resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz#2cf5f91add28116748440866a0a1d26f3a6ce468" + integrity sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig== + debounce@1.2.0, debounce@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" @@ -12295,11 +12291,6 @@ delayed-stream@~1.0.0: resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegate@^3.1.2: - version "3.2.0" - resolved "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" - integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== - delegates@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" @@ -14206,11 +14197,16 @@ fn.name@1.x.x: resolved "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.0.0, follow-redirects@^1.10.0: +follow-redirects@^1.0.0: version "1.13.0" resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== +follow-redirects@^1.14.0: + version "1.14.4" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379" + integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g== + for-in@^0.1.3: version "0.1.8" resolved "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1" @@ -14954,13 +14950,6 @@ globby@^9.2.0: pify "^4.0.1" slash "^2.0.0" -good-listener@^1.2.2: - version "1.2.2" - resolved "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" - integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA= - dependencies: - delegate "^3.1.2" - google-auth-library@^7.0.0, google-auth-library@^7.0.2: version "7.0.2" resolved "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.0.2.tgz#cab6fc7f94ebecc97be6133d6519d9946ccf3e9d" @@ -16126,9 +16115,9 @@ inquirer@^7.0.4, inquirer@^7.3.3: through "^2.3.6" inquirer@^8.0.0: - version "8.1.4" - resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.1.4.tgz#d5734392ecaabad3c276afc1e8ff3406089b9280" - integrity sha512-Wi0b5XDuPSlmdq7MBb89/x2DG/5ApMFrwS7Mook/4bqukKla0gFfVYYdl/2O1pU8AomLe000evbxDgy/pUEodg== + version "8.1.5" + resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.1.5.tgz#2dc5159203c826d654915b5fe6990fd17f54a150" + integrity sha512-G6/9xUqmt/r+UvufSyrPpt84NYwhKZ9jLsgMbQzlx804XErNupor8WQdBnBRrXmBfTPpuwf1sV+ss2ovjgdXIg== dependencies: ansi-escapes "^4.2.1" chalk "^4.1.1" @@ -16930,9 +16919,9 @@ isomorphic-form-data@^2.0.0: form-data "^2.3.2" isomorphic-git@^1.8.0: - version "1.9.2" - resolved "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.9.2.tgz#0e492dbcd9873070b2a57eef257a45b90020ed72" - integrity sha512-puCXcGgtkDXdMYLZlAEGbpkbmHn/Q4Lsl2uMFwMLOKmmr8Qe7Fe3+c6k2+aHW3rMdJYg9xTv95BJ+PRzR8Ydww== + version "1.10.0" + resolved "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.10.0.tgz#59a4604d1190d1e7fc52172085da25e6a428bc07" + integrity sha512-CijspEYaOQAnsHWXyq8ICZXzLJ/1wYQAa0jdfLcugA/68oNzrxykjGZz8Up7B8huA1VfkFHm4VviExtj/zpViw== dependencies: async-lock "^1.1.0" clean-git-ref "^2.0.1" @@ -22332,12 +22321,10 @@ printj@~1.1.0: resolved "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== -prismjs@^1.21.0, prismjs@^1.22.0, prismjs@~1.23.0: - version "1.23.0" - resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz#d3b3967f7d72440690497652a9d40ff046067f33" - integrity sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA== - optionalDependencies: - clipboard "^2.0.0" +prismjs@^1.21.0, prismjs@^1.22.0, prismjs@~1.24.0: + version "1.24.1" + resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.24.1.tgz#c4d7895c4d6500289482fa8936d9cdd192684036" + integrity sha512-mNPsedLuk90RVJioIky8ANZEwYm5w9LcvCXrxHlwf4fNVSn8jEipMybMkWUyyF0JhnC+C4VcOVSBuHRKs1L5Ow== private@^0.1.8: version "0.1.8" @@ -23604,13 +23591,13 @@ reflect-metadata@^0.1.13: integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== refractor@^3.1.0, refractor@^3.2.0: - version "3.3.1" - resolved "https://registry.npmjs.org/refractor/-/refractor-3.3.1.tgz#ebbc04b427ea81dc25ad333f7f67a0b5f4f0be3a" - integrity sha512-vaN6R56kLMuBszHSWlwTpcZ8KTMG6aUCok4GrxYDT20UIOXxOc5o6oDc8tNTzSlH3m2sI+Eu9Jo2kVdDcUTWYw== + version "3.4.0" + resolved "https://registry.npmjs.org/refractor/-/refractor-3.4.0.tgz#62bd274b06c942041f390c371b676eb67cb0a678" + integrity sha512-dBeD02lC5eytm9Gld2Mx0cMcnR+zhSnsTfPpWqFaMgUMJfC9A6bcN3Br/NaXrnBJcuxnLFR90k1jrkaSyV8umg== dependencies: hastscript "^6.0.0" parse-entities "^2.0.0" - prismjs "~1.23.0" + prismjs "~1.24.0" regenerate-unicode-properties@^8.2.0: version "8.2.0" @@ -24441,11 +24428,6 @@ select-hose@^2.0.0: resolved "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= -select@^1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" - integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= - selfsigned@^1.10.11: version "1.10.11" resolved "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz#24929cd906fe0f44b6d01fb23999a739537acbe9" @@ -24906,9 +24888,9 @@ socks-proxy-agent@^5.0.0: socks "^2.3.3" socks-proxy-agent@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.0.0.tgz#9f8749cdc05976505fa9f9a958b1818d0e60573b" - integrity sha512-FIgZbQWlnjVEQvMkylz64/rUggGtrKstPnx8OZyYFG0tAFR8CSBtpXxSwbFLHyeXFn/cunFL7MpuSOvDSOPo9g== + version "6.1.0" + resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.0.tgz#869cf2d7bd10fea96c7ad3111e81726855e285c3" + integrity sha512-57e7lwCN4Tzt3mXz25VxOErJKXlPfXmkMLnk310v/jwW20jWRVcgsOit+xNkN3eIEdB47GwnfAEBLacZ/wVIKg== dependencies: agent-base "^6.0.2" debug "^4.3.1" @@ -26320,11 +26302,6 @@ timsort@^0.3.0, timsort@~0.3.0: resolved "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= -tiny-emitter@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" - integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== - tiny-invariant@^1.0.6: version "1.1.0" resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" @@ -26369,9 +26346,9 @@ tmp@^0.2.0, tmp@~0.2.1: rimraf "^3.0.0" tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" - integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + version "1.0.5" + resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== to-arraybuffer@^1.0.0: version "1.0.1" From 69405e395929917b96897b816cca16ee9f333721 Mon Sep 17 00:00:00 2001 From: "@pawelmitka" Date: Fri, 17 Sep 2021 13:42:25 +0200 Subject: [PATCH 25/26] fix: yarn.lock conflict - approach 2 Signed-off-by: @pawelmitka --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index d6b4f819b9..aa9530a805 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6817,6 +6817,11 @@ resolved "https://registry.npmjs.org/@types/humanize-duration/-/humanize-duration-3.18.1.tgz#10090d596053703e7de0ac43a37b96cd9fc78309" integrity sha512-MUgbY3CF7hg/a/jogixmAufLjJBQT7WEf8Q+kYJkOc47ytngg1IuZobCngdTjAgY83JWEogippge5O5fplaQlw== +"@types/humanize-duration@^3.25.1": + version "3.25.1" + resolved "https://registry.npmjs.org/@types/humanize-duration/-/humanize-duration-3.25.1.tgz#b6140d5fc00ff3917b3f521784abef4bc0387ccc" + integrity sha512-WZU/4bb+lvzyDmZzjJtp++9mfKy6B3lH6gGISgkcz6SU8hMILKRM0vi08TxIsb0dQB4Gzo68MWLmctu6xqUi9g== + "@types/inquirer@^7.3.1": version "7.3.1" resolved "https://registry.npmjs.org/@types/inquirer/-/inquirer-7.3.1.tgz#1f231224e7df11ccfaf4cf9acbcc3b935fea292d" @@ -12080,11 +12085,6 @@ dayjs@^1.10.4: resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2" integrity sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw== -dayjs@^1.9.4: - version "1.10.7" - resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz#2cf5f91add28116748440866a0a1d26f3a6ce468" - integrity sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig== - debounce@1.2.0, debounce@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" @@ -15822,7 +15822,7 @@ human-signals@^2.1.0: resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -humanize-duration@^3.25.1, humanize-duration@^3.26.0: +humanize-duration@^3.25.1, humanize-duration@^3.26.0, humanize-duration@^3.27.0: version "3.27.0" resolved "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.27.0.tgz#3f781b7cf8022ad587f76b9839b60bc2b29636b2" integrity sha512-qLo/08cNc3Tb0uD7jK0jAcU5cnqCM0n568918E7R2XhMr/+7F37p4EY062W/stg7tmzvknNn9b/1+UhVRzsYrQ== From ff32e8aa46b2b9343ab6dbfb2590842c0c06f0ae Mon Sep 17 00:00:00 2001 From: Jeff Feng Date: Fri, 17 Sep 2021 09:24:38 -0400 Subject: [PATCH 26/26] Add beta label to TechDocs on homepage Adding a beta label and link to the TechDocs announcement post. Signed-off-by: Jeff Feng --- microsite/pages/en/index.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/microsite/pages/en/index.js b/microsite/pages/en/index.js index ec80bbc01f..56b6c122ae 100644 --- a/microsite/pages/en/index.js +++ b/microsite/pages/en/index.js @@ -306,7 +306,15 @@ class Index extends React.Component { src={`${baseUrl}animations/backstage-techdocs-icon-1.gif`} /> - Backstage TechDocs + + Backstage TechDocs{' '} + + (beta) + + Docs like code