refactor(search-backend): use credential for authorized search engines

Signed-off-by: Camila Belo <camilaibs@gmail.com>
This commit is contained in:
Camila Belo
2024-02-20 14:14:30 +01:00
parent b7ce9dd933
commit 744c0cbf97
32 changed files with 308 additions and 95 deletions
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-search-backend-module-elasticsearch': patch
'@backstage/plugin-search-backend-module-pg': patch
---
Start importing `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` from the `@backstage/plugin-search-backend-node`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-search-common': patch
---
Deprecate `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` in favor of the types exported from `@backstage/plugin-search-backend-node`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-search-backend': patch
---
**BREAKING**: Update the router to use the new `auth` services. The router now requires a discovery service option to get credentials for the permission service.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-search-backend-node': patch
---
Exports `QueryTranslator`, `QueryRequestOptions` and `SearchEngine` types. These new types were extracted from the `@backstage/plugin-search-common` package and the `token` property was deprecated in favor of the a new credentials one.
-1
View File
@@ -72,7 +72,6 @@
"@backstage/plugin-search-backend-module-pg": "workspace:^",
"@backstage/plugin-search-backend-module-techdocs": "workspace:^",
"@backstage/plugin-search-backend-node": "workspace:^",
"@backstage/plugin-search-common": "workspace:^",
"@backstage/plugin-signals-backend": "workspace:^",
"@backstage/plugin-signals-node": "workspace:^",
"@backstage/plugin-tech-insights-backend": "workspace:^",
+2 -1
View File
@@ -23,9 +23,9 @@ import { ElasticSearchSearchEngine } from '@backstage/plugin-search-backend-modu
import { PgSearchEngine } from '@backstage/plugin-search-backend-module-pg';
import {
IndexBuilder,
SearchEngine,
LunrSearchEngine,
} from '@backstage/plugin-search-backend-node';
import { SearchEngine } from '@backstage/plugin-search-common';
import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-search-backend-module-techdocs';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
@@ -117,6 +117,7 @@ export default async function createPlugin(
return await createRouter({
engine: indexBuilder.getSearchEngine(),
types: indexBuilder.getDocumentTypes(),
discovery: env.discovery,
permissions: env.permissions,
config: env.config,
logger: env.logger,
@@ -60,6 +60,7 @@ export default async function createPlugin(
engine: indexBuilder.getSearchEngine(),
types: indexBuilder.getDocumentTypes(),
permissions: env.permissions,
discovery: env.discovery,
config: env.config,
logger: env.logger,
});
@@ -17,7 +17,7 @@ import { IndexableResultSet } from '@backstage/plugin-search-common';
import { Logger } from 'winston';
import { LoggerService } from '@backstage/backend-plugin-api';
import { Readable } from 'stream';
import { SearchEngine } from '@backstage/plugin-search-common';
import { SearchEngine } from '@backstage/plugin-search-backend-node';
import { SearchQuery } from '@backstage/plugin-search-common';
import { TransportRequestPromise } from '@opensearch-project/opensearch/lib/Transport';
import { TransportRequestPromise as TransportRequestPromise_2 } from '@elastic/elasticsearch/lib/Transport';
@@ -18,9 +18,9 @@ import {
IndexableDocument,
IndexableResult,
IndexableResultSet,
SearchEngine,
SearchQuery,
} from '@backstage/plugin-search-common';
import { SearchEngine } from '@backstage/plugin-search-backend-node';
import { isEmpty, isNumber, isNaN as nan } from 'lodash';
import { AwsSigv4Signer } from '@opensearch-project/opensearch/aws';
@@ -10,7 +10,7 @@ import { IndexableResultSet } from '@backstage/plugin-search-common';
import { Knex } from 'knex';
import { Logger } from 'winston';
import { PluginDatabaseManager } from '@backstage/backend-common';
import { SearchEngine } from '@backstage/plugin-search-common';
import { SearchEngine } from '@backstage/plugin-search-backend-node';
import { SearchQuery } from '@backstage/plugin-search-common';
// @public
@@ -15,7 +15,7 @@
*/
import { PluginDatabaseManager } from '@backstage/backend-common';
import { SearchEngine } from '@backstage/plugin-search-common';
import { SearchEngine } from '@backstage/plugin-search-backend-node';
import {
SearchQuery,
IndexableResultSet,
@@ -3,12 +3,39 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
/// <reference types="node" />
import { BackstageCredentials } from '@backstage/backend-plugin-api';
import { DocumentTypeInfo } from '@backstage/plugin-search-common';
import { ExtensionPoint } from '@backstage/backend-plugin-api';
import { IndexableResultSet } from '@backstage/plugin-search-common';
import { RegisterCollatorParameters } from '@backstage/plugin-search-backend-node';
import { RegisterDecoratorParameters } from '@backstage/plugin-search-backend-node';
import { SearchEngine } from '@backstage/plugin-search-common';
import { SearchQuery } from '@backstage/plugin-search-common';
import { ServiceRef } from '@backstage/backend-plugin-api';
import { Writable } from 'stream';
// @public
export type QueryRequestOptions =
| {
token?: string;
}
| {
credentials: BackstageCredentials;
};
// @public
export type QueryTranslator = (query: SearchQuery) => unknown;
// @public
export interface SearchEngine {
getIndexer(type: string): Promise<Writable>;
query(
query: SearchQuery,
options?: QueryRequestOptions,
): Promise<IndexableResultSet>;
setTranslator(translator: QueryTranslator): void;
}
// @alpha
export interface SearchEngineRegistryExtensionPoint {
+23 -2
View File
@@ -5,6 +5,7 @@
```ts
/// <reference types="node" />
import { BackstageCredentials } from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';
import { DocumentCollatorFactory } from '@backstage/plugin-search-common';
import { DocumentDecoratorFactory } from '@backstage/plugin-search-common';
@@ -14,9 +15,7 @@ import { IndexableResultSet } from '@backstage/plugin-search-common';
import { Logger } from 'winston';
import { default as lunr_2 } from 'lunr';
import { Permission } from '@backstage/plugin-permission-common';
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 { TaskFunction } from '@backstage/backend-tasks';
import { TaskRunner } from '@backstage/backend-tasks';
@@ -144,6 +143,18 @@ export type NewlineDelimitedJsonCollatorFactoryOptions = {
visibilityPermission?: Permission;
};
// @public
export type QueryRequestOptions =
| {
token?: string;
}
| {
credentials: BackstageCredentials;
};
// @public
export type QueryTranslator = (query: SearchQuery) => unknown;
// @public
export interface RegisterCollatorParameters {
factory: DocumentCollatorFactory;
@@ -170,6 +181,16 @@ export type ScheduleTaskParameters = {
scheduledRunner: TaskRunner;
};
// @public
export interface SearchEngine {
getIndexer(type: string): Promise<Writable>;
query(
query: SearchQuery,
options?: QueryRequestOptions,
): Promise<IndexableResultSet>;
setTranslator(translator: QueryTranslator): void;
}
// @public
export class TestPipeline {
execute(): Promise<TestPipelineResult>;
@@ -19,11 +19,10 @@ import { TaskInvocationDefinition, TaskRunner } from '@backstage/backend-tasks';
import {
DocumentCollatorFactory,
DocumentDecoratorFactory,
SearchEngine,
} from '@backstage/plugin-search-common';
import { Readable, Transform } from 'stream';
import { IndexBuilder } from './IndexBuilder';
import { LunrSearchEngine } from './index';
import { LunrSearchEngine, SearchEngine } from './index';
class TestDocumentCollatorFactory implements DocumentCollatorFactory {
readonly type: string = 'anything';
@@ -17,12 +17,12 @@
import {
DocumentDecoratorFactory,
DocumentTypeInfo,
SearchEngine,
} from '@backstage/plugin-search-common';
import { Transform, pipeline } from 'stream';
import { Logger } from 'winston';
import { Scheduler } from './Scheduler';
import {
SearchEngine,
IndexBuilderOptions,
RegisterCollatorParameters,
RegisterDecoratorParameters,
+8 -4
View File
@@ -22,10 +22,7 @@ import {
coreServices,
} from '@backstage/backend-plugin-api';
import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
DocumentTypeInfo,
SearchEngine,
} from '@backstage/plugin-search-common';
import { DocumentTypeInfo } from '@backstage/plugin-search-common';
import { createExtensionPoint } from '@backstage/backend-plugin-api';
import {
@@ -33,8 +30,15 @@ import {
RegisterDecoratorParameters,
} from '@backstage/plugin-search-backend-node';
import { SearchEngine } from './types';
import { IndexBuilder } from './IndexBuilder';
export type {
SearchEngine,
QueryRequestOptions,
QueryTranslator,
} from './types';
/**
* @alpha
* Options for build method on {@link SearchIndexService}.
@@ -16,10 +16,7 @@
import { getVoidLogger } from '@backstage/backend-common';
import lunr from 'lunr';
import {
IndexableDocument,
SearchEngine,
} from '@backstage/plugin-search-common';
import { IndexableDocument } from '@backstage/plugin-search-common';
import {
ConcreteLunrQuery,
LunrSearchEngine,
@@ -28,6 +25,7 @@ import {
parseHighlightFields,
} from './LunrSearchEngine';
import { LunrSearchEngineIndexer } from './LunrSearchEngineIndexer';
import { SearchEngine } from '../types';
import { TestPipeline } from '../test-utils';
/**
@@ -18,9 +18,8 @@ import {
IndexableDocument,
IndexableResultSet,
SearchQuery,
QueryTranslator,
SearchEngine,
} from '@backstage/plugin-search-common';
import { SearchEngine, QueryTranslator } from '../types';
import { MissingIndexError } from '../errors';
import lunr from 'lunr';
import { v4 as uuid } from 'uuid';
+3
View File
@@ -33,6 +33,9 @@ export type {
IndexBuilderOptions,
RegisterCollatorParameters,
RegisterDecoratorParameters,
SearchEngine,
QueryRequestOptions,
QueryTranslator,
} from './types';
export * from './errors';
export * from './indexing';
+56 -1
View File
@@ -14,12 +14,15 @@
* limitations under the License.
*/
import { BackstageCredentials } from '@backstage/backend-plugin-api';
import { TaskRunner } from '@backstage/backend-tasks';
import {
DocumentCollatorFactory,
DocumentDecoratorFactory,
SearchEngine,
IndexableResultSet,
SearchQuery,
} from '@backstage/plugin-search-common';
import { Writable } from 'stream';
import { Logger } from 'winston';
/**
@@ -57,3 +60,55 @@ export interface RegisterDecoratorParameters {
*/
factory: DocumentDecoratorFactory;
}
/**
* A type of function responsible for translating an abstract search query into
* a concrete query relevant to a particular search engine.
* @public
*/
export type QueryTranslator = (query: SearchQuery) => unknown;
/**
* Options when querying a search engine.
* @public
*/
export type QueryRequestOptions =
| {
/** @deprecated use the `credentials` option instead. */
token?: string;
}
| {
credentials: BackstageCredentials;
};
/**
* Interface that must be implemented by specific search engines, responsible
* for performing indexing and querying and translating abstract queries into
* concrete, search engine-specific queries.
* @public
*/
export interface SearchEngine {
/**
* Override the default translator provided by the SearchEngine.
*/
setTranslator(translator: QueryTranslator): void;
/**
* Factory method for getting a search engine indexer for a given document
* type.
*
* @param type - The type or name of the document set for which an indexer
* should be retrieved. This corresponds to the `type` property on the
* document collator/decorator factories and will most often be used to
* identify an index or group to which documents should be written.
*/
getIndexer(type: string): Promise<Writable>;
/**
* Perform a search query against the SearchEngine.
*/
query(
query: SearchQuery,
options?: QueryRequestOptions,
): Promise<IndexableResultSet>;
}
+7 -1
View File
@@ -3,13 +3,16 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { AuthService } from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';
import { DiscoveryService } from '@backstage/backend-plugin-api';
import { DocumentTypeInfo } from '@backstage/plugin-search-common';
import express from 'express';
import { HttpAuthService } from '@backstage/backend-plugin-api';
import { Logger } from 'winston';
import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
import { SearchEngine } from '@backstage/plugin-search-common';
import { SearchEngine } from '@backstage/plugin-search-backend-node';
// @public (undocumented)
export function createRouter(options: RouterOptions): Promise<express.Router>;
@@ -18,8 +21,11 @@ export function createRouter(options: RouterOptions): Promise<express.Router>;
export type RouterOptions = {
engine: SearchEngine;
types: Record<string, DocumentTypeInfo>;
discovery: DiscoveryService;
permissions: PermissionEvaluator | PermissionAuthorizer;
config: Config;
logger: Logger;
auth?: AuthService;
httpAuth?: HttpAuthService;
};
```
+17 -2
View File
@@ -22,6 +22,7 @@ import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
RegisterCollatorParameters,
RegisterDecoratorParameters,
SearchEngine,
LunrSearchEngine,
} from '@backstage/plugin-search-backend-node';
import {
@@ -33,7 +34,6 @@ import {
} from '@backstage/plugin-search-backend-node/alpha';
import { createRouter } from './service/router';
import { SearchEngine } from '@backstage/plugin-search-common';
class SearchIndexRegistry implements SearchIndexRegistryExtensionPoint {
private collators: RegisterCollatorParameters[] = [];
@@ -94,11 +94,23 @@ export default createBackendPlugin({
deps: {
logger: coreServices.logger,
config: coreServices.rootConfig,
discovery: coreServices.discovery,
permissions: coreServices.permissions,
auth: coreServices.auth,
http: coreServices.httpRouter,
httpAuth: coreServices.httpAuth,
searchIndexService: searchIndexServiceRef,
},
async init({ config, logger, permissions, http, searchIndexService }) {
async init({
config,
logger,
discovery,
permissions,
auth,
http,
httpAuth,
searchIndexService,
}) {
let searchEngine = searchEngineRegistry.getSearchEngine();
if (!searchEngine) {
searchEngine = new LunrSearchEngine({
@@ -117,7 +129,10 @@ export default createBackendPlugin({
const router = await createRouter({
config,
discovery,
permissions,
auth,
httpAuth,
logger: loggerToWinstonLogger(logger),
engine: searchEngine,
types: searchIndexService.getDocumentTypes(),
@@ -25,8 +25,8 @@ import {
import {
DocumentTypeInfo,
IndexableDocument,
SearchEngine,
} from '@backstage/plugin-search-common';
import { SearchEngine } from '@backstage/plugin-search-backend-node';
import {
encodePageCursor,
decodePageCursor,
@@ -23,21 +23,23 @@ import {
EvaluatePermissionRequest,
EvaluatePermissionResponse,
isResourcePermission,
PermissionEvaluator,
QueryPermissionRequest,
} from '@backstage/plugin-permission-common';
import {
DocumentTypeInfo,
IndexableResult,
IndexableResultSet,
SearchQuery,
} from '@backstage/plugin-search-common';
import {
QueryRequestOptions,
QueryTranslator,
SearchEngine,
SearchQuery,
} from '@backstage/plugin-search-common';
} from '@backstage/plugin-search-backend-node';
import { Config } from '@backstage/config';
import { InputError } from '@backstage/errors';
import { Writable } from 'stream';
import { PermissionsService } from '@backstage/backend-plugin-api';
export function decodePageCursor(pageCursor?: string): { page: number } {
if (!pageCursor) {
@@ -68,7 +70,7 @@ export class AuthorizedSearchEngine implements SearchEngine {
constructor(
private readonly searchEngine: SearchEngine,
private readonly types: Record<string, DocumentTypeInfo>,
private readonly permissions: PermissionEvaluator,
private readonly permissions: PermissionsService,
config: Config,
) {
this.queryLatencyBudgetMs =
@@ -14,16 +14,22 @@
* limitations under the License.
*/
import { getVoidLogger } from '@backstage/backend-common';
import {
PluginEndpointDiscovery,
getVoidLogger,
} from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
import { IndexBuilder } from '@backstage/plugin-search-backend-node';
import { SearchEngine } from '@backstage/plugin-search-common';
import {
IndexBuilder,
SearchEngine,
} from '@backstage/plugin-search-backend-node';
import express from 'express';
import request from 'supertest';
import { createRouter } from './router';
import { wrapInOpenApiTestServer } from '@backstage/backend-openapi-utils';
import { Server } from 'http';
import { mockCredentials, mockServices } from '@backstage/backend-test-utils';
const mockPermissionEvaluator: PermissionEvaluator = {
authorize: () => {
@@ -38,6 +44,16 @@ describe('createRouter', () => {
let app: express.Express | Server;
let mockSearchEngine: jest.Mocked<SearchEngine>;
const mockBaseUrl = 'http://backstage:9191/api/proxy';
const discovery: PluginEndpointDiscovery = {
async getBaseUrl() {
return mockBaseUrl;
},
async getExternalBaseUrl() {
return mockBaseUrl;
},
};
beforeAll(async () => {
const logger = getVoidLogger();
mockSearchEngine = {
@@ -65,7 +81,10 @@ describe('createRouter', () => {
search: { maxPageLimit: 200, maxTermLength: 20 },
}),
permissions: mockPermissionEvaluator,
discovery,
logger,
auth: mockServices.auth(),
httpAuth: mockServices.httpAuth(),
});
app = wrapInOpenApiTestServer(express().use(router));
});
@@ -227,7 +246,11 @@ describe('createRouter', () => {
unknownKey2: 'unknownValue1',
};
const secondArg = {
token: undefined,
credentials: mockCredentials.user(),
token: mockCredentials.service.token({
onBehalfOf: mockCredentials.user(),
targetPluginId: 'search',
}),
};
expect(response.status).toEqual(200);
expect(mockSearchEngine.query).toHaveBeenCalledWith(firstArg, secondArg);
@@ -251,6 +274,7 @@ describe('createRouter', () => {
types: indexBuilder.getDocumentTypes(),
config: new ConfigReader({ permissions: { enabled: false } }),
permissions: mockPermissionEvaluator,
discovery,
logger,
});
app = express().use(router);
+24 -8
View File
@@ -17,11 +17,13 @@
import express from 'express';
import { Logger } from 'winston';
import { z } from 'zod';
import { errorHandler } from '@backstage/backend-common';
import {
createLegacyAuthAdapters,
errorHandler,
} from '@backstage/backend-common';
import { InputError } from '@backstage/errors';
import { Config } from '@backstage/config';
import { JsonObject, JsonValue } from '@backstage/types';
import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';
import {
PermissionAuthorizer,
PermissionEvaluator,
@@ -32,9 +34,14 @@ import {
IndexableResultSet,
SearchResultSet,
} from '@backstage/plugin-search-common';
import { SearchEngine } from '@backstage/plugin-search-common';
import { SearchEngine } from '@backstage/plugin-search-backend-node';
import { AuthorizedSearchEngine } from './AuthorizedSearchEngine';
import { createOpenApiRouter } from '../schema/openapi.generated';
import {
AuthService,
DiscoveryService,
HttpAuthService,
} from '@backstage/backend-plugin-api';
const jsonObjectSchema: z.ZodSchema<JsonObject> = z.lazy(() => {
const jsonValueSchema: z.ZodSchema<JsonValue> = z.lazy(() =>
@@ -57,9 +64,12 @@ const jsonObjectSchema: z.ZodSchema<JsonObject> = z.lazy(() => {
export type RouterOptions = {
engine: SearchEngine;
types: Record<string, DocumentTypeInfo>;
discovery: DiscoveryService;
permissions: PermissionEvaluator | PermissionAuthorizer;
config: Config;
logger: Logger;
auth?: AuthService;
httpAuth?: HttpAuthService;
};
const defaultMaxPageLimit = 100;
@@ -75,6 +85,8 @@ export async function createRouter(
const router = await createOpenApiRouter();
const { engine: inputEngine, types, permissions, config, logger } = options;
const { auth, httpAuth } = createLegacyAuthAdapters(options);
const maxPageLimit =
config.getOptionalNumber('search.maxPageLimit') ?? defaultMaxPageLimit;
@@ -169,12 +181,16 @@ export async function createRouter(
}`,
);
const token = getBearerTokenFromAuthorizationHeader(
req.header('authorization'),
);
try {
const resultSet = await engine?.query(query, { token });
const credentials = await httpAuth.credentials(req);
const { token } = await auth.getPluginRequestToken({
onBehalfOf: credentials,
targetPluginId: 'search',
});
const resultSet = await engine?.query(query, {
token,
credentials,
});
res.json(filterResultSet(toSearchResults(resultSet)));
} catch (error) {
@@ -57,6 +57,7 @@ export async function startStandaloneServer(
const router = await createRouter({
engine: indexBuilder.getSearchEngine(),
types: indexBuilder.getDocumentTypes(),
discovery,
permissions,
config,
logger,
+3 -3
View File
@@ -42,12 +42,12 @@ export type IndexableResult = Result<IndexableDocument>;
// @public (undocumented)
export type IndexableResultSet = ResultSet<IndexableDocument>;
// @public
// @public @deprecated
export type QueryRequestOptions = {
token?: string;
};
// @public
// @public @deprecated
export type QueryTranslator = (query: SearchQuery) => unknown;
// @public (undocumented)
@@ -87,7 +87,7 @@ export interface SearchDocument {
title: string;
}
// @public
// @public @deprecated
export interface SearchEngine {
getIndexer(type: string): Promise<Writable>;
query(
+68
View File
@@ -0,0 +1,68 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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 { Writable } from 'stream';
import { SearchQuery, IndexableResultSet } from './types';
/**
* A type of function responsible for translating an abstract search query into
* a concrete query relevant to a particular search engine.
* @public
* @deprecated Import from `@backstage/plugin-search-backend-node` instead
*/
export type QueryTranslator = (query: SearchQuery) => unknown;
/**
* Options when querying a search engine.
* @public
* @deprecated Import from `@backstage/plugin-search-backend-node` instead
*/
export type QueryRequestOptions = {
token?: string;
};
/**
* Interface that must be implemented by specific search engines, responsible
* for performing indexing and querying and translating abstract queries into
* concrete, search engine-specific queries.
* @public
* @deprecated Import from `@backstage/plugin-search-backend-node` instead
*/
export interface SearchEngine {
/**
* Override the default translator provided by the SearchEngine.
*/
setTranslator(translator: QueryTranslator): void;
/**
* Factory method for getting a search engine indexer for a given document
* type.
*
* @param type - The type or name of the document set for which an indexer
* should be retrieved. This corresponds to the `type` property on the
* document collator/decorator factories and will most often be used to
* identify an index or group to which documents should be written.
*/
getIndexer(type: string): Promise<Writable>;
/**
* Perform a search query against the SearchEngine.
*/
query(
query: SearchQuery,
options?: QueryRequestOptions,
): Promise<IndexableResultSet>;
}
+1
View File
@@ -21,3 +21,4 @@
*/
export * from './types';
export * from './deprecated';
+1 -48
View File
@@ -16,7 +16,7 @@
import { Permission } from '@backstage/plugin-permission-common';
import { JsonObject } from '@backstage/types';
import { Readable, Transform, Writable } from 'stream';
import { Readable, Transform } from 'stream';
/**
* @public
@@ -206,50 +206,3 @@ export interface DocumentDecoratorFactory {
*/
getDecorator(): Promise<Transform>;
}
/**
* A type of function responsible for translating an abstract search query into
* a concrete query relevant to a particular search engine.
* @public
*/
export type QueryTranslator = (query: SearchQuery) => unknown;
/**
* Options when querying a search engine.
* @public
*/
export type QueryRequestOptions = {
token?: string;
};
/**
* Interface that must be implemented by specific search engines, responsible
* for performing indexing and querying and translating abstract queries into
* concrete, search engine-specific queries.
* @public
*/
export interface SearchEngine {
/**
* Override the default translator provided by the SearchEngine.
*/
setTranslator(translator: QueryTranslator): void;
/**
* Factory method for getting a search engine indexer for a given document
* type.
*
* @param type - The type or name of the document set for which an indexer
* should be retrieved. This corresponds to the `type` property on the
* document collator/decorator factories and will most often be used to
* identify an index or group to which documents should be written.
*/
getIndexer(type: string): Promise<Writable>;
/**
* Perform a search query against the SearchEngine.
*/
query(
query: SearchQuery,
options?: QueryRequestOptions,
): Promise<IndexableResultSet>;
}
-1
View File
@@ -27469,7 +27469,6 @@ __metadata:
"@backstage/plugin-search-backend-module-pg": "workspace:^"
"@backstage/plugin-search-backend-module-techdocs": "workspace:^"
"@backstage/plugin-search-backend-node": "workspace:^"
"@backstage/plugin-search-common": "workspace:^"
"@backstage/plugin-signals-backend": "workspace:^"
"@backstage/plugin-signals-node": "workspace:^"
"@backstage/plugin-tech-insights-backend": "workspace:^"