@retter/elasticsearch 8.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/.dockerignore +5 -0
  2. package/CHANGELOG.md +3 -0
  3. package/LICENSE +202 -0
  4. package/NOTICE.txt +2 -0
  5. package/README.md +186 -0
  6. package/codecov.yml +14 -0
  7. package/index.d.ts +27 -0
  8. package/index.js +55 -0
  9. package/lib/api/api/async_search.d.ts +23 -0
  10. package/lib/api/api/async_search.js +131 -0
  11. package/lib/api/api/async_search.js.map +1 -0
  12. package/lib/api/api/autoscaling.d.ts +23 -0
  13. package/lib/api/api/autoscaling.js +109 -0
  14. package/lib/api/api/autoscaling.js.map +1 -0
  15. package/lib/api/api/bulk.d.ts +10 -0
  16. package/lib/api/api/bulk.js +54 -0
  17. package/lib/api/api/bulk.js.map +1 -0
  18. package/lib/api/api/cat.d.ts +89 -0
  19. package/lib/api/api/cat.js +637 -0
  20. package/lib/api/api/cat.js.map +1 -0
  21. package/lib/api/api/ccr.d.ts +50 -0
  22. package/lib/api/api/ccr.js +320 -0
  23. package/lib/api/api/ccr.js.map +1 -0
  24. package/lib/api/api/clear_scroll.d.ts +10 -0
  25. package/lib/api/api/clear_scroll.js +54 -0
  26. package/lib/api/api/clear_scroll.js.map +1 -0
  27. package/lib/api/api/close_point_in_time.d.ts +10 -0
  28. package/lib/api/api/close_point_in_time.js +53 -0
  29. package/lib/api/api/close_point_in_time.js.map +1 -0
  30. package/lib/api/api/cluster.d.ts +56 -0
  31. package/lib/api/api/cluster.js +392 -0
  32. package/lib/api/api/cluster.js.map +1 -0
  33. package/lib/api/api/count.d.ts +10 -0
  34. package/lib/api/api/count.js +62 -0
  35. package/lib/api/api/count.js.map +1 -0
  36. package/lib/api/api/create.d.ts +10 -0
  37. package/lib/api/api/create.js +46 -0
  38. package/lib/api/api/create.js.map +1 -0
  39. package/lib/api/api/dangling_indices.d.ts +20 -0
  40. package/lib/api/api/dangling_indices.js +85 -0
  41. package/lib/api/api/dangling_indices.js.map +1 -0
  42. package/lib/api/api/delete.d.ts +10 -0
  43. package/lib/api/api/delete.js +39 -0
  44. package/lib/api/api/delete.js.map +1 -0
  45. package/lib/api/api/delete_by_query.d.ts +10 -0
  46. package/lib/api/api/delete_by_query.js +53 -0
  47. package/lib/api/api/delete_by_query.js.map +1 -0
  48. package/lib/api/api/delete_by_query_rethrottle.d.ts +10 -0
  49. package/lib/api/api/delete_by_query_rethrottle.js +39 -0
  50. package/lib/api/api/delete_by_query_rethrottle.js.map +1 -0
  51. package/lib/api/api/delete_script.d.ts +10 -0
  52. package/lib/api/api/delete_script.js +39 -0
  53. package/lib/api/api/delete_script.js.map +1 -0
  54. package/lib/api/api/enrich.d.ts +26 -0
  55. package/lib/api/api/enrich.js +142 -0
  56. package/lib/api/api/enrich.js.map +1 -0
  57. package/lib/api/api/eql.d.ts +23 -0
  58. package/lib/api/api/eql.js +115 -0
  59. package/lib/api/api/eql.js.map +1 -0
  60. package/lib/api/api/exists.d.ts +10 -0
  61. package/lib/api/api/exists.js +39 -0
  62. package/lib/api/api/exists.js.map +1 -0
  63. package/lib/api/api/exists_source.d.ts +10 -0
  64. package/lib/api/api/exists_source.js +39 -0
  65. package/lib/api/api/exists_source.js.map +1 -0
  66. package/lib/api/api/explain.d.ts +10 -0
  67. package/lib/api/api/explain.js +53 -0
  68. package/lib/api/api/explain.js.map +1 -0
  69. package/lib/api/api/features.d.ts +17 -0
  70. package/lib/api/api/features.js +69 -0
  71. package/lib/api/api/features.js.map +1 -0
  72. package/lib/api/api/field_caps.d.ts +10 -0
  73. package/lib/api/api/field_caps.js +61 -0
  74. package/lib/api/api/field_caps.js.map +1 -0
  75. package/lib/api/api/fleet.d.ts +20 -0
  76. package/lib/api/api/fleet.js +113 -0
  77. package/lib/api/api/fleet.js.map +1 -0
  78. package/lib/api/api/get.d.ts +10 -0
  79. package/lib/api/api/get.js +39 -0
  80. package/lib/api/api/get.js.map +1 -0
  81. package/lib/api/api/get_script.d.ts +10 -0
  82. package/lib/api/api/get_script.js +39 -0
  83. package/lib/api/api/get_script.js.map +1 -0
  84. package/lib/api/api/get_script_context.d.ts +10 -0
  85. package/lib/api/api/get_script_context.js +40 -0
  86. package/lib/api/api/get_script_context.js.map +1 -0
  87. package/lib/api/api/get_script_languages.d.ts +10 -0
  88. package/lib/api/api/get_script_languages.js +40 -0
  89. package/lib/api/api/get_script_languages.js.map +1 -0
  90. package/lib/api/api/get_source.d.ts +10 -0
  91. package/lib/api/api/get_source.js +39 -0
  92. package/lib/api/api/get_source.js.map +1 -0
  93. package/lib/api/api/graph.d.ts +14 -0
  94. package/lib/api/api/graph.js +64 -0
  95. package/lib/api/api/graph.js.map +1 -0
  96. package/lib/api/api/ilm.d.ts +44 -0
  97. package/lib/api/api/ilm.js +275 -0
  98. package/lib/api/api/ilm.js.map +1 -0
  99. package/lib/api/api/index.d.ts +10 -0
  100. package/lib/api/api/index.js +54 -0
  101. package/lib/api/api/index.js.map +1 -0
  102. package/lib/api/api/indices.d.ts +170 -0
  103. package/lib/api/api/indices.js +1378 -0
  104. package/lib/api/api/indices.js.map +1 -0
  105. package/lib/api/api/info.d.ts +10 -0
  106. package/lib/api/api/info.js +40 -0
  107. package/lib/api/api/info.js.map +1 -0
  108. package/lib/api/api/ingest.d.ts +29 -0
  109. package/lib/api/api/ingest.js +183 -0
  110. package/lib/api/api/ingest.js.map +1 -0
  111. package/lib/api/api/knn_search.d.ts +10 -0
  112. package/lib/api/api/knn_search.js +53 -0
  113. package/lib/api/api/knn_search.js.map +1 -0
  114. package/lib/api/api/license.d.ts +32 -0
  115. package/lib/api/api/license.js +172 -0
  116. package/lib/api/api/license.js.map +1 -0
  117. package/lib/api/api/logstash.d.ts +20 -0
  118. package/lib/api/api/logstash.js +91 -0
  119. package/lib/api/api/logstash.js.map +1 -0
  120. package/lib/api/api/mget.d.ts +10 -0
  121. package/lib/api/api/mget.js +62 -0
  122. package/lib/api/api/mget.js.map +1 -0
  123. package/lib/api/api/migration.d.ts +20 -0
  124. package/lib/api/api/migration.js +95 -0
  125. package/lib/api/api/migration.js.map +1 -0
  126. package/lib/api/api/ml.d.ts +224 -0
  127. package/lib/api/api/ml.js +1929 -0
  128. package/lib/api/api/ml.js.map +1 -0
  129. package/lib/api/api/monitoring.d.ts +14 -0
  130. package/lib/api/api/monitoring.js +57 -0
  131. package/lib/api/api/monitoring.js.map +1 -0
  132. package/lib/api/api/msearch.d.ts +10 -0
  133. package/lib/api/api/msearch.js +54 -0
  134. package/lib/api/api/msearch.js.map +1 -0
  135. package/lib/api/api/msearch_template.d.ts +10 -0
  136. package/lib/api/api/msearch_template.js +54 -0
  137. package/lib/api/api/msearch_template.js.map +1 -0
  138. package/lib/api/api/mtermvectors.d.ts +10 -0
  139. package/lib/api/api/mtermvectors.js +62 -0
  140. package/lib/api/api/mtermvectors.js.map +1 -0
  141. package/lib/api/api/nodes.d.ts +32 -0
  142. package/lib/api/api/nodes.js +243 -0
  143. package/lib/api/api/nodes.js.map +1 -0
  144. package/lib/api/api/open_point_in_time.d.ts +10 -0
  145. package/lib/api/api/open_point_in_time.js +39 -0
  146. package/lib/api/api/open_point_in_time.js.map +1 -0
  147. package/lib/api/api/ping.d.ts +10 -0
  148. package/lib/api/api/ping.js +40 -0
  149. package/lib/api/api/ping.js.map +1 -0
  150. package/lib/api/api/put_script.d.ts +10 -0
  151. package/lib/api/api/put_script.js +61 -0
  152. package/lib/api/api/put_script.js.map +1 -0
  153. package/lib/api/api/rank_eval.d.ts +10 -0
  154. package/lib/api/api/rank_eval.js +61 -0
  155. package/lib/api/api/rank_eval.js.map +1 -0
  156. package/lib/api/api/reindex.d.ts +10 -0
  157. package/lib/api/api/reindex.js +53 -0
  158. package/lib/api/api/reindex.js.map +1 -0
  159. package/lib/api/api/reindex_rethrottle.d.ts +10 -0
  160. package/lib/api/api/reindex_rethrottle.js +39 -0
  161. package/lib/api/api/reindex_rethrottle.js.map +1 -0
  162. package/lib/api/api/render_search_template.d.ts +10 -0
  163. package/lib/api/api/render_search_template.js +62 -0
  164. package/lib/api/api/render_search_template.js.map +1 -0
  165. package/lib/api/api/rollup.d.ts +38 -0
  166. package/lib/api/api/rollup.js +239 -0
  167. package/lib/api/api/rollup.js.map +1 -0
  168. package/lib/api/api/scripts_painless_execute.d.ts +10 -0
  169. package/lib/api/api/scripts_painless_execute.js +54 -0
  170. package/lib/api/api/scripts_painless_execute.js.map +1 -0
  171. package/lib/api/api/scroll.d.ts +10 -0
  172. package/lib/api/api/scroll.js +53 -0
  173. package/lib/api/api/scroll.js.map +1 -0
  174. package/lib/api/api/search.d.ts +10 -0
  175. package/lib/api/api/search.js +69 -0
  176. package/lib/api/api/search.js.map +1 -0
  177. package/lib/api/api/search_mvt.d.ts +10 -0
  178. package/lib/api/api/search_mvt.js +53 -0
  179. package/lib/api/api/search_mvt.js.map +1 -0
  180. package/lib/api/api/search_shards.d.ts +10 -0
  181. package/lib/api/api/search_shards.js +48 -0
  182. package/lib/api/api/search_shards.js.map +1 -0
  183. package/lib/api/api/search_template.d.ts +10 -0
  184. package/lib/api/api/search_template.js +62 -0
  185. package/lib/api/api/search_template.js.map +1 -0
  186. package/lib/api/api/searchable_snapshots.d.ts +23 -0
  187. package/lib/api/api/searchable_snapshots.js +142 -0
  188. package/lib/api/api/searchable_snapshots.js.map +1 -0
  189. package/lib/api/api/security.d.ts +173 -0
  190. package/lib/api/api/security.js +1344 -0
  191. package/lib/api/api/security.js.map +1 -0
  192. package/lib/api/api/shutdown.d.ts +20 -0
  193. package/lib/api/api/shutdown.js +107 -0
  194. package/lib/api/api/shutdown.js.map +1 -0
  195. package/lib/api/api/slm.d.ts +38 -0
  196. package/lib/api/api/slm.js +214 -0
  197. package/lib/api/api/slm.js.map +1 -0
  198. package/lib/api/api/snapshot.d.ts +47 -0
  199. package/lib/api/api/snapshot.js +315 -0
  200. package/lib/api/api/snapshot.js.map +1 -0
  201. package/lib/api/api/sql.d.ts +29 -0
  202. package/lib/api/api/sql.js +178 -0
  203. package/lib/api/api/sql.js.map +1 -0
  204. package/lib/api/api/ssl.d.ts +14 -0
  205. package/lib/api/api/ssl.js +51 -0
  206. package/lib/api/api/ssl.js.map +1 -0
  207. package/lib/api/api/tasks.d.ts +20 -0
  208. package/lib/api/api/tasks.js +94 -0
  209. package/lib/api/api/tasks.js.map +1 -0
  210. package/lib/api/api/terms_enum.d.ts +10 -0
  211. package/lib/api/api/terms_enum.js +53 -0
  212. package/lib/api/api/terms_enum.js.map +1 -0
  213. package/lib/api/api/termvectors.d.ts +10 -0
  214. package/lib/api/api/termvectors.js +61 -0
  215. package/lib/api/api/termvectors.js.map +1 -0
  216. package/lib/api/api/text_structure.d.ts +14 -0
  217. package/lib/api/api/text_structure.js +57 -0
  218. package/lib/api/api/text_structure.js.map +1 -0
  219. package/lib/api/api/transform.d.ts +41 -0
  220. package/lib/api/api/transform.js +264 -0
  221. package/lib/api/api/transform.js.map +1 -0
  222. package/lib/api/api/update.d.ts +10 -0
  223. package/lib/api/api/update.js +53 -0
  224. package/lib/api/api/update.js.map +1 -0
  225. package/lib/api/api/update_by_query.d.ts +10 -0
  226. package/lib/api/api/update_by_query.js +53 -0
  227. package/lib/api/api/update_by_query.js.map +1 -0
  228. package/lib/api/api/update_by_query_rethrottle.d.ts +10 -0
  229. package/lib/api/api/update_by_query_rethrottle.js +39 -0
  230. package/lib/api/api/update_by_query_rethrottle.js.map +1 -0
  231. package/lib/api/api/watcher.d.ts +44 -0
  232. package/lib/api/api/watcher.js +291 -0
  233. package/lib/api/api/watcher.js.map +1 -0
  234. package/lib/api/api/xpack.d.ts +17 -0
  235. package/lib/api/api/xpack.js +69 -0
  236. package/lib/api/api/xpack.js.map +1 -0
  237. package/lib/api/index.d.ts +225 -0
  238. package/lib/api/index.js +520 -0
  239. package/lib/api/index.js.map +1 -0
  240. package/lib/api/types.d.ts +15306 -0
  241. package/lib/api/types.js +21 -0
  242. package/lib/api/types.js.map +1 -0
  243. package/lib/api/typesWithBodyKey.d.ts +15718 -0
  244. package/lib/api/typesWithBodyKey.js +21 -0
  245. package/lib/api/typesWithBodyKey.js.map +1 -0
  246. package/lib/client.d.ts +70 -0
  247. package/lib/client.js +287 -0
  248. package/lib/client.js.map +1 -0
  249. package/lib/helpers.d.ts +149 -0
  250. package/lib/helpers.js +776 -0
  251. package/lib/helpers.js.map +1 -0
  252. package/lib/sniffingTransport.d.ts +4 -0
  253. package/lib/sniffingTransport.js +56 -0
  254. package/lib/sniffingTransport.js.map +1 -0
  255. package/package.json +93 -0
  256. package/tsconfig.json +37 -0
