lemon-core 2.2.20 → 3.0.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 (230) hide show
  1. package/dist/common/test-helper.js +1 -1
  2. package/dist/common/test-helper.js.map +1 -1
  3. package/dist/controllers/dummy-controller.js.map +1 -1
  4. package/dist/cores/api-service.js.map +1 -1
  5. package/dist/cores/aws/aws-sns-service.js +3 -3
  6. package/dist/cores/aws/aws-sns-service.js.map +1 -1
  7. package/dist/cores/core-types.d.ts +92 -2
  8. package/dist/cores/core-types.js +1 -0
  9. package/dist/cores/core-types.js.map +1 -1
  10. package/dist/cores/dynamo-service.js +2 -2
  11. package/dist/cores/dynamo-service.js.map +1 -1
  12. package/dist/cores/elastic6-query-service.d.ts +42 -9
  13. package/dist/cores/elastic6-query-service.js +144 -134
  14. package/dist/cores/elastic6-query-service.js.map +1 -1
  15. package/dist/cores/elastic6-service.d.ts +144 -57
  16. package/dist/cores/elastic6-service.js +506 -322
  17. package/dist/cores/elastic6-service.js.map +1 -1
  18. package/dist/cores/lambda/lambda-cognito-handler.js.map +1 -1
  19. package/dist/cores/lambda/lambda-cron-handler.js.map +1 -1
  20. package/dist/cores/lambda/lambda-dynamo-stream-handler.js +3 -3
  21. package/dist/cores/lambda/lambda-dynamo-stream-handler.js.map +1 -1
  22. package/dist/cores/lambda/lambda-notification-handler.js.map +1 -1
  23. package/dist/cores/lambda/lambda-sns-handler.js.map +1 -1
  24. package/dist/cores/lambda/lambda-web-handler.js +2 -4
  25. package/dist/cores/lambda/lambda-web-handler.js.map +1 -1
  26. package/dist/cores/lambda/lambda-wss-handler.js.map +1 -1
  27. package/dist/cores/protocol/protocol-service.d.ts +1 -2
  28. package/dist/cores/protocol/protocol-service.js +5 -3
  29. package/dist/cores/protocol/protocol-service.js.map +1 -1
  30. package/dist/engine/builder.d.ts +1 -0
  31. package/dist/engine/builder.js +1 -1
  32. package/dist/engine/builder.js.map +1 -1
  33. package/dist/engine/engine.js +2 -1
  34. package/dist/engine/engine.js.map +1 -1
  35. package/dist/engine/index.d.ts +0 -1
  36. package/dist/engine/index.js +2 -4
  37. package/dist/engine/index.js.map +1 -1
  38. package/dist/engine/types.d.ts +0 -4
  39. package/dist/engine/types.js.map +1 -1
  40. package/dist/engine/utilities.d.ts +5 -1
  41. package/dist/engine/utilities.js +126 -11
  42. package/dist/engine/utilities.js.map +1 -1
  43. package/dist/tools/express.js +0 -3
  44. package/dist/tools/express.js.map +1 -1
  45. package/package.json +6 -11
  46. package/CHANGELOG.md +0 -61
  47. package/dist/docs/assets/css/main.css +0 -2321
  48. package/dist/docs/assets/images/icons.png +0 -0
  49. package/dist/docs/assets/images/icons@2x.png +0 -0
  50. package/dist/docs/assets/images/widgets.png +0 -0
  51. package/dist/docs/assets/images/widgets@2x.png +0 -0
  52. package/dist/docs/assets/js/main.js +0 -1
  53. package/dist/docs/assets/js/search.js +0 -3
  54. package/dist/docs/classes/abstractmanager.html +0 -1054
  55. package/dist/docs/classes/apiproxyclient.html +0 -509
  56. package/dist/docs/classes/apiservice.html +0 -805
  57. package/dist/docs/classes/awskmsservice.html +0 -468
  58. package/dist/docs/classes/awsmodule.html +0 -353
  59. package/dist/docs/classes/awss3service.html +0 -563
  60. package/dist/docs/classes/awssnsservice.html +0 -543
  61. package/dist/docs/classes/awssqsservice.html +0 -517
  62. package/dist/docs/classes/cacheservice.html +0 -996
  63. package/dist/docs/classes/configmodule.html +0 -311
  64. package/dist/docs/classes/dummycacheservice.html +0 -1000
  65. package/dist/docs/classes/dummycontroller.html +0 -709
  66. package/dist/docs/classes/dummydynamoservice.html +0 -915
  67. package/dist/docs/classes/dummyelastic6service.html +0 -791
  68. package/dist/docs/classes/dummyredisstorageservice.html +0 -804
  69. package/dist/docs/classes/dummystoragemaker.html +0 -383
  70. package/dist/docs/classes/dummystorageservice.html +0 -592
  71. package/dist/docs/classes/dynamoqueryservice.html +0 -413
  72. package/dist/docs/classes/dynamoscanservice.html +0 -358
  73. package/dist/docs/classes/dynamoservice.html +0 -844
  74. package/dist/docs/classes/dynamostorageservice.html +0 -623
  75. package/dist/docs/classes/elastic6queryservice.html +0 -458
  76. package/dist/docs/classes/elastic6service.html +0 -804
  77. package/dist/docs/classes/generalapicontroller.html +0 -877
  78. package/dist/docs/classes/generalcontroller.html +0 -454
  79. package/dist/docs/classes/generalcontrollerlocal.html +0 -499
  80. package/dist/docs/classes/generalcontrollerlocal2.html +0 -523
  81. package/dist/docs/classes/generalkeymaker.html +0 -335
  82. package/dist/docs/classes/generalmodelfilter.html +0 -529
  83. package/dist/docs/classes/generalwebcontroller.html +0 -580
  84. package/dist/docs/classes/hangulservice.html +0 -636
  85. package/dist/docs/classes/httpstorageservice.html +0 -539
  86. package/dist/docs/classes/lambdacognitohandler.html +0 -355
  87. package/dist/docs/classes/lambdacronhandler.html +0 -390
  88. package/dist/docs/classes/lambdacronhandlerlocal.html +0 -371
  89. package/dist/docs/classes/lambdadynamostreamhandler.html +0 -472
  90. package/dist/docs/classes/lambdadynamostreamhandlerlocal.html +0 -455
  91. package/dist/docs/classes/lambdahandler.html +0 -479
  92. package/dist/docs/classes/lambdahandlerlocal.html +0 -472
  93. package/dist/docs/classes/lambdamodule.html +0 -433
  94. package/dist/docs/classes/lambdanotificationhandler.html +0 -474
  95. package/dist/docs/classes/lambdanotificationhandlerlocal.html +0 -457
  96. package/dist/docs/classes/lambdasnshandler.html +0 -394
  97. package/dist/docs/classes/lambdasnshandlerlocal.html +0 -397
  98. package/dist/docs/classes/lambdasqshandler.html +0 -394
  99. package/dist/docs/classes/lambdasqshandlerlocal.html +0 -397
  100. package/dist/docs/classes/lambdasubhandler.html +0 -305
  101. package/dist/docs/classes/lambdawebhandler.html +0 -603
  102. package/dist/docs/classes/lambdawebhandlerlocal.html +0 -581
  103. package/dist/docs/classes/lambdawsshandler.html +0 -359
  104. package/dist/docs/classes/memcachedbackend.html +0 -900
  105. package/dist/docs/classes/mocksapiservice.html +0 -691
  106. package/dist/docs/classes/modelutil.html +0 -311
  107. package/dist/docs/classes/myconfigservice.html +0 -561
  108. package/dist/docs/classes/myconfigservicetest.html +0 -527
  109. package/dist/docs/classes/myconfigservicetest2.html +0 -522
  110. package/dist/docs/classes/mydummysqsservice.html +0 -419
  111. package/dist/docs/classes/myenginemodules.html +0 -357
  112. package/dist/docs/classes/mygeneralapicontroller.html +0 -837
  113. package/dist/docs/classes/mylemonwebcontroller.html +0 -356
  114. package/dist/docs/classes/mymodelfilter.html +0 -479
  115. package/dist/docs/classes/myprotocolservice.html +0 -993
  116. package/dist/docs/classes/myprotocolservicetest.html +0 -983
  117. package/dist/docs/classes/myservice.html +0 -329
  118. package/dist/docs/classes/mystorage.html +0 -1370
  119. package/dist/docs/classes/nodecachebackend.html +0 -714
  120. package/dist/docs/classes/protocolmodule.html +0 -311
  121. package/dist/docs/classes/proxystorageservice.html +0 -1441
  122. package/dist/docs/classes/query.html +0 -850
  123. package/dist/docs/classes/redisbackend.html +0 -781
  124. package/dist/docs/classes/redisstorageservice.html +0 -867
  125. package/dist/docs/classes/s3putobjectrequestbuilder.html +0 -509
  126. package/dist/docs/classes/scan.html +0 -685
  127. package/dist/docs/classes/snsprotocoltransformer.html +0 -334
  128. package/dist/docs/classes/sqsprotocoltransformer.html +0 -334
  129. package/dist/docs/classes/typedstorageservice.html +0 -914
  130. package/dist/docs/classes/uniquefieldmanager.html +0 -477
  131. package/dist/docs/classes/usermanager.html +0 -931
  132. package/dist/docs/classes/utilities.html +0 -1914
  133. package/dist/docs/classes/webprotocoltransformer.html +0 -330
  134. package/dist/docs/globals.html +0 -7477
  135. package/dist/docs/index.html +0 -1519
  136. package/dist/docs/interfaces/accountitem.html +0 -277
  137. package/dist/docs/interfaces/accountmodel.html +0 -306
  138. package/dist/docs/interfaces/adaptiveparam.html +0 -203
  139. package/dist/docs/interfaces/apiheaders.html +0 -183
  140. package/dist/docs/interfaces/apihttpproxy.html +0 -304
  141. package/dist/docs/interfaces/apiserviceclient.html +0 -448
  142. package/dist/docs/interfaces/autocompletesearchparam.html +0 -309
  143. package/dist/docs/interfaces/betweencondition.html +0 -226
  144. package/dist/docs/interfaces/cachebackend.html +0 -714
  145. package/dist/docs/interfaces/cacheentry.html +0 -248
  146. package/dist/docs/interfaces/cacheoptions.html +0 -267
  147. package/dist/docs/interfaces/callbackdata.html +0 -279
  148. package/dist/docs/interfaces/callbackparam.html +0 -252
  149. package/dist/docs/interfaces/comparisoncondition.html +0 -226
  150. package/dist/docs/interfaces/coreconfigservice.html +0 -342
  151. package/dist/docs/interfaces/corekey.html +0 -278
  152. package/dist/docs/interfaces/corekeymakeable.html +0 -292
  153. package/dist/docs/interfaces/corekmsservice.html +0 -311
  154. package/dist/docs/interfaces/coremodel.html +0 -499
  155. package/dist/docs/interfaces/coremodelfilterable.html +0 -281
  156. package/dist/docs/interfaces/cores3service.html +0 -444
  157. package/dist/docs/interfaces/coreservices.html +0 -232
  158. package/dist/docs/interfaces/coresnsservice.html +0 -317
  159. package/dist/docs/interfaces/corewebcontroller.html +0 -271
  160. package/dist/docs/interfaces/cronevent.html +0 -223
  161. package/dist/docs/interfaces/cronparam.html +0 -212
  162. package/dist/docs/interfaces/dynamooption.html +0 -254
  163. package/dist/docs/interfaces/dynamoqueryresult.html +0 -244
  164. package/dist/docs/interfaces/dynamoscanresult.html +0 -244
  165. package/dist/docs/interfaces/dynamosimplequeriable.html +0 -308
  166. package/dist/docs/interfaces/dynamosimplescannable.html +0 -255
  167. package/dist/docs/interfaces/dynamostreambody.html +0 -268
  168. package/dist/docs/interfaces/dynamostreamcallback.html +0 -209
  169. package/dist/docs/interfaces/dynamostreamfilter.html +0 -218
  170. package/dist/docs/interfaces/dynamostreamparam.html +0 -240
  171. package/dist/docs/interfaces/elastic6item.html +0 -221
  172. package/dist/docs/interfaces/elastic6option.html +0 -275
  173. package/dist/docs/interfaces/elastic6simplequeriable.html +0 -284
  174. package/dist/docs/interfaces/engineconsole.html +0 -292
  175. package/dist/docs/interfaces/enginecore.html +0 -344
  176. package/dist/docs/interfaces/enginemodule.html +0 -269
  177. package/dist/docs/interfaces/enginemodules.html +0 -316
  178. package/dist/docs/interfaces/engineoption.html +0 -244
  179. package/dist/docs/interfaces/enginescope.html +0 -220
  180. package/dist/docs/interfaces/existencecondition.html +0 -212
  181. package/dist/docs/interfaces/filter.html +0 -253
  182. package/dist/docs/interfaces/generalfuntion.html +0 -207
  183. package/dist/docs/interfaces/generalitem.html +0 -212
  184. package/dist/docs/interfaces/handlermap.html +0 -171
  185. package/dist/docs/interfaces/incrementable.html +0 -190
  186. package/dist/docs/interfaces/internalkey.html +0 -210
  187. package/dist/docs/interfaces/internalmodel.html +0 -226
  188. package/dist/docs/interfaces/itementry.html +0 -241
  189. package/dist/docs/interfaces/jwtcommon.html +0 -242
  190. package/dist/docs/interfaces/lambdahandlerservice.html +0 -340
  191. package/dist/docs/interfaces/lemonengine.html +0 -593
  192. package/dist/docs/interfaces/metricpostbody.html +0 -220
  193. package/dist/docs/interfaces/mygeneral.html +0 -271
  194. package/dist/docs/interfaces/mymodel.html +0 -554
  195. package/dist/docs/interfaces/myprotocolparam.html +0 -359
  196. package/dist/docs/interfaces/nextcontext.html +0 -381
  197. package/dist/docs/interfaces/nextidentity.html +0 -325
  198. package/dist/docs/interfaces/nextidentityaccess.html +0 -495
  199. package/dist/docs/interfaces/nextidentitycognito.html +0 -422
  200. package/dist/docs/interfaces/notificationbody.html +0 -171
  201. package/dist/docs/interfaces/notificationparam.html +0 -304
  202. package/dist/docs/interfaces/options.html +0 -226
  203. package/dist/docs/interfaces/parrallelcallback.html +0 -203
  204. package/dist/docs/interfaces/parrallelparam.html +0 -285
  205. package/dist/docs/interfaces/protocolbody.html +0 -183
  206. package/dist/docs/interfaces/protocolparam.html +0 -336
  207. package/dist/docs/interfaces/protocolservice.html +0 -548
  208. package/dist/docs/interfaces/protocoltransformer.html +0 -295
  209. package/dist/docs/interfaces/proxyparams.html +0 -212
  210. package/dist/docs/interfaces/putobjectresult.html +0 -282
  211. package/dist/docs/interfaces/queryresult.html +0 -272
  212. package/dist/docs/interfaces/redisoptions.html +0 -248
  213. package/dist/docs/interfaces/simplesearchparam.html +0 -351
  214. package/dist/docs/interfaces/slackaction.html +0 -240
  215. package/dist/docs/interfaces/slackattachment.html +0 -459
  216. package/dist/docs/interfaces/slackpostbody.html +0 -240
  217. package/dist/docs/interfaces/sqsattribute.html +0 -171
  218. package/dist/docs/interfaces/sqsmessage.html +0 -254
  219. package/dist/docs/interfaces/sqsrecord.html +0 -324
  220. package/dist/docs/interfaces/sqsservice.html +0 -333
  221. package/dist/docs/interfaces/sqsstatistics.html +0 -240
  222. package/dist/docs/interfaces/storagemakeable.html +0 -258
  223. package/dist/docs/interfaces/storagemodel.html +0 -285
  224. package/dist/docs/interfaces/storageservice.html +0 -497
  225. package/dist/docs/interfaces/stringcondition.html +0 -226
  226. package/dist/docs/interfaces/tagset.html +0 -171
  227. package/dist/docs/interfaces/testmodel.html +0 -334
  228. package/dist/docs/interfaces/timeout.html +0 -233
  229. package/dist/docs/interfaces/updatable.html +0 -193
  230. package/dist/docs/interfaces/user.html +0 -534
