@backstage/plugin-search-backend-module-elasticsearch 0.1.5-next.0 → 0.1.5
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 +50 -0
- package/dist/index.cjs.js +13 -3
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +74 -6
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# @backstage/plugin-search-backend-module-elasticsearch
|
|
2
2
|
|
|
3
|
+
## 0.1.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 281cec1b61: Use more precise matching for query filters
|
|
8
|
+
- 915700f64f: The provided search engine now adds a pagination-aware `rank` value to all results.
|
|
9
|
+
- ddce23d080: Now possible to set a custom index template on the elasticsearch search engine.
|
|
10
|
+
- 7d8acfc32e: Additional types now exported publicly:
|
|
11
|
+
|
|
12
|
+
- ElasticSearchAgentOptions
|
|
13
|
+
- ElasticSearchConcreteQuery
|
|
14
|
+
- ElasticSearchQueryTranslator
|
|
15
|
+
- ElasticSearchConnectionConstructor,
|
|
16
|
+
- ElasticSearchTransportConstructor,
|
|
17
|
+
- ElasticSearchNodeOptions,
|
|
18
|
+
- ElasticSearchOptions,
|
|
19
|
+
- ElasticSearchAuth,
|
|
20
|
+
|
|
21
|
+
- Updated dependencies
|
|
22
|
+
- @backstage/plugin-search-common@0.3.5
|
|
23
|
+
- @backstage/plugin-search-backend-node@0.6.2
|
|
24
|
+
|
|
25
|
+
## 0.1.5-next.2
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- 7d8acfc32e: Additional types now exported publicly:
|
|
30
|
+
|
|
31
|
+
- ElasticSearchAgentOptions
|
|
32
|
+
- ElasticSearchConcreteQuery
|
|
33
|
+
- ElasticSearchQueryTranslator
|
|
34
|
+
- ElasticSearchConnectionConstructor,
|
|
35
|
+
- ElasticSearchTransportConstructor,
|
|
36
|
+
- ElasticSearchNodeOptions,
|
|
37
|
+
- ElasticSearchOptions,
|
|
38
|
+
- ElasticSearchAuth,
|
|
39
|
+
|
|
40
|
+
- Updated dependencies
|
|
41
|
+
- @backstage/plugin-search-common@0.3.5-next.1
|
|
42
|
+
- @backstage/plugin-search-backend-node@0.6.2-next.2
|
|
43
|
+
|
|
44
|
+
## 0.1.5-next.1
|
|
45
|
+
|
|
46
|
+
### Patch Changes
|
|
47
|
+
|
|
48
|
+
- 281cec1b61: Use more precise matching for query filters
|
|
49
|
+
- Updated dependencies
|
|
50
|
+
- @backstage/plugin-search-backend-node@0.6.2-next.1
|
|
51
|
+
- @backstage/plugin-search-common@0.3.5-next.0
|
|
52
|
+
|
|
3
53
|
## 0.1.5-next.0
|
|
4
54
|
|
|
5
55
|
### Patch Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -162,7 +162,8 @@ class ElasticSearchSearchEngine {
|
|
|
162
162
|
const { term, filters = {}, types, pageCursor } = query;
|
|
163
163
|
const filter = Object.entries(filters).filter(([_, value]) => Boolean(value)).map(([key, value]) => {
|
|
164
164
|
if (["string", "number", "boolean"].includes(typeof value)) {
|
|
165
|
-
|
|
165
|
+
const keyword = typeof value === "string" ? `${key}.keyword` : key;
|
|
166
|
+
return esb__default["default"].matchQuery(keyword, value.toString());
|
|
166
167
|
}
|
|
167
168
|
if (Array.isArray(value)) {
|
|
168
169
|
return esb__default["default"].boolQuery().should(value.map((it) => esb__default["default"].matchQuery(key, it.toString())));
|
|
@@ -186,6 +187,14 @@ class ElasticSearchSearchEngine {
|
|
|
186
187
|
setTranslator(translator) {
|
|
187
188
|
this.translator = translator;
|
|
188
189
|
}
|
|
190
|
+
async setIndexTemplate(template) {
|
|
191
|
+
try {
|
|
192
|
+
await this.elasticSearchClient.indices.putIndexTemplate(template);
|
|
193
|
+
this.logger.info("Custom index template set");
|
|
194
|
+
} catch (error) {
|
|
195
|
+
this.logger.error(`Unable to set custom index template: ${error}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
189
198
|
async getIndexer(type) {
|
|
190
199
|
const alias = this.constructSearchAlias(type);
|
|
191
200
|
const indexer = new ElasticSearchSearchEngineIndexer({
|
|
@@ -229,10 +238,11 @@ class ElasticSearchSearchEngine {
|
|
|
229
238
|
const nextPageCursor = hasNextPage ? encodePageCursor({ page: page + 1 }) : void 0;
|
|
230
239
|
const previousPageCursor = hasPreviousPage ? encodePageCursor({ page: page - 1 }) : void 0;
|
|
231
240
|
return {
|
|
232
|
-
results: result.body.hits.hits.map((d) => {
|
|
241
|
+
results: result.body.hits.hits.map((d, index) => {
|
|
233
242
|
const resultItem = {
|
|
234
243
|
type: this.getTypeFromIndex(d._index),
|
|
235
|
-
document: d._source
|
|
244
|
+
document: d._source,
|
|
245
|
+
rank: pageSize * page + index + 1
|
|
236
246
|
};
|
|
237
247
|
if (d.highlight) {
|
|
238
248
|
resultItem.highlight = {
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/engines/ElasticSearchSearchEngineIndexer.ts","../src/engines/ElasticSearchSearchEngine.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node';\nimport { IndexableDocument } from '@backstage/plugin-search-common';\nimport { Client } from '@elastic/elasticsearch';\nimport { Readable } from 'stream';\nimport { Logger } from 'winston';\n\nexport type ElasticSearchSearchEngineIndexerOptions = {\n type: string;\n indexPrefix: string;\n indexSeparator: string;\n alias: string;\n logger: Logger;\n elasticSearchClient: Client;\n};\n\nfunction duration(startTimestamp: [number, number]): string {\n const delta = process.hrtime(startTimestamp);\n const seconds = delta[0] + delta[1] / 1e9;\n return `${seconds.toFixed(1)}s`;\n}\n\nexport class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer {\n private received: number = 0;\n private processed: number = 0;\n private removableIndices: string[] = [];\n\n private readonly startTimestamp: [number, number];\n private readonly type: string;\n public readonly indexName: string;\n private readonly indexPrefix: string;\n private readonly indexSeparator: string;\n private readonly alias: string;\n private readonly removableAlias: string;\n private readonly logger: Logger;\n private readonly sourceStream: Readable;\n private readonly elasticSearchClient: Client;\n private bulkResult: Promise<any>;\n\n constructor(options: ElasticSearchSearchEngineIndexerOptions) {\n super({ batchSize: 1000 });\n this.logger = options.logger;\n this.startTimestamp = process.hrtime();\n this.type = options.type;\n this.indexPrefix = options.indexPrefix;\n this.indexSeparator = options.indexSeparator;\n this.indexName = this.constructIndexName(`${Date.now()}`);\n this.alias = options.alias;\n this.removableAlias = `${this.alias}_removable`;\n this.elasticSearchClient = options.elasticSearchClient;\n\n // The ES client bulk helper supports stream-based indexing, but we have to\n // supply the stream directly to it at instantiation-time. We can't supply\n // this class itself, so instead, we create this inline stream instead.\n this.sourceStream = new Readable({ objectMode: true });\n this.sourceStream._read = () => {};\n\n // eslint-disable-next-line consistent-this\n const that = this;\n\n // Keep a reference to the ES Bulk helper so that we can know when all\n // documents have been successfully written to ES.\n this.bulkResult = this.elasticSearchClient.helpers.bulk({\n datasource: this.sourceStream,\n onDocument() {\n that.processed++;\n return {\n index: { _index: that.indexName },\n };\n },\n refreshOnCompletion: that.indexName,\n });\n }\n\n async initialize(): Promise<void> {\n this.logger.info(`Started indexing documents for index ${this.type}`);\n\n const aliases = await this.elasticSearchClient.cat.aliases({\n format: 'json',\n name: [this.alias, this.removableAlias],\n });\n\n this.removableIndices = [\n ...new Set(aliases.body.map((r: Record<string, any>) => r.index)),\n ] as string[];\n\n await this.elasticSearchClient.indices.create({\n index: this.indexName,\n });\n }\n\n async index(documents: IndexableDocument[]): Promise<void> {\n await this.isReady();\n documents.forEach(document => {\n this.received++;\n this.sourceStream.push(document);\n });\n }\n\n async finalize(): Promise<void> {\n // Wait for all documents to be processed.\n await this.isReady();\n\n // Close off the underlying stream connected to ES, indicating that no more\n // documents will be written.\n this.sourceStream.push(null);\n\n // Wait for the bulk helper to finish processing.\n const result = await this.bulkResult;\n\n // Rotate main alias upon completion. Apply permanent secondary alias so\n // stale indices can be referenced for deletion in case initial attempt\n // fails. Allow errors to bubble up so that we can clean up the created index.\n this.logger.info(\n `Indexing completed for index ${this.type} in ${duration(\n this.startTimestamp,\n )}`,\n result,\n );\n await this.elasticSearchClient.indices.updateAliases({\n body: {\n actions: [\n {\n remove: { index: this.constructIndexName('*'), alias: this.alias },\n },\n this.removableIndices.length\n ? {\n add: {\n indices: this.removableIndices,\n alias: this.removableAlias,\n },\n }\n : undefined,\n {\n add: { index: this.indexName, alias: this.alias },\n },\n ].filter(Boolean),\n },\n });\n\n // If any indices are removable, remove them. Do not bubble up this error,\n // as doing so would delete the now aliased index. Log instead.\n if (this.removableIndices.length) {\n this.logger.info('Removing stale search indices', this.removableIndices);\n try {\n await this.elasticSearchClient.indices.delete({\n index: this.removableIndices,\n });\n } catch (e) {\n this.logger.warn(`Failed to remove stale search indices: ${e}`);\n }\n }\n }\n\n /**\n * Ensures that the number of documents sent over the wire to ES matches the\n * number of documents this stream has received so far. This helps manage\n * backpressure in other parts of the indexing pipeline.\n */\n private isReady(): Promise<void> {\n return new Promise(resolve => {\n const interval = setInterval(() => {\n if (this.received === this.processed) {\n clearInterval(interval);\n resolve();\n }\n }, 50);\n });\n }\n\n private constructIndexName(postFix: string) {\n return `${this.indexPrefix}${this.type}${this.indexSeparator}${postFix}`;\n }\n}\n","/*\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 awsGetCredentials,\n createAWSConnection,\n} from '@acuris/aws-es-connection';\nimport { Config } from '@backstage/config';\nimport {\n IndexableDocument,\n IndexableResult,\n IndexableResultSet,\n SearchEngine,\n SearchQuery,\n} from '@backstage/plugin-search-common';\nimport { Client } from '@elastic/elasticsearch';\nimport esb from 'elastic-builder';\nimport { isEmpty, isNaN as nan, isNumber } from 'lodash';\nimport { v4 as uuid } from 'uuid';\nimport { Logger } from 'winston';\nimport type { ElasticSearchClientOptions } from './ElasticSearchClientOptions';\nimport { ElasticSearchSearchEngineIndexer } from './ElasticSearchSearchEngineIndexer';\n\nexport type { ElasticSearchClientOptions };\n\nexport type ConcreteElasticSearchQuery = {\n documentTypes?: string[];\n elasticSearchQuery: Object;\n pageSize: number;\n};\n\n/**\n * @public\n */\nexport type ElasticSearchQueryTranslatorOptions = {\n highlightOptions?: ElasticSearchHighlightConfig;\n};\n\ntype ElasticSearchQueryTranslator = (\n query: SearchQuery,\n options?: ElasticSearchQueryTranslatorOptions,\n) => ConcreteElasticSearchQuery;\n\ntype ElasticSearchOptions = {\n logger: Logger;\n config: Config;\n aliasPostfix?: string;\n indexPrefix?: string;\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\n/**\n * @public\n */\nexport class ElasticSearchSearchEngine implements SearchEngine {\n private readonly elasticSearchClient: Client;\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: Logger,\n highlightOptions?: ElasticSearchHighlightOptions,\n ) {\n this.elasticSearchClient = this.newClient(options => new Client(options));\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({\n logger,\n config,\n aliasPostfix = `search`,\n indexPrefix = ``,\n }: ElasticSearchOptions) {\n const options = await createElasticSearchClientOptions(\n config.getConfig('search.elasticsearch'),\n );\n if (options.provider === 'elastic') {\n logger.info('Initializing Elastic.co ElasticSearch search engine.');\n } else if (options.provider === 'aws') {\n logger.info('Initializing AWS ElasticSearch search engine.');\n } else {\n logger.info('Initializing ElasticSearch search engine.');\n }\n\n return new ElasticSearchSearchEngine(\n options,\n aliasPostfix,\n indexPrefix,\n logger,\n config.getOptional<ElasticSearchHighlightOptions>(\n 'search.elasticsearch.highlightOptions',\n ),\n );\n }\n\n /**\n * Create a custom search client from the derived elastic search\n * configuration. This need not be the same client that the engine uses\n * internally.\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 ): ConcreteElasticSearchQuery {\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 return esb.matchQuery(key, 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(\n '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 const esbQuery = isBlank(term)\n ? esb.matchAllQuery()\n : esb\n .multiMatchQuery(['*'], term)\n .fuzziness('auto')\n .minimumShouldMatch(1);\n const pageSize = 25;\n const { page } = decodePageCursor(pageCursor);\n\n let esbRequestBodySearch = esb\n .requestBodySearch()\n .query(esb.boolQuery().filter(filter).must([esbQuery]))\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 getIndexer(type: string) {\n const alias = this.constructSearchAlias(type);\n const indexer = new ElasticSearchSearchEngineIndexer({\n type,\n indexPrefix: this.indexPrefix,\n indexSeparator: this.indexSeparator,\n alias,\n elasticSearchClient: this.elasticSearchClient,\n logger: this.logger,\n });\n\n // Attempt cleanup upon failure.\n indexer.on('error', async e => {\n this.logger.error(`Failed to index documents for type ${type}`, e);\n try {\n const response = await this.elasticSearchClient.indices.exists({\n index: indexer.indexName,\n });\n const indexCreated = response.body;\n if (indexCreated) {\n this.logger.info(`Removing created index ${indexer.indexName}`);\n await this.elasticSearchClient.indices.delete({\n index: indexer.indexName,\n });\n }\n } catch (error) {\n this.logger.error(`Unable to clean up elastic index: ${error}`);\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.elasticSearchClient.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((d: ElasticSearchResult) => {\n const resultItem: IndexableResult = {\n type: this.getTypeFromIndex(d._index),\n document: d._source,\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 nextPageCursor,\n previousPageCursor,\n };\n } catch (e) {\n this.logger.error(\n `Failed to query documents for indices ${queryIndices}`,\n e,\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\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\nasync function createElasticSearchClientOptions(\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 awsCredentials = await awsGetCredentials();\n const AWSConnection = createAWSConnection(awsCredentials);\n return {\n provider: 'aws',\n node: config.getString('node'),\n ...AWSConnection,\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"],"names":["BatchSearchEngineIndexer","Readable","isEmpty","isNumber","nan","Client","uuid","esb","awsGetCredentials","createAWSConnection"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/engines/ElasticSearchSearchEngineIndexer.ts","../src/engines/ElasticSearchSearchEngine.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node';\nimport { IndexableDocument } from '@backstage/plugin-search-common';\nimport { Client } from '@elastic/elasticsearch';\nimport { Readable } from 'stream';\nimport { Logger } from 'winston';\n\n/**\n * Options for instansiate ElasticSearchSearchEngineIndexer\n * @public\n */\nexport type ElasticSearchSearchEngineIndexerOptions = {\n type: string;\n indexPrefix: string;\n indexSeparator: string;\n alias: string;\n logger: Logger;\n elasticSearchClient: Client;\n};\n\nfunction duration(startTimestamp: [number, number]): string {\n const delta = process.hrtime(startTimestamp);\n const seconds = delta[0] + delta[1] / 1e9;\n return `${seconds.toFixed(1)}s`;\n}\n\n/**\n * Elasticsearch specific search engine indexer.\n * @public\n */\nexport class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer {\n private received: number = 0;\n private processed: number = 0;\n private removableIndices: string[] = [];\n\n private readonly startTimestamp: [number, number];\n private readonly type: string;\n public readonly indexName: string;\n private readonly indexPrefix: string;\n private readonly indexSeparator: string;\n private readonly alias: string;\n private readonly removableAlias: string;\n private readonly logger: Logger;\n private readonly sourceStream: Readable;\n private readonly elasticSearchClient: Client;\n private bulkResult: Promise<any>;\n\n constructor(options: ElasticSearchSearchEngineIndexerOptions) {\n super({ batchSize: 1000 });\n this.logger = options.logger;\n this.startTimestamp = process.hrtime();\n this.type = options.type;\n this.indexPrefix = options.indexPrefix;\n this.indexSeparator = options.indexSeparator;\n this.indexName = this.constructIndexName(`${Date.now()}`);\n this.alias = options.alias;\n this.removableAlias = `${this.alias}_removable`;\n this.elasticSearchClient = options.elasticSearchClient;\n\n // The ES client bulk helper supports stream-based indexing, but we have to\n // supply the stream directly to it at instantiation-time. We can't supply\n // this class itself, so instead, we create this inline stream instead.\n this.sourceStream = new Readable({ objectMode: true });\n this.sourceStream._read = () => {};\n\n // eslint-disable-next-line consistent-this\n const that = this;\n\n // Keep a reference to the ES Bulk helper so that we can know when all\n // documents have been successfully written to ES.\n this.bulkResult = this.elasticSearchClient.helpers.bulk({\n datasource: this.sourceStream,\n onDocument() {\n that.processed++;\n return {\n index: { _index: that.indexName },\n };\n },\n refreshOnCompletion: that.indexName,\n });\n }\n\n async initialize(): Promise<void> {\n this.logger.info(`Started indexing documents for index ${this.type}`);\n\n const aliases = await this.elasticSearchClient.cat.aliases({\n format: 'json',\n name: [this.alias, this.removableAlias],\n });\n\n this.removableIndices = [\n ...new Set(aliases.body.map((r: Record<string, any>) => r.index)),\n ] as string[];\n\n await this.elasticSearchClient.indices.create({\n index: this.indexName,\n });\n }\n\n async index(documents: IndexableDocument[]): Promise<void> {\n await this.isReady();\n documents.forEach(document => {\n this.received++;\n this.sourceStream.push(document);\n });\n }\n\n async finalize(): Promise<void> {\n // Wait for all documents to be processed.\n await this.isReady();\n\n // Close off the underlying stream connected to ES, indicating that no more\n // documents will be written.\n this.sourceStream.push(null);\n\n // Wait for the bulk helper to finish processing.\n const result = await this.bulkResult;\n\n // Rotate main alias upon completion. Apply permanent secondary alias so\n // stale indices can be referenced for deletion in case initial attempt\n // fails. Allow errors to bubble up so that we can clean up the created index.\n this.logger.info(\n `Indexing completed for index ${this.type} in ${duration(\n this.startTimestamp,\n )}`,\n result,\n );\n await this.elasticSearchClient.indices.updateAliases({\n body: {\n actions: [\n {\n remove: { index: this.constructIndexName('*'), alias: this.alias },\n },\n this.removableIndices.length\n ? {\n add: {\n indices: this.removableIndices,\n alias: this.removableAlias,\n },\n }\n : undefined,\n {\n add: { index: this.indexName, alias: this.alias },\n },\n ].filter(Boolean),\n },\n });\n\n // If any indices are removable, remove them. Do not bubble up this error,\n // as doing so would delete the now aliased index. Log instead.\n if (this.removableIndices.length) {\n this.logger.info('Removing stale search indices', this.removableIndices);\n try {\n await this.elasticSearchClient.indices.delete({\n index: this.removableIndices,\n });\n } catch (e) {\n this.logger.warn(`Failed to remove stale search indices: ${e}`);\n }\n }\n }\n\n /**\n * Ensures that the number of documents sent over the wire to ES matches the\n * number of documents this stream has received so far. This helps manage\n * backpressure in other parts of the indexing pipeline.\n */\n private isReady(): Promise<void> {\n return new Promise(resolve => {\n const interval = setInterval(() => {\n if (this.received === this.processed) {\n clearInterval(interval);\n resolve();\n }\n }, 50);\n });\n }\n\n private constructIndexName(postFix: string) {\n return `${this.indexPrefix}${this.type}${this.indexSeparator}${postFix}`;\n }\n}\n","/*\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 awsGetCredentials,\n createAWSConnection,\n} from '@acuris/aws-es-connection';\nimport { Config } from '@backstage/config';\nimport {\n IndexableDocument,\n IndexableResult,\n IndexableResultSet,\n SearchEngine,\n SearchQuery,\n} from '@backstage/plugin-search-common';\nimport { Client } from '@elastic/elasticsearch';\nimport esb from 'elastic-builder';\nimport { isEmpty, isNaN as nan, isNumber } from 'lodash';\nimport { v4 as uuid } from 'uuid';\nimport { Logger } from 'winston';\nimport type { ElasticSearchClientOptions } from './ElasticSearchClientOptions';\nimport { ElasticSearchSearchEngineIndexer } from './ElasticSearchSearchEngineIndexer';\n\nexport type { ElasticSearchClientOptions };\n\n/**\n * Elasticsearch specific index template\n * @public\n */\nexport type ElasticSearchCustomIndexTemplate = {\n name: string;\n body: ElasticSearchCustomIndexTemplateBody;\n};\n\n/**\n * Elasticsearch specific index template body\n * @public\n */\nexport type ElasticSearchCustomIndexTemplateBody = {\n /**\n * Array of wildcard (*) expressions used to match the names of data streams and indices during creation.\n */\n index_patterns: string[];\n /**\n * An ordered list of component template names.\n * Component templates are merged in the order specified,\n * meaning that the last component template specified has the highest precedence.\n */\n composed_of?: string[];\n /**\n * See available properties of template\n * https://www.elastic.co/guide/en/elasticsearch/reference/7.15/indices-put-template.html#put-index-template-api-request-body\n */\n template?: Record<string, any>;\n};\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 instansiate ElasticSearchSearchEngine\n * @public\n */\nexport type ElasticSearchOptions = {\n logger: Logger;\n config: Config;\n aliasPostfix?: string;\n indexPrefix?: string;\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\n/**\n * @public\n */\nexport class ElasticSearchSearchEngine implements SearchEngine {\n private readonly elasticSearchClient: Client;\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: Logger,\n highlightOptions?: ElasticSearchHighlightOptions,\n ) {\n this.elasticSearchClient = this.newClient(options => new Client(options));\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({\n logger,\n config,\n aliasPostfix = `search`,\n indexPrefix = ``,\n }: ElasticSearchOptions) {\n const options = await createElasticSearchClientOptions(\n config.getConfig('search.elasticsearch'),\n );\n if (options.provider === 'elastic') {\n logger.info('Initializing Elastic.co ElasticSearch search engine.');\n } else if (options.provider === 'aws') {\n logger.info('Initializing AWS ElasticSearch search engine.');\n } else {\n logger.info('Initializing ElasticSearch search engine.');\n }\n\n return new ElasticSearchSearchEngine(\n options,\n aliasPostfix,\n indexPrefix,\n logger,\n config.getOptional<ElasticSearchHighlightOptions>(\n 'search.elasticsearch.highlightOptions',\n ),\n );\n }\n\n /**\n * Create a custom search client from the derived elastic search\n * configuration. This need not be the same client that the engine uses\n * internally.\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(\n '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 const esbQuery = isBlank(term)\n ? esb.matchAllQuery()\n : esb\n .multiMatchQuery(['*'], term)\n .fuzziness('auto')\n .minimumShouldMatch(1);\n const pageSize = 25;\n const { page } = decodePageCursor(pageCursor);\n\n let esbRequestBodySearch = esb\n .requestBodySearch()\n .query(esb.boolQuery().filter(filter).must([esbQuery]))\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.elasticSearchClient.indices.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\n const indexer = new ElasticSearchSearchEngineIndexer({\n type,\n indexPrefix: this.indexPrefix,\n indexSeparator: this.indexSeparator,\n alias,\n elasticSearchClient: this.elasticSearchClient,\n logger: this.logger,\n });\n\n // Attempt cleanup upon failure.\n indexer.on('error', async e => {\n this.logger.error(`Failed to index documents for type ${type}`, e);\n try {\n const response = await this.elasticSearchClient.indices.exists({\n index: indexer.indexName,\n });\n const indexCreated = response.body;\n if (indexCreated) {\n this.logger.info(`Removing created index ${indexer.indexName}`);\n await this.elasticSearchClient.indices.delete({\n index: indexer.indexName,\n });\n }\n } catch (error) {\n this.logger.error(`Unable to clean up elastic index: ${error}`);\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.elasticSearchClient.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 };\n } catch (e) {\n this.logger.error(\n `Failed to query documents for indices ${queryIndices}`,\n e,\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\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\nasync function createElasticSearchClientOptions(\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 awsCredentials = await awsGetCredentials();\n const AWSConnection = createAWSConnection(awsCredentials);\n return {\n provider: 'aws',\n node: config.getString('node'),\n ...AWSConnection,\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"],"names":["BatchSearchEngineIndexer","Readable","isEmpty","isNumber","nan","Client","uuid","esb","awsGetCredentials","createAWSConnection"],"mappings":";;;;;;;;;;;;;;;;AAEA,SAAS,QAAQ,CAAC,cAAc,EAAE;AAClC,EAAE,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;AAC/C,EAAE,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AAC5C,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClC,CAAC;AACM,MAAM,gCAAgC,SAASA,gDAAwB,CAAC;AAC/E,EAAE,WAAW,CAAC,OAAO,EAAE;AACvB,IAAI,KAAK,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;AAC9B,IAAI,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;AACtB,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;AACvB,IAAI,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;AAC/B,IAAI,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;AACjC,IAAI,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;AAC3C,IAAI,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;AAC7B,IAAI,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;AAC3C,IAAI,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;AACjD,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9D,IAAI,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;AAC/B,IAAI,IAAI,CAAC,cAAc,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AACpD,IAAI,IAAI,CAAC,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC;AAC3D,IAAI,IAAI,CAAC,YAAY,GAAG,IAAIC,eAAQ,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3D,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,GAAG,MAAM;AACpC,KAAK,CAAC;AACN,IAAI,MAAM,IAAI,GAAG,IAAI,CAAC;AACtB,IAAI,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC;AAC5D,MAAM,UAAU,EAAE,IAAI,CAAC,YAAY;AACnC,MAAM,UAAU,GAAG;AACnB,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;AACzB,QAAQ,OAAO;AACf,UAAU,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE;AAC3C,SAAS,CAAC;AACV,OAAO;AACP,MAAM,mBAAmB,EAAE,IAAI,CAAC,SAAS;AACzC,KAAK,CAAC,CAAC;AACP,GAAG;AACH,EAAE,MAAM,UAAU,GAAG;AACrB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,qCAAqC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1E,IAAI,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC;AAC/D,MAAM,MAAM,EAAE,MAAM;AACpB,MAAM,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC;AAC7C,KAAK,CAAC,CAAC;AACP,IAAI,IAAI,CAAC,gBAAgB,GAAG;AAC5B,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;AAClD,KAAK,CAAC;AACN,IAAI,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC;AAClD,MAAM,KAAK,EAAE,IAAI,CAAC,SAAS;AAC3B,KAAK,CAAC,CAAC;AACP,GAAG;AACH,EAAE,MAAM,KAAK,CAAC,SAAS,EAAE;AACzB,IAAI,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;AACzB,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAK;AACpC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;AACtB,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACvC,KAAK,CAAC,CAAC;AACP,GAAG;AACH,EAAE,MAAM,QAAQ,GAAG;AACnB,IAAI,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;AACzB,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjC,IAAI,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;AACzC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,6BAA6B,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAC9G,IAAI,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,aAAa,CAAC;AACzD,MAAM,IAAI,EAAE;AACZ,QAAQ,OAAO,EAAE;AACjB,UAAU;AACV,YAAY,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;AAC9E,WAAW;AACX,UAAU,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG;AACzC,YAAY,GAAG,EAAE;AACjB,cAAc,OAAO,EAAE,IAAI,CAAC,gBAAgB;AAC5C,cAAc,KAAK,EAAE,IAAI,CAAC,cAAc;AACxC,aAAa;AACb,WAAW,GAAG,KAAK,CAAC;AACpB,UAAU;AACV,YAAY,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;AAC7D,WAAW;AACX,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC;AACzB,OAAO;AACP,KAAK,CAAC,CAAC;AACP,IAAI,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE;AACtC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;AAC/E,MAAM,IAAI;AACV,QAAQ,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC;AACtD,UAAU,KAAK,EAAE,IAAI,CAAC,gBAAgB;AACtC,SAAS,CAAC,CAAC;AACX,OAAO,CAAC,OAAO,CAAC,EAAE;AAClB,QAAQ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,uCAAuC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACxE,OAAO;AACP,KAAK;AACL,GAAG;AACH,EAAE,OAAO,GAAG;AACZ,IAAI,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK;AACpC,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM;AACzC,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,SAAS,EAAE;AAC9C,UAAU,aAAa,CAAC,QAAQ,CAAC,CAAC;AAClC,UAAU,OAAO,EAAE,CAAC;AACpB,SAAS;AACT,OAAO,EAAE,EAAE,CAAC,CAAC;AACb,KAAK,CAAC,CAAC;AACP,GAAG;AACH,EAAE,kBAAkB,CAAC,OAAO,EAAE;AAC9B,IAAI,OAAO,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7E,GAAG;AACH;;AC/FA,SAAS,OAAO,CAAC,GAAG,EAAE;AACtB,EAAE,OAAOC,cAAO,CAAC,GAAG,CAAC,IAAI,CAACC,eAAQ,CAAC,GAAG,CAAC,IAAIC,YAAG,CAAC,GAAG,CAAC,CAAC;AACpD,CAAC;AACM,MAAM,yBAAyB,CAAC;AACvC,EAAE,WAAW,CAAC,0BAA0B,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE;AAC/F,IAAI,IAAI,CAAC,0BAA0B,GAAG,0BAA0B,CAAC;AACjE,IAAI,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;AACrC,IAAI,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;AACnC,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;AACzB,IAAI,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC;AACrC,IAAI,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,KAAK,IAAIC,oBAAM,CAAC,OAAO,CAAC,CAAC,CAAC;AAChF,IAAI,MAAM,OAAO,GAAGC,OAAI,EAAE,CAAC;AAC3B,IAAI,IAAI,CAAC,gBAAgB,GAAG;AAC5B,MAAM,MAAM,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAC5B,MAAM,OAAO,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;AAC9B,MAAM,YAAY,EAAE,GAAG;AACvB,MAAM,YAAY,EAAE,CAAC;AACrB,MAAM,iBAAiB,EAAE,OAAO;AAChC,MAAM,GAAG,gBAAgB;AACzB,KAAK,CAAC;AACN,GAAG;AACH,EAAE,aAAa,UAAU,CAAC;AAC1B,IAAI,MAAM;AACV,IAAI,MAAM;AACV,IAAI,YAAY,GAAG,CAAC,MAAM,CAAC;AAC3B,IAAI,WAAW,GAAG,CAAC,CAAC;AACpB,GAAG,EAAE;AACL,IAAI,MAAM,OAAO,GAAG,MAAM,gCAAgC,CAAC,MAAM,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC,CAAC;AACrG,IAAI,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE;AACxC,MAAM,MAAM,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;AAC1E,KAAK,MAAM,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE;AAC3C,MAAM,MAAM,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;AACnE,KAAK,MAAM;AACX,MAAM,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;AAC/D,KAAK;AACL,IAAI,OAAO,IAAI,yBAAyB,CAAC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,uCAAuC,CAAC,CAAC,CAAC;AAClJ,GAAG;AACH,EAAE,SAAS,CAAC,MAAM,EAAE;AACpB,IAAI,OAAO,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;AACnD,GAAG;AACH,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE;AAC7B,IAAI,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;AAC5D,IAAI,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK;AACxG,MAAM,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,OAAO,KAAK,CAAC,EAAE;AAClE,QAAQ,MAAM,OAAO,GAAG,OAAO,KAAK,KAAK,QAAQ,GAAG,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC;AAC3E,QAAQ,OAAOC,uBAAG,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;AACzD,OAAO;AACP,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AAChC,QAAQ,OAAOA,uBAAG,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,KAAKA,uBAAG,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;AAC7F,OAAO;AACP,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2CAA2C,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AACjF,MAAM,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;AAClF,KAAK,CAAC,CAAC;AACP,IAAI,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,GAAGA,uBAAG,CAAC,aAAa,EAAE,GAAGA,uBAAG,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;AACpI,IAAI,MAAM,QAAQ,GAAG,EAAE,CAAC;AACxB,IAAI,MAAM,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;AAClD,IAAI,IAAI,oBAAoB,GAAGA,uBAAG,CAAC,iBAAiB,EAAE,CAAC,KAAK,CAACA,uBAAG,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACnJ,IAAI,IAAI,OAAO,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,gBAAgB,EAAE;AAC7D,MAAM,oBAAoB,GAAG,oBAAoB,CAAC,SAAS,CAACA,uBAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;AACjR,KAAK;AACL,IAAI,OAAO;AACX,MAAM,kBAAkB,EAAE,oBAAoB,CAAC,MAAM,EAAE;AACvD,MAAM,aAAa,EAAE,KAAK;AAC1B,MAAM,QAAQ;AACd,KAAK,CAAC;AACN,GAAG;AACH,EAAE,aAAa,CAAC,UAAU,EAAE;AAC5B,IAAI,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;AACjC,GAAG;AACH,EAAE,MAAM,gBAAgB,CAAC,QAAQ,EAAE;AACnC,IAAI,IAAI;AACR,MAAM,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AACxE,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;AACpD,KAAK,CAAC,OAAO,KAAK,EAAE;AACpB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AACzE,KAAK;AACL,GAAG;AACH,EAAE,MAAM,UAAU,CAAC,IAAI,EAAE;AACzB,IAAI,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;AAClD,IAAI,MAAM,OAAO,GAAG,IAAI,gCAAgC,CAAC;AACzD,MAAM,IAAI;AACV,MAAM,WAAW,EAAE,IAAI,CAAC,WAAW;AACnC,MAAM,cAAc,EAAE,IAAI,CAAC,cAAc;AACzC,MAAM,KAAK;AACX,MAAM,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;AACnD,MAAM,MAAM,EAAE,IAAI,CAAC,MAAM;AACzB,KAAK,CAAC,CAAC;AACP,IAAI,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK;AACrC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,mCAAmC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACzE,MAAM,IAAI;AACV,QAAQ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC;AACvE,UAAU,KAAK,EAAE,OAAO,CAAC,SAAS;AAClC,SAAS,CAAC,CAAC;AACX,QAAQ,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC;AAC3C,QAAQ,IAAI,YAAY,EAAE;AAC1B,UAAU,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,uBAAuB,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC1E,UAAU,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC;AACxD,YAAY,KAAK,EAAE,OAAO,CAAC,SAAS;AACpC,WAAW,CAAC,CAAC;AACb,SAAS;AACT,OAAO,CAAC,OAAO,KAAK,EAAE;AACtB,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AACxE,OAAO;AACP,KAAK,CAAC,CAAC;AACP,IAAI,OAAO,OAAO,CAAC;AACnB,GAAG;AACH,EAAE,MAAM,KAAK,CAAC,KAAK,EAAE;AACrB,IAAI,MAAM,EAAE,kBAAkB,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;AAChI,IAAI,MAAM,YAAY,GAAG,aAAa,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;AACnI,IAAI,IAAI;AACR,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC;AAC3D,QAAQ,KAAK,EAAE,YAAY;AAC3B,QAAQ,IAAI,EAAE,kBAAkB;AAChC,OAAO,CAAC,CAAC;AACT,MAAM,MAAM,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AAC1D,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,QAAQ,CAAC;AAC/E,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC;AACvC,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC;AACzF,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC;AACjG,MAAM,OAAO;AACb,QAAQ,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK;AACzD,UAAU,MAAM,UAAU,GAAG;AAC7B,YAAY,IAAI,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC;AACjD,YAAY,QAAQ,EAAE,CAAC,CAAC,OAAO;AAC/B,YAAY,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,KAAK,GAAG,CAAC;AAC7C,WAAW,CAAC;AACZ,UAAU,IAAI,CAAC,CAAC,SAAS,EAAE;AAC3B,YAAY,UAAU,CAAC,SAAS,GAAG;AACnC,cAAc,MAAM,EAAE,IAAI,CAAC,gBAAgB,CAAC,MAAM;AAClD,cAAc,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAAC,OAAO;AACpD,cAAc,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK;AACjG,gBAAgB,KAAK;AACrB,gBAAgB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,CAAC;AACvE,eAAe,CAAC,CAAC;AACjB,aAAa,CAAC;AACd,WAAW;AACX,UAAU,OAAO,UAAU,CAAC;AAC5B,SAAS,CAAC;AACV,QAAQ,cAAc;AACtB,QAAQ,kBAAkB;AAC1B,OAAO,CAAC;AACR,KAAK,CAAC,OAAO,CAAC,EAAE;AAChB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,sCAAsC,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACpF,MAAM,OAAO,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;AAC7C,KAAK;AACL,GAAG;AACH,EAAE,gBAAgB,CAAC,KAAK,EAAE;AAC1B,IAAI,OAAO,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AAClF,GAAG;AACH,EAAE,oBAAoB,CAAC,IAAI,EAAE;AAC7B,IAAI,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,CAAC;AACtE,IAAI,OAAO,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAClD,GAAG;AACH,CAAC;AACM,SAAS,gBAAgB,CAAC,UAAU,EAAE;AAC7C,EAAE,IAAI,CAAC,UAAU,EAAE;AACnB,IAAI,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACvB,GAAG;AACH,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACrE,GAAG,CAAC;AACJ,CAAC;AACM,SAAS,gBAAgB,CAAC,EAAE,IAAI,EAAE,EAAE;AAC3C,EAAE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC5D,CAAC;AACD,eAAe,gCAAgC,CAAC,MAAM,EAAE;AACxD,EAAE,IAAI,CAAC,MAAM,EAAE;AACf,IAAI,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;AACtD,GAAG;AACH,EAAE,MAAM,mBAAmB,GAAG,MAAM,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;AACxE,EAAE,MAAM,SAAS,GAAG,mBAAmB,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,mBAAmB,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;AACxG,EAAE,IAAI,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC,KAAK,SAAS,EAAE;AAC1D,IAAI,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AACjD,IAAI,OAAO;AACX,MAAM,QAAQ,EAAE,SAAS;AACzB,MAAM,KAAK,EAAE;AACb,QAAQ,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;AACvC,OAAO;AACP,MAAM,IAAI,EAAE;AACZ,QAAQ,QAAQ,EAAE,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC;AACnD,QAAQ,QAAQ,EAAE,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC;AACnD,OAAO;AACP,MAAM,GAAG,SAAS,GAAG;AACrB,QAAQ,GAAG,EAAE;AACb,UAAU,kBAAkB,EAAE,SAAS,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,SAAS,CAAC,kBAAkB,CAAC,oBAAoB,CAAC;AAC7G,SAAS;AACT,OAAO,GAAG,EAAE;AACZ,KAAK,CAAC;AACN,GAAG;AACH,EAAE,IAAI,MAAM,CAAC,iBAAiB,CAAC,UAAU,CAAC,KAAK,KAAK,EAAE;AACtD,IAAI,MAAM,cAAc,GAAG,MAAMC,iCAAiB,EAAE,CAAC;AACrD,IAAI,MAAM,aAAa,GAAGC,mCAAmB,CAAC,cAAc,CAAC,CAAC;AAC9D,IAAI,OAAO;AACX,MAAM,QAAQ,EAAE,KAAK;AACrB,MAAM,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;AACpC,MAAM,GAAG,aAAa;AACtB,MAAM,GAAG,SAAS,GAAG;AACrB,QAAQ,GAAG,EAAE;AACb,UAAU,kBAAkB,EAAE,SAAS,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,SAAS,CAAC,kBAAkB,CAAC,oBAAoB,CAAC;AAC7G,SAAS;AACT,OAAO,GAAG,EAAE;AACZ,KAAK,CAAC;AACN,GAAG;AACH,EAAE,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;AACtD,EAAE,MAAM,IAAI,GAAG,UAAU,KAAK,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG;AACzD,IAAI,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC;AAC1C,GAAG,GAAG;AACN,IAAI,QAAQ,EAAE,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC;AAC9C,IAAI,QAAQ,EAAE,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC;AAC9C,GAAG,CAAC,CAAC;AACL,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;AAClC,IAAI,IAAI;AACR,IAAI,GAAG,SAAS,GAAG;AACnB,MAAM,GAAG,EAAE;AACX,QAAQ,kBAAkB,EAAE,SAAS,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,SAAS,CAAC,kBAAkB,CAAC,oBAAoB,CAAC;AAC3G,OAAO;AACP,KAAK,GAAG,EAAE;AACV,GAAG,CAAC;AACJ;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { Config } from '@backstage/config';
|
|
3
|
-
import { IndexableDocument,
|
|
3
|
+
import { IndexableDocument, SearchQuery, SearchEngine, IndexableResultSet } from '@backstage/plugin-search-common';
|
|
4
4
|
import { Logger } from 'winston';
|
|
5
5
|
import { ConnectionOptions } from 'tls';
|
|
6
6
|
import { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node';
|
|
@@ -9,10 +9,12 @@ import { Client } from '@elastic/elasticsearch';
|
|
|
9
9
|
/**
|
|
10
10
|
* Options used to configure the `@elastic/elasticsearch` client and
|
|
11
11
|
* are what will be passed as an argument to the
|
|
12
|
-
* {@link
|
|
12
|
+
* {@link ElasticSearchSearchEngine.newClient} method
|
|
13
13
|
*
|
|
14
14
|
* They are drawn from the `ClientOptions` class of `@elastic/elasticsearch`,
|
|
15
15
|
* but are maintained separately so that this interface is not coupled to
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
16
18
|
*/
|
|
17
19
|
interface ElasticSearchClientOptions {
|
|
18
20
|
provider?: 'aws' | 'elastic';
|
|
@@ -47,6 +49,9 @@ interface ElasticSearchClientOptions {
|
|
|
47
49
|
};
|
|
48
50
|
disablePrototypePoisoningProtection?: boolean | 'proto' | 'constructor';
|
|
49
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* @public
|
|
54
|
+
*/
|
|
50
55
|
declare type ElasticSearchAuth = {
|
|
51
56
|
username: string;
|
|
52
57
|
password: string;
|
|
@@ -56,6 +61,9 @@ declare type ElasticSearchAuth = {
|
|
|
56
61
|
api_key: string;
|
|
57
62
|
};
|
|
58
63
|
};
|
|
64
|
+
/**
|
|
65
|
+
* @public
|
|
66
|
+
*/
|
|
59
67
|
interface ElasticSearchNodeOptions {
|
|
60
68
|
url: URL;
|
|
61
69
|
id?: string;
|
|
@@ -69,12 +77,18 @@ interface ElasticSearchNodeOptions {
|
|
|
69
77
|
ml: boolean;
|
|
70
78
|
};
|
|
71
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
72
83
|
interface ElasticSearchAgentOptions {
|
|
73
84
|
keepAlive?: boolean;
|
|
74
85
|
keepAliveMsecs?: number;
|
|
75
86
|
maxSockets?: number;
|
|
76
87
|
maxFreeSockets?: number;
|
|
77
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* @public
|
|
91
|
+
*/
|
|
78
92
|
interface ElasticSearchConnectionConstructor {
|
|
79
93
|
new (opts?: any): any;
|
|
80
94
|
statuses: {
|
|
@@ -88,6 +102,9 @@ interface ElasticSearchConnectionConstructor {
|
|
|
88
102
|
ML: string;
|
|
89
103
|
};
|
|
90
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* @public
|
|
107
|
+
*/
|
|
91
108
|
interface ElasticSearchTransportConstructor {
|
|
92
109
|
new (opts?: any): any;
|
|
93
110
|
sniffReasons: {
|
|
@@ -98,6 +115,10 @@ interface ElasticSearchTransportConstructor {
|
|
|
98
115
|
};
|
|
99
116
|
}
|
|
100
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Options for instansiate ElasticSearchSearchEngineIndexer
|
|
120
|
+
* @public
|
|
121
|
+
*/
|
|
101
122
|
declare type ElasticSearchSearchEngineIndexerOptions = {
|
|
102
123
|
type: string;
|
|
103
124
|
indexPrefix: string;
|
|
@@ -106,6 +127,10 @@ declare type ElasticSearchSearchEngineIndexerOptions = {
|
|
|
106
127
|
logger: Logger;
|
|
107
128
|
elasticSearchClient: Client;
|
|
108
129
|
};
|
|
130
|
+
/**
|
|
131
|
+
* Elasticsearch specific search engine indexer.
|
|
132
|
+
* @public
|
|
133
|
+
*/
|
|
109
134
|
declare class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer {
|
|
110
135
|
private received;
|
|
111
136
|
private processed;
|
|
@@ -134,18 +159,60 @@ declare class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer
|
|
|
134
159
|
private constructIndexName;
|
|
135
160
|
}
|
|
136
161
|
|
|
137
|
-
|
|
162
|
+
/**
|
|
163
|
+
* Elasticsearch specific index template
|
|
164
|
+
* @public
|
|
165
|
+
*/
|
|
166
|
+
declare type ElasticSearchCustomIndexTemplate = {
|
|
167
|
+
name: string;
|
|
168
|
+
body: ElasticSearchCustomIndexTemplateBody;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Elasticsearch specific index template body
|
|
172
|
+
* @public
|
|
173
|
+
*/
|
|
174
|
+
declare type ElasticSearchCustomIndexTemplateBody = {
|
|
175
|
+
/**
|
|
176
|
+
* Array of wildcard (*) expressions used to match the names of data streams and indices during creation.
|
|
177
|
+
*/
|
|
178
|
+
index_patterns: string[];
|
|
179
|
+
/**
|
|
180
|
+
* An ordered list of component template names.
|
|
181
|
+
* Component templates are merged in the order specified,
|
|
182
|
+
* meaning that the last component template specified has the highest precedence.
|
|
183
|
+
*/
|
|
184
|
+
composed_of?: string[];
|
|
185
|
+
/**
|
|
186
|
+
* See available properties of template
|
|
187
|
+
* https://www.elastic.co/guide/en/elasticsearch/reference/7.15/indices-put-template.html#put-index-template-api-request-body
|
|
188
|
+
*/
|
|
189
|
+
template?: Record<string, any>;
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* Search query that the elasticsearch engine understands.
|
|
193
|
+
* @public
|
|
194
|
+
*/
|
|
195
|
+
declare type ElasticSearchConcreteQuery = {
|
|
138
196
|
documentTypes?: string[];
|
|
139
197
|
elasticSearchQuery: Object;
|
|
140
198
|
pageSize: number;
|
|
141
199
|
};
|
|
142
200
|
/**
|
|
201
|
+
* Options available for the Elasticsearch specific query translator.
|
|
143
202
|
* @public
|
|
144
203
|
*/
|
|
145
204
|
declare type ElasticSearchQueryTranslatorOptions = {
|
|
146
205
|
highlightOptions?: ElasticSearchHighlightConfig;
|
|
147
206
|
};
|
|
148
|
-
|
|
207
|
+
/**
|
|
208
|
+
* Elasticsearch specific query translator.
|
|
209
|
+
* @public
|
|
210
|
+
*/
|
|
211
|
+
declare type ElasticSearchQueryTranslator = (query: SearchQuery, options?: ElasticSearchQueryTranslatorOptions) => ElasticSearchConcreteQuery;
|
|
212
|
+
/**
|
|
213
|
+
* Options for instansiate ElasticSearchSearchEngine
|
|
214
|
+
* @public
|
|
215
|
+
*/
|
|
149
216
|
declare type ElasticSearchOptions = {
|
|
150
217
|
logger: Logger;
|
|
151
218
|
config: Config;
|
|
@@ -188,8 +255,9 @@ declare class ElasticSearchSearchEngine implements SearchEngine {
|
|
|
188
255
|
* internally.
|
|
189
256
|
*/
|
|
190
257
|
newClient<T>(create: (options: ElasticSearchClientOptions) => T): T;
|
|
191
|
-
protected translator(query: SearchQuery, options?: ElasticSearchQueryTranslatorOptions):
|
|
258
|
+
protected translator(query: SearchQuery, options?: ElasticSearchQueryTranslatorOptions): ElasticSearchConcreteQuery;
|
|
192
259
|
setTranslator(translator: ElasticSearchQueryTranslator): void;
|
|
260
|
+
setIndexTemplate(template: ElasticSearchCustomIndexTemplate): Promise<void>;
|
|
193
261
|
getIndexer(type: string): Promise<ElasticSearchSearchEngineIndexer>;
|
|
194
262
|
query(query: SearchQuery): Promise<IndexableResultSet>;
|
|
195
263
|
private readonly indexSeparator;
|
|
@@ -197,4 +265,4 @@ declare class ElasticSearchSearchEngine implements SearchEngine {
|
|
|
197
265
|
private constructSearchAlias;
|
|
198
266
|
}
|
|
199
267
|
|
|
200
|
-
export { ElasticSearchClientOptions, ElasticSearchHighlightConfig, ElasticSearchHighlightOptions, ElasticSearchQueryTranslatorOptions, ElasticSearchSearchEngine, ElasticSearchSearchEngineIndexer, ElasticSearchSearchEngineIndexerOptions };
|
|
268
|
+
export { ElasticSearchAgentOptions, ElasticSearchAuth, ElasticSearchClientOptions, ElasticSearchConcreteQuery, ElasticSearchConnectionConstructor, ElasticSearchCustomIndexTemplate, ElasticSearchCustomIndexTemplateBody, ElasticSearchHighlightConfig, ElasticSearchHighlightOptions, ElasticSearchNodeOptions, ElasticSearchOptions, ElasticSearchQueryTranslator, ElasticSearchQueryTranslatorOptions, ElasticSearchSearchEngine, ElasticSearchSearchEngineIndexer, ElasticSearchSearchEngineIndexerOptions, ElasticSearchTransportConstructor };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-search-backend-module-elasticsearch",
|
|
3
3
|
"description": "A module for the search backend that implements search using ElasticSearch",
|
|
4
|
-
"version": "0.1.5
|
|
4
|
+
"version": "0.1.5",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@acuris/aws-es-connection": "^2.2.0",
|
|
27
27
|
"@backstage/config": "^1.0.1",
|
|
28
|
-
"@backstage/plugin-search-backend-node": "^0.6.2
|
|
29
|
-
"@backstage/plugin-search-common": "^0.3.
|
|
28
|
+
"@backstage/plugin-search-backend-node": "^0.6.2",
|
|
29
|
+
"@backstage/plugin-search-common": "^0.3.5",
|
|
30
30
|
"@elastic/elasticsearch": "7.13.0",
|
|
31
31
|
"aws-sdk": "^2.948.0",
|
|
32
32
|
"elastic-builder": "^2.16.0",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"winston": "^3.2.1"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@backstage/backend-common": "^0.
|
|
39
|
-
"@backstage/cli": "^0.17.2
|
|
38
|
+
"@backstage/backend-common": "^0.14.0",
|
|
39
|
+
"@backstage/cli": "^0.17.2",
|
|
40
40
|
"@elastic/elasticsearch-mock": "^1.0.0"
|
|
41
41
|
},
|
|
42
42
|
"files": [
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"config.d.ts"
|
|
45
45
|
],
|
|
46
46
|
"configSchema": "config.d.ts",
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "e42cb3887e41f756c16380d757d93feda27f40ee"
|
|
48
48
|
}
|