@backstage/plugin-search-backend-module-elasticsearch 1.6.6-next.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @backstage/plugin-search-backend-module-elasticsearch
|
|
2
2
|
|
|
3
|
+
## 1.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5f66007: Add the option to configure the fuzziness of the elasticsearch results by defining the fuzziness and `prefix_length` property.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 37e5386: Allow `indexPrefix` configuration through the `app-config.yaml`
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
- @backstage/integration-aws-node@0.1.15
|
|
14
|
+
- @backstage/backend-plugin-api@1.2.1
|
|
15
|
+
- @backstage/config@1.3.2
|
|
16
|
+
- @backstage/plugin-search-backend-node@1.3.9
|
|
17
|
+
- @backstage/plugin-search-common@1.2.17
|
|
18
|
+
|
|
3
19
|
## 1.6.6-next.1
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/config.d.ts
CHANGED
|
@@ -47,6 +47,26 @@ export interface Config {
|
|
|
47
47
|
*/
|
|
48
48
|
fragmentDelimiter?: string;
|
|
49
49
|
};
|
|
50
|
+
queryOptions?: {
|
|
51
|
+
/**
|
|
52
|
+
* Fuzziness allows you to define the maximum Levenshtein distance for fuzzy queries,
|
|
53
|
+
* which determines how many single-character edits (insertions, deletions, substitutions)
|
|
54
|
+
* are allowed for a term to be considered a match.
|
|
55
|
+
*
|
|
56
|
+
* - 'AUTO': Automatically determines the fuzziness level based on the length of the term.
|
|
57
|
+
* This is the default and widely accepted standard.
|
|
58
|
+
* - number: Specifies a fixed fuzziness level. For example, a value of 1 allows for one edit.
|
|
59
|
+
*
|
|
60
|
+
* Example:
|
|
61
|
+
* - For a term "apple" with fuzziness set to 1, queries like "aple" or "apply" would match.
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
fuzziness?: 'AUTO' | number;
|
|
65
|
+
/**
|
|
66
|
+
* Minimum number of characters that must match exactly at the beginning of the qeury. Defaults to 0.
|
|
67
|
+
*/
|
|
68
|
+
prefixLength?: number;
|
|
69
|
+
};
|
|
50
70
|
|
|
51
71
|
/** Elasticsearch specific index template bodies */
|
|
52
72
|
indexTemplates?: Array<{
|
|
@@ -19,7 +19,7 @@ function isBlank(str) {
|
|
|
19
19
|
}
|
|
20
20
|
const DEFAULT_INDEXER_BATCH_SIZE = 1e3;
|
|
21
21
|
class ElasticSearchSearchEngine {
|
|
22
|
-
constructor(elasticSearchClientOptions, aliasPostfix, indexPrefix, logger, batchSize, highlightOptions) {
|
|
22
|
+
constructor(elasticSearchClientOptions, aliasPostfix, indexPrefix, logger, batchSize, highlightOptions, queryOptions) {
|
|
23
23
|
this.elasticSearchClientOptions = elasticSearchClientOptions;
|
|
24
24
|
this.aliasPostfix = aliasPostfix;
|
|
25
25
|
this.indexPrefix = indexPrefix;
|
|
@@ -35,9 +35,11 @@ class ElasticSearchSearchEngine {
|
|
|
35
35
|
fragmentDelimiter: " ... ",
|
|
36
36
|
...highlightOptions
|
|
37
37
|
};
|
|
38
|
+
this.queryOptions = queryOptions;
|
|
38
39
|
}
|
|
39
40
|
elasticSearchClientWrapper;
|
|
40
41
|
highlightOptions;
|
|
42
|
+
queryOptions;
|
|
41
43
|
static async fromConfig(options) {
|
|
42
44
|
const {
|
|
43
45
|
logger,
|
|
@@ -134,11 +136,11 @@ class ElasticSearchSearchEngine {
|
|
|
134
136
|
esbQueries.push(esbPhraseQuery);
|
|
135
137
|
}
|
|
136
138
|
if (restTerm?.length > 0) {
|
|
137
|
-
const esbRestQuery = esb__default.default.multiMatchQuery(["*"], restTerm.trim()).fuzziness("auto");
|
|
139
|
+
const esbRestQuery = esb__default.default.multiMatchQuery(["*"], restTerm.trim()).fuzziness(options?.queryOptions?.fuzziness ?? "auto").prefixLength(options?.queryOptions?.prefixLength ?? 0);
|
|
138
140
|
esbQueries.push(esbRestQuery);
|
|
139
141
|
}
|
|
140
142
|
} else {
|
|
141
|
-
const esbQuery = esb__default.default.multiMatchQuery(["*"], term).fuzziness("auto");
|
|
143
|
+
const esbQuery = esb__default.default.multiMatchQuery(["*"], term).fuzziness(options?.queryOptions?.fuzziness ?? "auto").prefixLength(options?.queryOptions?.prefixLength ?? 0);
|
|
142
144
|
esbQueries.push(esbQuery);
|
|
143
145
|
}
|
|
144
146
|
const pageSize = query.pageLimit || 25;
|
|
@@ -216,7 +218,10 @@ class ElasticSearchSearchEngine {
|
|
|
216
218
|
async query(query) {
|
|
217
219
|
const { elasticSearchQuery, documentTypes, pageSize } = this.translator(
|
|
218
220
|
query,
|
|
219
|
-
{
|
|
221
|
+
{
|
|
222
|
+
highlightOptions: this.highlightOptions,
|
|
223
|
+
queryOptions: this.queryOptions
|
|
224
|
+
}
|
|
220
225
|
);
|
|
221
226
|
const queryIndices = documentTypes ? documentTypes.map((it) => this.constructSearchAlias(it)) : this.constructSearchAlias("*");
|
|
222
227
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElasticSearchSearchEngine.cjs.js","sources":["../../src/engines/ElasticSearchSearchEngine.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n IndexableDocument,\n IndexableResult,\n IndexableResultSet,\n SearchQuery,\n} from '@backstage/plugin-search-common';\nimport { SearchEngine } from '@backstage/plugin-search-backend-node';\nimport { isEmpty, isNumber, isNaN as nan } from 'lodash';\n\nimport { AwsSigv4Signer } from '@opensearch-project/opensearch/aws';\nimport { RequestSigner } from 'aws4';\nimport { Config } from '@backstage/config';\nimport {\n ElasticSearchClientOptions,\n OpenSearchElasticSearchClientOptions,\n} from './ElasticSearchClientOptions';\nimport { ElasticSearchClientWrapper } from './ElasticSearchClientWrapper';\nimport { ElasticSearchCustomIndexTemplate } from './types';\nimport { ElasticSearchSearchEngineIndexer } from './ElasticSearchSearchEngineIndexer';\nimport { MissingIndexError } from '@backstage/plugin-search-backend-node';\nimport esb from 'elastic-builder';\nimport { v4 as uuid } from 'uuid';\nimport {\n AwsCredentialProvider,\n DefaultAwsCredentialsManager,\n} from '@backstage/integration-aws-node';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nexport type { ElasticSearchClientOptions };\n\n/**\n * Search query that the elasticsearch engine understands.\n * @public\n */\nexport type ElasticSearchConcreteQuery = {\n documentTypes?: string[];\n elasticSearchQuery: Object;\n pageSize: number;\n};\n\n/**\n * Options available for the Elasticsearch specific query translator.\n * @public\n */\nexport type ElasticSearchQueryTranslatorOptions = {\n highlightOptions?: ElasticSearchHighlightConfig;\n};\n\n/**\n * Elasticsearch specific query translator.\n * @public\n */\nexport type ElasticSearchQueryTranslator = (\n query: SearchQuery,\n options?: ElasticSearchQueryTranslatorOptions,\n) => ElasticSearchConcreteQuery;\n\n/**\n * Options for instantiate ElasticSearchSearchEngine\n * @public\n */\nexport type ElasticSearchOptions = {\n logger: LoggerService;\n config: Config;\n aliasPostfix?: string;\n indexPrefix?: string;\n translator?: ElasticSearchQueryTranslator;\n};\n\n/**\n * @public\n */\nexport type ElasticSearchHighlightOptions = {\n fragmentDelimiter?: string;\n fragmentSize?: number;\n numFragments?: number;\n};\n\n/**\n * @public\n */\nexport type ElasticSearchHighlightConfig = {\n fragmentDelimiter: string;\n fragmentSize: number;\n numFragments: number;\n preTag: string;\n postTag: string;\n};\n\ntype ElasticSearchResult = {\n _index: string;\n _type: string;\n _score: number;\n _source: IndexableDocument;\n highlight?: {\n [field: string]: string[];\n };\n};\n\nfunction isBlank(str: string) {\n return (isEmpty(str) && !isNumber(str)) || nan(str);\n}\n\nconst DEFAULT_INDEXER_BATCH_SIZE = 1000;\n\n/**\n * @public\n */\nexport class ElasticSearchSearchEngine implements SearchEngine {\n private readonly elasticSearchClientWrapper: ElasticSearchClientWrapper;\n private readonly highlightOptions: ElasticSearchHighlightConfig;\n\n constructor(\n private readonly elasticSearchClientOptions: ElasticSearchClientOptions,\n private readonly aliasPostfix: string,\n private readonly indexPrefix: string,\n private readonly logger: LoggerService,\n private readonly batchSize: number,\n highlightOptions?: ElasticSearchHighlightOptions,\n ) {\n this.elasticSearchClientWrapper =\n ElasticSearchClientWrapper.fromClientOptions(elasticSearchClientOptions);\n const uuidTag = uuid();\n this.highlightOptions = {\n preTag: `<${uuidTag}>`,\n postTag: `</${uuidTag}>`,\n fragmentSize: 1000,\n numFragments: 1,\n fragmentDelimiter: ' ... ',\n ...highlightOptions,\n };\n }\n\n static async fromConfig(options: ElasticSearchOptions) {\n const {\n logger,\n config,\n aliasPostfix = `search`,\n indexPrefix = ``,\n translator,\n } = options;\n const credentialProvider = DefaultAwsCredentialsManager.fromConfig(config);\n const clientOptions = await this.createElasticSearchClientOptions(\n await credentialProvider?.getCredentialProvider(),\n config.getConfig('search.elasticsearch'),\n );\n if (clientOptions.provider === 'elastic') {\n logger.info('Initializing Elastic.co ElasticSearch search engine.');\n } else if (clientOptions.provider === 'aws') {\n logger.info('Initializing AWS OpenSearch search engine.');\n } else if (clientOptions.provider === 'opensearch') {\n logger.info('Initializing OpenSearch search engine.');\n } else {\n logger.info('Initializing ElasticSearch search engine.');\n }\n\n const engine = new ElasticSearchSearchEngine(\n clientOptions,\n aliasPostfix,\n indexPrefix,\n logger,\n config.getOptionalNumber('search.elasticsearch.batchSize') ??\n DEFAULT_INDEXER_BATCH_SIZE,\n config.getOptional<ElasticSearchHighlightOptions>(\n 'search.elasticsearch.highlightOptions',\n ),\n );\n\n for (const indexTemplate of this.readIndexTemplateConfig(\n config.getConfig('search.elasticsearch'),\n )) {\n await engine.setIndexTemplate(indexTemplate);\n }\n\n if (translator) {\n await engine.setTranslator(translator);\n }\n\n return engine;\n }\n\n /**\n * Create a custom search client from the derived search client configuration.\n * This need not be the same client that the engine uses internally.\n *\n * @example Instantiate an instance of an Elasticsearch client.\n *\n * ```ts\n * import { isOpenSearchCompatible } from '@backstage/plugin-search-backend-module-elasticsearch';\n * import { Client } from '@elastic/elasticsearch';\n *\n * const client = searchEngine.newClient<Client>(options => {\n * // This type guard ensures options are compatible with either OpenSearch\n * // or Elasticsearch client constructors.\n * if (!isOpenSearchCompatible(options)) {\n * return new Client(options);\n * }\n * throw new Error('Incompatible options provided');\n * });\n * ```\n */\n newClient<T>(create: (options: ElasticSearchClientOptions) => T): T {\n return create(this.elasticSearchClientOptions);\n }\n\n protected translator(\n query: SearchQuery,\n options?: ElasticSearchQueryTranslatorOptions,\n ): ElasticSearchConcreteQuery {\n const { term, filters = {}, types, pageCursor } = query;\n\n const filter = Object.entries(filters)\n .filter(([_, value]) => Boolean(value))\n .map(([key, value]: [key: string, value: any]) => {\n if (['string', 'number', 'boolean'].includes(typeof value)) {\n // Use exact matching for string datatype fields\n const keyword = typeof value === 'string' ? `${key}.keyword` : key;\n return esb.matchQuery(keyword, value.toString());\n }\n if (Array.isArray(value)) {\n return esb\n .boolQuery()\n .should(value.map(it => esb.matchQuery(key, it.toString())));\n }\n this.logger.error('Failed to query, unrecognized filter type', {\n key,\n value,\n });\n throw new Error(\n 'Failed to add filters to query. Unrecognized filter type',\n );\n });\n\n const esbQueries = [];\n // https://regex101.com/r/Lr0MqS/1\n const phraseTerms = term.match(/\"[^\"]*\"/g);\n\n if (isBlank(term)) {\n const esbQuery = esb.matchAllQuery();\n esbQueries.push(esbQuery);\n } else if (phraseTerms && phraseTerms.length > 0) {\n let restTerm = term;\n for (const phraseTerm of phraseTerms) {\n restTerm = restTerm.replace(phraseTerm, '');\n const esbPhraseQuery = esb\n .multiMatchQuery(['*'], phraseTerm.replace(/\"/g, ''))\n .type('phrase');\n esbQueries.push(esbPhraseQuery);\n }\n if (restTerm?.length > 0) {\n const esbRestQuery = esb\n .multiMatchQuery(['*'], restTerm.trim())\n .fuzziness('auto');\n esbQueries.push(esbRestQuery);\n }\n } else {\n const esbQuery = esb.multiMatchQuery(['*'], term).fuzziness('auto');\n esbQueries.push(esbQuery);\n }\n\n const pageSize = query.pageLimit || 25;\n const { page } = decodePageCursor(pageCursor);\n\n let esbRequestBodySearch = esb\n .requestBodySearch()\n .query(esb.boolQuery().filter(filter).should(esbQueries))\n .from(page * pageSize)\n .size(pageSize);\n\n if (options?.highlightOptions) {\n esbRequestBodySearch = esbRequestBodySearch.highlight(\n esb\n .highlight('*')\n .numberOfFragments(options.highlightOptions.numFragments as number)\n .fragmentSize(options.highlightOptions.fragmentSize as number)\n .preTags(options.highlightOptions.preTag)\n .postTags(options.highlightOptions.postTag),\n );\n }\n\n return {\n elasticSearchQuery: esbRequestBodySearch.toJSON(),\n documentTypes: types,\n pageSize,\n };\n }\n\n setTranslator(translator: ElasticSearchQueryTranslator) {\n this.translator = translator;\n }\n\n async setIndexTemplate(template: ElasticSearchCustomIndexTemplate) {\n try {\n await this.elasticSearchClientWrapper.putIndexTemplate(template);\n this.logger.info('Custom index template set');\n } catch (error) {\n this.logger.error(`Unable to set custom index template: ${error}`);\n }\n }\n\n async getIndexer(type: string) {\n const alias = this.constructSearchAlias(type);\n const indexerLogger = this.logger.child({ documentType: type });\n\n const indexer = new ElasticSearchSearchEngineIndexer({\n type,\n indexPrefix: this.indexPrefix,\n indexSeparator: this.indexSeparator,\n alias,\n elasticSearchClientWrapper: this.elasticSearchClientWrapper,\n logger: indexerLogger,\n batchSize: this.batchSize,\n skipRefresh:\n (\n this\n .elasticSearchClientOptions as OpenSearchElasticSearchClientOptions\n )?.service === 'aoss',\n });\n\n // Attempt cleanup upon failure.\n // todo(@backstage/search-maintainers): Consider introducing a more\n // formal mechanism for handling such errors in BatchSearchEngineIndexer and\n // replacing this handler with it. See: #17291\n indexer.on('error', async e => {\n indexerLogger.error(`Failed to index documents for type ${type}`, e);\n let cleanupError: Error | undefined;\n\n // In some cases, a failure may have occurred before the indexer was able\n // to complete initialization. Try up to 5 times to remove the dangling\n // index.\n await new Promise<void>(async done => {\n const maxAttempts = 5;\n let attempts = 0;\n\n while (attempts < maxAttempts) {\n try {\n await this.elasticSearchClientWrapper.deleteIndex({\n index: indexer.indexName,\n });\n\n attempts = maxAttempts;\n cleanupError = undefined;\n done();\n } catch (err) {\n cleanupError = err;\n }\n\n // Wait 1 second between retries.\n await new Promise(okay => setTimeout(okay, 1000));\n\n attempts++;\n }\n done();\n });\n\n if (cleanupError) {\n indexerLogger.error(\n `Unable to clean up elastic index ${indexer.indexName}: ${cleanupError}`,\n );\n } else {\n indexerLogger.info(\n `Removed partial, failed index ${indexer.indexName}`,\n );\n }\n });\n\n return indexer;\n }\n\n async query(query: SearchQuery): Promise<IndexableResultSet> {\n const { elasticSearchQuery, documentTypes, pageSize } = this.translator(\n query,\n { highlightOptions: this.highlightOptions },\n );\n const queryIndices = documentTypes\n ? documentTypes.map(it => this.constructSearchAlias(it))\n : this.constructSearchAlias('*');\n try {\n const result = await this.elasticSearchClientWrapper.search({\n index: queryIndices,\n body: elasticSearchQuery,\n });\n const { page } = decodePageCursor(query.pageCursor);\n const hasNextPage = result.body.hits.total.value > (page + 1) * pageSize;\n const hasPreviousPage = page > 0;\n const nextPageCursor = hasNextPage\n ? encodePageCursor({ page: page + 1 })\n : undefined;\n const previousPageCursor = hasPreviousPage\n ? encodePageCursor({ page: page - 1 })\n : undefined;\n\n return {\n results: result.body.hits.hits.map(\n (d: ElasticSearchResult, index: number) => {\n const resultItem: IndexableResult = {\n type: this.getTypeFromIndex(d._index),\n document: d._source,\n rank: pageSize * page + index + 1,\n };\n\n if (d.highlight) {\n resultItem.highlight = {\n preTag: this.highlightOptions.preTag as string,\n postTag: this.highlightOptions.postTag as string,\n fields: Object.fromEntries(\n Object.entries(d.highlight).map(([field, fragments]) => [\n field,\n fragments.join(this.highlightOptions.fragmentDelimiter),\n ]),\n ),\n };\n }\n\n return resultItem;\n },\n ),\n nextPageCursor,\n previousPageCursor,\n numberOfResults: result.body.hits.total.value,\n };\n } catch (error) {\n if (error.meta?.body?.error?.type === 'index_not_found_exception') {\n throw new MissingIndexError(\n `Missing index for ${queryIndices}. This means there are no documents to search through.`,\n error,\n );\n }\n this.logger.error(\n `Failed to query documents for indices ${queryIndices}`,\n error,\n );\n return Promise.reject({ results: [] });\n }\n }\n\n private readonly indexSeparator = '-index__';\n\n private getTypeFromIndex(index: string) {\n return index\n .substring(this.indexPrefix.length)\n .split(this.indexSeparator)[0];\n }\n\n private constructSearchAlias(type: string) {\n const postFix = this.aliasPostfix ? `__${this.aliasPostfix}` : '';\n return `${this.indexPrefix}${type}${postFix}`;\n }\n\n private static async createElasticSearchClientOptions(\n credentialProvider: AwsCredentialProvider,\n config?: Config,\n ): Promise<ElasticSearchClientOptions> {\n if (!config) {\n throw new Error('No elastic search config found');\n }\n const clientOptionsConfig = config.getOptionalConfig('clientOptions');\n const sslConfig = clientOptionsConfig?.getOptionalConfig('ssl');\n\n if (config.getOptionalString('provider') === 'elastic') {\n const authConfig = config.getConfig('auth');\n return {\n provider: 'elastic',\n cloud: {\n id: config.getString('cloudId'),\n },\n auth: {\n username: authConfig.getString('username'),\n password: authConfig.getString('password'),\n },\n ...(sslConfig\n ? {\n ssl: {\n rejectUnauthorized:\n sslConfig?.getOptionalBoolean('rejectUnauthorized'),\n },\n }\n : {}),\n };\n }\n if (config.getOptionalString('provider') === 'aws') {\n const requestSigner = new RequestSigner(config.getString('node'));\n const service =\n config.getOptionalString('service') ?? requestSigner.service;\n if (service !== 'es' && service !== 'aoss')\n throw new Error(`Unrecognized serivce type: ${service}`);\n return {\n provider: 'aws',\n node: config.getString('node'),\n region: config.getOptionalString('region'),\n service,\n ...(sslConfig\n ? {\n ssl: {\n rejectUnauthorized:\n sslConfig?.getOptionalBoolean('rejectUnauthorized'),\n },\n }\n : {}),\n ...AwsSigv4Signer({\n region: config.getOptionalString('region') ?? requestSigner.region, // for backwards compatibility\n service: service,\n getCredentials: async () =>\n await credentialProvider.sdkCredentialProvider(),\n }),\n };\n }\n if (config.getOptionalString('provider') === 'opensearch') {\n const authConfig = config.getConfig('auth');\n return {\n provider: 'opensearch',\n node: config.getString('node'),\n auth: {\n username: authConfig.getString('username'),\n password: authConfig.getString('password'),\n },\n ...(sslConfig\n ? {\n ssl: {\n rejectUnauthorized:\n sslConfig?.getOptionalBoolean('rejectUnauthorized'),\n },\n }\n : {}),\n };\n }\n const authConfig = config.getOptionalConfig('auth');\n const auth =\n authConfig &&\n (authConfig.has('apiKey')\n ? {\n apiKey: authConfig.getString('apiKey'),\n }\n : {\n username: authConfig.getString('username'),\n password: authConfig.getString('password'),\n });\n return {\n node: config.getString('node'),\n auth,\n ...(sslConfig\n ? {\n ssl: {\n rejectUnauthorized:\n sslConfig?.getOptionalBoolean('rejectUnauthorized'),\n },\n }\n : {}),\n };\n }\n\n private static readIndexTemplateConfig(\n config: Config,\n ): ElasticSearchCustomIndexTemplate[] {\n return (\n config.getOptionalConfigArray('indexTemplates')?.map(templateConfig => {\n const bodyConfig = templateConfig.getConfig('body');\n return {\n name: templateConfig.getString('name'),\n body: {\n index_patterns: bodyConfig.getStringArray('index_patterns'),\n composed_of: bodyConfig.getOptionalStringArray('composed_of'),\n template: bodyConfig.getOptionalConfig('template')?.get(),\n },\n };\n }) ?? []\n );\n }\n}\n\n/**\n * @public\n */\nexport function decodePageCursor(pageCursor?: string): { page: number } {\n if (!pageCursor) {\n return { page: 0 };\n }\n\n return {\n page: Number(Buffer.from(pageCursor, 'base64').toString('utf-8')),\n };\n}\n\nexport function encodePageCursor({ page }: { page: number }): string {\n return Buffer.from(`${page}`, 'utf-8').toString('base64');\n}\n"],"names":["isEmpty","isNumber","nan","ElasticSearchClientWrapper","uuid","DefaultAwsCredentialsManager","esb","ElasticSearchSearchEngineIndexer","MissingIndexError","authConfig","RequestSigner","AwsSigv4Signer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ElasticSearchSearchEngine.cjs.js","sources":["../../src/engines/ElasticSearchSearchEngine.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n IndexableDocument,\n IndexableResult,\n IndexableResultSet,\n SearchQuery,\n} from '@backstage/plugin-search-common';\nimport { SearchEngine } from '@backstage/plugin-search-backend-node';\nimport { isEmpty, isNumber, isNaN as nan } from 'lodash';\n\nimport { AwsSigv4Signer } from '@opensearch-project/opensearch/aws';\nimport { RequestSigner } from 'aws4';\nimport { Config } from '@backstage/config';\nimport {\n ElasticSearchClientOptions,\n OpenSearchElasticSearchClientOptions,\n} from './ElasticSearchClientOptions';\nimport { ElasticSearchClientWrapper } from './ElasticSearchClientWrapper';\nimport { ElasticSearchCustomIndexTemplate } from './types';\nimport { ElasticSearchSearchEngineIndexer } from './ElasticSearchSearchEngineIndexer';\nimport { MissingIndexError } from '@backstage/plugin-search-backend-node';\nimport esb from 'elastic-builder';\nimport { v4 as uuid } from 'uuid';\nimport {\n AwsCredentialProvider,\n DefaultAwsCredentialsManager,\n} from '@backstage/integration-aws-node';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nexport type { ElasticSearchClientOptions };\n\n/**\n * Search query that the elasticsearch engine understands.\n * @public\n */\nexport type ElasticSearchConcreteQuery = {\n documentTypes?: string[];\n elasticSearchQuery: Object;\n pageSize: number;\n};\n\n/**\n * Options available for the Elasticsearch specific query translator.\n * @public\n */\nexport type ElasticSearchQueryTranslatorOptions = {\n highlightOptions?: ElasticSearchHighlightConfig;\n queryOptions?: ElasticSearchQueryConfig;\n};\n\n/**\n * Elasticsearch specific query translator.\n * @public\n */\nexport type ElasticSearchQueryTranslator = (\n query: SearchQuery,\n options?: ElasticSearchQueryTranslatorOptions,\n) => ElasticSearchConcreteQuery;\n\n/**\n * Options for instantiate ElasticSearchSearchEngine\n * @public\n */\nexport type ElasticSearchOptions = {\n logger: LoggerService;\n config: Config;\n aliasPostfix?: string;\n indexPrefix?: string;\n translator?: ElasticSearchQueryTranslator;\n};\n\n/**\n * @public\n */\nexport type ElasticSearchHighlightOptions = {\n fragmentDelimiter?: string;\n fragmentSize?: number;\n numFragments?: number;\n};\n\n/**\n * @public\n */\nexport type ElasticSearchQueryConfig = {\n fuzziness?: string | number;\n prefixLength?: number;\n};\n\n/**\n * @public\n */\nexport type ElasticSearchHighlightConfig = {\n fragmentDelimiter: string;\n fragmentSize: number;\n numFragments: number;\n preTag: string;\n postTag: string;\n};\n\ntype ElasticSearchResult = {\n _index: string;\n _type: string;\n _score: number;\n _source: IndexableDocument;\n highlight?: {\n [field: string]: string[];\n };\n};\n\nfunction isBlank(str: string) {\n return (isEmpty(str) && !isNumber(str)) || nan(str);\n}\n\nconst DEFAULT_INDEXER_BATCH_SIZE = 1000;\n\n/**\n * @public\n */\nexport class ElasticSearchSearchEngine implements SearchEngine {\n private readonly elasticSearchClientWrapper: ElasticSearchClientWrapper;\n private readonly highlightOptions: ElasticSearchHighlightConfig;\n private readonly queryOptions?: ElasticSearchQueryConfig;\n\n constructor(\n private readonly elasticSearchClientOptions: ElasticSearchClientOptions,\n private readonly aliasPostfix: string,\n private readonly indexPrefix: string,\n private readonly logger: LoggerService,\n private readonly batchSize: number,\n highlightOptions?: ElasticSearchHighlightOptions,\n queryOptions?: ElasticSearchQueryConfig,\n ) {\n this.elasticSearchClientWrapper =\n ElasticSearchClientWrapper.fromClientOptions(elasticSearchClientOptions);\n const uuidTag = uuid();\n this.highlightOptions = {\n preTag: `<${uuidTag}>`,\n postTag: `</${uuidTag}>`,\n fragmentSize: 1000,\n numFragments: 1,\n fragmentDelimiter: ' ... ',\n ...highlightOptions,\n };\n this.queryOptions = queryOptions;\n }\n\n static async fromConfig(options: ElasticSearchOptions) {\n const {\n logger,\n config,\n aliasPostfix = `search`,\n indexPrefix = ``,\n translator,\n } = options;\n const credentialProvider = DefaultAwsCredentialsManager.fromConfig(config);\n const clientOptions = await this.createElasticSearchClientOptions(\n await credentialProvider?.getCredentialProvider(),\n config.getConfig('search.elasticsearch'),\n );\n if (clientOptions.provider === 'elastic') {\n logger.info('Initializing Elastic.co ElasticSearch search engine.');\n } else if (clientOptions.provider === 'aws') {\n logger.info('Initializing AWS OpenSearch search engine.');\n } else if (clientOptions.provider === 'opensearch') {\n logger.info('Initializing OpenSearch search engine.');\n } else {\n logger.info('Initializing ElasticSearch search engine.');\n }\n\n const engine = new ElasticSearchSearchEngine(\n clientOptions,\n aliasPostfix,\n indexPrefix,\n logger,\n config.getOptionalNumber('search.elasticsearch.batchSize') ??\n DEFAULT_INDEXER_BATCH_SIZE,\n config.getOptional<ElasticSearchHighlightOptions>(\n 'search.elasticsearch.highlightOptions',\n ),\n );\n\n for (const indexTemplate of this.readIndexTemplateConfig(\n config.getConfig('search.elasticsearch'),\n )) {\n await engine.setIndexTemplate(indexTemplate);\n }\n\n if (translator) {\n await engine.setTranslator(translator);\n }\n\n return engine;\n }\n\n /**\n * Create a custom search client from the derived search client configuration.\n * This need not be the same client that the engine uses internally.\n *\n * @example Instantiate an instance of an Elasticsearch client.\n *\n * ```ts\n * import { isOpenSearchCompatible } from '@backstage/plugin-search-backend-module-elasticsearch';\n * import { Client } from '@elastic/elasticsearch';\n *\n * const client = searchEngine.newClient<Client>(options => {\n * // This type guard ensures options are compatible with either OpenSearch\n * // or Elasticsearch client constructors.\n * if (!isOpenSearchCompatible(options)) {\n * return new Client(options);\n * }\n * throw new Error('Incompatible options provided');\n * });\n * ```\n */\n newClient<T>(create: (options: ElasticSearchClientOptions) => T): T {\n return create(this.elasticSearchClientOptions);\n }\n\n protected translator(\n query: SearchQuery,\n options?: ElasticSearchQueryTranslatorOptions,\n ): ElasticSearchConcreteQuery {\n const { term, filters = {}, types, pageCursor } = query;\n\n const filter = Object.entries(filters)\n .filter(([_, value]) => Boolean(value))\n .map(([key, value]: [key: string, value: any]) => {\n if (['string', 'number', 'boolean'].includes(typeof value)) {\n // Use exact matching for string datatype fields\n const keyword = typeof value === 'string' ? `${key}.keyword` : key;\n return esb.matchQuery(keyword, value.toString());\n }\n if (Array.isArray(value)) {\n return esb\n .boolQuery()\n .should(value.map(it => esb.matchQuery(key, it.toString())));\n }\n this.logger.error('Failed to query, unrecognized filter type', {\n key,\n value,\n });\n throw new Error(\n 'Failed to add filters to query. Unrecognized filter type',\n );\n });\n\n const esbQueries = [];\n // https://regex101.com/r/Lr0MqS/1\n const phraseTerms = term.match(/\"[^\"]*\"/g);\n\n if (isBlank(term)) {\n const esbQuery = esb.matchAllQuery();\n esbQueries.push(esbQuery);\n } else if (phraseTerms && phraseTerms.length > 0) {\n let restTerm = term;\n for (const phraseTerm of phraseTerms) {\n restTerm = restTerm.replace(phraseTerm, '');\n const esbPhraseQuery = esb\n .multiMatchQuery(['*'], phraseTerm.replace(/\"/g, ''))\n .type('phrase');\n esbQueries.push(esbPhraseQuery);\n }\n if (restTerm?.length > 0) {\n const esbRestQuery = esb\n .multiMatchQuery(['*'], restTerm.trim())\n .fuzziness(options?.queryOptions?.fuzziness ?? 'auto')\n .prefixLength(options?.queryOptions?.prefixLength ?? 0);\n esbQueries.push(esbRestQuery);\n }\n } else {\n const esbQuery = esb\n .multiMatchQuery(['*'], term)\n .fuzziness(options?.queryOptions?.fuzziness ?? 'auto')\n .prefixLength(options?.queryOptions?.prefixLength ?? 0);\n esbQueries.push(esbQuery);\n }\n\n const pageSize = query.pageLimit || 25;\n const { page } = decodePageCursor(pageCursor);\n\n let esbRequestBodySearch = esb\n .requestBodySearch()\n .query(esb.boolQuery().filter(filter).should(esbQueries))\n .from(page * pageSize)\n .size(pageSize);\n\n if (options?.highlightOptions) {\n esbRequestBodySearch = esbRequestBodySearch.highlight(\n esb\n .highlight('*')\n .numberOfFragments(options.highlightOptions.numFragments as number)\n .fragmentSize(options.highlightOptions.fragmentSize as number)\n .preTags(options.highlightOptions.preTag)\n .postTags(options.highlightOptions.postTag),\n );\n }\n\n return {\n elasticSearchQuery: esbRequestBodySearch.toJSON(),\n documentTypes: types,\n pageSize,\n };\n }\n\n setTranslator(translator: ElasticSearchQueryTranslator) {\n this.translator = translator;\n }\n\n async setIndexTemplate(template: ElasticSearchCustomIndexTemplate) {\n try {\n await this.elasticSearchClientWrapper.putIndexTemplate(template);\n this.logger.info('Custom index template set');\n } catch (error) {\n this.logger.error(`Unable to set custom index template: ${error}`);\n }\n }\n\n async getIndexer(type: string) {\n const alias = this.constructSearchAlias(type);\n const indexerLogger = this.logger.child({ documentType: type });\n\n const indexer = new ElasticSearchSearchEngineIndexer({\n type,\n indexPrefix: this.indexPrefix,\n indexSeparator: this.indexSeparator,\n alias,\n elasticSearchClientWrapper: this.elasticSearchClientWrapper,\n logger: indexerLogger,\n batchSize: this.batchSize,\n skipRefresh:\n (\n this\n .elasticSearchClientOptions as OpenSearchElasticSearchClientOptions\n )?.service === 'aoss',\n });\n\n // Attempt cleanup upon failure.\n // todo(@backstage/search-maintainers): Consider introducing a more\n // formal mechanism for handling such errors in BatchSearchEngineIndexer and\n // replacing this handler with it. See: #17291\n indexer.on('error', async e => {\n indexerLogger.error(`Failed to index documents for type ${type}`, e);\n let cleanupError: Error | undefined;\n\n // In some cases, a failure may have occurred before the indexer was able\n // to complete initialization. Try up to 5 times to remove the dangling\n // index.\n await new Promise<void>(async done => {\n const maxAttempts = 5;\n let attempts = 0;\n\n while (attempts < maxAttempts) {\n try {\n await this.elasticSearchClientWrapper.deleteIndex({\n index: indexer.indexName,\n });\n\n attempts = maxAttempts;\n cleanupError = undefined;\n done();\n } catch (err) {\n cleanupError = err;\n }\n\n // Wait 1 second between retries.\n await new Promise(okay => setTimeout(okay, 1000));\n\n attempts++;\n }\n done();\n });\n\n if (cleanupError) {\n indexerLogger.error(\n `Unable to clean up elastic index ${indexer.indexName}: ${cleanupError}`,\n );\n } else {\n indexerLogger.info(\n `Removed partial, failed index ${indexer.indexName}`,\n );\n }\n });\n\n return indexer;\n }\n\n async query(query: SearchQuery): Promise<IndexableResultSet> {\n const { elasticSearchQuery, documentTypes, pageSize } = this.translator(\n query,\n {\n highlightOptions: this.highlightOptions,\n queryOptions: this.queryOptions,\n },\n );\n const queryIndices = documentTypes\n ? documentTypes.map(it => this.constructSearchAlias(it))\n : this.constructSearchAlias('*');\n try {\n const result = await this.elasticSearchClientWrapper.search({\n index: queryIndices,\n body: elasticSearchQuery,\n });\n const { page } = decodePageCursor(query.pageCursor);\n const hasNextPage = result.body.hits.total.value > (page + 1) * pageSize;\n const hasPreviousPage = page > 0;\n const nextPageCursor = hasNextPage\n ? encodePageCursor({ page: page + 1 })\n : undefined;\n const previousPageCursor = hasPreviousPage\n ? encodePageCursor({ page: page - 1 })\n : undefined;\n\n return {\n results: result.body.hits.hits.map(\n (d: ElasticSearchResult, index: number) => {\n const resultItem: IndexableResult = {\n type: this.getTypeFromIndex(d._index),\n document: d._source,\n rank: pageSize * page + index + 1,\n };\n\n if (d.highlight) {\n resultItem.highlight = {\n preTag: this.highlightOptions.preTag as string,\n postTag: this.highlightOptions.postTag as string,\n fields: Object.fromEntries(\n Object.entries(d.highlight).map(([field, fragments]) => [\n field,\n fragments.join(this.highlightOptions.fragmentDelimiter),\n ]),\n ),\n };\n }\n\n return resultItem;\n },\n ),\n nextPageCursor,\n previousPageCursor,\n numberOfResults: result.body.hits.total.value,\n };\n } catch (error) {\n if (error.meta?.body?.error?.type === 'index_not_found_exception') {\n throw new MissingIndexError(\n `Missing index for ${queryIndices}. This means there are no documents to search through.`,\n error,\n );\n }\n this.logger.error(\n `Failed to query documents for indices ${queryIndices}`,\n error,\n );\n return Promise.reject({ results: [] });\n }\n }\n\n private readonly indexSeparator = '-index__';\n\n private getTypeFromIndex(index: string) {\n return index\n .substring(this.indexPrefix.length)\n .split(this.indexSeparator)[0];\n }\n\n private constructSearchAlias(type: string) {\n const postFix = this.aliasPostfix ? `__${this.aliasPostfix}` : '';\n return `${this.indexPrefix}${type}${postFix}`;\n }\n\n private static async createElasticSearchClientOptions(\n credentialProvider: AwsCredentialProvider,\n config?: Config,\n ): Promise<ElasticSearchClientOptions> {\n if (!config) {\n throw new Error('No elastic search config found');\n }\n const clientOptionsConfig = config.getOptionalConfig('clientOptions');\n const sslConfig = clientOptionsConfig?.getOptionalConfig('ssl');\n\n if (config.getOptionalString('provider') === 'elastic') {\n const authConfig = config.getConfig('auth');\n return {\n provider: 'elastic',\n cloud: {\n id: config.getString('cloudId'),\n },\n auth: {\n username: authConfig.getString('username'),\n password: authConfig.getString('password'),\n },\n ...(sslConfig\n ? {\n ssl: {\n rejectUnauthorized:\n sslConfig?.getOptionalBoolean('rejectUnauthorized'),\n },\n }\n : {}),\n };\n }\n if (config.getOptionalString('provider') === 'aws') {\n const requestSigner = new RequestSigner(config.getString('node'));\n const service =\n config.getOptionalString('service') ?? requestSigner.service;\n if (service !== 'es' && service !== 'aoss')\n throw new Error(`Unrecognized serivce type: ${service}`);\n return {\n provider: 'aws',\n node: config.getString('node'),\n region: config.getOptionalString('region'),\n service,\n ...(sslConfig\n ? {\n ssl: {\n rejectUnauthorized:\n sslConfig?.getOptionalBoolean('rejectUnauthorized'),\n },\n }\n : {}),\n ...AwsSigv4Signer({\n region: config.getOptionalString('region') ?? requestSigner.region, // for backwards compatibility\n service: service,\n getCredentials: async () =>\n await credentialProvider.sdkCredentialProvider(),\n }),\n };\n }\n if (config.getOptionalString('provider') === 'opensearch') {\n const authConfig = config.getConfig('auth');\n return {\n provider: 'opensearch',\n node: config.getString('node'),\n auth: {\n username: authConfig.getString('username'),\n password: authConfig.getString('password'),\n },\n ...(sslConfig\n ? {\n ssl: {\n rejectUnauthorized:\n sslConfig?.getOptionalBoolean('rejectUnauthorized'),\n },\n }\n : {}),\n };\n }\n const authConfig = config.getOptionalConfig('auth');\n const auth =\n authConfig &&\n (authConfig.has('apiKey')\n ? {\n apiKey: authConfig.getString('apiKey'),\n }\n : {\n username: authConfig.getString('username'),\n password: authConfig.getString('password'),\n });\n return {\n node: config.getString('node'),\n auth,\n ...(sslConfig\n ? {\n ssl: {\n rejectUnauthorized:\n sslConfig?.getOptionalBoolean('rejectUnauthorized'),\n },\n }\n : {}),\n };\n }\n\n private static readIndexTemplateConfig(\n config: Config,\n ): ElasticSearchCustomIndexTemplate[] {\n return (\n config.getOptionalConfigArray('indexTemplates')?.map(templateConfig => {\n const bodyConfig = templateConfig.getConfig('body');\n return {\n name: templateConfig.getString('name'),\n body: {\n index_patterns: bodyConfig.getStringArray('index_patterns'),\n composed_of: bodyConfig.getOptionalStringArray('composed_of'),\n template: bodyConfig.getOptionalConfig('template')?.get(),\n },\n };\n }) ?? []\n );\n }\n}\n\n/**\n * @public\n */\nexport function decodePageCursor(pageCursor?: string): { page: number } {\n if (!pageCursor) {\n return { page: 0 };\n }\n\n return {\n page: Number(Buffer.from(pageCursor, 'base64').toString('utf-8')),\n };\n}\n\nexport function encodePageCursor({ page }: { page: number }): string {\n return Buffer.from(`${page}`, 'utf-8').toString('base64');\n}\n"],"names":["isEmpty","isNumber","nan","ElasticSearchClientWrapper","uuid","DefaultAwsCredentialsManager","esb","ElasticSearchSearchEngineIndexer","MissingIndexError","authConfig","RequestSigner","AwsSigv4Signer"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
3
2
|
import { LoggerService } from '@backstage/backend-plugin-api';
|
|
4
3
|
import { ElasticSearchQueryTranslator as ElasticSearchQueryTranslator$1 } from '@backstage/plugin-search-backend-module-elasticsearch';
|
|
@@ -390,6 +389,7 @@ type ElasticSearchConcreteQuery = {
|
|
|
390
389
|
*/
|
|
391
390
|
type ElasticSearchQueryTranslatorOptions = {
|
|
392
391
|
highlightOptions?: ElasticSearchHighlightConfig;
|
|
392
|
+
queryOptions?: ElasticSearchQueryConfig;
|
|
393
393
|
};
|
|
394
394
|
/**
|
|
395
395
|
* Elasticsearch specific query translator.
|
|
@@ -415,6 +415,13 @@ type ElasticSearchHighlightOptions = {
|
|
|
415
415
|
fragmentSize?: number;
|
|
416
416
|
numFragments?: number;
|
|
417
417
|
};
|
|
418
|
+
/**
|
|
419
|
+
* @public
|
|
420
|
+
*/
|
|
421
|
+
type ElasticSearchQueryConfig = {
|
|
422
|
+
fuzziness?: string | number;
|
|
423
|
+
prefixLength?: number;
|
|
424
|
+
};
|
|
418
425
|
/**
|
|
419
426
|
* @public
|
|
420
427
|
*/
|
|
@@ -436,7 +443,8 @@ declare class ElasticSearchSearchEngine implements SearchEngine {
|
|
|
436
443
|
private readonly batchSize;
|
|
437
444
|
private readonly elasticSearchClientWrapper;
|
|
438
445
|
private readonly highlightOptions;
|
|
439
|
-
|
|
446
|
+
private readonly queryOptions?;
|
|
447
|
+
constructor(elasticSearchClientOptions: ElasticSearchClientOptions, aliasPostfix: string, indexPrefix: string, logger: LoggerService, batchSize: number, highlightOptions?: ElasticSearchHighlightOptions, queryOptions?: ElasticSearchQueryConfig);
|
|
440
448
|
static fromConfig(options: ElasticSearchOptions): Promise<ElasticSearchSearchEngine>;
|
|
441
449
|
/**
|
|
442
450
|
* Create a custom search client from the derived search client configuration.
|
|
@@ -477,4 +485,4 @@ declare function decodePageCursor(pageCursor?: string): {
|
|
|
477
485
|
page: number;
|
|
478
486
|
};
|
|
479
487
|
|
|
480
|
-
export { type BaseElasticSearchClientOptions, type ElasticSearchAgentOptions, type ElasticSearchAliasAction, type ElasticSearchAuth, type ElasticSearchClientOptions, ElasticSearchClientWrapper, type ElasticSearchConcreteQuery, type ElasticSearchConnectionConstructor, type ElasticSearchCustomIndexTemplate, type ElasticSearchCustomIndexTemplateBody, type ElasticSearchElasticSearchClientOptions, type ElasticSearchHighlightConfig, type ElasticSearchHighlightOptions, type ElasticSearchIndexAction, type ElasticSearchNodeOptions, type ElasticSearchOptions, type ElasticSearchQueryTranslator, type ElasticSearchQueryTranslatorExtensionPoint, type ElasticSearchQueryTranslatorOptions, ElasticSearchSearchEngine, ElasticSearchSearchEngineIndexer, type ElasticSearchSearchEngineIndexerOptions, type ElasticSearchTransportConstructor, type OpenSearchAuth, type OpenSearchConnectionConstructor, type OpenSearchElasticSearchClientOptions, type OpenSearchNodeOptions, decodePageCursor as decodeElasticSearchPageCursor, _default as default, elasticsearchTranslatorExtensionPoint, isOpenSearchCompatible };
|
|
488
|
+
export { type BaseElasticSearchClientOptions, type ElasticSearchAgentOptions, type ElasticSearchAliasAction, type ElasticSearchAuth, type ElasticSearchClientOptions, ElasticSearchClientWrapper, type ElasticSearchConcreteQuery, type ElasticSearchConnectionConstructor, type ElasticSearchCustomIndexTemplate, type ElasticSearchCustomIndexTemplateBody, type ElasticSearchElasticSearchClientOptions, type ElasticSearchHighlightConfig, type ElasticSearchHighlightOptions, type ElasticSearchIndexAction, type ElasticSearchNodeOptions, type ElasticSearchOptions, type ElasticSearchQueryConfig, type ElasticSearchQueryTranslator, type ElasticSearchQueryTranslatorExtensionPoint, type ElasticSearchQueryTranslatorOptions, ElasticSearchSearchEngine, ElasticSearchSearchEngineIndexer, type ElasticSearchSearchEngineIndexerOptions, type ElasticSearchTransportConstructor, type OpenSearchAuth, type OpenSearchConnectionConstructor, type OpenSearchElasticSearchClientOptions, type OpenSearchNodeOptions, decodePageCursor as decodeElasticSearchPageCursor, _default as default, elasticsearchTranslatorExtensionPoint, isOpenSearchCompatible };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-search-backend-module-elasticsearch",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "A module for the search backend that implements search using ElasticSearch",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "backend-plugin-module",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"types": "./dist/index.d.ts",
|
|
41
41
|
"typesVersions": {
|
|
42
42
|
"*": {
|
|
43
|
-
"
|
|
43
|
+
"*": [
|
|
44
44
|
"dist/index.d.ts"
|
|
45
45
|
],
|
|
46
46
|
"alpha": [
|
|
@@ -62,11 +62,11 @@
|
|
|
62
62
|
"test": "backstage-cli package test"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@backstage/backend-plugin-api": "1.2.1
|
|
66
|
-
"@backstage/config": "1.3.2",
|
|
67
|
-
"@backstage/integration-aws-node": "0.1.15",
|
|
68
|
-
"@backstage/plugin-search-backend-node": "1.3.9
|
|
69
|
-
"@backstage/plugin-search-common": "1.2.17",
|
|
65
|
+
"@backstage/backend-plugin-api": "^1.2.1",
|
|
66
|
+
"@backstage/config": "^1.3.2",
|
|
67
|
+
"@backstage/integration-aws-node": "^0.1.15",
|
|
68
|
+
"@backstage/plugin-search-backend-node": "^1.3.9",
|
|
69
|
+
"@backstage/plugin-search-common": "^1.2.17",
|
|
70
70
|
"@elastic/elasticsearch": "^7.13.0",
|
|
71
71
|
"@opensearch-project/opensearch": "^2.2.1",
|
|
72
72
|
"aws4": "^1.12.0",
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
"uuid": "^11.0.0"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
|
-
"@backstage/backend-test-utils": "1.3.1
|
|
79
|
-
"@backstage/cli": "0.
|
|
78
|
+
"@backstage/backend-test-utils": "^1.3.1",
|
|
79
|
+
"@backstage/cli": "^0.31.0",
|
|
80
80
|
"@elastic/elasticsearch-mock": "^1.0.0",
|
|
81
81
|
"@short.io/opensearch-mock": "^0.4.0"
|
|
82
82
|
},
|