package/lib/helpers.js ADDED
@@ -0,0 +1,776 @@
1
+ "use strict";
2
+ /*
3
+ * Licensed to Elasticsearch B.V. under one or more contributor
4
+ * license agreements. See the NOTICE file distributed with
5
+ * this work for additional information regarding copyright
6
+ * ownership. Elasticsearch B.V. licenses this file to you under
7
+ * the Apache License, Version 2.0 (the "License") you may
8
+ * not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing,
14
+ * software distributed under the License is distributed on an
15
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ * KIND, either express or implied. See the License for the
17
+ * specific language governing permissions and limitations
18
+ * under the License.
19
+ */
20
+ var _a, _b, _c;
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ const tslib_1 = require("tslib");
23
+ /* eslint-disable @typescript-eslint/naming-convention */
24
+ /* eslint-disable @typescript-eslint/promise-function-async */
25
+ /* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
26
+ const assert_1 = tslib_1.__importDefault(require("assert"));
27
+ const util_1 = require("util");
28
+ const stream_1 = require("stream");
29
+ const transport_1 = require("@elastic/transport");
30
+ const { ResponseError, ConfigurationError } = transport_1.errors;
31
+ const sleep = (0, util_1.promisify)(setTimeout);
32
+ const pImmediate = (0, util_1.promisify)(setImmediate);
33
+ /* istanbul ignore next */
34
+ const noop = () => { };
35
+ const kClient = Symbol('elasticsearch-client');
36
+ const kMetaHeader = Symbol('meta header');
37
+ const kMaxRetries = Symbol('max retries');
38
+ class Helpers {
39
+ constructor(opts) {
40
+ Object.defineProperty(this, _a, {
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true,
44
+ value: void 0
45
+ });
46
+ Object.defineProperty(this, _b, {
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ value: void 0
51
+ });
52
+ Object.defineProperty(this, _c, {
53
+ enumerable: true,
54
+ configurable: true,
55
+ writable: true,
56
+ value: void 0
57
+ });
58
+ this[kClient] = opts.client;
59
+ this[kMetaHeader] = opts.metaHeader;
60
+ this[kMaxRetries] = opts.maxRetries;
61
+ }
62
+ /**
63
+ * Runs a search operation. The only difference between client.search and this utility,
64
+ * is that we are only returning the hits to the user and not the full ES response.
65
+ * This helper automatically adds `filter_path=hits.hits._source` to the querystring,
66
+ * as it will only need the documents source.
67
+ * @param {object} params - The Elasticsearch's search parameters.
68
+ * @param {object} options - The client optional configuration for this request.
69
+ * @return {array} The documents that matched the request.
70
+ */
71
+ async search(params, options = {}) {
72
+ var _d;
73
+ appendFilterPath('hits.hits._source', params, true);
74
+ options.meta = true;
75
+ const { body: result } = await this[kClient].search(params, options);
76
+ if (((_d = result.hits) === null || _d === void 0 ? void 0 : _d.hits) != null) {
77
+ return result.hits.hits.map(d => d._source);
78
+ }
79
+ return [];
80
+ }
81
+ /**
82
+ * Runs a scroll search operation. This function returns an async iterator, allowing
83
+ * the user to use a for await loop to get all the results of a given search.
84
+ * ```js
85
+ * for await (const result of client.helpers.scrollSearch({ params })) {
86
+ * console.log(result)
87
+ * }
88
+ * ```
89
+ * Each result represents the entire body of a single scroll search request,
90
+ * if you just need to scroll the results, use scrollDocuments.
91
+ * This function handles automatically retries on 429 status code.
92
+ * @param {object} params - The Elasticsearch's search parameters.
93
+ * @param {object} options - The client optional configuration for this request.
94
+ * @return {iterator} the async iterator
95
+ */
96
+ async *scrollSearch(params, options = {}) {
97
+ var _d, _e, _f, _g;
98
+ options.meta = true;
99
+ if (this[kMetaHeader] !== null) {
100
+ options.headers = (_d = options.headers) !== null && _d !== void 0 ? _d : {};
101
+ options.headers['x-elastic-client-meta'] = `${this[kMetaHeader]},h=s`;
102
+ }
103
+ const wait = (_e = options.wait) !== null && _e !== void 0 ? _e : 5000;
104
+ const maxRetries = (_f = options.maxRetries) !== null && _f !== void 0 ? _f : this[kMaxRetries];
105
+ if (Array.isArray(options.ignore)) {
106
+ options.ignore.push(429);
107
+ }
108
+ else {
109
+ options.ignore = [429];
110
+ }
111
+ params.scroll = (_g = params.scroll) !== null && _g !== void 0 ? _g : '1m';
112
+ appendFilterPath('_scroll_id', params, false);
113
+ let response;
114
+ for (let i = 0; i <= maxRetries; i++) {
115
+ response = await this[kClient].search(params, options);
116
+ if (response.statusCode !== 429)
117
+ break;
118
+ await sleep(wait);
119
+ }
120
+ (0, assert_1.default)(response !== undefined, 'The response is undefined, please file a bug report');
121
+ if (response.statusCode === 429) {
122
+ throw new ResponseError(response);
123
+ }
124
+ let scroll_id = response.body._scroll_id;
125
+ let stop = false;
126
+ const clear = async () => {
127
+ stop = true;
128
+ await this[kClient].clearScroll({ scroll_id }, { ignore: [400], ...options });
129
+ };
130
+ while (response.body.hits != null && response.body.hits.hits.length > 0) {
131
+ // scroll id is always present in the response, but it might
132
+ // change over time based on the number of shards
133
+ scroll_id = response.body._scroll_id;
134
+ // @ts-expect-error
135
+ response.clear = clear;
136
+ addDocumentsGetter(response);
137
+ // @ts-expect-error
138
+ yield response;
139
+ if (stop) {
140
+ break;
141
+ }
142
+ for (let i = 0; i <= maxRetries; i++) {
143
+ const r = await this[kClient].scroll({
144
+ scroll: params.scroll,
145
+ rest_total_hits_as_int: params.rest_total_hits_as_int,
146
+ scroll_id
147
+ }, options);
148
+ response = r;
149
+ (0, assert_1.default)(response !== undefined, 'The response is undefined, please file a bug report');
150
+ if (response.statusCode !== 429)
151
+ break;
152
+ await sleep(wait);
153
+ }
154
+ if (response.statusCode === 429) {
155
+ throw new ResponseError(response);
156
+ }
157
+ }
158
+ if (!stop) {
159
+ await clear();
160
+ }
161
+ }
162
+ /**
163
+ * Runs a scroll search operation. This function returns an async iterator, allowing
164
+ * the user to use a for await loop to get all the documents of a given search.
165
+ * ```js
166
+ * for await (const document of client.helpers.scrollSearch({ params })) {
167
+ * console.log(document)
168
+ * }
169
+ * ```
170
+ * Each document is what you will find by running a scrollSearch and iterating on the hits array.
171
+ * This helper automatically adds `filter_path=hits.hits._source` to the querystring,
172
+ * as it will only need the documents source.
173
+ * @param {object} params - The Elasticsearch's search parameters.
174
+ * @param {object} options - The client optional configuration for this request.
175
+ * @return {iterator} the async iterator
176
+ */
177
+ async *scrollDocuments(params, options = {}) {
178
+ appendFilterPath('hits.hits._source', params, true);
179
+ for await (const { documents } of this.scrollSearch(params, options)) {
180
+ for (const document of documents) {
181
+ yield document;
182
+ }
183
+ }
184
+ }
185
+ /**
186
+ * Creates a msearch helper instance. Once you configure it, you can use the provided
187
+ * `search` method to add new searches in the queue.
188
+ * @param {object} options - The configuration of the msearch operations.
189
+ * @param {object} reqOptions - The client optional configuration for this request.
190
+ * @return {object} The possible operations to run.
191
+ */
192
+ msearch(options = {}, reqOptions = {}) {
193
+ const client = this[kClient];
194
+ const { operations = 5, concurrency = 5, flushInterval = 500, retries = this[kMaxRetries], wait = 5000, ...msearchOptions } = options;
195
+ reqOptions.meta = true;
196
+ let stopReading = false;
197
+ let stopError = null;
198
+ let timeoutRef = null;
199
+ const operationsStream = new stream_1.Readable({
200
+ objectMode: true,
201
+ read(size) { }
202
+ });
203
+ const p = iterate();
204
+ const helper = {
205
+ [Symbol.toStringTag]: 'Promise',
206
+ then(onFulfilled, onRejected) {
207
+ return p.then(onFulfilled, onRejected);
208
+ },
209
+ catch(onRejected) {
210
+ return p.catch(onRejected);
211
+ },
212
+ finally(onFinally) {
213
+ return p.finally(onFinally);
214
+ },
215
+ stop(error = null) {
216
+ if (stopReading)
217
+ return;
218
+ stopReading = true;
219
+ stopError = error;
220
+ operationsStream.push(null);
221
+ },
222
+ // TODO: support abort a single search?
223
+ // NOTE: the validation checks are synchronous and the callback/promise will
224
+ // be resolved in the same tick. We might want to fix this in the future.
225
+ search(header, body) {
226
+ if (stopReading) {
227
+ const error = stopError === null
228
+ ? new ConfigurationError('The msearch processor has been stopped')
229
+ : stopError;
230
+ return Promise.reject(error);
231
+ }
232
+ if (!(typeof header === 'object' && header !== null && !Array.isArray(header))) {
233
+ return Promise.reject(new ConfigurationError('The header should be an object'));
234
+ }
235
+ if (!(typeof body === 'object' && body !== null && !Array.isArray(body))) {
236
+ return Promise.reject(new ConfigurationError('The body should be an object'));
237
+ }
238
+ let onFulfilled = null;
239
+ let onRejected = null;
240
+ const promise = new Promise((resolve, reject) => {
241
+ onFulfilled = resolve;
242
+ onRejected = reject;
243
+ });
244
+ const callback = function callback(err, result) {
245
+ err !== null ? onRejected(err) : onFulfilled(result);
246
+ };
247
+ operationsStream.push([header, body, callback]);
248
+ return promise;
249
+ }
250
+ };
251
+ return helper;
252
+ async function iterate() {
253
+ const { semaphore, finish } = buildSemaphore();
254
+ const msearchBody = [];
255
+ const callbacks = [];
256
+ let loadedOperations = 0;
257
+ timeoutRef = setTimeout(onFlushTimeout, flushInterval); // eslint-disable-line
258
+ try {
259
+ for await (const operation of operationsStream) {
260
+ timeoutRef.refresh();
261
+ loadedOperations += 1;
262
+ msearchBody.push(operation[0], operation[1]);
263
+ callbacks.push(operation[2]);
264
+ if (loadedOperations >= operations) {
265
+ const send = await semaphore();
266
+ send(msearchBody.slice(), callbacks.slice());
267
+ msearchBody.length = 0;
268
+ callbacks.length = 0;
269
+ loadedOperations = 0;
270
+ }
271
+ }
272
+ }
273
+ finally {
274
+ clearTimeout(timeoutRef);
275
+ }
276
+ // In some cases the previos http call does not have finished,
277
+ // or we didn't reach the flush bytes threshold, so we force one last operation.
278
+ if (loadedOperations > 0) {
279
+ const send = await semaphore();
280
+ send(msearchBody, callbacks);
281
+ }
282
+ await finish();
283
+ if (stopError !== null) {
284
+ throw stopError;
285
+ }
286
+ async function onFlushTimeout() {
287
+ if (loadedOperations === 0)
288
+ return;
289
+ const msearchBodyCopy = msearchBody.slice();
290
+ const callbacksCopy = callbacks.slice();
291
+ msearchBody.length = 0;
292
+ callbacks.length = 0;
293
+ loadedOperations = 0;
294
+ try {
295
+ const send = await semaphore();
296
+ send(msearchBodyCopy, callbacksCopy);
297
+ }
298
+ catch (err) {
299
+ /* istanbul ignore next */
300
+ // @ts-expect-error
301
+ helper.stop(err);
302
+ }
303
+ }
304
+ }
305
+ // This function builds a semaphore using the concurrency
306
+ // options of the msearch helper. It is used inside the iterator
307
+ // to guarantee that no more than the number of operations
308
+ // allowed to run at the same time are executed.
309
+ // It returns a semaphore function which resolves in the next tick
310
+ // if we didn't reach the maximim concurrency yet, otherwise it returns
311
+ // a promise that resolves as soon as one of the running request has finshed.
312
+ // The semaphore function resolves a send function, which will be used
313
+ // to send the actual msearch request.
314
+ // It also returns a finish function, which returns a promise that is resolved
315
+ // when there are no longer request running.
316
+ function buildSemaphore() {
317
+ let resolveSemaphore = null;
318
+ let resolveFinish = null;
319
+ let running = 0;
320
+ return { semaphore, finish };
321
+ function finish() {
322
+ return new Promise((resolve, reject) => {
323
+ if (running === 0) {
324
+ resolve();
325
+ }
326
+ else {
327
+ resolveFinish = resolve;
328
+ }
329
+ });
330
+ }
331
+ function semaphore() {
332
+ if (running < concurrency) {
333
+ running += 1;
334
+ return pImmediate(send);
335
+ }
336
+ else {
337
+ return new Promise((resolve, reject) => {
338
+ resolveSemaphore = resolve;
339
+ });
340
+ }
341
+ }
342
+ function send(msearchBody, callbacks) {
343
+ /* istanbul ignore if */
344
+ if (running > concurrency) {
345
+ throw new Error('Max concurrency reached');
346
+ }
347
+ msearchOperation(msearchBody, callbacks, () => {
348
+ running -= 1;
349
+ if (resolveSemaphore !== null) {
350
+ running += 1;
351
+ resolveSemaphore(send);
352
+ resolveSemaphore = null;
353
+ }
354
+ else if (resolveFinish != null && running === 0) {
355
+ resolveFinish();
356
+ }
357
+ });
358
+ }
359
+ }
360
+ function msearchOperation(msearchBody, callbacks, done) {
361
+ let retryCount = retries;
362
+ // Instead of going full on async-await, which would make the code easier to read,
363
+ // we have decided to use callback style instead.
364
+ // This because every time we use async await, V8 will create multiple promises
365
+ // behind the scenes, making the code slightly slower.
366
+ tryMsearch(msearchBody, callbacks, retrySearch);
367
+ function retrySearch(msearchBody, callbacks) {
368
+ if (msearchBody.length > 0 && retryCount > 0) {
369
+ retryCount -= 1;
370
+ setTimeout(tryMsearch, wait, msearchBody, callbacks, retrySearch);
371
+ return;
372
+ }
373
+ done();
374
+ }
375
+ // This function never returns an error, if the msearch operation fails,
376
+ // the error is dispatched to all search executors.
377
+ function tryMsearch(msearchBody, callbacks, done) {
378
+ client.msearch(Object.assign({}, msearchOptions, { body: msearchBody }), reqOptions)
379
+ .then(results => {
380
+ const retryBody = [];
381
+ const retryCallbacks = [];
382
+ const { responses } = results.body;
383
+ for (let i = 0, len = responses.length; i < len; i++) {
384
+ const response = responses[i];
385
+ if (response.status === 429 && retryCount > 0) {
386
+ retryBody.push(msearchBody[i * 2]);
387
+ retryBody.push(msearchBody[(i * 2) + 1]);
388
+ retryCallbacks.push(callbacks[i]);
389
+ continue;
390
+ }
391
+ const result = { ...results, body: response };
392
+ // @ts-expect-error
393
+ addDocumentsGetter(result);
394
+ if (response.status != null && response.status >= 400) {
395
+ callbacks[i](new ResponseError(result), result);
396
+ }
397
+ else {
398
+ callbacks[i](null, result);
399
+ }
400
+ }
401
+ done(retryBody, retryCallbacks);
402
+ })
403
+ .catch(err => {
404
+ for (const callback of callbacks) {
405
+ callback(err, null);
406
+ }
407
+ return done([], []);
408
+ });
409
+ }
410
+ }
411
+ }
412
+ /**
413
+ * Creates a bulk helper instance. Once you configure it, you can pick which operation
414
+ * to execute with the given dataset, index, create, update, and delete.
415
+ * @param {object} options - The configuration of the bulk operation.
416
+ * @param {object} reqOptions - The client optional configuration for this request.
417
+ * @return {object} The possible operations to run with the datasource.
418
+ */
419
+ bulk(options, reqOptions = {}) {
420
+ var _d;
421
+ const client = this[kClient];
422
+ const { serializer } = client;
423
+ if (this[kMetaHeader] !== null) {
424
+ reqOptions.headers = (_d = reqOptions.headers) !== null && _d !== void 0 ? _d : {};
425
+ reqOptions.headers['x-elastic-client-meta'] = `${this[kMetaHeader]},h=bp`;
426
+ }
427
+ reqOptions.meta = true;
428
+ const { datasource, onDocument, flushBytes = 5000000, flushInterval = 30000, concurrency = 5, retries = this[kMaxRetries], wait = 5000, onDrop = noop, refreshOnCompletion = false, ...bulkOptions } = options;
429
+ if (datasource === undefined) {
430
+ // @ts-expect-error
431
+ return Promise.reject(new ConfigurationError('bulk helper: the datasource is required'));
432
+ }
433
+ if (!(Array.isArray(datasource) || Buffer.isBuffer(datasource) || isReadableStream(datasource) || isAsyncIterator(datasource))) {
434
+ // @ts-expect-error
435
+ return Promise.reject(new ConfigurationError('bulk helper: the datasource must be an array or a buffer or a readable stream or an async generator'));
436
+ }
437
+ if (onDocument === undefined) {
438
+ // @ts-expect-error
439
+ return Promise.reject(new ConfigurationError('bulk helper: the onDocument callback is required'));
440
+ }
441
+ let shouldAbort = false;
442
+ let timeoutRef = null;
443
+ const stats = {
444
+ total: 0,
445
+ failed: 0,
446
+ retry: 0,
447
+ successful: 0,
448
+ noop: 0,
449
+ time: 0,
450
+ bytes: 0,
451
+ aborted: false
452
+ };
453
+ const p = iterate();
454
+ const helper = {
455
+ [Symbol.toStringTag]: 'Promise',
456
+ then(onFulfilled, onRejected) {
457
+ return p.then(onFulfilled, onRejected);
458
+ },
459
+ catch(onRejected) {
460
+ return p.catch(onRejected);
461
+ },
462
+ finally(onFinally) {
463
+ return p.finally(onFinally);
464
+ },
465
+ get stats() {
466
+ return stats;
467
+ },
468
+ abort() {
469
+ clearTimeout(timeoutRef);
470
+ shouldAbort = true;
471
+ stats.aborted = true;
472
+ return this;
473
+ }
474
+ };
475
+ return helper;
476
+ /**
477
+ * Function that iterates over the given datasource and start a bulk operation as soon
478
+ * as it reaches the configured bulk size. It's designed to use the Node.js asynchronous
479
+ * model at this maximum capacity, as it will collect the next body to send while there is
480
+ * a running http call. In this way, the CPU time will be used carefully.
481
+ * The objects will be serialized right away, to approximate the byte length of the body.
482
+ * It creates an array of strings instead of a ndjson string because the bulkOperation
483
+ * will navigate the body for matching failed operations with the original document.
484
+ */
485
+ async function iterate() {
486
+ const { semaphore, finish } = buildSemaphore();
487
+ const startTime = Date.now();
488
+ const bulkBody = [];
489
+ let actionBody = '';
490
+ let payloadBody = '';
491
+ let chunkBytes = 0;
492
+ timeoutRef = setTimeout(onFlushTimeout, flushInterval); // eslint-disable-line
493
+ // @ts-expect-error datasoruce is an iterable
494
+ for await (const chunk of datasource) {
495
+ if (shouldAbort)
496
+ break;
497
+ timeoutRef.refresh();
498
+ const action = onDocument(chunk);
499
+ const operation = Array.isArray(action)
500
+ ? Object.keys(action[0])[0]
501
+ : Object.keys(action)[0];
502
+ if (operation === 'index' || operation === 'create') {
503
+ actionBody = serializer.serialize(action);
504
+ payloadBody = typeof chunk === 'string' ? chunk : serializer.serialize(chunk);
505
+ chunkBytes += Buffer.byteLength(actionBody) + Buffer.byteLength(payloadBody);
506
+ bulkBody.push(actionBody, payloadBody);
507
+ }
508
+ else if (operation === 'update') {
509
+ // @ts-expect-error in case of update action is an array
510
+ actionBody = serializer.serialize(action[0]);
511
+ payloadBody = typeof chunk === 'string'
512
+ ? `{"doc":${chunk}}`
513
+ // @ts-expect-error in case of update action is an array
514
+ : serializer.serialize({ doc: chunk, ...action[1] });
515
+ chunkBytes += Buffer.byteLength(actionBody) + Buffer.byteLength(payloadBody);
516
+ bulkBody.push(actionBody, payloadBody);
517
+ }
518
+ else if (operation === 'delete') {
519
+ actionBody = serializer.serialize(action);
520
+ chunkBytes += Buffer.byteLength(actionBody);
521
+ bulkBody.push(actionBody);
522
+ }
523
+ else {
524
+ clearTimeout(timeoutRef);
525
+ throw new ConfigurationError(`Bulk helper invalid action: '${operation}'`);
526
+ }
527
+ if (chunkBytes >= flushBytes) {
528
+ stats.bytes += chunkBytes;
529
+ const send = await semaphore();
530
+ send(bulkBody.slice());
531
+ bulkBody.length = 0;
532
+ chunkBytes = 0;
533
+ }
534
+ }
535
+ clearTimeout(timeoutRef);
536
+ // In some cases the previos http call does not have finished,
537
+ // or we didn't reach the flush bytes threshold, so we force one last operation.
538
+ if (!shouldAbort && chunkBytes > 0) {
539
+ const send = await semaphore();
540
+ stats.bytes += chunkBytes;
541
+ send(bulkBody);
542
+ }
543
+ await finish();
544
+ if (refreshOnCompletion !== false) {
545
+ await client.indices.refresh({
546
+ index: typeof refreshOnCompletion === 'string'
547
+ ? refreshOnCompletion
548
+ : '_all'
549
+ }, reqOptions);
550
+ }
551
+ stats.time = Date.now() - startTime;
552
+ stats.total = stats.successful + stats.failed;
553
+ return stats;
554
+ async function onFlushTimeout() {
555
+ if (chunkBytes === 0)
556
+ return;
557
+ stats.bytes += chunkBytes;
558
+ const bulkBodyCopy = bulkBody.slice();
559
+ bulkBody.length = 0;
560
+ chunkBytes = 0;
561
+ try {
562
+ const send = await semaphore();
563
+ send(bulkBodyCopy);
564
+ }
565
+ catch (err) {
566
+ /* istanbul ignore next */
567
+ helper.abort(); // eslint-disable-line
568
+ }
569
+ }
570
+ }
571
+ // This function builds a semaphore using the concurrency
572
+ // options of the bulk helper. It is used inside the iterator
573
+ // to guarantee that no more than the number of operations
574
+ // allowed to run at the same time are executed.
575
+ // It returns a semaphore function which resolves in the next tick
576
+ // if we didn't reach the maximim concurrency yet, otherwise it returns
577
+ // a promise that resolves as soon as one of the running request has finshed.
578
+ // The semaphore function resolves a send function, which will be used
579
+ // to send the actual bulk request.
580
+ // It also returns a finish function, which returns a promise that is resolved
581
+ // when there are no longer request running. It rejects an error if one
582
+ // of the request has failed for some reason.
583
+ function buildSemaphore() {
584
+ let resolveSemaphore = null;
585
+ let resolveFinish = null;
586
+ let rejectFinish = null;
587
+ let error = null;
588
+ let running = 0;
589
+ return { semaphore, finish };
590
+ function finish() {
591
+ return new Promise((resolve, reject) => {
592
+ if (running === 0) {
593
+ if (error !== null) {
594
+ reject(error);
595
+ }
596
+ else {
597
+ resolve();
598
+ }
599
+ }
600
+ else {
601
+ resolveFinish = resolve;
602
+ rejectFinish = reject;
603
+ }
604
+ });
605
+ }
606
+ function semaphore() {
607
+ if (running < concurrency) {
608
+ running += 1;
609
+ return pImmediate(send);
610
+ }
611
+ else {
612
+ return new Promise((resolve, reject) => {
613
+ resolveSemaphore = resolve;
614
+ });
615
+ }
616
+ }
617
+ function send(bulkBody) {
618
+ /* istanbul ignore if */
619
+ if (running > concurrency) {
620
+ throw new Error('Max concurrency reached');
621
+ }
622
+ bulkOperation(bulkBody, err => {
623
+ running -= 1;
624
+ if (err != null) {
625
+ shouldAbort = true;
626
+ error = err;
627
+ }
628
+ if (resolveSemaphore !== null) {
629
+ running += 1;
630
+ resolveSemaphore(send);
631
+ resolveSemaphore = null;
632
+ }
633
+ else if (resolveFinish != null && rejectFinish != null && running === 0) {
634
+ if (error != null) {
635
+ rejectFinish(error);
636
+ }
637
+ else {
638
+ resolveFinish();
639
+ }
640
+ }
641
+ });
642
+ }
643
+ }
644
+ function bulkOperation(bulkBody, callback) {
645
+ let retryCount = retries;
646
+ let isRetrying = false;
647
+ // Instead of going full on async-await, which would make the code easier to read,
648
+ // we have decided to use callback style instead.
649
+ // This because every time we use async await, V8 will create multiple promises
650
+ // behind the scenes, making the code slightly slower.
651
+ tryBulk(bulkBody, retryDocuments);
652
+ function retryDocuments(err, bulkBody) {
653
+ if (err != null)
654
+ return callback(err);
655
+ if (shouldAbort)
656
+ return callback();
657
+ if (bulkBody.length > 0) {
658
+ if (retryCount > 0) {
659
+ isRetrying = true;
660
+ retryCount -= 1;
661
+ stats.retry += bulkBody.length;
662
+ setTimeout(tryBulk, wait, bulkBody, retryDocuments);
663
+ return;
664
+ }
665
+ for (let i = 0, len = bulkBody.length; i < len; i = i + 2) {
666
+ const operation = Object.keys(serializer.deserialize(bulkBody[i]))[0];
667
+ onDrop({
668
+ status: 429,
669
+ error: null,
670
+ operation: serializer.deserialize(bulkBody[i]),
671
+ // @ts-expect-error
672
+ document: operation !== 'delete'
673
+ ? serializer.deserialize(bulkBody[i + 1])
674
+ /* istanbul ignore next */
675
+ : null,
676
+ retried: isRetrying
677
+ });
678
+ stats.failed += 1;
679
+ }
680
+ }
681
+ callback();
682
+ }
683
+ function tryBulk(bulkBody, callback) {
684
+ if (shouldAbort)
685
+ return callback(null, []);
686
+ client.bulk(Object.assign({}, bulkOptions, { body: bulkBody }), reqOptions)
687
+ .then(response => {
688
+ var _d, _e;
689
+ const result = response.body;
690
+ if (!result.errors) {
691
+ stats.successful += result.items.length;
692
+ for (const item of result.items) {
693
+ if (((_d = item.update) === null || _d === void 0 ? void 0 : _d.result) === 'noop') {
694
+ stats.noop++;
695
+ }
696
+ }
697
+ return callback(null, []);
698
+ }
699
+ const retry = [];
700
+ const { items } = result;
701
+ for (let i = 0, len = items.length; i < len; i++) {
702
+ const action = items[i];
703
+ const operation = Object.keys(action)[0];
704
+ // @ts-expect-error
705
+ const responseItem = action[operation];
706
+ (0, assert_1.default)(responseItem !== undefined, 'The responseItem is undefined, please file a bug report');
707
+ const indexSlice = operation !== 'delete' ? i * 2 : i;
708
+ if (responseItem.status >= 400) {
709
+ // 429 is the only staus code where we might want to retry
710
+ // a document, because it was not an error in the document itself,
711
+ // but the ES node were handling too many operations.
712
+ if (responseItem.status === 429) {
713
+ retry.push(bulkBody[indexSlice]);
714
+ /* istanbul ignore next */
715
+ if (operation !== 'delete') {
716
+ retry.push(bulkBody[indexSlice + 1]);
717
+ }
718
+ }
719
+ else {
720
+ onDrop({
721
+ status: responseItem.status,
722
+ error: (_e = responseItem.error) !== null && _e !== void 0 ? _e : null,
723
+ operation: serializer.deserialize(bulkBody[indexSlice]),
724
+ // @ts-expect-error
725
+ document: operation !== 'delete'
726
+ ? serializer.deserialize(bulkBody[indexSlice + 1])
727
+ : null,
728
+ retried: isRetrying
729
+ });
730
+ stats.failed += 1;
731
+ }
732
+ }
733
+ else {
734
+ stats.successful += 1;
735
+ }
736
+ }
737
+ callback(null, retry);
738
+ })
739
+ .catch(err => {
740
+ callback(err, []);
741
+ });
742
+ }
743
+ }
744
+ }
745
+ }
746
+ exports.default = Helpers;
747
+ _a = kClient, _b = kMetaHeader, _c = kMaxRetries;
748
+ // Using a getter will improve the overall performances of the code,
749
+ // as we will reed the documents only if needed.
750
+ function addDocumentsGetter(result) {
751
+ Object.defineProperty(result, 'documents', {
752
+ get() {
753
+ var _d;
754
+ if (((_d = this.body.hits) === null || _d === void 0 ? void 0 : _d.hits) != null) {
755
+ // @ts-expect-error
756
+ return this.body.hits.hits.map(d => d._source);
757
+ }
758
+ return [];
759
+ }
760
+ });
761
+ }
762
+ function appendFilterPath(filter, params, force) {
763
+ if (params.filter_path !== undefined) {
764
+ params.filter_path += ',' + filter; // eslint-disable-line
765
+ }
766
+ else if (force) {
767
+ params.filter_path = filter;
768
+ }
769
+ }
770
+ function isReadableStream(obj) {
771
+ return obj != null && typeof obj.pipe === 'function';
772
+ }
773
+ function isAsyncIterator(obj) {
774
+ return (obj === null || obj === void 0 ? void 0 : obj[Symbol.asyncIterator]) != null;
775
+ }
776
+ //# sourceMappingURL=helpers.js.map