From c8b295f2fbf92dc5a4350575c91c1350fd291787 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 11 Mar 2022 16:14:50 +0000 Subject: [PATCH 01/10] search-common: introduce SearchDocument type This type is a subset of `IndexableDocument`, and is intended to be used in place of `IndexableDocument` in the frontend. Signed-off-by: Mike Lewis --- .changeset/happy-mugs-camp.md | 7 ++++ plugins/search-common/api-report.md | 56 ++++++++++++++++++----------- plugins/search-common/src/types.ts | 43 +++++++++++++++++----- 3 files changed, 77 insertions(+), 29 deletions(-) create mode 100644 .changeset/happy-mugs-camp.md diff --git a/.changeset/happy-mugs-camp.md b/.changeset/happy-mugs-camp.md new file mode 100644 index 0000000000..22d13d80d1 --- /dev/null +++ b/.changeset/happy-mugs-camp.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-search-common': patch +--- + +- Introduce `SearchDocument` type. This type contains the subset of `IndexableDocument` properties relevant to the frontend, and is intended to be used for documents returned to the frontend from the search API. +- `SearchResultSet` is now a wrapper for documents of type `SearchDocument`, and is intended to be used in the frontend. This isn't a breaking change, since `IndexableDocument`s are valid `SearchDocument`s, so the old and new types are compatible. +- Introduce `IndexableResultSet` type, which wraps `IndexableDocument` instances in the same way as `SearchResultSet`. diff --git a/plugins/search-common/api-report.md b/plugins/search-common/api-report.md index 8ab25d5e42..6befd6d1ca 100644 --- a/plugins/search-common/api-report.md +++ b/plugins/search-common/api-report.md @@ -30,14 +30,17 @@ export type DocumentTypeInfo = { }; // @beta -export interface IndexableDocument { +export type IndexableDocument = SearchDocument & { authorization?: { resourceRef: string; }; - location: string; - text: string; - title: string; -} +}; + +// @beta (undocumented) +export type IndexableResult = Result; + +// @beta (undocumented) +export type IndexableResultSet = ResultSet; // @beta export type QueryRequestOptions = { @@ -47,13 +50,38 @@ export type QueryRequestOptions = { // @beta export type QueryTranslator = (query: SearchQuery) => unknown; +// @beta (undocumented) +export interface Result { + // (undocumented) + document: TDocument; + // (undocumented) + type: string; +} + +// @beta (undocumented) +export interface ResultSet { + // (undocumented) + nextPageCursor?: string; + // (undocumented) + previousPageCursor?: string; + // (undocumented) + results: Result[]; +} + +// @beta +export interface SearchDocument { + location: string; + text: string; + title: string; +} + // @beta export interface SearchEngine { getIndexer(type: string): Promise; query( query: SearchQuery, options?: QueryRequestOptions, - ): Promise; + ): Promise; setTranslator(translator: QueryTranslator): void; } @@ -70,20 +98,8 @@ export interface SearchQuery { } // @beta (undocumented) -export interface SearchResult { - // (undocumented) - document: IndexableDocument; - // (undocumented) - type: string; -} +export type SearchResult = Result; // @beta (undocumented) -export interface SearchResultSet { - // (undocumented) - nextPageCursor?: string; - // (undocumented) - previousPageCursor?: string; - // (undocumented) - results: SearchResult[]; -} +export type SearchResultSet = ResultSet; ``` diff --git a/plugins/search-common/src/types.ts b/plugins/search-common/src/types.ts index 51ce45617b..cf385cfa64 100644 --- a/plugins/search-common/src/types.ts +++ b/plugins/search-common/src/types.ts @@ -31,26 +31,45 @@ export interface SearchQuery { /** * @beta */ -export interface SearchResult { +export interface Result { type: string; - document: IndexableDocument; + document: TDocument; } /** * @beta */ -export interface SearchResultSet { - results: SearchResult[]; +export interface ResultSet { + results: Result[]; nextPageCursor?: string; previousPageCursor?: string; } /** - * Base properties that all indexed documents must include, as well as some - * common properties that documents are encouraged to use where appropriate. * @beta */ -export interface IndexableDocument { +export type SearchResult = Result; + +/** + * @beta + */ +export type SearchResultSet = ResultSet; + +/** + * @beta + */ +export type IndexableResult = Result; + +/** + * @beta + */ +export type IndexableResultSet = ResultSet; + +/** + * Base properties that all search documents must include. + * @beta + */ +export interface SearchDocument { /** * The primary name of the document (e.g. name, title, identifier, etc). */ @@ -66,7 +85,13 @@ export interface IndexableDocument { * is clicked). */ location: string; +} +/** + * Properties related to indexing of documents. + * @beta + */ +export type IndexableDocument = SearchDocument & { /** * Optional authorization information to be used when determining whether this * search result should be visible to a given user. @@ -77,7 +102,7 @@ export interface IndexableDocument { */ resourceRef: string; }; -} +}; /** * Information about a specific document type. Intended to be used in the @@ -178,5 +203,5 @@ export interface SearchEngine { query( query: SearchQuery, options?: QueryRequestOptions, - ): Promise; + ): Promise; } From 62ee65422cd20b13608c098c2c8eef0b66be2083 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 11 Mar 2022 18:23:54 +0000 Subject: [PATCH 02/10] elasticsearch: use new IndexableResultSet type as return type of engine#query Signed-off-by: Mike Lewis --- .changeset/light-drinks-rule.md | 5 +++++ plugins/search-backend-module-elasticsearch/api-report.md | 4 ++-- .../src/engines/ElasticSearchSearchEngine.ts | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 .changeset/light-drinks-rule.md diff --git a/.changeset/light-drinks-rule.md b/.changeset/light-drinks-rule.md new file mode 100644 index 0000000000..61849b514a --- /dev/null +++ b/.changeset/light-drinks-rule.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-module-elasticsearch': patch +--- + +Use new `IndexableResultSet` type as return type of engine#query. diff --git a/plugins/search-backend-module-elasticsearch/api-report.md b/plugins/search-backend-module-elasticsearch/api-report.md index 265fdda686..10231f3a83 100644 --- a/plugins/search-backend-module-elasticsearch/api-report.md +++ b/plugins/search-backend-module-elasticsearch/api-report.md @@ -10,10 +10,10 @@ import { Client } from '@elastic/elasticsearch'; import { Config } from '@backstage/config'; import type { ConnectionOptions } from 'tls'; import { IndexableDocument } from '@backstage/plugin-search-common'; +import { IndexableResultSet } from '@backstage/plugin-search-common'; import { Logger } from 'winston'; import { SearchEngine } from '@backstage/plugin-search-common'; import { SearchQuery } from '@backstage/plugin-search-common'; -import { SearchResultSet } from '@backstage/plugin-search-common'; // Warning: (ae-missing-release-tag) "ElasticSearchClientOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-search-backend-module-elasticsearch" does not have an export "ElasticSearchEngine" @@ -119,7 +119,7 @@ export class ElasticSearchSearchEngine implements SearchEngine { getIndexer(type: string): Promise; newClient(create: (options: ElasticSearchClientOptions) => T): T; // (undocumented) - query(query: SearchQuery): Promise; + query(query: SearchQuery): Promise; // Warning: (ae-forgotten-export) The symbol "ElasticSearchQueryTranslator" needs to be exported by the entry point index.d.ts // // (undocumented) diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts index f2ed5ed2b0..aec225a64b 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts @@ -21,9 +21,9 @@ import { import { Config } from '@backstage/config'; import { IndexableDocument, + IndexableResultSet, SearchEngine, SearchQuery, - SearchResultSet, } from '@backstage/plugin-search-common'; import { Client } from '@elastic/elasticsearch'; import esb from 'elastic-builder'; @@ -192,7 +192,7 @@ export class ElasticSearchSearchEngine implements SearchEngine { return indexer; } - async query(query: SearchQuery): Promise { + async query(query: SearchQuery): Promise { const { elasticSearchQuery, documentTypes, pageSize } = this.translator(query); const queryIndices = documentTypes From 234e91e2eda637a28da8e8dbd188653651135347 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 11 Mar 2022 18:29:02 +0000 Subject: [PATCH 03/10] search-module-pg: use new IndexableResultSet type as return type of engine#query Signed-off-by: Mike Lewis --- .changeset/light-drinks-rule.md | 1 + plugins/search-backend-module-pg/api-report.md | 4 ++-- .../src/PgSearchEngine/PgSearchEngine.ts | 7 +++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.changeset/light-drinks-rule.md b/.changeset/light-drinks-rule.md index 61849b514a..75eca35ad9 100644 --- a/.changeset/light-drinks-rule.md +++ b/.changeset/light-drinks-rule.md @@ -1,5 +1,6 @@ --- '@backstage/plugin-search-backend-module-elasticsearch': patch +'@backstage/plugin-search-backend-module-pg': patch --- Use new `IndexableResultSet` type as return type of engine#query. diff --git a/plugins/search-backend-module-pg/api-report.md b/plugins/search-backend-module-pg/api-report.md index 39847a4935..71ceac996e 100644 --- a/plugins/search-backend-module-pg/api-report.md +++ b/plugins/search-backend-module-pg/api-report.md @@ -5,11 +5,11 @@ ```ts import { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node'; import { IndexableDocument } from '@backstage/plugin-search-common'; +import { IndexableResultSet } from '@backstage/plugin-search-common'; import { Knex } from 'knex'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { SearchEngine } from '@backstage/plugin-search-backend-node'; import { SearchQuery } from '@backstage/plugin-search-common'; -import { SearchResultSet } from '@backstage/plugin-search-common'; // Warning: (ae-missing-release-tag) "ConcretePgSearchQuery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -88,7 +88,7 @@ export class PgSearchEngine implements SearchEngine { // (undocumented) getIndexer(type: string): Promise; // (undocumented) - query(query: SearchQuery): Promise; + query(query: SearchQuery): Promise; // (undocumented) setTranslator( translator: (query: SearchQuery) => ConcretePgSearchQuery, diff --git a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts index 8f75112837..ea363d8ea1 100644 --- a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts +++ b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts @@ -15,7 +15,10 @@ */ import { PluginDatabaseManager } from '@backstage/backend-common'; import { SearchEngine } from '@backstage/plugin-search-backend-node'; -import { SearchQuery, SearchResultSet } from '@backstage/plugin-search-common'; +import { + SearchQuery, + IndexableResultSet, +} from '@backstage/plugin-search-common'; import { PgSearchEngineIndexer } from './PgSearchEngineIndexer'; import { DatabaseDocumentStore, @@ -81,7 +84,7 @@ export class PgSearchEngine implements SearchEngine { }); } - async query(query: SearchQuery): Promise { + async query(query: SearchQuery): Promise { const { pgQuery, pageSize } = this.translator(query); const rows = await this.databaseStore.transaction(async tx => From d07ed471dcab452bd82ccf692daf1d3e3aa6c588 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 11 Mar 2022 18:31:40 +0000 Subject: [PATCH 04/10] search-backend-node: use new IndexableResultSet type as return type of engine#query Signed-off-by: Mike Lewis --- .changeset/light-drinks-rule.md | 3 ++- plugins/search-backend-node/api-report.md | 4 ++-- .../search-backend-node/src/engines/LunrSearchEngine.ts | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.changeset/light-drinks-rule.md b/.changeset/light-drinks-rule.md index 75eca35ad9..b83a14c986 100644 --- a/.changeset/light-drinks-rule.md +++ b/.changeset/light-drinks-rule.md @@ -1,6 +1,7 @@ --- +'@backstage/plugin-search-backend-node': patch '@backstage/plugin-search-backend-module-elasticsearch': patch '@backstage/plugin-search-backend-module-pg': patch --- -Use new `IndexableResultSet` type as return type of engine#query. +Use new `IndexableResultSet` type as return type of query method in `SearchEngine` implementation. diff --git a/plugins/search-backend-node/api-report.md b/plugins/search-backend-node/api-report.md index e4359eafac..ebc49df280 100644 --- a/plugins/search-backend-node/api-report.md +++ b/plugins/search-backend-node/api-report.md @@ -9,13 +9,13 @@ import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; import { DocumentDecoratorFactory } from '@backstage/plugin-search-common'; import { DocumentTypeInfo } from '@backstage/plugin-search-common'; import { IndexableDocument } from '@backstage/plugin-search-common'; +import { IndexableResultSet } from '@backstage/plugin-search-common'; import { Logger } from 'winston'; import { default as lunr_2 } from 'lunr'; import { QueryTranslator } from '@backstage/plugin-search-common'; import { Readable } from 'stream'; import { SearchEngine } from '@backstage/plugin-search-common'; import { SearchQuery } from '@backstage/plugin-search-common'; -import { SearchResultSet } from '@backstage/plugin-search-common'; import { Transform } from 'stream'; import { Writable } from 'stream'; @@ -87,7 +87,7 @@ export class LunrSearchEngine implements SearchEngine { // (undocumented) protected lunrIndices: Record; // (undocumented) - query(query: SearchQuery): Promise; + query(query: SearchQuery): Promise; // (undocumented) setTranslator(translator: LunrQueryTranslator): void; // (undocumented) diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts index b1d695ad1d..09e8729ba8 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts @@ -16,8 +16,8 @@ import { IndexableDocument, + IndexableResultSet, SearchQuery, - SearchResultSet, QueryTranslator, SearchEngine, } from '@backstage/plugin-search-common'; @@ -147,7 +147,7 @@ export class LunrSearchEngine implements SearchEngine { return indexer; } - async query(query: SearchQuery): Promise { + async query(query: SearchQuery): Promise { const { lunrQueryBuilder, documentTypes, pageSize } = this.translator( query, ) as ConcreteLunrQuery; @@ -196,8 +196,8 @@ export class LunrSearchEngine implements SearchEngine { ? encodePageCursor({ page: page - 1 }) : undefined; - // Translate results into SearchResultSet - const realResultSet: SearchResultSet = { + // Translate results into IndexableResultSet + const realResultSet: IndexableResultSet = { results: results.slice(offset, offset + pageSize).map(d => { return { type: d.type, document: this.docStore[d.result.ref] }; }), From a0fbae7aeb2081efde0e17640f58a6d50d50a2ac Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 11 Mar 2022 18:39:39 +0000 Subject: [PATCH 05/10] search-backend: use new IndexableResultSet type as return type of engine#query Signed-off-by: Mike Lewis --- .changeset/light-drinks-rule.md | 1 + .../src/service/AuthorizedSearchEngine.ts | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.changeset/light-drinks-rule.md b/.changeset/light-drinks-rule.md index b83a14c986..2b99f5988c 100644 --- a/.changeset/light-drinks-rule.md +++ b/.changeset/light-drinks-rule.md @@ -1,4 +1,5 @@ --- +'@backstage/plugin-search-backend': patch '@backstage/plugin-search-backend-node': patch '@backstage/plugin-search-backend-module-elasticsearch': patch '@backstage/plugin-search-backend-module-pg': patch diff --git a/plugins/search-backend/src/service/AuthorizedSearchEngine.ts b/plugins/search-backend/src/service/AuthorizedSearchEngine.ts index 2e65e18a84..2a5fc471f5 100644 --- a/plugins/search-backend/src/service/AuthorizedSearchEngine.ts +++ b/plugins/search-backend/src/service/AuthorizedSearchEngine.ts @@ -25,12 +25,12 @@ import { } from '@backstage/plugin-permission-common'; import { DocumentTypeInfo, + IndexableResult, + IndexableResultSet, QueryRequestOptions, QueryTranslator, SearchEngine, SearchQuery, - SearchResult, - SearchResultSet, } from '@backstage/plugin-search-common'; import { Config } from '@backstage/config'; import { InputError } from '@backstage/errors'; @@ -85,7 +85,7 @@ export class AuthorizedSearchEngine implements SearchEngine { async query( query: SearchQuery, options: QueryRequestOptions, - ): Promise { + ): Promise { const queryStartTime = Date.now(); const authorizer = new DataLoader( @@ -144,7 +144,7 @@ export class AuthorizedSearchEngine implements SearchEngine { const { page } = decodePageCursor(query.pageCursor); const targetResults = (page + 1) * this.pageSize; - let filteredResults: SearchResult[] = []; + let filteredResults: IndexableResult[] = []; let nextPageCursor: string | undefined; let latencyBudgetExhausted = false; @@ -183,7 +183,7 @@ export class AuthorizedSearchEngine implements SearchEngine { } private async filterResults( - results: SearchResult[], + results: IndexableResult[], typeDecisions: Record, authorizer: DataLoader, ) { From 94ccd772d4796008aff3d218b8ed77b4d1977ed6 Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 11 Mar 2022 18:57:09 +0000 Subject: [PATCH 06/10] search-backend: filter out authorization property in api responses Signed-off-by: Mike Lewis --- .changeset/empty-pens-invent.md | 5 ++ .../search-backend/src/service/router.test.ts | 54 +++++++++++++++++-- plugins/search-backend/src/service/router.ts | 14 ++++- 3 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 .changeset/empty-pens-invent.md diff --git a/.changeset/empty-pens-invent.md b/.changeset/empty-pens-invent.md new file mode 100644 index 0000000000..4f94028fc0 --- /dev/null +++ b/.changeset/empty-pens-invent.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend': patch +--- + +Filter out `authorization` property before returning API responses. diff --git a/plugins/search-backend/src/service/router.test.ts b/plugins/search-backend/src/service/router.test.ts index bdf46a240b..2efab91256 100644 --- a/plugins/search-backend/src/service/router.test.ts +++ b/plugins/search-backend/src/service/router.test.ts @@ -19,7 +19,6 @@ import { ConfigReader } from '@backstage/config'; import { PermissionAuthorizer } from '@backstage/plugin-permission-common'; import { IndexBuilder, - LunrSearchEngine, SearchEngine, } from '@backstage/plugin-search-backend-node'; import express from 'express'; @@ -39,8 +38,19 @@ describe('createRouter', () => { beforeAll(async () => { const logger = getVoidLogger(); - const searchEngine = new LunrSearchEngine({ logger }); - const indexBuilder = new IndexBuilder({ logger, searchEngine }); + mockSearchEngine = { + getIndexer: jest.fn(), + setTranslator: jest.fn(), + query: jest.fn().mockResolvedValue({ + results: [], + nextPageCursor: '', + previousPageCursor: '', + }), + }; + const indexBuilder = new IndexBuilder({ + logger, + searchEngine: mockSearchEngine, + }); const router = await createRouter({ engine: indexBuilder.getSearchEngine(), @@ -56,7 +66,7 @@ describe('createRouter', () => { }); beforeEach(() => { - jest.resetAllMocks(); + jest.clearAllMocks(); }); describe('GET /query', () => { @@ -101,6 +111,42 @@ describe('createRouter', () => { }); }); + it('removes backend-only properties from search documents', async () => { + mockSearchEngine.query.mockResolvedValue({ + results: [ + { + type: 'software-catalog', + document: { + text: 'foo', + title: 'bar baz', + location: '/catalog/default/component/example', + authorization: { + resourceRef: 'component:default/example', + }, + }, + }, + ], + nextPageCursor: '', + previousPageCursor: '', + }); + + const response = await request(app).get('/query'); + + expect(response.status).toEqual(200); + expect(response.body).toMatchObject({ + results: [ + { + type: 'software-catalog', + document: { + text: 'foo', + title: 'bar baz', + location: '/catalog/default/component/example', + }, + }, + ], + }); + }); + describe('search result filtering', () => { beforeAll(async () => { const logger = getVoidLogger(); diff --git a/plugins/search-backend/src/service/router.ts b/plugins/search-backend/src/service/router.ts index 92e4e5526f..ff91465cf4 100644 --- a/plugins/search-backend/src/service/router.ts +++ b/plugins/search-backend/src/service/router.ts @@ -26,6 +26,7 @@ import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-no import { PermissionAuthorizer } from '@backstage/plugin-permission-common'; import { DocumentTypeInfo, + IndexableResultSet, SearchResultSet, } from '@backstage/plugin-search-common'; import { SearchEngine } from '@backstage/plugin-search-backend-node'; @@ -89,6 +90,17 @@ export async function createRouter( }), }); + const toSearchResults = (resultSet: IndexableResultSet): SearchResultSet => ({ + ...resultSet, + results: resultSet.results.map(result => ({ + ...result, + document: { + ...result.document, + authorization: undefined, + }, + })), + }); + const router = Router(); router.get( '/query', @@ -116,7 +128,7 @@ export async function createRouter( try { const resultSet = await engine?.query(query, { token }); - res.send(filterResultSet(resultSet)); + res.send(filterResultSet(toSearchResults(resultSet))); } catch (err) { throw new Error( `There was a problem performing the search query. ${err}`, From 38e01f2f7040f26eb4aecc47728a0c9015d0abea Mon Sep 17 00:00:00 2001 From: Mike Lewis Date: Fri, 11 Mar 2022 18:59:18 +0000 Subject: [PATCH 07/10] search: switch to SearchDocument type in DefaultResultListItem props Signed-off-by: Mike Lewis --- .changeset/ninety-fishes-vanish.md | 5 +++++ plugins/search/api-report.md | 4 ++-- .../DefaultResultListItem/DefaultResultListItem.tsx | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 .changeset/ninety-fishes-vanish.md diff --git a/.changeset/ninety-fishes-vanish.md b/.changeset/ninety-fishes-vanish.md new file mode 100644 index 0000000000..b0d3ac370f --- /dev/null +++ b/.changeset/ninety-fishes-vanish.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Switch to `SearchDocument` type in `DefaultResultListItem` props diff --git a/plugins/search/api-report.md b/plugins/search/api-report.md index 0a277dab85..1bdd918802 100644 --- a/plugins/search/api-report.md +++ b/plugins/search/api-report.md @@ -9,13 +9,13 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { AsyncState } from 'react-use/lib/useAsync'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; -import { IndexableDocument } from '@backstage/plugin-search-common'; import { InputBaseProps } from '@material-ui/core'; import { JsonObject } from '@backstage/types'; import { default as React_2 } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; +import { SearchDocument } from '@backstage/plugin-search-common'; import { SearchQuery } from '@backstage/plugin-search-common'; import { SearchResult as SearchResult_2 } from '@backstage/plugin-search-common'; import { SearchResultSet } from '@backstage/plugin-search-common'; @@ -31,7 +31,7 @@ export const DefaultResultListItem: ({ }: { icon?: ReactNode; secondaryAction?: ReactNode; - result: IndexableDocument; + result: SearchDocument; lineClamp?: number | undefined; }) => JSX.Element; diff --git a/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.tsx b/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.tsx index d9fbfe315e..46045f91ee 100644 --- a/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.tsx +++ b/plugins/search/src/components/DefaultResultListItem/DefaultResultListItem.tsx @@ -15,7 +15,7 @@ */ import React, { ReactNode } from 'react'; -import { IndexableDocument } from '@backstage/plugin-search-common'; +import { SearchDocument } from '@backstage/plugin-search-common'; import { ListItem, ListItemIcon, @@ -29,7 +29,7 @@ import TextTruncate from 'react-text-truncate'; type Props = { icon?: ReactNode; secondaryAction?: ReactNode; - result: IndexableDocument; + result: SearchDocument; lineClamp?: number; }; From aab3bac7fca6d53b58ad109e4ef6dc019f04b345 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Tue, 15 Mar 2022 09:57:55 +0000 Subject: [PATCH 08/10] search-backend: switch to minor bump in changeset Signed-off-by: MT Lewis --- .changeset/empty-pens-invent.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/empty-pens-invent.md b/.changeset/empty-pens-invent.md index 4f94028fc0..d6937afc84 100644 --- a/.changeset/empty-pens-invent.md +++ b/.changeset/empty-pens-invent.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-search-backend': patch +'@backstage/plugin-search-backend': minor --- -Filter out `authorization` property before returning API responses. +**BREAKING**: The `authorization` property is no longer returned on search results when queried. Note: this will only result in a breaking change if you have custom code in your frontend that relies on the `authorization.resourceRef` property on documents. From a6d402200d21b82bd48e6e50169d06f312cb3815 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Tue, 15 Mar 2022 10:01:28 +0000 Subject: [PATCH 09/10] search-common: restrict allowed type parameters for Result and ResultSet Signed-off-by: MT Lewis --- plugins/search-common/api-report.md | 4 ++-- plugins/search-common/src/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/search-common/api-report.md b/plugins/search-common/api-report.md index 6befd6d1ca..bd5a56c5cc 100644 --- a/plugins/search-common/api-report.md +++ b/plugins/search-common/api-report.md @@ -51,7 +51,7 @@ export type QueryRequestOptions = { export type QueryTranslator = (query: SearchQuery) => unknown; // @beta (undocumented) -export interface Result { +export interface Result { // (undocumented) document: TDocument; // (undocumented) @@ -59,7 +59,7 @@ export interface Result { } // @beta (undocumented) -export interface ResultSet { +export interface ResultSet { // (undocumented) nextPageCursor?: string; // (undocumented) diff --git a/plugins/search-common/src/types.ts b/plugins/search-common/src/types.ts index cf385cfa64..21aed101f6 100644 --- a/plugins/search-common/src/types.ts +++ b/plugins/search-common/src/types.ts @@ -31,7 +31,7 @@ export interface SearchQuery { /** * @beta */ -export interface Result { +export interface Result { type: string; document: TDocument; } @@ -39,7 +39,7 @@ export interface Result { /** * @beta */ -export interface ResultSet { +export interface ResultSet { results: Result[]; nextPageCursor?: string; previousPageCursor?: string; From d48122a4390080c67f4045a46e7046ccfe77e97d Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Thu, 17 Mar 2022 16:00:26 +0000 Subject: [PATCH 10/10] search: discourage use of IndexableDocument in the frontend Signed-off-by: MT Lewis --- plugins/search-common/src/types.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/search-common/src/types.ts b/plugins/search-common/src/types.ts index 21aed101f6..4eedabeb71 100644 --- a/plugins/search-common/src/types.ts +++ b/plugins/search-common/src/types.ts @@ -88,7 +88,10 @@ export interface SearchDocument { } /** - * Properties related to indexing of documents. + * Properties related to indexing of documents. This type is only useful for + * backends working directly with documents being inserted or retrieved from + * search indexes. When dealing with documents in the frontend, use + * {@link SearchDocument}. * @beta */ export type IndexableDocument = SearchDocument & {