@@ -19,47 +19,127 @@ exports.DummyElastic6Service = exports.$ERROR = exports.Elastic6Service = void 0
19
19
  *
20
20
  * @author Steve Jung <steve@lemoncloud.io>
21
21
  * @date 2019-11-20 initial version via backbone
22
+ * @date 2022-02-21 optimized error handler, and search.
23
+ * @date 2022-02-22 optimized w/ elastic client (elasticsearch-js)
22
24
  *
23
25
  * @copyright (C) 2019 LemonCloud Co Ltd. - All Rights Reserved.
24
26
  */
25
27
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
28
  const engine_1 = require("../engine/");
27
- const NS = engine_1.$U.NS('ES6', 'green'); // NAMESPACE TO BE PRINTED.
28
- const elasticsearch_1 = __importDefault(require("elasticsearch"));
29
+ const elasticsearch_1 = __importDefault(require("@elastic/elasticsearch"));
29
30
  const hangul_service_1 = __importDefault(require("./hangul-service"));
30
31
  const tools_1 = require("../tools");
31
- //! create(or get) instance.
32
- const instance = (endpoint) => {
33
- return Elastic6Service.instance(endpoint);
34
- };
32
+ const test_helper_1 = require("../common/test-helper");
33
+ const NS = engine_1.$U.NS('ES6', 'green'); // NAMESPACE TO BE PRINTED.
34
+ /**
35
+ * convert to string.
36
+ */
37
+ const _S = (v, def = '') => typeof v === 'string' ? v : v === undefined || v === null ? def : typeof v === 'object' ? engine_1.$U.json(v) : `${v}`;
35
38
  /**
36
39
  * class: `Elastic6Service`
37
40
  * - basic CRUD service for Elastic Search 6
38
41
  */
