@backstage/plugin-search-backend-module-elasticsearch 1.5.7-next.0 → 1.5.7-next.2

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/dist/index.cjs.js CHANGED
@@ -1,667 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var lodash = require('lodash');
4
- var aws = require('@opensearch-project/opensearch/aws');
5
- var aws4 = require('aws4');
6
- var elasticsearch = require('@elastic/elasticsearch');
7
- var opensearch = require('@opensearch-project/opensearch');
8
- var pluginSearchBackendNode = require('@backstage/plugin-search-backend-node');
9
- var stream = require('stream');
10
- var esb = require('elastic-builder');
11
- var uuid = require('uuid');
12
- var integrationAwsNode = require('@backstage/integration-aws-node');
3
+ var ElasticSearchSearchEngine = require('./engines/ElasticSearchSearchEngine.cjs.js');
4
+ var ElasticSearchClientOptions = require('./engines/ElasticSearchClientOptions.cjs.js');
13
5
 
14
- function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
15
6
 
16
- var esb__default = /*#__PURE__*/_interopDefaultCompat(esb);
17
7
 
18
- const isOpenSearchCompatible = (opts) => {
19
- return ["aws", "opensearch"].includes(opts?.provider ?? "");
20
- };
21
-
22
- class ElasticSearchClientWrapper {
23
- elasticSearchClient;
24
- openSearchClient;
25
- constructor(options) {
26
- this.openSearchClient = options.openSearchClient;
27
- this.elasticSearchClient = options.elasticSearchClient;
28
- }
29
- static fromClientOptions(options) {
30
- if (isOpenSearchCompatible(options)) {
31
- return new ElasticSearchClientWrapper({
32
- openSearchClient: new opensearch.Client(options)
33
- });
34
- }
35
- return new ElasticSearchClientWrapper({
36
- elasticSearchClient: new elasticsearch.Client(options)
37
- });
38
- }
39
- search(options) {
40
- const searchOptions = {
41
- ignore_unavailable: true,
42
- allow_no_indices: true
43
- };
44
- if (this.openSearchClient) {
45
- return this.openSearchClient.search({
46
- ...options,
47
- ...searchOptions
48
- });
49
- }
50
- if (this.elasticSearchClient) {
51
- return this.elasticSearchClient.search({
52
- ...options,
53
- ...searchOptions
54
- });
55
- }
56
- throw new Error("No client defined");
57
- }
58
- bulk(bulkOptions) {
59
- if (this.openSearchClient) {
60
- return this.openSearchClient.helpers.bulk(bulkOptions);
61
- }
62
- if (this.elasticSearchClient) {
63
- return this.elasticSearchClient.helpers.bulk(bulkOptions);
64
- }
65
- throw new Error("No client defined");
66
- }
67
- putIndexTemplate(template) {
68
- if (this.openSearchClient) {
69
- return this.openSearchClient.indices.putIndexTemplate(template);
70
- }
71
- if (this.elasticSearchClient) {
72
- return this.elasticSearchClient.indices.putIndexTemplate(template);
73
- }
74
- throw new Error("No client defined");
75
- }
76
- listIndices(options) {
77
- if (this.openSearchClient) {
78
- return this.openSearchClient.indices.get(options);
79
- }
80
- if (this.elasticSearchClient) {
81
- return this.elasticSearchClient.indices.get(options);
82
- }
83
- throw new Error("No client defined");
84
- }
85
- indexExists(options) {
86
- if (this.openSearchClient) {
87
- return this.openSearchClient.indices.exists(options);
88
- }
89
- if (this.elasticSearchClient) {
90
- return this.elasticSearchClient.indices.exists(options);
91
- }
92
- throw new Error("No client defined");
93
- }
94
- deleteIndex(options) {
95
- if (this.openSearchClient) {
96
- return this.openSearchClient.indices.delete(options);
97
- }
98
- if (this.elasticSearchClient) {
99
- return this.elasticSearchClient.indices.delete(options);
100
- }
101
- throw new Error("No client defined");
102
- }
103
- /**
104
- * @deprecated unused by the ElasticSearch Engine, will be removed in the future
105
- */
106
- getAliases(options) {
107
- const { aliases } = options;
108
- if (this.openSearchClient) {
109
- return this.openSearchClient.cat.aliases({
110
- format: "json",
111
- name: aliases
112
- });
113
- }
114
- if (this.elasticSearchClient) {
115
- return this.elasticSearchClient.cat.aliases({
116
- format: "json",
117
- name: aliases
118
- });
119
- }
120
- throw new Error("No client defined");
121
- }
122
- createIndex(options) {
123
- if (this.openSearchClient) {
124
- return this.openSearchClient.indices.create(options);
125
- }
126
- if (this.elasticSearchClient) {
127
- return this.elasticSearchClient.indices.create(options);
128
- }
129
- throw new Error("No client defined");
130
- }
131
- updateAliases(options) {
132
- const filteredActions = options.actions.filter(Boolean);
133
- if (this.openSearchClient) {
134
- return this.openSearchClient.indices.updateAliases({
135
- body: {
136
- actions: filteredActions
137
- }
138
- });
139
- }
140
- if (this.elasticSearchClient) {
141
- return this.elasticSearchClient.indices.updateAliases({
142
- body: {
143
- actions: filteredActions
144
- }
145
- });
146
- }
147
- throw new Error("No client defined");
148
- }
149
- }
150
-
151
- function duration(startTimestamp) {
152
- const delta = process.hrtime(startTimestamp);
153
- const seconds = delta[0] + delta[1] / 1e9;
154
- return `${seconds.toFixed(1)}s`;
155
- }
156
- class ElasticSearchSearchEngineIndexer extends pluginSearchBackendNode.BatchSearchEngineIndexer {
157
- processed = 0;
158
- removableIndices = [];
159
- startTimestamp;
160
- type;
161
- indexName;
162
- indexPrefix;
163
- indexSeparator;
164
- alias;
165
- logger;
166
- sourceStream;
167
- elasticSearchClientWrapper;
168
- configuredBatchSize;
169
- bulkResult;
170
- bulkClientError;
171
- constructor(options) {
172
- super({ batchSize: options.batchSize });
173
- this.configuredBatchSize = options.batchSize;
174
- this.logger = options.logger.child({ documentType: options.type });
175
- this.startTimestamp = process.hrtime();
176
- this.type = options.type;
177
- this.indexPrefix = options.indexPrefix;
178
- this.indexSeparator = options.indexSeparator;
179
- this.indexName = this.constructIndexName(`${Date.now()}`);
180
- this.alias = options.alias;
181
- this.elasticSearchClientWrapper = options.elasticSearchClientWrapper;
182
- this.sourceStream = new stream.Readable({ objectMode: true });
183
- this.sourceStream._read = () => {
184
- };
185
- const that = this;
186
- this.bulkResult = this.elasticSearchClientWrapper.bulk({
187
- datasource: this.sourceStream,
188
- onDocument() {
189
- that.processed++;
190
- return {
191
- index: { _index: that.indexName }
192
- };
193
- },
194
- refreshOnCompletion: options.skipRefresh !== true
195
- });
196
- this.bulkResult.catch((e) => {
197
- this.bulkClientError = e;
198
- });
199
- }
200
- async initialize() {
201
- this.logger.info(`Started indexing documents for index ${this.type}`);
202
- const indices = await this.elasticSearchClientWrapper.listIndices({
203
- index: this.constructIndexName("*")
204
- });
205
- for (const key of Object.keys(indices.body)) {
206
- this.removableIndices.push(key);
207
- }
208
- await this.elasticSearchClientWrapper.createIndex({
209
- index: this.indexName
210
- });
211
- }
212
- async index(documents) {
213
- await this.isReady();
214
- documents.forEach((document) => {
215
- this.sourceStream.push(document);
216
- });
217
- }
218
- async finalize() {
219
- await this.isReady();
220
- this.sourceStream.push(null);
221
- const result = await this.bulkResult;
222
- if (this.processed === 0) {
223
- this.logger.warn(
224
- `Index for ${this.type} was not ${this.removableIndices.length ? "replaced" : "created"}: indexer received 0 documents`
225
- );
226
- try {
227
- await this.elasticSearchClientWrapper.deleteIndex({
228
- index: this.indexName
229
- });
230
- } catch (error) {
231
- this.logger.error(`Unable to clean up elastic index: ${error}`);
232
- }
233
- return;
234
- }
235
- this.logger.info(
236
- `Indexing completed for index ${this.type} in ${duration(
237
- this.startTimestamp
238
- )}`,
239
- result
240
- );
241
- await this.elasticSearchClientWrapper.updateAliases({
242
- actions: [
243
- {
244
- remove: { index: this.constructIndexName("*"), alias: this.alias }
245
- },
246
- {
247
- add: { index: this.indexName, alias: this.alias }
248
- }
249
- ].filter(Boolean)
250
- });
251
- if (this.removableIndices.length) {
252
- this.logger.info("Removing stale search indices", {
253
- removableIndices: this.removableIndices
254
- });
255
- const chunks = this.removableIndices.reduce(
256
- (resultArray, item, index) => {
257
- const chunkIndex = Math.floor(index / 50);
258
- if (!resultArray[chunkIndex]) {
259
- resultArray[chunkIndex] = [];
260
- }
261
- resultArray[chunkIndex].push(item);
262
- return resultArray;
263
- },
264
- []
265
- );
266
- for (const chunk of chunks) {
267
- try {
268
- await this.elasticSearchClientWrapper.deleteIndex({
269
- index: chunk
270
- });
271
- } catch (e) {
272
- this.logger.warn(`Failed to remove stale search indices: ${e}`);
273
- }
274
- }
275
- }
276
- }
277
- /**
278
- * Ensures that the number of documents sent over the wire to ES matches the
279
- * number of documents this stream has received so far. This helps manage
280
- * backpressure in other parts of the indexing pipeline.
281
- */
282
- isReady() {
283
- if (this.bulkClientError) {
284
- return Promise.reject(this.bulkClientError);
285
- }
286
- if (this.sourceStream.readableLength < this.configuredBatchSize) {
287
- return Promise.resolve();
288
- }
289
- return new Promise((isReady, abort) => {
290
- let streamLengthChecks = 0;
291
- const interval = setInterval(() => {
292
- streamLengthChecks++;
293
- if (this.sourceStream.readableLength < this.configuredBatchSize) {
294
- clearInterval(interval);
295
- isReady();
296
- }
297
- if (streamLengthChecks >= 6e3) {
298
- clearInterval(interval);
299
- abort(
300
- new Error(
301
- "Exceeded 5 minutes waiting for elastic to be ready to accept more documents. Check the elastic logs for possible problems."
302
- )
303
- );
304
- }
305
- }, 50);
306
- });
307
- }
308
- constructIndexName(postFix) {
309
- return `${this.indexPrefix}${this.type}${this.indexSeparator}${postFix}`;
310
- }
311
- }
312
-
313
- function isBlank(str) {
314
- return lodash.isEmpty(str) && !lodash.isNumber(str) || lodash.isNaN(str);
315
- }
316
- const DEFAULT_INDEXER_BATCH_SIZE = 1e3;
317
- class ElasticSearchSearchEngine {
318
- constructor(elasticSearchClientOptions, aliasPostfix, indexPrefix, logger, batchSize, highlightOptions) {
319
- this.elasticSearchClientOptions = elasticSearchClientOptions;
320
- this.aliasPostfix = aliasPostfix;
321
- this.indexPrefix = indexPrefix;
322
- this.logger = logger;
323
- this.batchSize = batchSize;
324
- this.elasticSearchClientWrapper = ElasticSearchClientWrapper.fromClientOptions(elasticSearchClientOptions);
325
- const uuidTag = uuid.v4();
326
- this.highlightOptions = {
327
- preTag: `<${uuidTag}>`,
328
- postTag: `</${uuidTag}>`,
329
- fragmentSize: 1e3,
330
- numFragments: 1,
331
- fragmentDelimiter: " ... ",
332
- ...highlightOptions
333
- };
334
- }
335
- elasticSearchClientWrapper;
336
- highlightOptions;
337
- static async fromConfig(options) {
338
- const {
339
- logger,
340
- config,
341
- aliasPostfix = `search`,
342
- indexPrefix = ``,
343
- translator
344
- } = options;
345
- const credentialProvider = integrationAwsNode.DefaultAwsCredentialsManager.fromConfig(config);
346
- const clientOptions = await this.createElasticSearchClientOptions(
347
- await credentialProvider?.getCredentialProvider(),
348
- config.getConfig("search.elasticsearch")
349
- );
350
- if (clientOptions.provider === "elastic") {
351
- logger.info("Initializing Elastic.co ElasticSearch search engine.");
352
- } else if (clientOptions.provider === "aws") {
353
- logger.info("Initializing AWS OpenSearch search engine.");
354
- } else if (clientOptions.provider === "opensearch") {
355
- logger.info("Initializing OpenSearch search engine.");
356
- } else {
357
- logger.info("Initializing ElasticSearch search engine.");
358
- }
359
- const engine = new ElasticSearchSearchEngine(
360
- clientOptions,
361
- aliasPostfix,
362
- indexPrefix,
363
- logger,
364
- config.getOptionalNumber("search.elasticsearch.batchSize") ?? DEFAULT_INDEXER_BATCH_SIZE,
365
- config.getOptional(
366
- "search.elasticsearch.highlightOptions"
367
- )
368
- );
369
- for (const indexTemplate of this.readIndexTemplateConfig(
370
- config.getConfig("search.elasticsearch")
371
- )) {
372
- await engine.setIndexTemplate(indexTemplate);
373
- }
374
- if (translator) {
375
- await engine.setTranslator(translator);
376
- }
377
- return engine;
378
- }
379
- /**
380
- * Create a custom search client from the derived search client configuration.
381
- * This need not be the same client that the engine uses internally.
382
- *
383
- * @example Instantiate an instance of an Elasticsearch client.
384
- *
385
- * ```ts
386
- * import { isOpenSearchCompatible } from '@backstage/plugin-search-backend-module-elasticsearch';
387
- * import { Client } from '@elastic/elasticsearch';
388
- *
389
- * const client = searchEngine.newClient<Client>(options => {
390
- * // This type guard ensures options are compatible with either OpenSearch
391
- * // or Elasticsearch client constructors.
392
- * if (!isOpenSearchCompatible(options)) {
393
- * return new Client(options);
394
- * }
395
- * throw new Error('Incompatible options provided');
396
- * });
397
- * ```
398
- */
399
- newClient(create) {
400
- return create(this.elasticSearchClientOptions);
401
- }
402
- translator(query, options) {
403
- const { term, filters = {}, types, pageCursor } = query;
404
- const filter = Object.entries(filters).filter(([_, value]) => Boolean(value)).map(([key, value]) => {
405
- if (["string", "number", "boolean"].includes(typeof value)) {
406
- const keyword = typeof value === "string" ? `${key}.keyword` : key;
407
- return esb__default.default.matchQuery(keyword, value.toString());
408
- }
409
- if (Array.isArray(value)) {
410
- return esb__default.default.boolQuery().should(value.map((it) => esb__default.default.matchQuery(key, it.toString())));
411
- }
412
- this.logger.error("Failed to query, unrecognized filter type", {
413
- key,
414
- value
415
- });
416
- throw new Error(
417
- "Failed to add filters to query. Unrecognized filter type"
418
- );
419
- });
420
- const esbQuery = isBlank(term) ? esb__default.default.matchAllQuery() : esb__default.default.multiMatchQuery(["*"], term).fuzziness("auto").minimumShouldMatch(1);
421
- const pageSize = query.pageLimit || 25;
422
- const { page } = decodePageCursor(pageCursor);
423
- let esbRequestBodySearch = esb__default.default.requestBodySearch().query(esb__default.default.boolQuery().filter(filter).must([esbQuery])).from(page * pageSize).size(pageSize);
424
- if (options?.highlightOptions) {
425
- esbRequestBodySearch = esbRequestBodySearch.highlight(
426
- esb__default.default.highlight("*").numberOfFragments(options.highlightOptions.numFragments).fragmentSize(options.highlightOptions.fragmentSize).preTags(options.highlightOptions.preTag).postTags(options.highlightOptions.postTag)
427
- );
428
- }
429
- return {
430
- elasticSearchQuery: esbRequestBodySearch.toJSON(),
431
- documentTypes: types,
432
- pageSize
433
- };
434
- }
435
- setTranslator(translator) {
436
- this.translator = translator;
437
- }
438
- async setIndexTemplate(template) {
439
- try {
440
- await this.elasticSearchClientWrapper.putIndexTemplate(template);
441
- this.logger.info("Custom index template set");
442
- } catch (error) {
443
- this.logger.error(`Unable to set custom index template: ${error}`);
444
- }
445
- }
446
- async getIndexer(type) {
447
- const alias = this.constructSearchAlias(type);
448
- const indexerLogger = this.logger.child({ documentType: type });
449
- const indexer = new ElasticSearchSearchEngineIndexer({
450
- type,
451
- indexPrefix: this.indexPrefix,
452
- indexSeparator: this.indexSeparator,
453
- alias,
454
- elasticSearchClientWrapper: this.elasticSearchClientWrapper,
455
- logger: indexerLogger,
456
- batchSize: this.batchSize,
457
- skipRefresh: this.elasticSearchClientOptions?.service === "aoss"
458
- });
459
- indexer.on("error", async (e) => {
460
- indexerLogger.error(`Failed to index documents for type ${type}`, e);
461
- let cleanupError;
462
- await new Promise(async (done) => {
463
- const maxAttempts = 5;
464
- let attempts = 0;
465
- while (attempts < maxAttempts) {
466
- try {
467
- await this.elasticSearchClientWrapper.deleteIndex({
468
- index: indexer.indexName
469
- });
470
- attempts = maxAttempts;
471
- cleanupError = void 0;
472
- done();
473
- } catch (err) {
474
- cleanupError = err;
475
- }
476
- await new Promise((okay) => setTimeout(okay, 1e3));
477
- attempts++;
478
- }
479
- done();
480
- });
481
- if (cleanupError) {
482
- indexerLogger.error(
483
- `Unable to clean up elastic index ${indexer.indexName}: ${cleanupError}`
484
- );
485
- } else {
486
- indexerLogger.info(
487
- `Removed partial, failed index ${indexer.indexName}`
488
- );
489
- }
490
- });
491
- return indexer;
492
- }
493
- async query(query) {
494
- const { elasticSearchQuery, documentTypes, pageSize } = this.translator(
495
- query,
496
- { highlightOptions: this.highlightOptions }
497
- );
498
- const queryIndices = documentTypes ? documentTypes.map((it) => this.constructSearchAlias(it)) : this.constructSearchAlias("*");
499
- try {
500
- const result = await this.elasticSearchClientWrapper.search({
501
- index: queryIndices,
502
- body: elasticSearchQuery
503
- });
504
- const { page } = decodePageCursor(query.pageCursor);
505
- const hasNextPage = result.body.hits.total.value > (page + 1) * pageSize;
506
- const hasPreviousPage = page > 0;
507
- const nextPageCursor = hasNextPage ? encodePageCursor({ page: page + 1 }) : void 0;
508
- const previousPageCursor = hasPreviousPage ? encodePageCursor({ page: page - 1 }) : void 0;
509
- return {
510
- results: result.body.hits.hits.map(
511
- (d, index) => {
512
- const resultItem = {
513
- type: this.getTypeFromIndex(d._index),
514
- document: d._source,
515
- rank: pageSize * page + index + 1
516
- };
517
- if (d.highlight) {
518
- resultItem.highlight = {
519
- preTag: this.highlightOptions.preTag,
520
- postTag: this.highlightOptions.postTag,
521
- fields: Object.fromEntries(
522
- Object.entries(d.highlight).map(([field, fragments]) => [
523
- field,
524
- fragments.join(this.highlightOptions.fragmentDelimiter)
525
- ])
526
- )
527
- };
528
- }
529
- return resultItem;
530
- }
531
- ),
532
- nextPageCursor,
533
- previousPageCursor,
534
- numberOfResults: result.body.hits.total.value
535
- };
536
- } catch (error) {
537
- if (error.meta?.body?.error?.type === "index_not_found_exception") {
538
- throw new pluginSearchBackendNode.MissingIndexError(
539
- `Missing index for ${queryIndices}. This means there are no documents to search through.`,
540
- error
541
- );
542
- }
543
- this.logger.error(
544
- `Failed to query documents for indices ${queryIndices}`,
545
- error
546
- );
547
- return Promise.reject({ results: [] });
548
- }
549
- }
550
- indexSeparator = "-index__";
551
- getTypeFromIndex(index) {
552
- return index.substring(this.indexPrefix.length).split(this.indexSeparator)[0];
553
- }
554
- constructSearchAlias(type) {
555
- const postFix = this.aliasPostfix ? `__${this.aliasPostfix}` : "";
556
- return `${this.indexPrefix}${type}${postFix}`;
557
- }
558
- static async createElasticSearchClientOptions(credentialProvider, config) {
559
- if (!config) {
560
- throw new Error("No elastic search config found");
561
- }
562
- const clientOptionsConfig = config.getOptionalConfig("clientOptions");
563
- const sslConfig = clientOptionsConfig?.getOptionalConfig("ssl");
564
- if (config.getOptionalString("provider") === "elastic") {
565
- const authConfig2 = config.getConfig("auth");
566
- return {
567
- provider: "elastic",
568
- cloud: {
569
- id: config.getString("cloudId")
570
- },
571
- auth: {
572
- username: authConfig2.getString("username"),
573
- password: authConfig2.getString("password")
574
- },
575
- ...sslConfig ? {
576
- ssl: {
577
- rejectUnauthorized: sslConfig?.getOptionalBoolean("rejectUnauthorized")
578
- }
579
- } : {}
580
- };
581
- }
582
- if (config.getOptionalString("provider") === "aws") {
583
- const requestSigner = new aws4.RequestSigner(config.getString("node"));
584
- const service = config.getOptionalString("service") ?? requestSigner.service;
585
- if (service !== "es" && service !== "aoss")
586
- throw new Error(`Unrecognized serivce type: ${service}`);
587
- return {
588
- provider: "aws",
589
- node: config.getString("node"),
590
- region: config.getOptionalString("region"),
591
- service,
592
- ...sslConfig ? {
593
- ssl: {
594
- rejectUnauthorized: sslConfig?.getOptionalBoolean("rejectUnauthorized")
595
- }
596
- } : {},
597
- ...aws.AwsSigv4Signer({
598
- region: config.getOptionalString("region") ?? requestSigner.region,
599
- // for backwards compatibility
600
- service,
601
- getCredentials: async () => await credentialProvider.sdkCredentialProvider()
602
- })
603
- };
604
- }
605
- if (config.getOptionalString("provider") === "opensearch") {
606
- const authConfig2 = config.getConfig("auth");
607
- return {
608
- provider: "opensearch",
609
- node: config.getString("node"),
610
- auth: {
611
- username: authConfig2.getString("username"),
612
- password: authConfig2.getString("password")
613
- },
614
- ...sslConfig ? {
615
- ssl: {
616
- rejectUnauthorized: sslConfig?.getOptionalBoolean("rejectUnauthorized")
617
- }
618
- } : {}
619
- };
620
- }
621
- const authConfig = config.getOptionalConfig("auth");
622
- const auth = authConfig && (authConfig.has("apiKey") ? {
623
- apiKey: authConfig.getString("apiKey")
624
- } : {
625
- username: authConfig.getString("username"),
626
- password: authConfig.getString("password")
627
- });
628
- return {
629
- node: config.getString("node"),
630
- auth,
631
- ...sslConfig ? {
632
- ssl: {
633
- rejectUnauthorized: sslConfig?.getOptionalBoolean("rejectUnauthorized")
634
- }
635
- } : {}
636
- };
637
- }
638
- static readIndexTemplateConfig(config) {
639
- return config.getOptionalConfigArray("indexTemplates")?.map((templateConfig) => {
640
- const bodyConfig = templateConfig.getConfig("body");
641
- return {
642
- name: templateConfig.getString("name"),
643
- body: {
644
- index_patterns: bodyConfig.getStringArray("index_patterns"),
645
- composed_of: bodyConfig.getOptionalStringArray("composed_of"),
646
- template: bodyConfig.getOptionalConfig("template")?.get()
647
- }
648
- };
649
- }) ?? [];
650
- }
651
- }
652
- function decodePageCursor(pageCursor) {
653
- if (!pageCursor) {
654
- return { page: 0 };
655
- }
656
- return {
657
- page: Number(Buffer.from(pageCursor, "base64").toString("utf-8"))
658
- };
659
- }
660
- function encodePageCursor({ page }) {
661
- return Buffer.from(`${page}`, "utf-8").toString("base64");
662
- }
663
-
664
- exports.ElasticSearchSearchEngine = ElasticSearchSearchEngine;
665
- exports.decodeElasticSearchPageCursor = decodePageCursor;
666
- exports.isOpenSearchCompatible = isOpenSearchCompatible;
8
+ exports.ElasticSearchSearchEngine = ElasticSearchSearchEngine.ElasticSearchSearchEngine;
9
+ exports.decodeElasticSearchPageCursor = ElasticSearchSearchEngine.decodePageCursor;
10
+ exports.isOpenSearchCompatible = ElasticSearchClientOptions.isOpenSearchCompatible;
667
11
  //# sourceMappingURL=index.cjs.js.map