lemon-core 2.2.19 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/README.md +11 -20
  2. package/dist/common/test-helper.js +1 -1
  3. package/dist/common/test-helper.js.map +1 -1
  4. package/dist/controllers/dummy-controller.js.map +1 -1
  5. package/dist/cores/api-service.js.map +1 -1
  6. package/dist/cores/aws/aws-s3-service.d.ts +24 -46
  7. package/dist/cores/aws/aws-s3-service.js +103 -223
  8. package/dist/cores/aws/aws-s3-service.js.map +1 -1
  9. package/dist/cores/aws/aws-sns-service.js +3 -3
  10. package/dist/cores/aws/aws-sns-service.js.map +1 -1
  11. package/dist/cores/cache-service.js +12 -12
  12. package/dist/cores/cache-service.js.map +1 -1
  13. package/dist/cores/core-types.d.ts +92 -2
  14. package/dist/cores/core-types.js +1 -0
  15. package/dist/cores/core-types.js.map +1 -1
  16. package/dist/cores/dynamo-service.js +2 -2
  17. package/dist/cores/dynamo-service.js.map +1 -1
  18. package/dist/cores/elastic6-query-service.d.ts +42 -9
  19. package/dist/cores/elastic6-query-service.js +144 -134
  20. package/dist/cores/elastic6-query-service.js.map +1 -1
  21. package/dist/cores/elastic6-service.d.ts +144 -57
  22. package/dist/cores/elastic6-service.js +506 -322
  23. package/dist/cores/elastic6-service.js.map +1 -1
  24. package/dist/cores/lambda/lambda-cognito-handler.js.map +1 -1
  25. package/dist/cores/lambda/lambda-cron-handler.js.map +1 -1
  26. package/dist/cores/lambda/lambda-dynamo-stream-handler.js +3 -3
  27. package/dist/cores/lambda/lambda-dynamo-stream-handler.js.map +1 -1
  28. package/dist/cores/lambda/lambda-notification-handler.js.map +1 -1
  29. package/dist/cores/lambda/lambda-sns-handler.js.map +1 -1
  30. package/dist/cores/lambda/lambda-web-handler.js +2 -4
  31. package/dist/cores/lambda/lambda-web-handler.js.map +1 -1
  32. package/dist/cores/lambda/lambda-wss-handler.js.map +1 -1
  33. package/dist/cores/protocol/protocol-service.d.ts +1 -2
  34. package/dist/cores/protocol/protocol-service.js +5 -3
  35. package/dist/cores/protocol/protocol-service.js.map +1 -1
  36. package/dist/engine/builder.d.ts +1 -0
  37. package/dist/engine/builder.js +1 -1
  38. package/dist/engine/builder.js.map +1 -1
  39. package/dist/engine/engine.js +2 -1
  40. package/dist/engine/engine.js.map +1 -1
  41. package/dist/engine/index.d.ts +0 -1
  42. package/dist/engine/index.js +2 -4
  43. package/dist/engine/index.js.map +1 -1
  44. package/dist/engine/types.d.ts +0 -4
  45. package/dist/engine/types.js.map +1 -1
  46. package/dist/engine/utilities.d.ts +5 -1
  47. package/dist/engine/utilities.js +126 -11
  48. package/dist/engine/utilities.js.map +1 -1
  49. package/dist/helpers/helpers.d.ts +266 -0
  50. package/dist/helpers/helpers.js +600 -0
  51. package/dist/helpers/helpers.js.map +1 -0
  52. package/dist/helpers/index.d.ts +10 -0
  53. package/dist/helpers/index.js +23 -0
  54. package/dist/helpers/index.js.map +1 -0
  55. package/dist/index.d.ts +1 -0
  56. package/dist/index.js +1 -0
  57. package/dist/index.js.map +1 -1
  58. package/dist/tools/express.js +0 -3
  59. package/dist/tools/express.js.map +1 -1
  60. package/dist/tools/helpers.d.ts +243 -0
  61. package/dist/tools/helpers.js +593 -0
  62. package/dist/tools/helpers.js.map +1 -0
  63. package/package.json +5 -12
  64. package/CHANGELOG.md +0 -61
  65. package/dist/docs/assets/css/main.css +0 -2321
  66. package/dist/docs/assets/images/icons.png +0 -0
  67. package/dist/docs/assets/images/icons@2x.png +0 -0
  68. package/dist/docs/assets/images/widgets.png +0 -0
  69. package/dist/docs/assets/images/widgets@2x.png +0 -0
  70. package/dist/docs/assets/js/main.js +0 -1
  71. package/dist/docs/assets/js/search.js +0 -3
  72. package/dist/docs/classes/abstractmanager.html +0 -1054
  73. package/dist/docs/classes/apiproxyclient.html +0 -509
  74. package/dist/docs/classes/apiservice.html +0 -805
  75. package/dist/docs/classes/awskmsservice.html +0 -468
  76. package/dist/docs/classes/awsmodule.html +0 -353
  77. package/dist/docs/classes/awss3service.html +0 -689
  78. package/dist/docs/classes/awssnsservice.html +0 -543
  79. package/dist/docs/classes/awssqsservice.html +0 -517
  80. package/dist/docs/classes/cacheservice.html +0 -996
  81. package/dist/docs/classes/configmodule.html +0 -311
  82. package/dist/docs/classes/dummycacheservice.html +0 -1000
  83. package/dist/docs/classes/dummycontroller.html +0 -709
  84. package/dist/docs/classes/dummydynamoservice.html +0 -915
  85. package/dist/docs/classes/dummyelastic6service.html +0 -791
  86. package/dist/docs/classes/dummyredisstorageservice.html +0 -804
  87. package/dist/docs/classes/dummystoragemaker.html +0 -383
  88. package/dist/docs/classes/dummystorageservice.html +0 -592
  89. package/dist/docs/classes/dynamoqueryservice.html +0 -413
  90. package/dist/docs/classes/dynamoscanservice.html +0 -358
  91. package/dist/docs/classes/dynamoservice.html +0 -844
  92. package/dist/docs/classes/dynamostorageservice.html +0 -623
  93. package/dist/docs/classes/elastic6queryservice.html +0 -458
  94. package/dist/docs/classes/elastic6service.html +0 -804
  95. package/dist/docs/classes/file.html +0 -579
  96. package/dist/docs/classes/generalapicontroller.html +0 -877
  97. package/dist/docs/classes/generalcontroller.html +0 -454
  98. package/dist/docs/classes/generalcontrollerlocal.html +0 -499
  99. package/dist/docs/classes/generalcontrollerlocal2.html +0 -523
  100. package/dist/docs/classes/generalkeymaker.html +0 -335
  101. package/dist/docs/classes/generalmodelfilter.html +0 -529
  102. package/dist/docs/classes/generalwebcontroller.html +0 -580
  103. package/dist/docs/classes/hangulservice.html +0 -636
  104. package/dist/docs/classes/httpstorageservice.html +0 -539
  105. package/dist/docs/classes/lambdacognitohandler.html +0 -355
  106. package/dist/docs/classes/lambdacronhandler.html +0 -390
  107. package/dist/docs/classes/lambdacronhandlerlocal.html +0 -371
  108. package/dist/docs/classes/lambdadynamostreamhandler.html +0 -472
  109. package/dist/docs/classes/lambdadynamostreamhandlerlocal.html +0 -455
  110. package/dist/docs/classes/lambdahandler.html +0 -479
  111. package/dist/docs/classes/lambdahandlerlocal.html +0 -472
  112. package/dist/docs/classes/lambdamodule.html +0 -433
  113. package/dist/docs/classes/lambdanotificationhandler.html +0 -474
  114. package/dist/docs/classes/lambdanotificationhandlerlocal.html +0 -457
  115. package/dist/docs/classes/lambdasnshandler.html +0 -394
  116. package/dist/docs/classes/lambdasnshandlerlocal.html +0 -397
  117. package/dist/docs/classes/lambdasqshandler.html +0 -394
  118. package/dist/docs/classes/lambdasqshandlerlocal.html +0 -397
  119. package/dist/docs/classes/lambdasubhandler.html +0 -305
  120. package/dist/docs/classes/lambdawebhandler.html +0 -603
  121. package/dist/docs/classes/lambdawebhandlerlocal.html +0 -581
  122. package/dist/docs/classes/lambdawsshandler.html +0 -359
  123. package/dist/docs/classes/memcachedbackend.html +0 -900
  124. package/dist/docs/classes/mocksapiservice.html +0 -691
  125. package/dist/docs/classes/modelutil.html +0 -311
  126. package/dist/docs/classes/myconfigservice.html +0 -561
  127. package/dist/docs/classes/myconfigservicetest.html +0 -527
  128. package/dist/docs/classes/myconfigservicetest2.html +0 -522
  129. package/dist/docs/classes/mydummysqsservice.html +0 -419
  130. package/dist/docs/classes/myenginemodules.html +0 -357
  131. package/dist/docs/classes/mygeneralapicontroller.html +0 -837
  132. package/dist/docs/classes/mylemonwebcontroller.html +0 -356
  133. package/dist/docs/classes/mymodelfilter.html +0 -479
  134. package/dist/docs/classes/myprotocolservice.html +0 -993
  135. package/dist/docs/classes/myprotocolservicetest.html +0 -983
  136. package/dist/docs/classes/myservice.html +0 -329
  137. package/dist/docs/classes/mystorage.html +0 -1370
  138. package/dist/docs/classes/nodecachebackend.html +0 -714
  139. package/dist/docs/classes/protocolmodule.html +0 -311
  140. package/dist/docs/classes/proxystorageservice.html +0 -1441
  141. package/dist/docs/classes/query.html +0 -850
  142. package/dist/docs/classes/redisbackend.html +0 -781
  143. package/dist/docs/classes/redisstorageservice.html +0 -867
  144. package/dist/docs/classes/scan.html +0 -685
  145. package/dist/docs/classes/snsprotocoltransformer.html +0 -334
  146. package/dist/docs/classes/sqsprotocoltransformer.html +0 -334
  147. package/dist/docs/classes/typedstorageservice.html +0 -914
  148. package/dist/docs/classes/uniquefieldmanager.html +0 -477
  149. package/dist/docs/classes/usermanager.html +0 -931
  150. package/dist/docs/classes/utilities.html +0 -1914
  151. package/dist/docs/classes/webprotocoltransformer.html +0 -330
  152. package/dist/docs/globals.html +0 -7477
  153. package/dist/docs/index.html +0 -1515
  154. package/dist/docs/interfaces/accountitem.html +0 -277
  155. package/dist/docs/interfaces/accountmodel.html +0 -306
  156. package/dist/docs/interfaces/adaptiveparam.html +0 -203
  157. package/dist/docs/interfaces/apiheaders.html +0 -183
  158. package/dist/docs/interfaces/apihttpproxy.html +0 -304
  159. package/dist/docs/interfaces/apiserviceclient.html +0 -448
  160. package/dist/docs/interfaces/autocompletesearchparam.html +0 -309
  161. package/dist/docs/interfaces/betweencondition.html +0 -226
  162. package/dist/docs/interfaces/cachebackend.html +0 -714
  163. package/dist/docs/interfaces/cacheentry.html +0 -248
  164. package/dist/docs/interfaces/cacheoptions.html +0 -267
  165. package/dist/docs/interfaces/callbackdata.html +0 -279
  166. package/dist/docs/interfaces/callbackparam.html +0 -252
  167. package/dist/docs/interfaces/comparisoncondition.html +0 -226
  168. package/dist/docs/interfaces/coreconfigservice.html +0 -342
  169. package/dist/docs/interfaces/corekey.html +0 -278
  170. package/dist/docs/interfaces/corekeymakeable.html +0 -292
  171. package/dist/docs/interfaces/corekmsservice.html +0 -311
  172. package/dist/docs/interfaces/coremodel.html +0 -499
  173. package/dist/docs/interfaces/coremodelfilterable.html +0 -281
  174. package/dist/docs/interfaces/cores3service.html +0 -485
  175. package/dist/docs/interfaces/coreservices.html +0 -232
  176. package/dist/docs/interfaces/coresnsservice.html +0 -317
  177. package/dist/docs/interfaces/corewebcontroller.html +0 -271
  178. package/dist/docs/interfaces/cronevent.html +0 -223
  179. package/dist/docs/interfaces/cronparam.html +0 -212
  180. package/dist/docs/interfaces/dynamooption.html +0 -254
  181. package/dist/docs/interfaces/dynamoqueryresult.html +0 -244
  182. package/dist/docs/interfaces/dynamoscanresult.html +0 -244
  183. package/dist/docs/interfaces/dynamosimplequeriable.html +0 -308
  184. package/dist/docs/interfaces/dynamosimplescannable.html +0 -255
  185. package/dist/docs/interfaces/dynamostreambody.html +0 -268
  186. package/dist/docs/interfaces/dynamostreamcallback.html +0 -209
  187. package/dist/docs/interfaces/dynamostreamfilter.html +0 -218
  188. package/dist/docs/interfaces/dynamostreamparam.html +0 -240
  189. package/dist/docs/interfaces/elastic6item.html +0 -221
  190. package/dist/docs/interfaces/elastic6option.html +0 -275
  191. package/dist/docs/interfaces/elastic6simplequeriable.html +0 -284
  192. package/dist/docs/interfaces/engineconsole.html +0 -292
  193. package/dist/docs/interfaces/enginecore.html +0 -344
  194. package/dist/docs/interfaces/enginemodule.html +0 -269
  195. package/dist/docs/interfaces/enginemodules.html +0 -316
  196. package/dist/docs/interfaces/engineoption.html +0 -244
  197. package/dist/docs/interfaces/enginescope.html +0 -220
  198. package/dist/docs/interfaces/existencecondition.html +0 -212
  199. package/dist/docs/interfaces/filter.html +0 -253
  200. package/dist/docs/interfaces/generalfuntion.html +0 -207
  201. package/dist/docs/interfaces/generalitem.html +0 -212
  202. package/dist/docs/interfaces/handlermap.html +0 -171
  203. package/dist/docs/interfaces/incrementable.html +0 -190
  204. package/dist/docs/interfaces/internalkey.html +0 -210
  205. package/dist/docs/interfaces/internalmodel.html +0 -226
  206. package/dist/docs/interfaces/itementry.html +0 -241
  207. package/dist/docs/interfaces/jwtcommon.html +0 -242
  208. package/dist/docs/interfaces/lambdahandlerservice.html +0 -340
  209. package/dist/docs/interfaces/lemonengine.html +0 -593
  210. package/dist/docs/interfaces/metricpostbody.html +0 -220
  211. package/dist/docs/interfaces/mygeneral.html +0 -271
  212. package/dist/docs/interfaces/mymodel.html +0 -554
  213. package/dist/docs/interfaces/myprotocolparam.html +0 -359
  214. package/dist/docs/interfaces/nextcontext.html +0 -381
  215. package/dist/docs/interfaces/nextidentity.html +0 -325
  216. package/dist/docs/interfaces/nextidentityaccess.html +0 -495
  217. package/dist/docs/interfaces/nextidentitycognito.html +0 -422
  218. package/dist/docs/interfaces/notificationbody.html +0 -171
  219. package/dist/docs/interfaces/notificationparam.html +0 -304
  220. package/dist/docs/interfaces/options.html +0 -226
  221. package/dist/docs/interfaces/parrallelcallback.html +0 -203
  222. package/dist/docs/interfaces/parrallelparam.html +0 -285
  223. package/dist/docs/interfaces/protocolbody.html +0 -183
  224. package/dist/docs/interfaces/protocolparam.html +0 -336
  225. package/dist/docs/interfaces/protocolservice.html +0 -548
  226. package/dist/docs/interfaces/protocoltransformer.html +0 -295
  227. package/dist/docs/interfaces/proxyparams.html +0 -212
  228. package/dist/docs/interfaces/putobjectresult.html +0 -282
  229. package/dist/docs/interfaces/queryresult.html +0 -272
  230. package/dist/docs/interfaces/redisoptions.html +0 -248
  231. package/dist/docs/interfaces/simplesearchparam.html +0 -351
  232. package/dist/docs/interfaces/slackaction.html +0 -240
  233. package/dist/docs/interfaces/slackattachment.html +0 -459
  234. package/dist/docs/interfaces/slackpostbody.html +0 -240
  235. package/dist/docs/interfaces/sqsattribute.html +0 -171
  236. package/dist/docs/interfaces/sqsmessage.html +0 -254
  237. package/dist/docs/interfaces/sqsrecord.html +0 -324
  238. package/dist/docs/interfaces/sqsservice.html +0 -333
  239. package/dist/docs/interfaces/sqsstatistics.html +0 -240
  240. package/dist/docs/interfaces/storagemakeable.html +0 -258
  241. package/dist/docs/interfaces/storagemodel.html +0 -285
  242. package/dist/docs/interfaces/storageservice.html +0 -497
  243. package/dist/docs/interfaces/stringcondition.html +0 -226
  244. package/dist/docs/interfaces/tagset.html +0 -171
  245. package/dist/docs/interfaces/testmodel.html +0 -334
  246. package/dist/docs/interfaces/timeout.html +0 -233
  247. package/dist/docs/interfaces/updatable.html +0 -193
  248. 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
  }