@backstage/plugin-search-backend-module-elasticsearch 0.1.5-next.2 → 0.2.0-next.1
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 +60 -0
- package/dist/index.cjs.js +154 -35
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +206 -20
- package/package.json +11 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
1
|
# @backstage/plugin-search-backend-module-elasticsearch
|
|
2
2
|
|
|
3
|
+
## 0.2.0-next.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- c5af773757: **BREAKING**: In order to remain interoperable with all currently supported
|
|
8
|
+
deployments of Elasticsearch, this package will now conditionally use either
|
|
9
|
+
the `@elastic/elasticsearch` or `@opensearch-project/opensearch` client when
|
|
10
|
+
communicating with your deployed cluster.
|
|
11
|
+
|
|
12
|
+
If you do not rely on types exported from this package, or if you do not make
|
|
13
|
+
use of the `createElasticSearchClientOptions` or `newClient` methods on the
|
|
14
|
+
`ElasticSearchSearchEngine` class, then upgrading to this version should not
|
|
15
|
+
require any further action on your part. Everything will continue to work as it
|
|
16
|
+
always has.
|
|
17
|
+
|
|
18
|
+
If you _do_ rely on either of the above methods or any underlying types, some
|
|
19
|
+
changes may be needed to your custom code. A type guard is now exported by this
|
|
20
|
+
package (`isOpenSearchCompatible(options)`), which you may use to help clarify
|
|
21
|
+
which client options are compatible with which client constructors.
|
|
22
|
+
|
|
23
|
+
If you are using this package with the `search.elasticsearch.provider` set to
|
|
24
|
+
`aws`, and you are making use of the `newClient` method in particular, you may
|
|
25
|
+
wish to start using the `@opensearch-project/opensearch` client in your custom
|
|
26
|
+
code.
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- Updated dependencies
|
|
31
|
+
- @backstage/plugin-search-backend-node@0.6.3-next.1
|
|
32
|
+
- @backstage/plugin-search-common@0.3.6-next.0
|
|
33
|
+
|
|
34
|
+
## 0.1.6-next.0
|
|
35
|
+
|
|
36
|
+
### Patch Changes
|
|
37
|
+
|
|
38
|
+
- Updated dependencies
|
|
39
|
+
- @backstage/plugin-search-backend-node@0.6.3-next.0
|
|
40
|
+
|
|
41
|
+
## 0.1.5
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- 281cec1b61: Use more precise matching for query filters
|
|
46
|
+
- 915700f64f: The provided search engine now adds a pagination-aware `rank` value to all results.
|
|
47
|
+
- ddce23d080: Now possible to set a custom index template on the elasticsearch search engine.
|
|
48
|
+
- 7d8acfc32e: Additional types now exported publicly:
|
|
49
|
+
|
|
50
|
+
- ElasticSearchAgentOptions
|
|
51
|
+
- ElasticSearchConcreteQuery
|
|
52
|
+
- ElasticSearchQueryTranslator
|
|
53
|
+
- ElasticSearchConnectionConstructor,
|
|
54
|
+
- ElasticSearchTransportConstructor,
|
|
55
|
+
- ElasticSearchNodeOptions,
|
|
56
|
+
- ElasticSearchOptions,
|
|
57
|
+
- ElasticSearchAuth,
|
|
58
|
+
|
|
59
|
+
- Updated dependencies
|
|
60
|
+
- @backstage/plugin-search-common@0.3.5
|
|
61
|
+
- @backstage/plugin-search-backend-node@0.6.2
|
|
62
|
+
|
|
3
63
|
## 0.1.5-next.2
|
|
4
64
|
|
|
5
65
|
### Patch Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
6
|
-
var elasticsearch = require('@elastic/elasticsearch');
|
|
5
|
+
var awsOsConnection = require('aws-os-connection');
|
|
7
6
|
var esb = require('elastic-builder');
|
|
8
7
|
var lodash = require('lodash');
|
|
9
8
|
var uuid = require('uuid');
|
|
10
9
|
var pluginSearchBackendNode = require('@backstage/plugin-search-backend-node');
|
|
11
10
|
var stream = require('stream');
|
|
11
|
+
var elasticsearch = require('@elastic/elasticsearch');
|
|
12
|
+
var opensearch = require('@opensearch-project/opensearch');
|
|
12
13
|
|
|
13
14
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
14
15
|
|
|
@@ -33,12 +34,12 @@ class ElasticSearchSearchEngineIndexer extends pluginSearchBackendNode.BatchSear
|
|
|
33
34
|
this.indexName = this.constructIndexName(`${Date.now()}`);
|
|
34
35
|
this.alias = options.alias;
|
|
35
36
|
this.removableAlias = `${this.alias}_removable`;
|
|
36
|
-
this.
|
|
37
|
+
this.elasticSearchClientWrapper = options.elasticSearchClientWrapper;
|
|
37
38
|
this.sourceStream = new stream.Readable({ objectMode: true });
|
|
38
39
|
this.sourceStream._read = () => {
|
|
39
40
|
};
|
|
40
41
|
const that = this;
|
|
41
|
-
this.bulkResult = this.
|
|
42
|
+
this.bulkResult = this.elasticSearchClientWrapper.bulk({
|
|
42
43
|
datasource: this.sourceStream,
|
|
43
44
|
onDocument() {
|
|
44
45
|
that.processed++;
|
|
@@ -51,14 +52,13 @@ class ElasticSearchSearchEngineIndexer extends pluginSearchBackendNode.BatchSear
|
|
|
51
52
|
}
|
|
52
53
|
async initialize() {
|
|
53
54
|
this.logger.info(`Started indexing documents for index ${this.type}`);
|
|
54
|
-
const aliases = await this.
|
|
55
|
-
|
|
56
|
-
name: [this.alias, this.removableAlias]
|
|
55
|
+
const aliases = await this.elasticSearchClientWrapper.getAliases({
|
|
56
|
+
aliases: [this.alias, this.removableAlias]
|
|
57
57
|
});
|
|
58
58
|
this.removableIndices = [
|
|
59
59
|
...new Set(aliases.body.map((r) => r.index))
|
|
60
60
|
];
|
|
61
|
-
await this.
|
|
61
|
+
await this.elasticSearchClientWrapper.createIndex({
|
|
62
62
|
index: this.indexName
|
|
63
63
|
});
|
|
64
64
|
}
|
|
@@ -74,28 +74,26 @@ class ElasticSearchSearchEngineIndexer extends pluginSearchBackendNode.BatchSear
|
|
|
74
74
|
this.sourceStream.push(null);
|
|
75
75
|
const result = await this.bulkResult;
|
|
76
76
|
this.logger.info(`Indexing completed for index ${this.type} in ${duration(this.startTimestamp)}`, result);
|
|
77
|
-
await this.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
{
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
alias: this.removableAlias
|
|
87
|
-
}
|
|
88
|
-
} : void 0,
|
|
89
|
-
{
|
|
90
|
-
add: { index: this.indexName, alias: this.alias }
|
|
77
|
+
await this.elasticSearchClientWrapper.updateAliases({
|
|
78
|
+
actions: [
|
|
79
|
+
{
|
|
80
|
+
remove: { index: this.constructIndexName("*"), alias: this.alias }
|
|
81
|
+
},
|
|
82
|
+
this.removableIndices.length ? {
|
|
83
|
+
add: {
|
|
84
|
+
indices: this.removableIndices,
|
|
85
|
+
alias: this.removableAlias
|
|
91
86
|
}
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
} : void 0,
|
|
88
|
+
{
|
|
89
|
+
add: { index: this.indexName, alias: this.alias }
|
|
90
|
+
}
|
|
91
|
+
].filter(Boolean)
|
|
94
92
|
});
|
|
95
93
|
if (this.removableIndices.length) {
|
|
96
94
|
this.logger.info("Removing stale search indices", this.removableIndices);
|
|
97
95
|
try {
|
|
98
|
-
await this.
|
|
96
|
+
await this.elasticSearchClientWrapper.deleteIndex({
|
|
99
97
|
index: this.removableIndices
|
|
100
98
|
});
|
|
101
99
|
} catch (e) {
|
|
@@ -118,6 +116,117 @@ class ElasticSearchSearchEngineIndexer extends pluginSearchBackendNode.BatchSear
|
|
|
118
116
|
}
|
|
119
117
|
}
|
|
120
118
|
|
|
119
|
+
const isOpenSearchCompatible = (opts) => {
|
|
120
|
+
return (opts == null ? void 0 : opts.provider) === "aws";
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
class ElasticSearchClientWrapper {
|
|
124
|
+
constructor({
|
|
125
|
+
openSearchClient,
|
|
126
|
+
elasticSearchClient
|
|
127
|
+
}) {
|
|
128
|
+
this.openSearchClient = openSearchClient;
|
|
129
|
+
this.elasticSearchClient = elasticSearchClient;
|
|
130
|
+
}
|
|
131
|
+
static fromClientOptions(options) {
|
|
132
|
+
if (isOpenSearchCompatible(options)) {
|
|
133
|
+
return new ElasticSearchClientWrapper({
|
|
134
|
+
openSearchClient: new opensearch.Client(options)
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return new ElasticSearchClientWrapper({
|
|
138
|
+
elasticSearchClient: new elasticsearch.Client(options)
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
search({ index, body }) {
|
|
142
|
+
if (this.openSearchClient) {
|
|
143
|
+
return this.openSearchClient.search({ index, body });
|
|
144
|
+
}
|
|
145
|
+
if (this.elasticSearchClient) {
|
|
146
|
+
return this.elasticSearchClient.search({ index, body });
|
|
147
|
+
}
|
|
148
|
+
throw new Error("No client defined");
|
|
149
|
+
}
|
|
150
|
+
bulk(bulkOptions) {
|
|
151
|
+
if (this.openSearchClient) {
|
|
152
|
+
return this.openSearchClient.helpers.bulk(bulkOptions);
|
|
153
|
+
}
|
|
154
|
+
if (this.elasticSearchClient) {
|
|
155
|
+
return this.elasticSearchClient.helpers.bulk(bulkOptions);
|
|
156
|
+
}
|
|
157
|
+
throw new Error("No client defined");
|
|
158
|
+
}
|
|
159
|
+
putIndexTemplate(template) {
|
|
160
|
+
if (this.openSearchClient) {
|
|
161
|
+
return this.openSearchClient.indices.putIndexTemplate(template);
|
|
162
|
+
}
|
|
163
|
+
if (this.elasticSearchClient) {
|
|
164
|
+
return this.elasticSearchClient.indices.putIndexTemplate(template);
|
|
165
|
+
}
|
|
166
|
+
throw new Error("No client defined");
|
|
167
|
+
}
|
|
168
|
+
indexExists({ index }) {
|
|
169
|
+
if (this.openSearchClient) {
|
|
170
|
+
return this.openSearchClient.indices.exists({ index });
|
|
171
|
+
}
|
|
172
|
+
if (this.elasticSearchClient) {
|
|
173
|
+
return this.elasticSearchClient.indices.exists({ index });
|
|
174
|
+
}
|
|
175
|
+
throw new Error("No client defined");
|
|
176
|
+
}
|
|
177
|
+
deleteIndex({ index }) {
|
|
178
|
+
if (this.openSearchClient) {
|
|
179
|
+
return this.openSearchClient.indices.delete({ index });
|
|
180
|
+
}
|
|
181
|
+
if (this.elasticSearchClient) {
|
|
182
|
+
return this.elasticSearchClient.indices.delete({ index });
|
|
183
|
+
}
|
|
184
|
+
throw new Error("No client defined");
|
|
185
|
+
}
|
|
186
|
+
createIndex({ index }) {
|
|
187
|
+
if (this.openSearchClient) {
|
|
188
|
+
return this.openSearchClient.indices.create({ index });
|
|
189
|
+
}
|
|
190
|
+
if (this.elasticSearchClient) {
|
|
191
|
+
return this.elasticSearchClient.indices.create({ index });
|
|
192
|
+
}
|
|
193
|
+
throw new Error("No client defined");
|
|
194
|
+
}
|
|
195
|
+
getAliases({ aliases }) {
|
|
196
|
+
if (this.openSearchClient) {
|
|
197
|
+
return this.openSearchClient.cat.aliases({
|
|
198
|
+
format: "json",
|
|
199
|
+
name: aliases
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
if (this.elasticSearchClient) {
|
|
203
|
+
return this.elasticSearchClient.cat.aliases({
|
|
204
|
+
format: "json",
|
|
205
|
+
name: aliases
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
throw new Error("No client defined");
|
|
209
|
+
}
|
|
210
|
+
updateAliases({ actions }) {
|
|
211
|
+
const filteredActions = actions.filter(Boolean);
|
|
212
|
+
if (this.openSearchClient) {
|
|
213
|
+
return this.openSearchClient.indices.updateAliases({
|
|
214
|
+
body: {
|
|
215
|
+
actions: filteredActions
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
if (this.elasticSearchClient) {
|
|
220
|
+
return this.elasticSearchClient.indices.updateAliases({
|
|
221
|
+
body: {
|
|
222
|
+
actions: filteredActions
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
throw new Error("No client defined");
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
121
230
|
function isBlank(str) {
|
|
122
231
|
return lodash.isEmpty(str) && !lodash.isNumber(str) || lodash.isNaN(str);
|
|
123
232
|
}
|
|
@@ -128,7 +237,7 @@ class ElasticSearchSearchEngine {
|
|
|
128
237
|
this.indexPrefix = indexPrefix;
|
|
129
238
|
this.logger = logger;
|
|
130
239
|
this.indexSeparator = "-index__";
|
|
131
|
-
this.
|
|
240
|
+
this.elasticSearchClientWrapper = ElasticSearchClientWrapper.fromClientOptions(elasticSearchClientOptions);
|
|
132
241
|
const uuidTag = uuid.v4();
|
|
133
242
|
this.highlightOptions = {
|
|
134
243
|
preTag: `<${uuidTag}>`,
|
|
@@ -149,7 +258,7 @@ class ElasticSearchSearchEngine {
|
|
|
149
258
|
if (options.provider === "elastic") {
|
|
150
259
|
logger.info("Initializing Elastic.co ElasticSearch search engine.");
|
|
151
260
|
} else if (options.provider === "aws") {
|
|
152
|
-
logger.info("Initializing AWS
|
|
261
|
+
logger.info("Initializing AWS OpenSearch search engine.");
|
|
153
262
|
} else {
|
|
154
263
|
logger.info("Initializing ElasticSearch search engine.");
|
|
155
264
|
}
|
|
@@ -187,6 +296,14 @@ class ElasticSearchSearchEngine {
|
|
|
187
296
|
setTranslator(translator) {
|
|
188
297
|
this.translator = translator;
|
|
189
298
|
}
|
|
299
|
+
async setIndexTemplate(template) {
|
|
300
|
+
try {
|
|
301
|
+
await this.elasticSearchClientWrapper.putIndexTemplate(template);
|
|
302
|
+
this.logger.info("Custom index template set");
|
|
303
|
+
} catch (error) {
|
|
304
|
+
this.logger.error(`Unable to set custom index template: ${error}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
190
307
|
async getIndexer(type) {
|
|
191
308
|
const alias = this.constructSearchAlias(type);
|
|
192
309
|
const indexer = new ElasticSearchSearchEngineIndexer({
|
|
@@ -194,19 +311,19 @@ class ElasticSearchSearchEngine {
|
|
|
194
311
|
indexPrefix: this.indexPrefix,
|
|
195
312
|
indexSeparator: this.indexSeparator,
|
|
196
313
|
alias,
|
|
197
|
-
|
|
314
|
+
elasticSearchClientWrapper: this.elasticSearchClientWrapper,
|
|
198
315
|
logger: this.logger
|
|
199
316
|
});
|
|
200
317
|
indexer.on("error", async (e) => {
|
|
201
318
|
this.logger.error(`Failed to index documents for type ${type}`, e);
|
|
202
319
|
try {
|
|
203
|
-
const response = await this.
|
|
320
|
+
const response = await this.elasticSearchClientWrapper.indexExists({
|
|
204
321
|
index: indexer.indexName
|
|
205
322
|
});
|
|
206
323
|
const indexCreated = response.body;
|
|
207
324
|
if (indexCreated) {
|
|
208
325
|
this.logger.info(`Removing created index ${indexer.indexName}`);
|
|
209
|
-
await this.
|
|
326
|
+
await this.elasticSearchClientWrapper.deleteIndex({
|
|
210
327
|
index: indexer.indexName
|
|
211
328
|
});
|
|
212
329
|
}
|
|
@@ -220,7 +337,7 @@ class ElasticSearchSearchEngine {
|
|
|
220
337
|
const { elasticSearchQuery, documentTypes, pageSize } = this.translator(query, { highlightOptions: this.highlightOptions });
|
|
221
338
|
const queryIndices = documentTypes ? documentTypes.map((it) => this.constructSearchAlias(it)) : this.constructSearchAlias("*");
|
|
222
339
|
try {
|
|
223
|
-
const result = await this.
|
|
340
|
+
const result = await this.elasticSearchClientWrapper.search({
|
|
224
341
|
index: queryIndices,
|
|
225
342
|
body: elasticSearchQuery
|
|
226
343
|
});
|
|
@@ -230,10 +347,11 @@ class ElasticSearchSearchEngine {
|
|
|
230
347
|
const nextPageCursor = hasNextPage ? encodePageCursor({ page: page + 1 }) : void 0;
|
|
231
348
|
const previousPageCursor = hasPreviousPage ? encodePageCursor({ page: page - 1 }) : void 0;
|
|
232
349
|
return {
|
|
233
|
-
results: result.body.hits.hits.map((d) => {
|
|
350
|
+
results: result.body.hits.hits.map((d, index) => {
|
|
234
351
|
const resultItem = {
|
|
235
352
|
type: this.getTypeFromIndex(d._index),
|
|
236
|
-
document: d._source
|
|
353
|
+
document: d._source,
|
|
354
|
+
rank: pageSize * page + index + 1
|
|
237
355
|
};
|
|
238
356
|
if (d.highlight) {
|
|
239
357
|
resultItem.highlight = {
|
|
@@ -299,8 +417,8 @@ async function createElasticSearchClientOptions(config) {
|
|
|
299
417
|
};
|
|
300
418
|
}
|
|
301
419
|
if (config.getOptionalString("provider") === "aws") {
|
|
302
|
-
const awsCredentials = await
|
|
303
|
-
const AWSConnection =
|
|
420
|
+
const awsCredentials = await awsOsConnection.awsGetCredentials();
|
|
421
|
+
const AWSConnection = awsOsConnection.createAWSConnection(awsCredentials);
|
|
304
422
|
return {
|
|
305
423
|
provider: "aws",
|
|
306
424
|
node: config.getString("node"),
|
|
@@ -331,4 +449,5 @@ async function createElasticSearchClientOptions(config) {
|
|
|
331
449
|
}
|
|
332
450
|
|
|
333
451
|
exports.ElasticSearchSearchEngine = ElasticSearchSearchEngine;
|
|
452
|
+
exports.isOpenSearchCompatible = isOpenSearchCompatible;
|
|
334
453
|
//# sourceMappingURL=index.cjs.js.map
|
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\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 * 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 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/ElasticSearchClientOptions.ts","../src/engines/ElasticSearchClientWrapper.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 { Readable } from 'stream';\nimport { Logger } from 'winston';\nimport { ElasticSearchClientWrapper } from './ElasticSearchClientWrapper';\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 elasticSearchClientWrapper: ElasticSearchClientWrapper;\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 elasticSearchClientWrapper: ElasticSearchClientWrapper;\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.elasticSearchClientWrapper = options.elasticSearchClientWrapper;\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.elasticSearchClientWrapper.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.elasticSearchClientWrapper.getAliases({\n aliases: [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.elasticSearchClientWrapper.createIndex({\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.elasticSearchClientWrapper.updateAliases({\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 // 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.elasticSearchClientWrapper.deleteIndex({\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 */\nimport type { ConnectionOptions as TLSConnectionOptions } from 'tls';\n\n/**\n * Typeguard to differentiate ElasticSearch client options which are compatible\n * with OpenSearch vs. ElasticSearch clients. Useful when calling the\n * {@link ElasticSearchSearchEngine.newClient} method.\n *\n * @public\n */\nexport const isOpenSearchCompatible = (\n opts: ElasticSearchClientOptions,\n): opts is OpenSearchElasticSearchClientOptions => {\n return opts?.provider === 'aws';\n};\n\n/**\n * Options used to configure the `@elastic/elasticsearch` client or the\n * `@opensearch-project/opensearch` client, depending on the given config. It\n * will be passed as an argument to the\n * {@link ElasticSearchSearchEngine.newClient} method.\n *\n * @public\n */\nexport type ElasticSearchClientOptions =\n | ElasticSearchElasticSearchClientOptions\n | OpenSearchElasticSearchClientOptions;\n\n/**\n * Options used to configure the `@opensearch-project/opensearch` client.\n *\n * They are drawn from the `ClientOptions` class of `@opensearch-project/opensearch`,\n * but are maintained separately so that this interface is not coupled to it.\n *\n * @public\n */\nexport interface OpenSearchElasticSearchClientOptions\n extends BaseElasticSearchClientOptions {\n provider?: 'aws';\n auth?: OpenSearchAuth;\n connection?: OpenSearchConnectionConstructor;\n node?: string | string[] | OpenSearchNodeOptions | OpenSearchNodeOptions[];\n nodes?: string | string[] | OpenSearchNodeOptions | OpenSearchNodeOptions[];\n}\n\n/**\n * Options used to configure the `@elastic/elasticsearch` client.\n *\n * They are drawn from the `ClientOptions` class of `@elastic/elasticsearch`,\n * but are maintained separately so that this interface is not coupled to it.\n *\n * @public\n */\nexport interface ElasticSearchElasticSearchClientOptions\n extends BaseElasticSearchClientOptions {\n provider?: 'elastic';\n auth?: ElasticSearchAuth;\n Connection?: ElasticSearchConnectionConstructor;\n node?:\n | string\n | string[]\n | ElasticSearchNodeOptions\n | ElasticSearchNodeOptions[];\n nodes?:\n | string\n | string[]\n | ElasticSearchNodeOptions\n | ElasticSearchNodeOptions[];\n cloud?: {\n id: string;\n username?: string;\n password?: string;\n };\n}\n\n/**\n * Base client options that are shared across `@opensearch-project/opensearch`\n * and `@elastic/elasticsearch` clients.\n *\n * @public\n */\nexport interface BaseElasticSearchClientOptions {\n Transport?: ElasticSearchTransportConstructor;\n maxRetries?: number;\n requestTimeout?: number;\n pingTimeout?: number;\n sniffInterval?: number | boolean;\n sniffOnStart?: boolean;\n sniffEndpoint?: string;\n sniffOnConnectionFault?: boolean;\n resurrectStrategy?: 'ping' | 'optimistic' | 'none';\n suggestCompression?: boolean;\n compression?: 'gzip';\n ssl?: TLSConnectionOptions;\n agent?: ElasticSearchAgentOptions | ((opts?: any) => unknown) | false;\n nodeFilter?: (connection: any) => boolean;\n nodeSelector?: ((connections: any[]) => any) | string;\n headers?: Record<string, any>;\n opaqueIdPrefix?: string;\n name?: string | symbol;\n proxy?: string | URL;\n enableMetaHeader?: boolean;\n disablePrototypePoisoningProtection?: boolean | 'proto' | 'constructor';\n}\n\n/**\n * @public\n */\nexport type OpenSearchAuth = {\n username: string;\n password: string;\n};\n\n/**\n * @public\n */\nexport type ElasticSearchAuth =\n | OpenSearchAuth\n | {\n apiKey:\n | string\n | {\n id: string;\n api_key: string;\n };\n };\n\n/**\n * @public\n */\nexport interface ElasticSearchNodeOptions {\n url: URL;\n id?: string;\n agent?: ElasticSearchAgentOptions;\n ssl?: TLSConnectionOptions;\n headers?: Record<string, any>;\n roles?: {\n master: boolean;\n data: boolean;\n ingest: boolean;\n ml: boolean;\n };\n}\n\n/**\n * @public\n */\nexport interface OpenSearchNodeOptions {\n url: URL;\n id?: string;\n agent?: ElasticSearchAgentOptions;\n ssl?: TLSConnectionOptions;\n headers?: Record<string, any>;\n roles?: {\n master: boolean;\n data: boolean;\n ingest: boolean;\n };\n}\n\n/**\n * @public\n */\nexport interface ElasticSearchAgentOptions {\n keepAlive?: boolean;\n keepAliveMsecs?: number;\n maxSockets?: number;\n maxFreeSockets?: number;\n}\n\n/**\n * @public\n */\nexport interface ElasticSearchConnectionConstructor {\n new (opts?: any): any;\n statuses: {\n ALIVE: string;\n DEAD: string;\n };\n roles: {\n MASTER: string;\n DATA: string;\n INGEST: string;\n ML: string;\n };\n}\n\n/**\n * @public\n */\nexport interface OpenSearchConnectionConstructor {\n new (opts?: any): any;\n statuses: {\n ALIVE: string;\n DEAD: string;\n };\n roles: {\n MASTER: string;\n DATA: string;\n INGEST: string;\n };\n}\n\n/**\n * @public\n */\nexport interface ElasticSearchTransportConstructor {\n new (opts?: any): any;\n sniffReasons: {\n SNIFF_ON_START: string;\n SNIFF_INTERVAL: string;\n SNIFF_ON_CONNECTION_FAULT: string;\n DEFAULT: string;\n };\n}\n\n// todo(iamEAP) implement canary types to ensure we remain compatible through upgrades.\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 */\nimport { Client as ElasticSearchClient } from '@elastic/elasticsearch';\nimport { Client as OpenSearchClient } from '@opensearch-project/opensearch';\nimport { Readable } from 'stream';\nimport {\n ElasticSearchClientOptions,\n isOpenSearchCompatible,\n} from './ElasticSearchClientOptions';\nimport { ElasticSearchCustomIndexTemplate } from './types';\n\n/**\n * @public\n */\nexport type ElasticSearchAliasAction =\n | {\n remove: { index: any; alias: any };\n add?: undefined;\n }\n | {\n add: { indices: any; alias: any; index?: undefined };\n remove?: undefined;\n }\n | {\n add: { index: any; alias: any; indices?: undefined };\n remove?: undefined;\n }\n | undefined;\n\n/**\n * @public\n */\nexport type ElasticSearchIndexAction = {\n index: {\n _index: string;\n [key: string]: any;\n };\n};\n\n/**\n * A wrapper class that exposes logical methods that are conditionally fired\n * against either a configured Elasticsearch client or a configured Opensearch\n * client.\n *\n * This is necessary because, despite its intention to be API-compatible, the\n * opensearch client does not support API key-based authentication. This is\n * also the sanest way to accomplish this while making typescript happy.\n *\n * In the future, if the differences between implementations become\n * unmaintainably divergent, we should split out the Opensearch and\n * Elasticsearch search engine implementations.\n *\n * @public\n */\nexport class ElasticSearchClientWrapper {\n private readonly elasticSearchClient: ElasticSearchClient | undefined;\n private readonly openSearchClient: OpenSearchClient | undefined;\n\n private constructor({\n openSearchClient,\n elasticSearchClient,\n }: {\n openSearchClient?: OpenSearchClient;\n elasticSearchClient?: ElasticSearchClient;\n }) {\n this.openSearchClient = openSearchClient;\n this.elasticSearchClient = elasticSearchClient;\n }\n\n static fromClientOptions(options: ElasticSearchClientOptions) {\n if (isOpenSearchCompatible(options)) {\n return new ElasticSearchClientWrapper({\n openSearchClient: new OpenSearchClient(options),\n });\n }\n\n return new ElasticSearchClientWrapper({\n elasticSearchClient: new ElasticSearchClient(options),\n });\n }\n\n search({ index, body }: { index: string | string[]; body: Object }) {\n if (this.openSearchClient) {\n return this.openSearchClient.search({ index, body });\n }\n\n if (this.elasticSearchClient) {\n return this.elasticSearchClient.search({ index, body });\n }\n\n throw new Error('No client defined');\n }\n\n bulk(bulkOptions: {\n datasource: Readable;\n onDocument: () => ElasticSearchIndexAction;\n refreshOnCompletion?: string | boolean;\n }) {\n if (this.openSearchClient) {\n return this.openSearchClient.helpers.bulk(bulkOptions);\n }\n\n if (this.elasticSearchClient) {\n return this.elasticSearchClient.helpers.bulk(bulkOptions);\n }\n\n throw new Error('No client defined');\n }\n\n putIndexTemplate(template: ElasticSearchCustomIndexTemplate) {\n if (this.openSearchClient) {\n return this.openSearchClient.indices.putIndexTemplate(template);\n }\n\n if (this.elasticSearchClient) {\n return this.elasticSearchClient.indices.putIndexTemplate(template);\n }\n\n throw new Error('No client defined');\n }\n\n indexExists({ index }: { index: string | string[] }) {\n if (this.openSearchClient) {\n return this.openSearchClient.indices.exists({ index });\n }\n\n if (this.elasticSearchClient) {\n return this.elasticSearchClient.indices.exists({ index });\n }\n\n throw new Error('No client defined');\n }\n\n deleteIndex({ index }: { index: string | string[] }) {\n if (this.openSearchClient) {\n return this.openSearchClient.indices.delete({ index });\n }\n\n if (this.elasticSearchClient) {\n return this.elasticSearchClient.indices.delete({ index });\n }\n\n throw new Error('No client defined');\n }\n\n createIndex({ index }: { index: string }) {\n if (this.openSearchClient) {\n return this.openSearchClient.indices.create({ index });\n }\n\n if (this.elasticSearchClient) {\n return this.elasticSearchClient.indices.create({ index });\n }\n\n throw new Error('No client defined');\n }\n\n getAliases({ aliases }: { aliases: string[] }) {\n if (this.openSearchClient) {\n return this.openSearchClient.cat.aliases({\n format: 'json',\n name: aliases,\n });\n }\n\n if (this.elasticSearchClient) {\n return this.elasticSearchClient.cat.aliases({\n format: 'json',\n name: aliases,\n });\n }\n\n throw new Error('No client defined');\n }\n\n updateAliases({ actions }: { actions: ElasticSearchAliasAction[] }) {\n const filteredActions = actions.filter(Boolean);\n if (this.openSearchClient) {\n return this.openSearchClient.indices.updateAliases({\n body: {\n actions: filteredActions,\n },\n });\n }\n\n if (this.elasticSearchClient) {\n return this.elasticSearchClient.indices.updateAliases({\n body: {\n actions: filteredActions,\n },\n });\n }\n\n throw new Error('No client defined');\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 { awsGetCredentials, createAWSConnection } from 'aws-os-connection';\nimport { Config } from '@backstage/config';\nimport {\n IndexableDocument,\n IndexableResult,\n IndexableResultSet,\n SearchEngine,\n SearchQuery,\n} from '@backstage/plugin-search-common';\nimport esb from 'elastic-builder';\nimport { isEmpty, isNaN as nan, isNumber } from 'lodash';\nimport { v4 as uuid } from 'uuid';\nimport { Logger } from 'winston';\nimport { ElasticSearchClientOptions } from './ElasticSearchClientOptions';\nimport { ElasticSearchSearchEngineIndexer } from './ElasticSearchSearchEngineIndexer';\nimport { ElasticSearchCustomIndexTemplate } from './types';\nimport { ElasticSearchClientWrapper } from './ElasticSearchClientWrapper';\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 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 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: Logger,\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({\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 OpenSearch 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.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\n const indexer = new ElasticSearchSearchEngineIndexer({\n type,\n indexPrefix: this.indexPrefix,\n indexSeparator: this.indexSeparator,\n alias,\n elasticSearchClientWrapper: this.elasticSearchClientWrapper,\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.elasticSearchClientWrapper.indexExists({\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.elasticSearchClientWrapper.deleteIndex({\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.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 };\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\nexport async 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","OpenSearchClient","ElasticSearchClient","isEmpty","isNumber","nan","uuid","esb","awsGetCredentials","createAWSConnection"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,24 +4,71 @@ import { IndexableDocument, SearchQuery, SearchEngine, IndexableResultSet } from
|
|
|
4
4
|
import { Logger } from 'winston';
|
|
5
5
|
import { ConnectionOptions } from 'tls';
|
|
6
6
|
import { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node';
|
|
7
|
-
import
|
|
7
|
+
import * as _opensearch_project_opensearch_lib_Helpers from '@opensearch-project/opensearch/lib/Helpers';
|
|
8
|
+
import * as _opensearch_project_opensearch_lib_Transport from '@opensearch-project/opensearch/lib/Transport';
|
|
9
|
+
import * as _opensearch_project_opensearch from '@opensearch-project/opensearch';
|
|
10
|
+
import { Readable } from 'stream';
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* {@link ElasticSearchSearchEngine.newClient} method
|
|
13
|
+
* Typeguard to differentiate ElasticSearch client options which are compatible
|
|
14
|
+
* with OpenSearch vs. ElasticSearch clients. Useful when calling the
|
|
15
|
+
* {@link ElasticSearchSearchEngine.newClient} method.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
declare const isOpenSearchCompatible: (opts: ElasticSearchClientOptions) => opts is OpenSearchElasticSearchClientOptions;
|
|
20
|
+
/**
|
|
21
|
+
* Options used to configure the `@elastic/elasticsearch` client or the
|
|
22
|
+
* `@opensearch-project/opensearch` client, depending on the given config. It
|
|
23
|
+
* will be passed as an argument to the
|
|
24
|
+
* {@link ElasticSearchSearchEngine.newClient} method.
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
declare type ElasticSearchClientOptions = ElasticSearchElasticSearchClientOptions | OpenSearchElasticSearchClientOptions;
|
|
29
|
+
/**
|
|
30
|
+
* Options used to configure the `@opensearch-project/opensearch` client.
|
|
31
|
+
*
|
|
32
|
+
* They are drawn from the `ClientOptions` class of `@opensearch-project/opensearch`,
|
|
33
|
+
* but are maintained separately so that this interface is not coupled to it.
|
|
34
|
+
*
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
interface OpenSearchElasticSearchClientOptions extends BaseElasticSearchClientOptions {
|
|
38
|
+
provider?: 'aws';
|
|
39
|
+
auth?: OpenSearchAuth;
|
|
40
|
+
connection?: OpenSearchConnectionConstructor;
|
|
41
|
+
node?: string | string[] | OpenSearchNodeOptions | OpenSearchNodeOptions[];
|
|
42
|
+
nodes?: string | string[] | OpenSearchNodeOptions | OpenSearchNodeOptions[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Options used to configure the `@elastic/elasticsearch` client.
|
|
13
46
|
*
|
|
14
47
|
* They are drawn from the `ClientOptions` class of `@elastic/elasticsearch`,
|
|
15
|
-
* but are maintained separately so that this interface is not coupled to
|
|
48
|
+
* but are maintained separately so that this interface is not coupled to it.
|
|
16
49
|
*
|
|
17
50
|
* @public
|
|
18
51
|
*/
|
|
19
|
-
interface
|
|
20
|
-
provider?: '
|
|
52
|
+
interface ElasticSearchElasticSearchClientOptions extends BaseElasticSearchClientOptions {
|
|
53
|
+
provider?: 'elastic';
|
|
54
|
+
auth?: ElasticSearchAuth;
|
|
55
|
+
Connection?: ElasticSearchConnectionConstructor;
|
|
21
56
|
node?: string | string[] | ElasticSearchNodeOptions | ElasticSearchNodeOptions[];
|
|
22
57
|
nodes?: string | string[] | ElasticSearchNodeOptions | ElasticSearchNodeOptions[];
|
|
58
|
+
cloud?: {
|
|
59
|
+
id: string;
|
|
60
|
+
username?: string;
|
|
61
|
+
password?: string;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Base client options that are shared across `@opensearch-project/opensearch`
|
|
66
|
+
* and `@elastic/elasticsearch` clients.
|
|
67
|
+
*
|
|
68
|
+
* @public
|
|
69
|
+
*/
|
|
70
|
+
interface BaseElasticSearchClientOptions {
|
|
23
71
|
Transport?: ElasticSearchTransportConstructor;
|
|
24
|
-
Connection?: ElasticSearchConnectionConstructor;
|
|
25
72
|
maxRetries?: number;
|
|
26
73
|
requestTimeout?: number;
|
|
27
74
|
pingTimeout?: number;
|
|
@@ -39,23 +86,21 @@ interface ElasticSearchClientOptions {
|
|
|
39
86
|
headers?: Record<string, any>;
|
|
40
87
|
opaqueIdPrefix?: string;
|
|
41
88
|
name?: string | symbol;
|
|
42
|
-
auth?: ElasticSearchAuth;
|
|
43
89
|
proxy?: string | URL;
|
|
44
90
|
enableMetaHeader?: boolean;
|
|
45
|
-
cloud?: {
|
|
46
|
-
id: string;
|
|
47
|
-
username?: string;
|
|
48
|
-
password?: string;
|
|
49
|
-
};
|
|
50
91
|
disablePrototypePoisoningProtection?: boolean | 'proto' | 'constructor';
|
|
51
92
|
}
|
|
52
93
|
/**
|
|
53
94
|
* @public
|
|
54
95
|
*/
|
|
55
|
-
declare type
|
|
96
|
+
declare type OpenSearchAuth = {
|
|
56
97
|
username: string;
|
|
57
98
|
password: string;
|
|
58
|
-
}
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* @public
|
|
102
|
+
*/
|
|
103
|
+
declare type ElasticSearchAuth = OpenSearchAuth | {
|
|
59
104
|
apiKey: string | {
|
|
60
105
|
id: string;
|
|
61
106
|
api_key: string;
|
|
@@ -77,6 +122,21 @@ interface ElasticSearchNodeOptions {
|
|
|
77
122
|
ml: boolean;
|
|
78
123
|
};
|
|
79
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* @public
|
|
127
|
+
*/
|
|
128
|
+
interface OpenSearchNodeOptions {
|
|
129
|
+
url: URL;
|
|
130
|
+
id?: string;
|
|
131
|
+
agent?: ElasticSearchAgentOptions;
|
|
132
|
+
ssl?: ConnectionOptions;
|
|
133
|
+
headers?: Record<string, any>;
|
|
134
|
+
roles?: {
|
|
135
|
+
master: boolean;
|
|
136
|
+
data: boolean;
|
|
137
|
+
ingest: boolean;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
80
140
|
/**
|
|
81
141
|
* @public
|
|
82
142
|
*/
|
|
@@ -102,6 +162,21 @@ interface ElasticSearchConnectionConstructor {
|
|
|
102
162
|
ML: string;
|
|
103
163
|
};
|
|
104
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* @public
|
|
167
|
+
*/
|
|
168
|
+
interface OpenSearchConnectionConstructor {
|
|
169
|
+
new (opts?: any): any;
|
|
170
|
+
statuses: {
|
|
171
|
+
ALIVE: string;
|
|
172
|
+
DEAD: string;
|
|
173
|
+
};
|
|
174
|
+
roles: {
|
|
175
|
+
MASTER: string;
|
|
176
|
+
DATA: string;
|
|
177
|
+
INGEST: string;
|
|
178
|
+
};
|
|
179
|
+
}
|
|
105
180
|
/**
|
|
106
181
|
* @public
|
|
107
182
|
*/
|
|
@@ -115,6 +190,116 @@ interface ElasticSearchTransportConstructor {
|
|
|
115
190
|
};
|
|
116
191
|
}
|
|
117
192
|
|
|
193
|
+
/**
|
|
194
|
+
* Elasticsearch specific index template
|
|
195
|
+
* @public
|
|
196
|
+
*/
|
|
197
|
+
declare type ElasticSearchCustomIndexTemplate = {
|
|
198
|
+
name: string;
|
|
199
|
+
body: ElasticSearchCustomIndexTemplateBody;
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* Elasticsearch specific index template body
|
|
203
|
+
* @public
|
|
204
|
+
*/
|
|
205
|
+
declare type ElasticSearchCustomIndexTemplateBody = {
|
|
206
|
+
/**
|
|
207
|
+
* Array of wildcard (*) expressions used to match the names of data streams and indices during creation.
|
|
208
|
+
*/
|
|
209
|
+
index_patterns: string[];
|
|
210
|
+
/**
|
|
211
|
+
* An ordered list of component template names.
|
|
212
|
+
* Component templates are merged in the order specified,
|
|
213
|
+
* meaning that the last component template specified has the highest precedence.
|
|
214
|
+
*/
|
|
215
|
+
composed_of?: string[];
|
|
216
|
+
/**
|
|
217
|
+
* See available properties of template
|
|
218
|
+
* https://www.elastic.co/guide/en/elasticsearch/reference/7.15/indices-put-template.html#put-index-template-api-request-body
|
|
219
|
+
*/
|
|
220
|
+
template?: Record<string, any>;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* @public
|
|
225
|
+
*/
|
|
226
|
+
declare type ElasticSearchAliasAction = {
|
|
227
|
+
remove: {
|
|
228
|
+
index: any;
|
|
229
|
+
alias: any;
|
|
230
|
+
};
|
|
231
|
+
add?: undefined;
|
|
232
|
+
} | {
|
|
233
|
+
add: {
|
|
234
|
+
indices: any;
|
|
235
|
+
alias: any;
|
|
236
|
+
index?: undefined;
|
|
237
|
+
};
|
|
238
|
+
remove?: undefined;
|
|
239
|
+
} | {
|
|
240
|
+
add: {
|
|
241
|
+
index: any;
|
|
242
|
+
alias: any;
|
|
243
|
+
indices?: undefined;
|
|
244
|
+
};
|
|
245
|
+
remove?: undefined;
|
|
246
|
+
} | undefined;
|
|
247
|
+
/**
|
|
248
|
+
* @public
|
|
249
|
+
*/
|
|
250
|
+
declare type ElasticSearchIndexAction = {
|
|
251
|
+
index: {
|
|
252
|
+
_index: string;
|
|
253
|
+
[key: string]: any;
|
|
254
|
+
};
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* A wrapper class that exposes logical methods that are conditionally fired
|
|
258
|
+
* against either a configured Elasticsearch client or a configured Opensearch
|
|
259
|
+
* client.
|
|
260
|
+
*
|
|
261
|
+
* This is necessary because, despite its intention to be API-compatible, the
|
|
262
|
+
* opensearch client does not support API key-based authentication. This is
|
|
263
|
+
* also the sanest way to accomplish this while making typescript happy.
|
|
264
|
+
*
|
|
265
|
+
* In the future, if the differences between implementations become
|
|
266
|
+
* unmaintainably divergent, we should split out the Opensearch and
|
|
267
|
+
* Elasticsearch search engine implementations.
|
|
268
|
+
*
|
|
269
|
+
* @public
|
|
270
|
+
*/
|
|
271
|
+
declare class ElasticSearchClientWrapper {
|
|
272
|
+
private readonly elasticSearchClient;
|
|
273
|
+
private readonly openSearchClient;
|
|
274
|
+
private constructor();
|
|
275
|
+
static fromClientOptions(options: ElasticSearchClientOptions): ElasticSearchClientWrapper;
|
|
276
|
+
search({ index, body }: {
|
|
277
|
+
index: string | string[];
|
|
278
|
+
body: Object;
|
|
279
|
+
}): _opensearch_project_opensearch_lib_Transport.TransportRequestPromise<_opensearch_project_opensearch.ApiResponse<Record<string, any>, unknown>>;
|
|
280
|
+
bulk(bulkOptions: {
|
|
281
|
+
datasource: Readable;
|
|
282
|
+
onDocument: () => ElasticSearchIndexAction;
|
|
283
|
+
refreshOnCompletion?: string | boolean;
|
|
284
|
+
}): _opensearch_project_opensearch_lib_Helpers.BulkHelper<_opensearch_project_opensearch_lib_Helpers.BulkStats>;
|
|
285
|
+
putIndexTemplate(template: ElasticSearchCustomIndexTemplate): _opensearch_project_opensearch_lib_Transport.TransportRequestPromise<_opensearch_project_opensearch.ApiResponse<Record<string, any>, unknown>>;
|
|
286
|
+
indexExists({ index }: {
|
|
287
|
+
index: string | string[];
|
|
288
|
+
}): _opensearch_project_opensearch_lib_Transport.TransportRequestPromise<_opensearch_project_opensearch.ApiResponse<boolean, unknown>>;
|
|
289
|
+
deleteIndex({ index }: {
|
|
290
|
+
index: string | string[];
|
|
291
|
+
}): _opensearch_project_opensearch_lib_Transport.TransportRequestPromise<_opensearch_project_opensearch.ApiResponse<Record<string, any>, unknown>>;
|
|
292
|
+
createIndex({ index }: {
|
|
293
|
+
index: string;
|
|
294
|
+
}): _opensearch_project_opensearch_lib_Transport.TransportRequestPromise<_opensearch_project_opensearch.ApiResponse<Record<string, any>, unknown>>;
|
|
295
|
+
getAliases({ aliases }: {
|
|
296
|
+
aliases: string[];
|
|
297
|
+
}): _opensearch_project_opensearch_lib_Transport.TransportRequestPromise<_opensearch_project_opensearch.ApiResponse<Record<string, any>, unknown>>;
|
|
298
|
+
updateAliases({ actions }: {
|
|
299
|
+
actions: ElasticSearchAliasAction[];
|
|
300
|
+
}): _opensearch_project_opensearch_lib_Transport.TransportRequestPromise<_opensearch_project_opensearch.ApiResponse<Record<string, any>, unknown>>;
|
|
301
|
+
}
|
|
302
|
+
|
|
118
303
|
/**
|
|
119
304
|
* Options for instansiate ElasticSearchSearchEngineIndexer
|
|
120
305
|
* @public
|
|
@@ -125,7 +310,7 @@ declare type ElasticSearchSearchEngineIndexerOptions = {
|
|
|
125
310
|
indexSeparator: string;
|
|
126
311
|
alias: string;
|
|
127
312
|
logger: Logger;
|
|
128
|
-
|
|
313
|
+
elasticSearchClientWrapper: ElasticSearchClientWrapper;
|
|
129
314
|
};
|
|
130
315
|
/**
|
|
131
316
|
* Elasticsearch specific search engine indexer.
|
|
@@ -144,7 +329,7 @@ declare class ElasticSearchSearchEngineIndexer extends BatchSearchEngineIndexer
|
|
|
144
329
|
private readonly removableAlias;
|
|
145
330
|
private readonly logger;
|
|
146
331
|
private readonly sourceStream;
|
|
147
|
-
private readonly
|
|
332
|
+
private readonly elasticSearchClientWrapper;
|
|
148
333
|
private bulkResult;
|
|
149
334
|
constructor(options: ElasticSearchSearchEngineIndexerOptions);
|
|
150
335
|
initialize(): Promise<void>;
|
|
@@ -216,7 +401,7 @@ declare class ElasticSearchSearchEngine implements SearchEngine {
|
|
|
216
401
|
private readonly aliasPostfix;
|
|
217
402
|
private readonly indexPrefix;
|
|
218
403
|
private readonly logger;
|
|
219
|
-
private readonly
|
|
404
|
+
private readonly elasticSearchClientWrapper;
|
|
220
405
|
private readonly highlightOptions;
|
|
221
406
|
constructor(elasticSearchClientOptions: ElasticSearchClientOptions, aliasPostfix: string, indexPrefix: string, logger: Logger, highlightOptions?: ElasticSearchHighlightOptions);
|
|
222
407
|
static fromConfig({ logger, config, aliasPostfix, indexPrefix, }: ElasticSearchOptions): Promise<ElasticSearchSearchEngine>;
|
|
@@ -228,6 +413,7 @@ declare class ElasticSearchSearchEngine implements SearchEngine {
|
|
|
228
413
|
newClient<T>(create: (options: ElasticSearchClientOptions) => T): T;
|
|
229
414
|
protected translator(query: SearchQuery, options?: ElasticSearchQueryTranslatorOptions): ElasticSearchConcreteQuery;
|
|
230
415
|
setTranslator(translator: ElasticSearchQueryTranslator): void;
|
|
416
|
+
setIndexTemplate(template: ElasticSearchCustomIndexTemplate): Promise<void>;
|
|
231
417
|
getIndexer(type: string): Promise<ElasticSearchSearchEngineIndexer>;
|
|
232
418
|
query(query: SearchQuery): Promise<IndexableResultSet>;
|
|
233
419
|
private readonly indexSeparator;
|
|
@@ -235,4 +421,4 @@ declare class ElasticSearchSearchEngine implements SearchEngine {
|
|
|
235
421
|
private constructSearchAlias;
|
|
236
422
|
}
|
|
237
423
|
|
|
238
|
-
export { ElasticSearchAgentOptions, ElasticSearchAuth, ElasticSearchClientOptions, ElasticSearchConcreteQuery, ElasticSearchConnectionConstructor, ElasticSearchHighlightConfig, ElasticSearchHighlightOptions, ElasticSearchNodeOptions, ElasticSearchOptions, ElasticSearchQueryTranslator, ElasticSearchQueryTranslatorOptions, ElasticSearchSearchEngine, ElasticSearchSearchEngineIndexer, ElasticSearchSearchEngineIndexerOptions, ElasticSearchTransportConstructor };
|
|
424
|
+
export { BaseElasticSearchClientOptions, ElasticSearchAgentOptions, ElasticSearchAliasAction, ElasticSearchAuth, ElasticSearchClientOptions, ElasticSearchClientWrapper, ElasticSearchConcreteQuery, ElasticSearchConnectionConstructor, ElasticSearchCustomIndexTemplate, ElasticSearchCustomIndexTemplateBody, ElasticSearchElasticSearchClientOptions, ElasticSearchHighlightConfig, ElasticSearchHighlightOptions, ElasticSearchIndexAction, ElasticSearchNodeOptions, ElasticSearchOptions, ElasticSearchQueryTranslator, ElasticSearchQueryTranslatorOptions, ElasticSearchSearchEngine, ElasticSearchSearchEngineIndexer, ElasticSearchSearchEngineIndexerOptions, ElasticSearchTransportConstructor, OpenSearchAuth, OpenSearchConnectionConstructor, OpenSearchElasticSearchClientOptions, OpenSearchNodeOptions, isOpenSearchCompatible };
|
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.
|
|
4
|
+
"version": "0.2.0-next.1",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -23,11 +23,12 @@
|
|
|
23
23
|
"clean": "backstage-cli package clean"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@acuris/aws-es-connection": "^2.2.0",
|
|
27
26
|
"@backstage/config": "^1.0.1",
|
|
28
|
-
"@backstage/plugin-search-backend-node": "^0.6.
|
|
29
|
-
"@backstage/plugin-search-common": "^0.3.
|
|
30
|
-
"@elastic/elasticsearch": "7.13.0",
|
|
27
|
+
"@backstage/plugin-search-backend-node": "^0.6.3-next.1",
|
|
28
|
+
"@backstage/plugin-search-common": "^0.3.6-next.0",
|
|
29
|
+
"@elastic/elasticsearch": "^7.13.0",
|
|
30
|
+
"@opensearch-project/opensearch": "^1.1.0",
|
|
31
|
+
"aws-os-connection": "^0.1.0",
|
|
31
32
|
"aws-sdk": "^2.948.0",
|
|
32
33
|
"elastic-builder": "^2.16.0",
|
|
33
34
|
"lodash": "^4.17.21",
|
|
@@ -35,14 +36,15 @@
|
|
|
35
36
|
"winston": "^3.2.1"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
|
-
"@backstage/backend-common": "^0.14.
|
|
39
|
-
"@backstage/cli": "^0.
|
|
40
|
-
"@elastic/elasticsearch-mock": "^1.0.0"
|
|
39
|
+
"@backstage/backend-common": "^0.14.1-next.1",
|
|
40
|
+
"@backstage/cli": "^0.18.0-next.1",
|
|
41
|
+
"@elastic/elasticsearch-mock": "^1.0.0",
|
|
42
|
+
"@short.io/opensearch-mock": "^0.3.1"
|
|
41
43
|
},
|
|
42
44
|
"files": [
|
|
43
45
|
"dist",
|
|
44
46
|
"config.d.ts"
|
|
45
47
|
],
|
|
46
48
|
"configSchema": "config.d.ts",
|
|
47
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "e0a993834c31487a97a1ae6878eaf3685f03fc1a"
|
|
48
50
|
}
|