39
42
  class Elastic6Service {
43
+ /**
44
+ * default constuctor w/ options.
45
+ * @param options { endpoint, indexName } is required.
46
+ */
40
47
  constructor(options) {
41
48
  /**
42
49
  * say hello of identity.
43
50
  */
44
- this.hello = () => `elastic6-service:${this.options.indexName}`;
51
+ this.hello = () => `elastic6-service:${this.options.indexName}:${this.version}`;
45
52
  engine_1._inf(NS, `Elastic6Service(${options.indexName}/${options.idName})...`);
46
53
  if (!options.endpoint)
47
54
  throw new Error('.endpoint (URL) is required');
48
55
  if (!options.indexName)
49
56
  throw new Error('.indexName (string) is required');
50
57
  // default option values: docType='_doc', idName='$id'
51
- this.options = Object.assign({ docType: '_doc', idName: '$id' }, options);
58
+ const { client } = Elastic6Service.instance(options.endpoint);
59
+ this._options = Object.assign({ docType: '_doc', idName: '$id', version: '6.8' }, options);
60
+ this._client = client;
52
61
  }
53
62
  /**
54
63
  * simple instance maker.
64
+ *
65
+ * ```js
66
+ * const { client } = Elastic6Service.instance(endpoint);
67
+ * ```
68
+ *
55
69
  * @param endpoint service-url
56
70
  * @param version Elasticsearch version (default: '6.8')
57
71
  * @see https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/16.x/configuration.html
58
72
  */
59
73
  static instance(endpoint) {
60
- const client = new elasticsearch_1.default.Client({ host: endpoint });
74
+ const client = new elasticsearch_1.default.Client({
75
+ node: endpoint,
76
+ ssl: {
77
+ ca: process.env.elasticsearch_certificate,
78
+ rejectUnauthorized: false,
79
+ },
80
+ });
61
81
  return { client };
62
82
  }
83
+ /**
84
+ * get the client instance.
85
+ */
86
+ get client() {
87
+ return this._client;
88
+ }
89
+ /**
90
+ * get the current options.
91
+ */
92
+ get options() {
93
+ return this._options;
94
+ }
95
+ get version() {
96
+ const ver = engine_1.$U.F(this.options.version, 6.8);
97
+ return ver;
98
+ }
99
+ /**
100
+ * list of index
101
+ */
102
+ listIndices() {
103
+ return __awaiter(this, void 0, void 0, function* () {
104
+ engine_1._log(NS, `- listIndices()`);
105
+ //! call create index..
106
+ // const { client } = instance(endpoint);
107
+ const client = this.client;
108
+ const res = yield client.cat.indices({ format: 'json' });
109
+ engine_1._log(NS, `> indices =`, engine_1.$U.json(res));
110
+ // eslint-disable-next-line prettier/prettier
111
+ const list0 = Array.isArray(res) ? res : (res === null || res === void 0 ? void 0 : res.body) && Array.isArray(res === null || res === void 0 ? void 0 : res.body) ? res === null || res === void 0 ? void 0 : res.body : null;
112
+ if (!list0)
113
+ throw new Error(`@result<${typeof res}> is invalid - ${engine_1.$U.json(res)}!`);
114
+ // {"docs.count": "84", "docs.deleted": "7", "health": "green", "index": "dev-eureka-alarms-v1", "pri": "5", "pri.store.size": "234.3kb", "rep": "1", "status": "open", "store.size": "468.6kb", "uuid": "xPp-Sx86SgmhAWxT3cGAFw"}
115
+ const list = list0.map(N => ({
116
+ pri: engine_1.$U.N(N['pri']),
117
+ rep: engine_1.$U.N(N['rep']),
118
+ docsCount: engine_1.$U.N(N['docs.count']),
119
+ docsDeleted: engine_1.$U.N(N['docs.deleted']),
120
+ health: _S(N['health']),
121
+ index: _S(N['index']),
122
+ status: _S(N['status']),
123
+ uuid: _S(N['uuid']),
124
+ priStoreSize: _S(N['pri.store.size']),
125
+ storeSize: _S(N['store.size']),
126
+ }));
127
+ //! returns.
128
+ return { list };
129
+ });
130
+ }
131
+ /**
132
+ * find the index by name
133
+ */
134
+ findIndex(indexName) {
135
+ return __awaiter(this, void 0, void 0, function* () {
136
+ indexName = indexName || this.options.indexName;
137
+ engine_1._log(NS, `- findIndex(${indexName})`);
138
+ const { list } = yield this.listIndices();
139
+ const found = list.findIndex(N => N.index == indexName);
140
+ return found >= 0 ? list[found] : null;
141
+ });
142
+ }
63
143
  /**
64
144
  * create index by name
65
145
  *
@@ -67,12 +147,11 @@ class Elastic6Service {
67
147
  */
68
148
  createIndex(settings) {
69
149
  return __awaiter(this, void 0, void 0, function* () {
70
- const { endpoint, indexName, docType, idName, timeSeries } = this.options;
71
- settings = settings || Elastic6Service.prepareSettings(docType, idName, timeSeries);
150
+ const { indexName, docType, idName, timeSeries, version } = this.options;
151
+ settings = settings || Elastic6Service.prepareSettings({ docType, idName, timeSeries, version });
72
152
  if (!indexName)
73
153
  new Error('@index is required!');
74
154
  engine_1._log(NS, `- createIndex(${indexName})`);
75
- settings = settings || {};
76
155
  //! prepare payload
77
156
  const payload = Object.assign({ settings: {
78
157
  number_of_shards: 5,
@@ -80,18 +159,24 @@ class Elastic6Service {
80
159
  } }, settings);
81
160
  engine_1._log(NS, `> settings[${indexName}] = `, engine_1.$U.json(payload));
82
161
  //! call create index..
83
- const { client } = instance(endpoint);
84
- const res = yield client.indices.create({ index: indexName, body: payload }).catch(exports.$ERROR.handler('create', e => {
85
- engine_1._err(NS, `> create[${indexName}].err =`, e instanceof Error ? e : engine_1.$U.json(e));
86
- if (`${e.message}`.startsWith('400 resource_already_exists_exception'))
162
+ // const { client } = instance(endpoint);
163
+ const client = this.client;
164
+ const res = yield client.indices.create({ index: indexName, body: payload }).catch(
165
+ // $ERROR.throwAsJson,
166
+ exports.$ERROR.handler('create', e => {
167
+ const msg = test_helper_1.GETERR(e);
168
+ if (msg.startsWith('400 RESOURCE ALREADY EXISTS'))
87
169
  throw new Error(`400 IN USE - index:${indexName}`);
88
170
  throw e;
89
171
  }));
90
- engine_1._log(NS, `> create[${indexName}] =`, engine_1.$U.json(res));
91
- engine_1._log(NS, `> create[${indexName}].acknowledged =`, res.acknowledged); // true
92
- engine_1._log(NS, `> create[${indexName}].index =`, res.index); // index
93
- engine_1._log(NS, `> create[${indexName}].shards_acknowledged =`, res.shards_acknowledged); // true
94
- return res;
172
+ // if (res) throw res;
173
+ engine_1._log(NS, `> create[${indexName}] =`, engine_1.$U.json(Object.assign(Object.assign({}, res), { meta: undefined })));
174
+ //! build result.
175
+ return {
176
+ status: res.statusCode,
177
+ index: indexName,
178
+ acknowledged: res.body.shards_acknowledged,
179
+ };
95
180
  });
96
181
  }
97
182
  /**
@@ -99,21 +184,28 @@ class Elastic6Service {
99
184
  */
100
185
  destroyIndex() {
101
186
  return __awaiter(this, void 0, void 0, function* () {
102
- const { endpoint, indexName } = this.options;
187
+ const { indexName } = this.options;
103
188
  if (!indexName)
104
189
  new Error('@index is required!');
105
190
  engine_1._log(NS, `- destroyIndex(${indexName})`);
106
191
  //! call create index..
107
- const { client } = instance(endpoint);
108
- const res = yield client.indices.delete({ index: indexName }).catch(exports.$ERROR.handler('destroy', e => {
109
- engine_1._err(NS, `> destory[${indexName}].err =`, e instanceof Error ? e : engine_1.$U.json(e));
110
- if (`${e.message}`.startsWith('404 index_not_found_exception'))
192
+ // const { client } = instance(endpoint);
193
+ const client = this.client;
194
+ const res = yield client.indices.delete({ index: indexName }).catch(
195
+ // $ERROR.throwAsJson,
196
+ exports.$ERROR.handler('destroy', e => {
197
+ const msg = test_helper_1.GETERR(e);
198
+ if (msg.startsWith('404 INDEX NOT FOUND'))
111
199
  throw new Error(`404 NOT FOUND - index:${indexName}`);
112
200
  throw e;
113
201
  }));
114
- engine_1._log(NS, `> destroy[${indexName}] =`, engine_1.$U.json(res));
115
- engine_1._log(NS, `> destroy[${indexName}].acknowledged =`, res.acknowledged); // true
116
- return res;
202
+ // if (res) throw res;
203
+ engine_1._log(NS, `> destroy[${indexName}] =`, engine_1.$U.json(Object.assign(Object.assign({}, res), { meta: undefined })));
204
+ return {
205
+ status: res.statusCode,
206
+ index: indexName,
207
+ acknowledged: res.body.acknowledged,
208
+ };
117
209
  });
118
210
  }
119
211
  /**
@@ -121,18 +213,23 @@ class Elastic6Service {
121
213
  */
122
214
  refreshIndex() {
123
215
  return __awaiter(this, void 0, void 0, function* () {
124
- const { endpoint, indexName } = this.options;
216
+ const { indexName } = this.options;
125
217
  if (!indexName)
126
218
  throw new Error('.indexName is required!');
127
219
  engine_1._log(NS, `- refreshIndex(${indexName})`);
128
220
  //! call refresh index..
129
- const { client } = instance(endpoint);
130
- const res = yield client.indices.refresh({ index: indexName }).catch(exports.$ERROR.handler('refresh', e => {
131
- engine_1._err(NS, `> refresh[${indexName}].err =`, e instanceof Error ? e : engine_1.$U.json(e));
221
+ // const { client } = instance(endpoint);
222
+ const client = this.client;
223
+ const res = yield client.indices.refresh({ index: indexName }).catch(
224
+ // $ERROR.throwAsJson,
225
+ exports.$ERROR.handler('refresh', e => {
226
+ const msg = test_helper_1.GETERR(e);
227
+ if (msg.startsWith('404 INDEX NOT FOUND'))
228
+ throw new Error(`404 NOT FOUND - index:${indexName}`);
132
229
  throw e;
133
230
  }));
134
- engine_1._log(NS, `> refresh[${indexName}] =`, engine_1.$U.json(res));
135
- return res;
231
+ engine_1._log(NS, `> refresh[${indexName}] =`, engine_1.$U.json(Object.assign(Object.assign({}, res), { meta: undefined })));
232
+ return res.body;
136
233
  });
137
234
  }
138
235
  /**
@@ -140,18 +237,23 @@ class Elastic6Service {
140
237
  */
141
238
  flushIndex() {
142
239
  return __awaiter(this, void 0, void 0, function* () {
143
- const { endpoint, indexName } = this.options;
240
+ const { indexName } = this.options;
144
241
  if (!indexName)
145
242
  throw new Error('.indexName is required!');
146
243
  engine_1._log(NS, `- flushIndex(${indexName})`);
147
244
  //! call flush index..
148
- const { client } = instance(endpoint);
149
- const res = yield client.indices.flush({ index: indexName }).catch(exports.$ERROR.handler('flush', e => {
150
- engine_1._err(NS, `> flush[${indexName}].err =`, e instanceof Error ? e : engine_1.$U.json(e));
245
+ // const { client } = instance(endpoint);
246
+ const client = this.client;
247
+ const res = yield client.indices.flush({ index: indexName }).catch(
248
+ // $ERROR.throwAsJson,
249
+ exports.$ERROR.handler('flush', e => {
250
+ const msg = test_helper_1.GETERR(e);
251
+ if (msg.startsWith('404 INDEX NOT FOUND'))
252
+ throw new Error(`404 NOT FOUND - index:${indexName}`);
151
253
  throw e;
152
254
  }));
153
- engine_1._log(NS, `> flush[${indexName}] =`, engine_1.$U.json(res));
154
- return res;
255
+ engine_1._log(NS, `> flush[${indexName}] =`, engine_1.$U.json(Object.assign(Object.assign({}, res), { meta: undefined })));
256
+ return res.body;
155
257
  });
156
258
  }
157
259
  /**
@@ -159,25 +261,28 @@ class Elastic6Service {
159
261
  */
160
262
  describe() {
161
263
  return __awaiter(this, void 0, void 0, function* () {
162
- const { endpoint, indexName } = this.options;
264
+ const { indexName } = this.options;
163
265
  //! call create index..
164
- const { client } = instance(endpoint);
165
266
  engine_1._log(NS, `- describe(${indexName})`);
166
267
  //! read settings.
167
- const res = yield client.indices.getSettings({ index: indexName }).catch(exports.$ERROR.handler('describe', e => {
168
- engine_1._err(NS, `> describe[${indexName}].err =`, e instanceof Error ? e : engine_1.$U.json(e));
169
- if (`${e.message}`.startsWith('404 index_not_found_exception'))
268
+ // const { client } = instance(endpoint);
269
+ const client = this.client;
270
+ const res = yield client.indices.getSettings({ index: indexName }).catch(
271
+ // $ERROR.throwAsJson,
272
+ exports.$ERROR.handler('describe', e => {
273
+ const msg = test_helper_1.GETERR(e);
274
+ if (msg.startsWith('404 INDEX NOT FOUND'))
170
275
  throw new Error(`404 NOT FOUND - index:${indexName}`);
171
276
  throw e;
172
277
  }));
173
- engine_1._log(NS, `> settings[${indexName}] =`, engine_1.$U.json(res));
174
- const settings = (res[indexName] && res[indexName].settings) || {};
278
+ engine_1._log(NS, `> settings[${indexName}] =`, engine_1.$U.json(Object.assign(Object.assign({}, res), { meta: undefined })));
279
+ const settings = (res.body && res.body[indexName] && res.body[indexName].settings) || {};
175
280
  engine_1._log(NS, `> number_of_shards =`, settings.index && settings.index.number_of_shards); // 5
176
281
  engine_1._log(NS, `> number_of_replicas =`, settings.index && settings.index.number_of_replicas); // 1
177
282
  //! read mappings.
178
283
  const res2 = yield client.indices.getMapping({ index: indexName });
179
284
  engine_1._log(NS, `> mappings[${indexName}] =`, engine_1.$U.json(res2));
180
- const mappings = (res2[indexName] && res2[indexName].mappings) || {};
285
+ const mappings = (res2.body && res2.body[indexName] && res2.body[indexName].mappings) || {};
181
286
  //! returns
182
287
  return { settings, mappings };
183
288
  });
@@ -190,43 +295,38 @@ class Elastic6Service {
190
295
  * @param type document type (default: doc-type given at construction time)
191
296
  */
192
297
  saveItem(id, item, type) {
298
+ var _a, _b;
193
299
  return __awaiter(this, void 0, void 0, function* () {
194
- const { endpoint, indexName, docType, idName } = this.options;
195
- const { client } = instance(endpoint);
300
+ const { indexName, docType, idName } = this.options;
196
301
  engine_1._log(NS, `- saveItem(${id})`);
302
+ // const { client } = instance(endpoint);
303
+ const client = this.client;
197
304
  // prepare item body and autocomplete fields
198
305
  const body = Object.assign(Object.assign({}, item), { [idName]: id });
199
- this.prepareAutocompleteFields(body);
306
+ const body2 = this.popullateAutocompleteFields(body);
200
307
  type = `${type || docType}`;
201
- const params = {
202
- index: indexName,
203
- type,
204
- id,
205
- body,
206
- };
207
- if (idName == '_id')
208
- delete params.body[idName]; // `_id` is reserved in ES6.
308
+ const params = { index: indexName, type, id, body: body2 };
309
+ if (idName === '_id')
310
+ delete params.body[idName]; //WARN! `_id` is reserved in ES6.
209
311
  engine_1._log(NS, `> params[${id}] =`, engine_1.$U.json(params));
210
312
  //NOTE - use npm `elasticsearch#13.2.0` for avoiding error.
211
- const res = yield client.create(params).catch(exports.$ERROR.handler('save', e => {
212
- engine_1._log(NS, `> save[${indexName}].err =`, e instanceof Error ? e : engine_1.$U.json(e));
213
- if (`${e.message}`.startsWith('409 version_conflict_engine_exception')) {
214
- //! try to update document...
215
- delete body[idName]; // do set id while update
216
- const params = { index: indexName, type, id, body: { doc: body } };
217
- return client.update(params);
313
+ const res = yield client.create(params).catch(
314
+ // $ERROR.throwAsJson,
315
+ exports.$ERROR.handler('save', e => {
316
+ const msg = test_helper_1.GETERR(e);
317
+ //! try to update document..
318
+ if (msg.startsWith('409 VERSION CONFLICT ENGINE')) {
319
+ delete body2[idName]; // do set id while update
320
+ // return this.updateItem(id, body2);
321
+ const param2 = { index: indexName, type, id, body: { doc: body2 } };
322
+ return client.update(param2);
218
323
  }
219
324
  throw e;
220
325
  }));
221
- // {"_index":"test-v3","_type":"_doc","_id":"aaa","_version":1,"result":"created","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":0,"_primary_term":1}
222
- // {"_index":"test-v3","_type":"_doc","_id":"aaa","_version":1,"result":"noop","_shards":{"total":0,"successful":0,"failed":0}}
223
- engine_1._log(NS, `> create[${id}].res =`, engine_1.$U.json(res));
224
- engine_1._log(NS, `> create[${id}].result =`, res.result); // 'created','noop','updated'
225
- engine_1._log(NS, `> create[${id}]._version =`, res._version); // 1
226
- // return res;
227
- const _version = engine_1.$U.N(res._version, 0);
228
- const _id = res._id;
229
- const res2 = Object.assign(Object.assign({}, item), { _id, _version });
326
+ engine_1._log(NS, `> create[${id}].res =`, engine_1.$U.json(Object.assign(Object.assign({}, res), { meta: undefined })));
327
+ const _version = engine_1.$U.N((_a = res.body) === null || _a === void 0 ? void 0 : _a._version, 0);
328
+ const _id = (_b = res.body) === null || _b === void 0 ? void 0 : _b._id;
329
+ const res2 = Object.assign(Object.assign({}, body), { _id, _version });
230
330
  return res2;
231
331
  });
232
332
  }
@@ -236,28 +336,30 @@ class Elastic6Service {
236
336
  * @param item item to push
237
337
  */
238
338
  pushItem(item, type) {
339
+ var _a, _b;
239
340
  return __awaiter(this, void 0, void 0, function* () {
240
- const { endpoint, indexName, docType } = this.options;
241
- const { client } = instance(endpoint);
341
+ const { indexName, docType } = this.options;
242
342
  const id = '';
243
343
  type = `${type || docType}`;
244
344
  const body = Object.assign({}, item);
245
- this.prepareAutocompleteFields(body);
345
+ const body2 = this.popullateAutocompleteFields(body);
246
346
  engine_1._log(NS, `- pushItem(${id})`);
247
- const params = { index: indexName, type, body };
347
+ const params = { index: indexName, type, body: body2 };
248
348
  engine_1._log(NS, `> params[${id}] =`, engine_1.$U.json(params));
249
349
  //NOTE - use npm `elasticsearch#13.2.0` for avoiding error.
250
- const res = yield client.index(params).catch(exports.$ERROR.handler('index', e => {
350
+ // const { client } = instance(endpoint);
351
+ const client = this.client;
352
+ const res = yield client.index(params).catch(
353
+ // $ERROR.throwAsJson,
354
+ exports.$ERROR.handler('index', e => {
251
355
  engine_1._err(NS, `> index[${indexName}].err =`, e instanceof Error ? e : engine_1.$U.json(e));
252
356
  throw e;
253
357
  }));
254
358
  // {"_index":"test-v3","_type":"_doc","_id":"rTeHiW4BPb_liACrA9qa","_version":1,"result":"created","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":2,"_primary_term":1}
255
- engine_1._log(NS, `> create[${id}].res =`, engine_1.$U.json(res));
256
- engine_1._log(NS, `> create[${id}].result =`, res.result); // 'created','noop','updated'
257
- engine_1._log(NS, `> create[${id}]._version =`, res._version); // 1
258
- const _id = res._id;
259
- const _version = res._version;
260
- const res2 = Object.assign(Object.assign({}, item), { _id, _version });
359
+ engine_1._log(NS, `> create[${id}].res =`, engine_1.$U.json(Object.assign(Object.assign({}, res), { meta: undefined })));
360
+ const _id = (_a = res.body) === null || _a === void 0 ? void 0 : _a._id;
361
+ const _version = (_b = res.body) === null || _b === void 0 ? void 0 : _b._version;
362
+ const res2 = Object.assign(Object.assign({}, body), { _id, _version });
261
363
  return res2;
262
364
  });
263
365
  }
@@ -268,34 +370,35 @@ class Elastic6Service {
268
370
  * @param views projections
269
371
  */
270
372
  readItem(id, views) {
373
+ var _a, _b, _c;
271
374
  return __awaiter(this, void 0, void 0, function* () {
272
- const { endpoint, indexName, docType } = this.options;
273
- const { client } = instance(endpoint);
375
+ const { indexName, docType } = this.options;
274
376
  const type = `${docType}`;
275
377
  engine_1._log(NS, `- readItem(${id})`);
276
378
  const params = { index: indexName, type, id };
277
379
  if (views) {
278
380
  const fields = [];
279
- const is_array = Array.isArray(views);
280
- engine_1.$_.each(views, (v, k) => {
281
- fields.push(is_array ? v : k);
381
+ const keys = Array.isArray(views) ? views : Object.keys(views);
382
+ keys.forEach((k) => {
383
+ fields.push(k);
282
384
  });
283
385
  params._source = fields;
284
386
  }
285
387
  engine_1._log(NS, `> params[${id}] =`, engine_1.$U.json(params));
286
- const res = yield client.get(params).catch(exports.$ERROR.handler('read', e => {
287
- engine_1._err(NS, `> read[${indexName}].err =`, e instanceof Error ? e : engine_1.$U.json(e));
288
- if (`${e.message}`.startsWith('404 Not Found'))
388
+ // const { client } = instance(endpoint);
389
+ const client = this.client;
390
+ const res = yield client.get(params).catch(
391
+ // $ERROR.throwAsJson,
392
+ exports.$ERROR.handler('read', e => {
393
+ const msg = test_helper_1.GETERR(e);
394
+ if (msg.startsWith('404 NOT FOUND'))
289
395
  throw new Error(`404 NOT FOUND - id:${id}`);
290
396
  throw e;
291
397
  }));
292
- // {"_index":"test-v3","_type":"_doc","_id":"aaa","_version":2,"found":true,"_source":{"name":"haha"}}
293
- engine_1._log(NS, `> read[${id}].res =`, engine_1.$U.json(res));
294
- engine_1._log(NS, `> create[${id}].found =`, res.found); // true
295
- engine_1._log(NS, `> create[${id}]._version =`, res._version); // 2
296
- const _id = res._id;
297
- const _version = res._version;
298
- const data = (res && res._source) || {};
398
+ engine_1._log(NS, `> read[${id}].res =`, engine_1.$U.json(Object.assign(Object.assign({}, res), { meta: undefined })));
399
+ const _id = (_a = res.body) === null || _a === void 0 ? void 0 : _a._id;
400
+ const _version = (_b = res.body) === null || _b === void 0 ? void 0 : _b._version;
401
+ const data = ((_c = res) === null || _c === void 0 ? void 0 : _c._source) || {};
299
402
  // delete internal (analyzed) field
300
403
  delete data[Elastic6Service.DECOMPOSED_FIELD];
301
404
  delete data[Elastic6Service.QWERTY_FIELD];
@@ -309,26 +412,26 @@ class Elastic6Service {
309
412
  * @param id item-id
310
413
  */
311
414
  deleteItem(id) {
415
+ var _a, _b, _c;
312
416
  return __awaiter(this, void 0, void 0, function* () {
313
- const { endpoint, indexName, docType } = this.options;
314
- const { client } = instance(endpoint);
417
+ const { indexName, docType } = this.options;
315
418
  const type = `${docType}`;
316
419
  engine_1._log(NS, `- readItem(${id})`);
317
420
  const params = { index: indexName, type, id };
318
421
  engine_1._log(NS, `> params[${id}] =`, engine_1.$U.json(params));
319
- const res = yield client.delete(params).catch(exports.$ERROR.handler('delete', e => {
320
- engine_1._err(NS, `> delete[${indexName}].err =`, e instanceof Error ? e : engine_1.$U.json(e));
321
- if (`${e.message}`.startsWith('404 Not Found'))
422
+ // const { client } = instance(endpoint);
423
+ const client = this.client;
424
+ const res = yield client.delete(params).catch(exports.$ERROR.handler('read', e => {
425
+ const msg = test_helper_1.GETERR(e);
426
+ if (msg.startsWith('404 NOT FOUND'))
322
427
  throw new Error(`404 NOT FOUND - id:${id}`);
323
428
  throw e;
324
429
  }));
325
430
  // {"_index":"test-v3","_type":"_doc","_id":"aaa","_version":3,"result":"deleted","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":4,"_primary_term":1}
326
- engine_1._log(NS, `> delete[${id}].res =`, engine_1.$U.json(res));
327
- engine_1._log(NS, `> delete[${id}].result =`, res.result); // true
328
- engine_1._log(NS, `> delete[${id}]._version =`, res._version); // 2
329
- const _id = res._id;
330
- const _version = res._version;
331
- const data = (res && res._source) || {};
431
+ engine_1._log(NS, `> delete[${id}].res =`, engine_1.$U.json(Object.assign(Object.assign({}, res), { meta: undefined })));
432
+ const _id = (_a = res.body) === null || _a === void 0 ? void 0 : _a._id;
433
+ const _version = (_b = res.body) === null || _b === void 0 ? void 0 : _b._version;
434
+ const data = ((_c = res.body) === null || _c === void 0 ? void 0 : _c._source) || {};
332
435
  const res2 = Object.assign(Object.assign({}, data), { _id, _version });
333
436
  return res2;
334
437
  });
@@ -341,47 +444,105 @@ class Elastic6Service {
341
444
  */
342
445
  updateItem(id, item, increments) {
343
446
  return __awaiter(this, void 0, void 0, function* () {
344
- const { endpoint, indexName, docType } = this.options;
345
- const { client } = instance(endpoint);
447
+ const { indexName, docType, idName } = this.options;
346
448
  const type = `${docType}`;
347
449
  engine_1._log(NS, `- updateItem(${id})`);
348
450
  item = !item && increments ? undefined : item;
349
451
  //! prepare params.
350
452
  const params = { index: indexName, type, id, body: { doc: item } };
453
+ const version = this.version;
351
454
  if (increments) {
352
455
  //! it will create if not exists.
353
- params.body.upsert = Object.assign(Object.assign({}, increments), { [indexName]: id });
354
- const scripts = engine_1.$_.reduce(increments, (L, val, key) => {
456
+ params.body.upsert = Object.assign(Object.assign({}, increments), { [idName]: id });
457
+ const scripts = Object.entries(increments).reduce((L, [key, val]) => {
355
458
  L.push(`ctx._source.${key} += ${val}`);
356
459
  return L;
357
460
  }, []);
358
- params.body.lang = 'painless';
461
+ if (version < 7.0)
462
+ params.body.lang = 'painless';
359
463
  params.body.script = scripts.join('; ');
360
464
  }
361
465
  engine_1._log(NS, `> params[${id}] =`, engine_1.$U.json(params));
362
- const res = yield client.update(params).catch(exports.$ERROR.handler('update', e => {
363
- engine_1._err(NS, `> update[${indexName}].err =`, e instanceof Error ? e : engine_1.$U.json(e));
466
+ // const { client } = instance(endpoint);
467
+ const client = this.client;
468
+ const res = yield client.update(params).catch(exports.$ERROR.handler('update', (e, E) => {
469
+ const msg = test_helper_1.GETERR(e);
364
470
  //! id 아이템이 없을 경우 발생함.
365
- if (`${e.message}`.startsWith('404 document_missing_exception'))
471
+ if (msg.startsWith('404 DOCUMENT MISSING'))
366
472
  throw new Error(`404 NOT FOUND - id:${id}`);
367
473
  //! 해당 속성이 없을때 업데이트 하려면 생길 수 있음.
368
- if (`${e.message}`.startsWith('400 remote_transport_exception'))
474
+ if (msg.startsWith('400 REMOTE TRANSPORT'))
369
475
  throw new Error(`400 INVALID FIELD - id:${id}`);
370
- if (`${e.message}`.startsWith('404 Not Found'))
476
+ if (msg.startsWith('404 NOT FOUND'))
371
477
  throw new Error(`404 NOT FOUND - id:${id}`);
372
- throw e;
478
+ if (msg.startsWith('400 ACTION REQUEST VALIDATION'))
479
+ throw e;
480
+ if (msg.startsWith('400 INVALID FIELD'))
481
+ throw e; // at ES6.8
482
+ if (msg.startsWith('400 ILLEGAL ARGUMENT'))
483
+ throw e; // at ES7.1
484
+ throw E;
373
485
  }));
374
486
  // {"_index":"test-v3","_type":"_doc","_id":"aaa","_version":2,"result":"updated","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":8,"_primary_term":1}
375
487
  // {"_index":"test-v3","_type":"_doc","_id":"aaa","_version":2,"result":"noop","_shards":{"total":0,"successful":0,"failed":0}}
376
- engine_1._log(NS, `> update[${id}].res =`, engine_1.$U.json(res));
377
- engine_1._log(NS, `> update[${id}].result =`, res.result); // true
378
- engine_1._log(NS, `> update[${id}]._version =`, res._version); // 2
379
- const _id = res._id;
380
- const _version = res._version;
488
+ engine_1._log(NS, `> update[${id}].res =`, engine_1.$U.json(Object.assign(Object.assign({}, res), { meta: undefined })));
489
+ const _id = res.body._id;
490
+ const _version = res.body._version;
381
491
  const res2 = Object.assign(Object.assign({}, item), { _id, _version });
382
492
  return res2;
383
493
  });
384
494
  }
495
+ /**
496
+ * run search and get the raw response.
497
+ */
498
+ searchRaw(body, searchType) {
499
+ return __awaiter(this, void 0, void 0, function* () {
500
+ if (!body)
501
+ throw new Error('@body (SearchBody) is required');
502
+ const { indexName, docType } = this.options;
503
+ engine_1._log(NS, `- search(${indexName}, ${searchType || ''})....`);
504
+ engine_1._log(NS, `> body =`, engine_1.$U.json(body));
505
+ const tmp = docType ? docType : '';
506
+ const type = docType ? `${docType}` : undefined;
507
+ const params = { index: indexName, type, body, searchType };
508
+ engine_1._log(NS, `> params[${tmp}] =`, engine_1.$U.json(Object.assign(Object.assign({}, params), { body: undefined })));
509
+ // const { client } = instance(endpoint);
510
+ const client = this.client;
511
+ const $res = yield client.search(params).catch(exports.$ERROR.handler('search', e => {
512
+ engine_1._err(NS, `> search[${indexName}].err =`, e);
513
+ throw e;
514
+ }));
515
+ // {"took":6,"timed_out":false,"_shards":{"total":4,"successful":4,"skipped":0,"failed":0},"hits":{"total":1,"max_score":0.2876821,"hits":[{"_index":"test-v3","_type":"_doc","_id":"aaa","_score":0.2876821,"_source":{"name":"AAA","@id":"aaa","a":-3,"b":-2}}]}}
516
+ // _log(NS, `> search[${id}].res =`, $U.json({ ...res, meta: undefined }));
517
+ // _log(NS, `> search[${tmp}].took =`, $res.took);
518
+ // _log(NS, `> search[${tmp}].hits.total =`, $res.hits?.total);
519
+ // _log(NS, `> search[${tmp}].hits.max_score =`, $res.hits?.max_score);
520
+ // _log(NS, `> search[${tmp}].hits.hits[0] =`, $res.hits && $U.json($res.hits.hits[0]));
521
+ //! return raw results.
522
+ return $res === null || $res === void 0 ? void 0 : $res.body;
523
+ });
524
+ }
525
+ /**
526
+ * run search, and get the formatmted response.
527
+ */
528
+ search(body, searchType) {
529
+ var _a, _b, _c;
530
+ return __awaiter(this, void 0, void 0, function* () {
531
+ const size = engine_1.$U.N(body.size, 0);
532
+ const response = yield this.searchRaw(body, searchType);
533
+ // return w/ transformed id
534
+ const hits = response.hits;
535
+ if (typeof hits !== 'object')
536
+ throw new Error(`.hits (object) is required - hits:${engine_1.$U.json(hits)}`);
537
+ //NOTE - ES6.8 w/ OS1.1
538
+ return {
539
+ total: typeof ((_a = hits.total) === null || _a === void 0 ? void 0 : _a.value) === 'number' ? (_b = hits.total) === null || _b === void 0 ? void 0 : _b.value : hits.total,
540
+ list: hits.hits.map((hit) => (Object.assign(Object.assign({}, hit._source), { _id: hit._id, _score: hit._score }))),
541
+ last: hits.hits.length === size && size > 0 ? (_c = hits.hits[size - 1]) === null || _c === void 0 ? void 0 : _c.sort : undefined,
542
+ aggregations: response.aggregations,
543
+ };
544
+ });
545
+ }
385
546
  /**
386
547
  * prepare default setting
387
548
  * - migrated from engine-v2.
@@ -392,14 +553,94 @@ class Elastic6Service {
392
553
  * @param replicas number of replicas (default 1)
393
554
  * @param timeSeries flag of TIMESERIES (default false)
394
555
  */
395
- static prepareSettings(docType, idName, timeSeries, shards, replicas) {
396
- shards = shards === undefined ? 4 : shards;
397
- replicas = replicas === undefined ? 1 : replicas;
398
- timeSeries = timeSeries === undefined ? false : timeSeries;
556
+ static prepareSettings(params) {
557
+ const docType = params.docType === undefined ? '_doc' : params.docType;
558
+ const idName = params.idName === undefined ? '$id' : params.idName;
559
+ const version = engine_1.$U.F(params.version === undefined ? '6.8' : params.version);
560
+ const shards = params.shards === undefined ? 4 : params.shards;
561
+ const replicas = params.replicas === undefined ? 1 : params.replicas;
562
+ const timeSeries = params.timeSeries === undefined ? false : params.timeSeries;
399
563
  //! core config.
400
564
  const CONF_ES_DOCTYPE = docType;
401
565
  const CONF_ID_NAME = idName;
402
566
  const CONF_ES_TIMESERIES = !!timeSeries;
567
+ const ES_MAPPINGS = {
568
+ // NOTE: the order of dynamic templates are important.
569
+ dynamic_templates: [
570
+ // 1. Search-as-You-Type (autocomplete search) - apply to '_decomposed.*' fields
571
+ {
572
+ autocomplete: {
573
+ path_match: `${Elastic6Service.DECOMPOSED_FIELD}.*`,
574
+ mapping: {
575
+ type: 'text',
576
+ analyzer: 'autocomplete_case_insensitive',
577
+ search_analyzer: 'standard',
578
+ },
579
+ },
580
+ },
581
+ // 2. Search-as-You-Type (Korean to Alphabet sequence in QWERTY/2벌식 keyboard) - apply to '_qwerty.*' fields
582
+ {
583
+ autocomplete_qwerty: {
584
+ path_match: `${Elastic6Service.QWERTY_FIELD}.*`,
585
+ mapping: {
586
+ type: 'text',
587
+ analyzer: 'autocomplete_case_sensitive',
588
+ search_analyzer: 'whitespace',
589
+ },
590
+ },
591
+ },
592
+ // 3. string type ID field
593
+ {
594
+ string_id: {
595
+ match_mapping_type: 'string',
596
+ match: CONF_ID_NAME,
597
+ mapping: {
598
+ type: 'keyword',
599
+ ignore_above: 256,
600
+ },
601
+ },
602
+ },
603
+ // 4. any other string fields - use Hangul analyzer and create 'keyword' sub-field
604
+ {
605
+ strings: {
606
+ match_mapping_type: 'string',
607
+ mapping: {
608
+ type: 'text',
609
+ analyzer: 'hangul',
610
+ search_analyzer: 'hangul',
611
+ fields: {
612
+ // keyword sub-field
613
+ // 문자열 타입에 대한 템플릿을 지정하지 않으면 기본으로 ES가 '.keyword' 서브필드를 생성하나
614
+ // 문자열 타입 템플릿 재정의 시 기본으로 생성되지 않으므로 명시적으로 선언함.
615
+ keyword: {
616
+ type: 'keyword',
617
+ ignore_above: 256,
618
+ },
619
+ },
620
+ },
621
+ },
622
+ },
623
+ ],
624
+ properties: {
625
+ '@version': {
626
+ type: 'keyword',
627
+ index: false,
628
+ },
629
+ created_at: {
630
+ type: 'date',
631
+ format: 'strict_date_optional_time||epoch_millis',
632
+ },
633
+ updated_at: {
634
+ type: 'date',
635
+ format: 'strict_date_optional_time||epoch_millis',
636
+ },
637
+ deleted_at: {
638
+ type: 'date',
639
+ format: 'strict_date_optional_time||epoch_millis',
640
+ },
641
+ },
642
+ };
643
+ //! default settings.
403
644
  const ES_SETTINGS = {
404
645
  settings: {
405
646
  number_of_shards: shards,
@@ -434,98 +675,31 @@ class Elastic6Service {
434
675
  autocomplete_case_sensitive: {
435
676
  type: 'custom',
436
677
  tokenizer: 'edge_30grams',
437
- filter: ['standard'],
438
- },
439
- },
440
- },
441
- },
442
- mappings: {
443
- [CONF_ES_DOCTYPE]: {
444
- // NOTE: the order of dynamic templates are important.
445
- dynamic_templates: [
446
- // 1. Search-as-You-Type (autocomplete search) - apply to '_decomposed.*' fields
447
- {
448
- autocomplete: {
449
- path_match: `${Elastic6Service.DECOMPOSED_FIELD}.*`,
450
- mapping: {
451
- type: 'text',
452
- analyzer: 'autocomplete_case_insensitive',
453
- search_analyzer: 'standard',
454
- },
455
- },
456
- },
457
- // 2. Search-as-You-Type (Korean to Alphabet sequence in QWERTY/2벌식 keyboard) - apply to '_qwerty.*' fields
458
- {
459
- autocomplete_qwerty: {
460
- path_match: `${Elastic6Service.QWERTY_FIELD}.*`,
461
- mapping: {
462
- type: 'text',
463
- analyzer: 'autocomplete_case_sensitive',
464
- search_analyzer: 'whitespace',
465
- },
466
- },
467
- },
468
- // 3. string type ID field
469
- {
470
- string_id: {
471
- match_mapping_type: 'string',
472
- match: CONF_ID_NAME,
473
- mapping: {
474
- type: 'keyword',
475
- ignore_above: 256,
476
- },
477
- },
478
- },
479
- // 4. any other string fields - use Hangul analyzer and create 'keyword' sub-field
480
- {
481
- strings: {
482
- match_mapping_type: 'string',
483
- mapping: {
484
- type: 'text',
485
- analyzer: 'hangul',
486
- search_analyzer: 'hangul',
487
- fields: {
488
- // keyword sub-field
489
- // 문자열 타입에 대한 템플릿을 지정하지 않으면 기본으로 ES가 '.keyword' 서브필드를 생성하나
490
- // 문자열 타입 템플릿 재정의 시 기본으로 생성되지 않으므로 명시적으로 선언함.
491
- keyword: {
492
- type: 'keyword',
493
- ignore_above: 256,
494
- },
495
- },
496
- },
497
- },
498
- },
499
- ],
500
- properties: {
501
- '@version': {
502
- type: 'keyword',
503
- index: false,
504
- },
505
- created_at: {
506
- type: 'date',
507
- format: 'strict_date_optional_time||epoch_millis',
508
- },
509
- updated_at: {
510
- type: 'date',
511
- format: 'strict_date_optional_time||epoch_millis',
512
- },
513
- deleted_at: {
514
- type: 'date',
515
- format: 'strict_date_optional_time||epoch_millis',
678
+ filter: version < 7.0 ? ['standard'] : [],
516
679
  },
517
680
  },
518
681
  },
519
682
  },
683
+ //! since 7.x. no mapping for types.
684
+ mappings: version < 7.0 ? { [CONF_ES_DOCTYPE]: ES_MAPPINGS } : ES_MAPPINGS,
520
685
  };
521
686
  //! timeseries 데이터로, 기본 timestamp 값을 넣어준다. (주의! save시 current-time 값 자동 저장)
522
687
  if (!!CONF_ES_TIMESERIES) {
523
688
  ES_SETTINGS.settings.refresh_interval = '5s';
524
- ES_SETTINGS.mappings[CONF_ES_DOCTYPE].properties['@timestamp'] = { type: 'date', doc_values: true };
525
- ES_SETTINGS.mappings[CONF_ES_DOCTYPE].properties['ip'] = { type: 'ip' };
526
- //! clear mappings.
527
- const CLEANS = '@version,created_at,updated_at,deleted_at'.split(',');
528
- CLEANS.map(key => delete ES_SETTINGS.mappings[CONF_ES_DOCTYPE].properties[key]);
689
+ if (version < 7.0) {
690
+ ES_SETTINGS.mappings[CONF_ES_DOCTYPE].properties['@timestamp'] = { type: 'date', doc_values: true };
691
+ ES_SETTINGS.mappings[CONF_ES_DOCTYPE].properties['ip'] = { type: 'ip' };
692
+ //! clear mappings.
693
+ const CLEANS = '@version,created_at,updated_at,deleted_at'.split(',');
694
+ CLEANS.map(key => delete ES_SETTINGS.mappings[CONF_ES_DOCTYPE].properties[key]);
695
+ }
696
+ else {
697
+ ES_SETTINGS.mappings.properties['@timestamp'] = { type: 'date', doc_values: true };
698
+ ES_SETTINGS.mappings.properties['ip'] = { type: 'ip' };
699
+ //! clear mappings.
700
+ const CLEANS = '@version,created_at,updated_at,deleted_at'.split(',');
701
+ CLEANS.map(key => delete ES_SETTINGS.properties[key]);
702
+ }
529
703
  }
530
704
  //! returns settings.
531
705
  return ES_SETTINGS;
@@ -535,31 +709,31 @@ class Elastic6Service {
535
709
  * @param body item body to be saved into ES6 index
536
710
  * @private
537
711
  */
538
- prepareAutocompleteFields(body) {
712
+ popullateAutocompleteFields(body) {
539
713
  const { autocompleteFields } = this.options;
540
- if (body && Array.isArray(autocompleteFields) && autocompleteFields.length > 0) {
541
- body[Elastic6Service.DECOMPOSED_FIELD] = {};
542
- body[Elastic6Service.QWERTY_FIELD] = {};
543
- autocompleteFields.forEach(field => {
544
- const value = body[field];
545
- if (typeof value == 'string' || value) {
546
- // 한글의 경우 자모 분해 형태와 영자판 변형 형태를 제공하고, 영문의 경우 원본 텍스트만 제공한다.
547
- // 다만 사용자가 공백/하이픈을 생략하고 입력하는 경우에 대응하기 위해 공백/하이픈을 제거한 형태를 공통으로 제공한다.
548
- if (hangul_service_1.default.isHangul(value, true)) {
549
- // 자모 분해 (e.g. '레몬' -> 'ㄹㅔㅁㅗㄴ')
550
- const decomposed = hangul_service_1.default.asJamoSequence(value);
551
- const recomposed = decomposed.replace(/[ -]/g, '');
552
- body[Elastic6Service.DECOMPOSED_FIELD][field] = [decomposed, recomposed];
553
- // 영자판 (e.g. '레몬' -> 'fpahs')
554
- body[Elastic6Service.QWERTY_FIELD][field] = hangul_service_1.default.asAlphabetKeyStokes(value);
555
- }
556
- else {
557
- const recomposed = value.replace(/[ -]/g, '');
558
- body[Elastic6Service.DECOMPOSED_FIELD][field] = [value, recomposed];
559
- }
714
+ const isAutoComplete = autocompleteFields && Array.isArray(autocompleteFields) && autocompleteFields.length > 0;
715
+ if (!isAutoComplete)
716
+ return body;
717
+ return autocompleteFields.reduce((N, field) => {
718
+ const value = body[field];
719
+ if (typeof value == 'string' || value) {
720
+ // 한글의 경우 자모 분해 형태와 영자판 변형 형태를 제공하고, 영문의 경우 원본 텍스트만 제공한다.
721
+ // 다만 사용자가 공백/하이픈을 생략하고 입력하는 경우에 대응하기 위해 공백/하이픈을 제거한 형태를 공통으로 제공한다.
722
+ if (hangul_service_1.default.isHangul(value, true)) {
723
+ // 자모 분해 (e.g. '레몬' -> 'ㄹㅔㅁㅗㄴ')
724
+ const decomposed = hangul_service_1.default.asJamoSequence(value);
725
+ const recomposed = decomposed.replace(/[ -]/g, '');
726
+ N[Elastic6Service.DECOMPOSED_FIELD][field] = [decomposed, recomposed];
727
+ // 영자판 (e.g. '레몬' -> 'fpahs')
728
+ N[Elastic6Service.QWERTY_FIELD][field] = hangul_service_1.default.asAlphabetKeyStokes(value);
560
729
  }
561
- });
562
- }
730
+ else {
731
+ const recomposed = value.replace(/[ -]/g, '');
732
+ N[Elastic6Service.DECOMPOSED_FIELD][field] = [value, recomposed];
733
+ }
734
+ }
735
+ return N;
736
+ }, Object.assign(Object.assign({}, body), { [Elastic6Service.DECOMPOSED_FIELD]: {}, [Elastic6Service.QWERTY_FIELD]: {} }));
563
737
  }
564
738
  }
565
739
  exports.Elastic6Service = Elastic6Service;
@@ -570,94 +744,104 @@ Elastic6Service.QWERTY_FIELD = '_qwerty';
570
744
  * error samples
571
745
  */
572
746
  exports.$ERROR = {
573
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
574
- handler: (name, cb) => (e) => {
575
- engine_1._err(NS, `! err[${name}]@a =`, e instanceof Error, engine_1.$U.json(e));
576
- const status = `${e.statusCode || ''}`;
577
- const message = `${e.message || e.msg || ''}`;
578
- const error = ((e) => {
579
- if (!e)
580
- return {};
581
- if (e.body && e.body.error) {
582
- const error = e.body.error;
583
- if (error.root_cause && Array.isArray(error.root_cause))
584
- return error.root_cause[0];
585
- else if (error.root_cause)
586
- return error.root_cause;
587
- return error;
747
+ asJson: (e) => {
748
+ const _pack = (o) => JSON.parse(JSON.stringify(o, Object.getOwnPropertyNames(o)));
749
+ if (e instanceof Error) {
750
+ const err = e;
751
+ const meta = err.meta && typeof err.meta === 'object' ? err.meta : undefined;
752
+ const $err = _pack(err);
753
+ return Object.assign(Object.assign({}, $err), { meta });
754
+ }
755
+ return e;
756
+ },
757
+ throwAsJson: (e) => {
758
+ throw exports.$ERROR.asJson(e);
759
+ },
760
+ parseMeta: (meta) => {
761
+ if (typeof meta === 'string' && meta) {
762
+ try {
763
+ if (meta.startsWith('[') && meta.endsWith(']')) {
764
+ const list = JSON.parse(meta);
765
+ const $ret = { list };
766
+ return $ret;
767
+ }
768
+ else if (meta.startsWith('{') && meta.endsWith('}')) {
769
+ return JSON.parse(meta);
770
+ }
771
+ else {
772
+ const $ret = { type: 'string', value: meta };
773
+ return $ret;
774
+ }
588
775
  }
589
- else if (e.response) {
590
- const error = typeof e.response == 'string' && e.response.startsWith('{') ? JSON.parse(e.response) : e.response;
591
- if (error.root_cause && Array.isArray(error.root_cause))
592
- return error.root_cause[0];
593
- else if (error.root_cause)
594
- return error.root_cause;
595
- return error;
776
+ catch (e) {
777
+ const $ret = { type: 'string', value: meta, error: test_helper_1.GETERR(e) };
778
+ return $ret;
596
779
  }
597
- else {
598
- const type = e.statusCode || e.status || 0;
599
- const reason = e.displayName || e.msg;
600
- const path = e.path || '';
601
- return { type, reason, path, message };
780
+ }
781
+ else if (meta === null || meta === undefined) {
782
+ return null;
783
+ }
784
+ else if (typeof meta === 'object') {
785
+ return meta;
786
+ }
787
+ else {
788
+ const type = typeof meta;
789
+ const $ret = { type, value: meta };
790
+ return $ret;
791
+ }
792
+ },
793
+ asError: (e) => {
794
+ const E = exports.$ERROR.asJson(e);
795
+ const status = `${E.statusCode || ''}`;
796
+ const message = `${E.message || E.msg || ''}`;
797
+ const reason = ((E) => {
798
+ var _a, _b, _c, _d;
799
+ //! from ES7.1
800
+ if (E.meta && typeof E.meta == 'object') {
801
+ const type = _S(E === null || E === void 0 ? void 0 : E.message)
802
+ .toUpperCase()
803
+ .split('_')
804
+ .slice(0, -1)
805
+ .join(' ');
806
+ const status = engine_1.$U.N((_a = E.meta) === null || _a === void 0 ? void 0 : _a.statusCode, type.includes('NOT FOUND') ? 404 : 400);
807
+ return { status, type: type || (status === 404 ? 'NOT FOUND' : 'UNKNOWN') };
602
808
  }
603
- })(e);
604
- error.status = error.status || status;
605
- error.message = error.message || message;
606
- //! print the unknown type exception
607
- if (!error || error.status) {
608
- // _err(NS, `! err[${name}]@b =`, e instanceof Error, $U.json(e));
609
- // _err(NS, `> err[${name}]@c =`, $U.json(error));
610
- // _err(NS, `> error[${name}].type =`, error.type);
611
- // _err(NS, `> error[${name}].reason =`, error.reason);
612
- // _err(NS, `> error[${name}].message =`, error.message);
809
+ //! from ES6.2
810
+ if (!E.response)
811
+ return null;
812
+ const $res = exports.$ERROR.parseMeta(E.response);
813
+ //! find the root-cause.
814
+ const pic1 = (N, i = 0) => (N && Array.isArray(N) ? N[i] : N);
815
+ const cause = pic1((_b = $res === null || $res === void 0 ? void 0 : $res.error) === null || _b === void 0 ? void 0 : _b.root_cause);
816
+ const status = engine_1.$U.N(((_c = $res.error) === null || _c === void 0 ? void 0 : _c.status) || $res.status);
817
+ const reason = _S((_d = $res.error) === null || _d === void 0 ? void 0 : _d.reason, $res.found === false || $res.result === 'not_found' ? 'NOT FOUND' : '');
818
+ const type = _S(cause === null || cause === void 0 ? void 0 : cause.type)
819
+ .toUpperCase()
820
+ .split('_')
821
+ .slice(0, -1)
822
+ .join(' ');
823
+ return { status, reason, cause, type: type || reason };
824
+ })(E);
825
+ //! FINAL. convert to error-object.
826
+ return {
827
+ status: engine_1.$U.N(status, (reason === null || reason === void 0 ? void 0 : reason.status) || 0),
828
+ message: message || (reason === null || reason === void 0 ? void 0 : reason.reason),
829
+ reason,
830
+ };
831
+ },
832
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
833
+ handler: (name, cb) => (e) => {
834
+ const E = exports.$ERROR.asError(e);
835
+ //! unknown error found..
836
+ if (!(E === null || E === void 0 ? void 0 : E.status)) {
837
+ engine_1._err(NS, `! err[${name}]@handler =`, e instanceof Error, engine_1.$U.json(e));
838
+ throw e;
613
839
  }
614
- //! build Error instance.
615
- const $e = new Error(`${error.status} ${error.type || error.reason || error.message} - ${error.reason || error.message}`);
840
+ const $e = new Error(`${E.status} ${E.reason.type} - ${E.message}`);
616
841
  if (cb)
617
- return cb($e);
842
+ return cb($e, E);
618
843
  throw $e;
619
844
  },
620
- index_not_found_exception: {
621
- msg: '[index_not_found_exception] no such index, with { resource.type="index_or_alias" & resource.id="test-v2" & index_uuid="_na_" & index="test-v2" }',
622
- path: '/test-v2',
623
- query: {},
624
- statusCode: 404,
625
- response: '{"error":{"root_cause":[{"type":"index_not_found_exception","reason":"no such index","resource.type":"index_or_alias","resource.id":"test-v2","index_uuid":"_na_","index":"test-v2"}],"type":"index_not_found_exception","reason":"no such index","resource.type":"index_or_alias","resource.id":"test-v2","index_uuid":"_na_","index":"test-v2"},"status":404}',
626
- },
627
- resource_already_exists_exception: {
628
- msg: '[resource_already_exists_exception] index [test-v2/R_X1Daw7S0e8qIh_W3M-Fg] already exists, with { index_uuid="R_X1Daw7S0e8qIh_W3M-Fg" & index="test-v2" }',
629
- path: '/test-v2',
630
- query: {},
631
- body: '{"settings":{"index":{"number_of_shards":4,"number_of_replicas":1}},"template":"test-v2","mappings":{"_default_":{"dynamic_templates":[{"string_fields":{"match":"*_multi","match_mapping_type":"string","mapping":{"type":"multi_field","fields":{"{name}":{"type":"text","index":"analyzed","omit_norms":true,"index_options":"docs"},"{name}.raw":{"type":"text","index":"not_analyzed","ignore_above":256}}}}}],"_source":{"enabled":true},"properties":{"@version":{"type":"text","index":false},"title":{"type":"text"},"name":{"type":"text"},"created_at":{"type":"date","format":"strict_date_optional_time||epoch_millis"},"updated_at":{"type":"date","format":"strict_date_optional_time||epoch_millis"},"deleted_at":{"type":"date","format":"strict_date_optional_time||epoch_millis"},"@id":{"type":"text","fields":{"keyword":{"type":"keyword","ignore_above":256}}}}}}}',
632
- statusCode: 400,
633
- response: '{"error":{"root_cause":[{"type":"resource_already_exists_exception","reason":"index [test-v2/R_X1Daw7S0e8qIh_W3M-Fg] already exists","index_uuid":"R_X1Daw7S0e8qIh_W3M-Fg","index":"test-v2"}],"type":"resource_already_exists_exception","reason":"index [test-v2/R_X1Daw7S0e8qIh_W3M-Fg] already exists","index_uuid":"R_X1Daw7S0e8qIh_W3M-Fg","index":"test-v2"},"status":400}',
634
- },
635
- not_found: {
636
- msg: 'Not Found',
637
- path: '/test-v3/_doc/bbb',
638
- query: {},
639
- statusCode: 404,
640
- response: '{"_index":"test-v3","_type":"_doc","_id":"bbb","found":false}',
641
- },
642
- action_request_validation_exception: {
643
- msg: '[action_request_validation_exception] Validation Failed: 1: script or doc is missing;',
644
- path: '/test-v3/_doc/aaa/_update',
645
- query: {},
646
- statusCode: 400,
647
- response: '{"error":{"root_cause":[{"type":"action_request_validation_exception","reason":"Validation Failed: 1: script or doc is missing;"}],"type":"action_request_validation_exception","reason":"Validation Failed: 1: script or doc is missing;"},"status":400}',
648
- },
649
- remote_transport_exception: {
650
- msg: '[remote_transport_exception] [rt8LrQT][x.x.x.x:9300][indices:data/write/update[s]]',
651
- path: '/test-v3/_doc/aaa/_update',
652
- query: {},
653
- body: '{"upsert":{"count":2,"a":5},"script":"ctx._source.count += 2,ctx._source.a += 5"}',
654
- statusCode: 400,
655
- response: '{"error":{"root_cause":[{"type":"remote_transport_exception","reason":"[rt8LrQT][x.x.x.x:9300][indices:data/write/update[s]]"}],"type":"illegal_argument_exception","reason":"failed to execute script","caused_by":{"type":"script_exception","reason":"compile error","script_stack":["ctx._source.count += 2,ctx._source.a += 5"," ^---- HERE"],"script":"ctx._source.count += 2,ctx._source.a += 5","lang":"painless","caused_by":{"type":"illegal_argument_exception","reason":"unexpected token [\',\'] was expecting one of [{<EOF>, \';\'}]."}}},"status":400}',
656
- },
657
- version_conflict_engine_exception: {
658
- '!': '가끔씩 update할때 나는것 같음! 개선 필요 @191121',
659
- msg: '[version_conflict_engine_exception] [item][TTDfu-tfwfoE0CFuQ=]: version conflict, current version [3] is different than the one provided [2], with { index_uuid="GxCGaNZoSZuoDFTmWfjqtg" & shard="4" & index="clusters-v1" }',
660
- },
661
845
  };
662
846
  /** ****************************************************************************************************************
663
847
  * Dummy Elastic6 Service
@@ -714,7 +898,7 @@ class DummyElastic6Service extends Elastic6Service {
714
898
  updateItem(id, updates, increments) {
715
899
  return __awaiter(this, void 0, void 0, function* () {
716
900
  const org = yield this.readItem(id);
717
- const item = Object.assign(Object.assign(Object.assign({}, org), updates), { _version: Number(org._version) + 1 });
901
+ const item = Object.assign(Object.assign(Object.assign({}, org), updates), { _version: Number(org._version || 0) + 1 });
718
902
  if (increments) {
719
903
  //TODO - support increments in dummy.
720
904
  }