lemon-core 4.1.15 → 4.2.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 (154) hide show
  1. package/dist/common/test-helper.d.ts +2 -2
  2. package/dist/common/test-helper.js +24 -26
  3. package/dist/common/test-helper.js.map +1 -1
  4. package/dist/controllers/dummy-controller.js +39 -46
  5. package/dist/controllers/dummy-controller.js.map +1 -1
  6. package/dist/controllers/general-api-controller.js +95 -100
  7. package/dist/controllers/general-api-controller.js.map +1 -1
  8. package/dist/controllers/general-controller.js +81 -82
  9. package/dist/controllers/general-controller.js.map +1 -1
  10. package/dist/cores/api/api-service.d.ts +1 -1
  11. package/dist/cores/api/api-service.js +228 -269
  12. package/dist/cores/api/api-service.js.map +1 -1
  13. package/dist/cores/aws/aws-kms-service.d.ts +1 -2
  14. package/dist/cores/aws/aws-kms-service.js +143 -153
  15. package/dist/cores/aws/aws-kms-service.js.map +1 -1
  16. package/dist/cores/aws/aws-s3-service.d.ts +2 -4
  17. package/dist/cores/aws/aws-s3-service.js +306 -330
  18. package/dist/cores/aws/aws-s3-service.js.map +1 -1
  19. package/dist/cores/aws/aws-sns-service.js +147 -153
  20. package/dist/cores/aws/aws-sns-service.js.map +1 -1
  21. package/dist/cores/aws/aws-sqs-service.js +149 -170
  22. package/dist/cores/aws/aws-sqs-service.js.map +1 -1
  23. package/dist/cores/aws/index.js +10 -20
  24. package/dist/cores/aws/index.js.map +1 -1
  25. package/dist/cores/cache/cache-service.d.ts +2 -2
  26. package/dist/cores/cache/cache-service.js +435 -499
  27. package/dist/cores/cache/cache-service.js.map +1 -1
  28. package/dist/cores/config/config-service.d.ts +1 -1
  29. package/dist/cores/config/config-service.js +56 -63
  30. package/dist/cores/config/config-service.js.map +1 -1
  31. package/dist/cores/config/index.js +14 -24
  32. package/dist/cores/config/index.js.map +1 -1
  33. package/dist/cores/core-services.d.ts +1 -1
  34. package/dist/cores/dynamo/dynamo-query-service.js +37 -51
  35. package/dist/cores/dynamo/dynamo-query-service.js.map +1 -1
  36. package/dist/cores/dynamo/dynamo-scan-service.d.ts +2 -2
  37. package/dist/cores/dynamo/dynamo-scan-service.js +29 -40
  38. package/dist/cores/dynamo/dynamo-scan-service.js.map +1 -1
  39. package/dist/cores/dynamo/dynamo-service.d.ts +2 -2
  40. package/dist/cores/dynamo/dynamo-service.js +528 -601
  41. package/dist/cores/dynamo/dynamo-service.js.map +1 -1
  42. package/dist/cores/dynamo/tools/expressions.js +17 -7
  43. package/dist/cores/dynamo/tools/expressions.js.map +1 -1
  44. package/dist/cores/dynamo/tools/query.js +142 -127
  45. package/dist/cores/dynamo/tools/query.js.map +1 -1
  46. package/dist/cores/dynamo/tools/scan.js +111 -97
  47. package/dist/cores/dynamo/tools/scan.js.map +1 -1
  48. package/dist/cores/dynamo/tools/serializer.js +17 -7
  49. package/dist/cores/dynamo/tools/serializer.js.map +1 -1
  50. package/dist/cores/dynamo/tools/utils.d.ts +0 -2
  51. package/dist/cores/dynamo/tools/utils.js.map +1 -1
  52. package/dist/cores/elastic/elastic6-query-service.js +307 -324
  53. package/dist/cores/elastic/elastic6-query-service.js.map +1 -1
  54. package/dist/cores/elastic/elastic6-service.d.ts +3 -3
  55. package/dist/cores/elastic/elastic6-service.js +568 -647
  56. package/dist/cores/elastic/elastic6-service.js.map +1 -1
  57. package/dist/cores/elastic/hangul-service.js +52 -54
  58. package/dist/cores/elastic/hangul-service.js.map +1 -1
  59. package/dist/cores/lambda/index.js +42 -36
  60. package/dist/cores/lambda/index.js.map +1 -1
  61. package/dist/cores/lambda/lambda-alb-handler.d.ts +2 -2
  62. package/dist/cores/lambda/lambda-alb-handler.js +59 -72
  63. package/dist/cores/lambda/lambda-alb-handler.js.map +1 -1
  64. package/dist/cores/lambda/lambda-cognito-handler.js +10 -19
  65. package/dist/cores/lambda/lambda-cognito-handler.js.map +1 -1
  66. package/dist/cores/lambda/lambda-cron-handler.d.ts +1 -1
  67. package/dist/cores/lambda/lambda-cron-handler.js +14 -23
  68. package/dist/cores/lambda/lambda-cron-handler.js.map +1 -1
  69. package/dist/cores/lambda/lambda-dynamo-stream-handler.d.ts +2 -2
  70. package/dist/cores/lambda/lambda-dynamo-stream-handler.js +57 -67
  71. package/dist/cores/lambda/lambda-dynamo-stream-handler.js.map +1 -1
  72. package/dist/cores/lambda/lambda-handler.d.ts +22 -22
  73. package/dist/cores/lambda/lambda-handler.js +93 -106
  74. package/dist/cores/lambda/lambda-handler.js.map +1 -1
  75. package/dist/cores/lambda/lambda-notification-handler.d.ts +1 -1
  76. package/dist/cores/lambda/lambda-notification-handler.js +39 -50
  77. package/dist/cores/lambda/lambda-notification-handler.js.map +1 -1
  78. package/dist/cores/lambda/lambda-sns-handler.js +79 -88
  79. package/dist/cores/lambda/lambda-sns-handler.js.map +1 -1
  80. package/dist/cores/lambda/lambda-sqs-handler.js +79 -88
  81. package/dist/cores/lambda/lambda-sqs-handler.js.map +1 -1
  82. package/dist/cores/lambda/lambda-web-handler.d.ts +6 -6
  83. package/dist/cores/lambda/lambda-web-handler.js +387 -412
  84. package/dist/cores/lambda/lambda-web-handler.js.map +1 -1
  85. package/dist/cores/lambda/lambda-wss-handler.js +23 -32
  86. package/dist/cores/lambda/lambda-wss-handler.js.map +1 -1
  87. package/dist/cores/protocol/index.js +10 -20
  88. package/dist/cores/protocol/index.js.map +1 -1
  89. package/dist/cores/protocol/protocol-service.d.ts +3 -3
  90. package/dist/cores/protocol/protocol-service.js +235 -227
  91. package/dist/cores/protocol/protocol-service.js.map +1 -1
  92. package/dist/cores/storage/http-storage-service.js +65 -85
  93. package/dist/cores/storage/http-storage-service.js.map +1 -1
  94. package/dist/cores/storage/model-manager.js +66 -85
  95. package/dist/cores/storage/model-manager.js.map +1 -1
  96. package/dist/cores/storage/proxy-storage-service.d.ts +2 -2
  97. package/dist/cores/storage/proxy-storage-service.js +562 -599
  98. package/dist/cores/storage/proxy-storage-service.js.map +1 -1
  99. package/dist/cores/storage/redis-storage-service.js +163 -177
  100. package/dist/cores/storage/redis-storage-service.js.map +1 -1
  101. package/dist/cores/storage/storage-service.js +281 -322
  102. package/dist/cores/storage/storage-service.js.map +1 -1
  103. package/dist/engine/builder.d.ts +1 -1
  104. package/dist/engine/builder.js +59 -63
  105. package/dist/engine/builder.js.map +1 -1
  106. package/dist/engine/engine.d.ts +4 -4
  107. package/dist/engine/engine.js +9 -18
  108. package/dist/engine/engine.js.map +1 -1
  109. package/dist/engine/types.d.ts +1 -1
  110. package/dist/engine/utilities.d.ts +5 -5
  111. package/dist/engine/utilities.js +301 -293
  112. package/dist/engine/utilities.js.map +1 -1
  113. package/dist/environ.js +4 -6
  114. package/dist/environ.js.map +1 -1
  115. package/dist/extended/abstract-service.js +595 -645
  116. package/dist/extended/abstract-service.js.map +1 -1
  117. package/dist/extended/libs/sig-v4.js.map +1 -1
  118. package/dist/generated/field-registry.d.ts +10 -0
  119. package/dist/generated/field-registry.js +17 -0
  120. package/dist/generated/field-registry.js.map +1 -0
  121. package/dist/helpers/helpers.d.ts +17 -9
  122. package/dist/helpers/helpers.js +88 -78
  123. package/dist/helpers/helpers.js.map +1 -1
  124. package/dist/index.js +17 -7
  125. package/dist/index.js.map +1 -1
  126. package/dist/lib/dynamodb-value.js +2 -3
  127. package/dist/lib/dynamodb-value.js.map +1 -1
  128. package/dist/tools/express.js +4 -5
  129. package/dist/tools/express.js.map +1 -1
  130. package/dist/tools/tools.d.ts +3 -1
  131. package/dist/tools/tools.js +14 -21
  132. package/dist/tools/tools.js.map +1 -1
  133. package/package.json +19 -18
  134. package/dist/exec-cli.d.ts +0 -2
  135. package/dist/exec-cli.js +0 -211
  136. package/dist/exec-cli.js.map +0 -1
  137. package/dist/lib/dynamo/expressions.d.ts +0 -14
  138. package/dist/lib/dynamo/expressions.js +0 -212
  139. package/dist/lib/dynamo/expressions.js.map +0 -1
  140. package/dist/lib/dynamo/query.d.ts +0 -43
  141. package/dist/lib/dynamo/query.js +0 -246
  142. package/dist/lib/dynamo/query.js.map +0 -1
  143. package/dist/lib/dynamo/scan.d.ts +0 -33
  144. package/dist/lib/dynamo/scan.js +0 -172
  145. package/dist/lib/dynamo/scan.js.map +0 -1
  146. package/dist/lib/dynamo/serializer.d.ts +0 -12
  147. package/dist/lib/dynamo/serializer.js +0 -243
  148. package/dist/lib/dynamo/serializer.js.map +0 -1
  149. package/dist/lib/dynamo/utils.d.ts +0 -15
  150. package/dist/lib/dynamo/utils.js +0 -129
  151. package/dist/lib/dynamo/utils.js.map +0 -1
  152. package/dist/tools/shared.d.ts +0 -28
  153. package/dist/tools/shared.js +0 -143
  154. package/dist/tools/shared.js.map +0 -1
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
@@ -34,260 +25,12 @@ const NS = engine_1.$U.NS('ES6Q', 'green'); // NAMESPACE TO BE PRINTED.
34
25
  * - support simple query like range search.
35
26
  */
36
27
  class Elastic6QueryService {
28
+ service;
37
29
  /**
38
30
  * use query w/ the given search-service.
39
31
  * @param service the origin search-service to use.
40
32
  */
41
33
  constructor(service) {
42
- /**
43
- * say hello of identity.
44
- */
45
- this.hello = () => `elastic6-query-service:${this.options.indexName}`;
46
- /**
47
- * build query parameter from search param.
48
- */
49
- this.buildQueryBody = (param) => {
50
- //* parameters.
51
- let $query = null;
52
- let $source = null;
53
- let $page = -1;
54
- let $limit = -1;
55
- let $A = ''; // Aggregation
56
- let $O = ''; // OrderBy
57
- let $H = ''; // Highlight
58
- //* build query.
59
- const queries = Object.keys(param).reduce((list, key) => {
60
- let val = param[key];
61
- // ignore internal values.
62
- if (key.startsWith('_'))
63
- return list;
64
- // _log(NS, `>> param[${key}] = `, val);
65
- if (key === '$query') {
66
- $query = {
67
- query: typeof val === 'object' ? val : typeof val === 'string' ? JSON.parse(val) : `${val || ''}`,
68
- };
69
- }
70
- else if (key === '$limit') {
71
- $limit = engine_1.$U.N(val, 0);
72
- }
73
- else if (key === '$page') {
74
- $page = engine_1.$U.N(val, 0);
75
- }
76
- else if (key === '$Q') {
77
- if (!val) {
78
- //NOP;
79
- }
80
- else if (typeof val === 'object') {
81
- // ONLY IF object. use it as raw query.
82
- $query = val;
83
- }
84
- else if (typeof val === 'string' && val.startsWith('{') && val.endsWith('}')) {
85
- // might be the json data.
86
- $query = JSON.parse(val);
87
- }
88
- else if (typeof val === 'string') {
89
- // might be query string.
90
- //* escape queries..
91
- // + - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /
92
- // val = val.replace(/([\(\)])/ig,'\\$1'); //TODO - 이걸 무시하면, 중복 조건 검색에 문제가 생김, 하여 일단 안하는걸루. @180828.
93
- list.push(`(${val})`);
94
- }
95
- }
96
- else if (key === '$A') {
97
- $A = `${val}`.trim(); // ',' delimited terms to count
98
- }
99
- else if (key === '$O') {
100
- $O = `${val}`.trim(); // ',' delimited terms to order
101
- }
102
- else if (key === '$H') {
103
- $H = `${val}`.trim(); // ',' delimited terms to highlight
104
- }
105
- else if (key === '$source') {
106
- // returned source fields set. '*', 'obj.*', '!abc'
107
- if (val === '*') {
108
- // all.
109
- $source = '*';
110
- }
111
- else if (typeof val === 'string' && val.indexOf !== undefined) {
112
- // string array set.
113
- const vals = val.split(',') || [];
114
- const $includes = [];
115
- const $excludes = [];
116
- vals.forEach(val => {
117
- val = `${val || ''}`.trim();
118
- if (!val)
119
- return;
120
- if (val.startsWith('!')) {
121
- $excludes.push(val.substr(1));
122
- }
123
- else {
124
- $includes.push(val);
125
- }
126
- });
127
- $source = { includes: $includes, excludes: $excludes };
128
- }
129
- else {
130
- $source = val;
131
- }
132
- }
133
- else if (key === '$exist' || key === '$exists') {
134
- (Array.isArray(val) ? val : `${val}`.split(',') || []).forEach((val) => {
135
- val = `${val || ''}`.trim();
136
- if (!val)
137
- return;
138
- if (val.startsWith('!')) {
139
- list.push('NOT _exists_:' + val.substr(1));
140
- }
141
- else {
142
- list.push('_exists_:' + val);
143
- }
144
- });
145
- }
146
- else {
147
- //* escape if there is ' ' except like '(a AND B)'
148
- const escape_val = (val) => {
149
- if (typeof val === 'string' && val === '') {
150
- return '"' + val + '"';
151
- }
152
- else if (val && typeof val === 'string') {
153
- if (val.startsWith('(') && val.endsWith(')')) {
154
- // nop
155
- }
156
- else if (val.startsWith('"') && val.endsWith('"')) {
157
- // must be string block
158
- return val;
159
- }
160
- else if (val.indexOf(',') > 0) {
161
- // list of array.
162
- return val.split(',').map(s => {
163
- return (s || '').trim();
164
- });
165
- }
166
- else if (
167
- // special chars
168
- val.indexOf(' ') >= 0 ||
169
- val.indexOf('\n') >= 0 ||
170
- val.indexOf(':') >= 0 ||
171
- val.indexOf('\\') >= 0 ||
172
- val.indexOf('#') >= 0 ||
173
- val.indexOf('^') >= 0) {
174
- const str = val.replace(/([\"\'])/gi, '\\$1'); // replace '"' -> '\"'
175
- return '"' + str + '"';
176
- }
177
- }
178
- return val;
179
- };
180
- val = escape_val(val);
181
- //* add to query-list.
182
- if (key.startsWith('!')) {
183
- if (val) {
184
- if (Array.isArray(val)) {
185
- const vals = val.map((_) => escape_val(_));
186
- list.push(key.substr(1) + ':(NOT (' + vals.join(' OR ') + '))');
187
- }
188
- else {
189
- list.push(key.substr(1) + ':(NOT ' + val + ')');
190
- }
191
- }
192
- else {
193
- list.push('_exists_:' + key.substr(1));
194
- }
195
- }
196
- else if (key.startsWith('#')) {
197
- // projection.
198
- $source = $source || { includes: [], excludes: [] };
199
- if ($source && $source.includes) {
200
- $source.includes.push(key.substr(1));
201
- }
202
- }
203
- else if (val === undefined) {
204
- //* nop
205
- }
206
- else if (val && Array.isArray(val)) {
207
- // list.push('(' + val.map(val => `${key}:${val}`).join(' OR ') + ')');
208
- list.push(`${key}:` + '(' + val.map((val) => `${escape_val(val)}`).join(' OR ') + ')');
209
- }
210
- else {
211
- list.push(`${key}:${val}`);
212
- }
213
- }
214
- return list;
215
- }, []);
216
- //* prepare returned body.
217
- const $body = $query
218
- ? $query
219
- : (queries.length && { query: { query_string: { query: queries.join(' AND ') } } }) || {}; // $query 이게 있으면 그냥 이걸 이용.
220
- //* Aggregation.
221
- if ($A) {
222
- // const $aggs = {
223
- // // "types_count" : { "value_count" : { "field" : "brand" } }
224
- // "types_count" : { "terms" : { "field" : "brand" } }
225
- // }
226
- const $aggs = $A.split(',').reduce(($a, val) => {
227
- val = ('' + val).trim();
228
- if (val) {
229
- if (val.indexOf(':') > 0) {
230
- // must be size.
231
- const [nm, size] = val.split(':', 2);
232
- $a[nm] = { terms: { field: nm, size: parseInt(size) } };
233
- }
234
- else {
235
- $a[val] = { terms: { field: val } };
236
- }
237
- }
238
- return $a;
239
- }, {});
240
- $body['aggs'] = $aggs;
241
- }
242
- //* OrderBy.
243
- if ($O) {
244
- //see sorting: see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html.
245
- const $sort = $O.split(',').reduce(($a, val) => {
246
- val = ('' + val).trim();
247
- if (val) {
248
- let name = val;
249
- let asc = true;
250
- if (val.startsWith('!')) {
251
- // reverse
252
- name = val.slice(1);
253
- asc = false;
254
- }
255
- if (name) {
256
- $a.push({ [name]: { order: asc ? 'asc' : 'desc' } });
257
- }
258
- }
259
- return $a;
260
- }, []);
261
- if ($sort.length) {
262
- $body.sort = $sort;
263
- }
264
- }
265
- //* Highlight.
266
- if ($H) {
267
- const $highlight = $H.split(',').reduce(($h, val) => {
268
- val = ('' + val).trim();
269
- if (val) {
270
- $h[val] = { type: 'unified' };
271
- }
272
- return $h;
273
- }, {});
274
- $body['highlight'] = {};
275
- $body['highlight']['fields'] = $highlight;
276
- }
277
- //* if valid limit, then paginating.
278
- if ($limit > -1) {
279
- $body.size = $limit;
280
- if ($page > -1) {
281
- // starts from 0
282
- $body.from = $page * $limit;
283
- }
284
- }
285
- //* field projection with _source parameter.
286
- if ($source !== null)
287
- $body._source = $source;
288
- //* returns body.
289
- return $body;
290
- };
291
34
  const options = service.options;
292
35
  if (!options.indexName)
293
36
  throw new Error('.indexName is required');
@@ -299,6 +42,10 @@ class Elastic6QueryService {
299
42
  get options() {
300
43
  return this.service.options;
301
44
  }
45
+ /**
46
+ * say hello of identity.
47
+ */
48
+ hello = () => `elastic6-query-service:${this.options.indexName}`;
302
49
  /**
303
50
  * query all by id.
304
51
  *
@@ -306,18 +53,16 @@ class Elastic6QueryService {
306
53
  * @param limit
307
54
  * @param isDesc
308
55
  */
309
- queryAll(id, limit, isDesc) {
310
- return __awaiter(this, void 0, void 0, function* () {
311
- const { idName } = this.options;
312
- const param = {
313
- [idName]: id,
314
- };
315
- if (limit !== undefined)
316
- param['$limit'] = limit;
317
- if (isDesc !== undefined)
318
- param['$O'] = (isDesc ? '!' : '') + id;
319
- return this.searchSimple(param);
320
- });
56
+ async queryAll(id, limit, isDesc) {
57
+ const { idName } = this.options;
58
+ const param = {
59
+ [idName]: id,
60
+ };
61
+ if (limit !== undefined)
62
+ param['$limit'] = limit;
63
+ if (isDesc !== undefined)
64
+ param['$O'] = (isDesc ? '!' : '') + id;
65
+ return this.searchSimple(param);
321
66
  }
322
67
  /**
323
68
  * search in simple mode
@@ -352,20 +97,18 @@ class Elastic6QueryService {
352
97
  *
353
98
  * @param param search param
354
99
  */
355
- searchSimple(param) {
356
- return __awaiter(this, void 0, void 0, function* () {
357
- if (!param)
358
- throw new Error('@param (SimpleSearchParam) is required');
359
- const { indexName } = this.options;
360
- (0, engine_1._log)(NS, `- searchSimple(${indexName})....`);
361
- (0, engine_1._log)(NS, `> param =`, engine_1.$U.json(param));
362
- //* build query body.
363
- const body = this.buildQueryBody(param);
364
- //* search via client
365
- const res = yield this.search(body);
366
- //* convert to query-result.
367
- return this.asQueryResult(body, res);
368
- });
100
+ async searchSimple(param) {
101
+ if (!param)
102
+ throw new Error('@param (SimpleSearchParam) is required');
103
+ const { indexName } = this.options;
104
+ (0, engine_1._log)(NS, `- searchSimple(${indexName})....`);
105
+ (0, engine_1._log)(NS, `> param =`, engine_1.$U.json(param));
106
+ //* build query body.
107
+ const body = this.buildQueryBody(param);
108
+ //* search via client
109
+ const res = await this.search(body);
110
+ //* convert to query-result.
111
+ return this.asQueryResult(body, res);
369
112
  }
370
113
  /**
371
114
  * search with raw query language.
@@ -373,12 +116,10 @@ class Elastic6QueryService {
373
116
  * @param body SearchBody.
374
117
  * @returns results.
375
118
  */
376
- search(body, searchType) {
377
- return __awaiter(this, void 0, void 0, function* () {
378
- if (!body)
379
- throw new Error('@body (SearchBody) is required');
380
- return this.service.searchRaw(body, searchType);
381
- });
119
+ async search(body, searchType) {
120
+ if (!body)
121
+ throw new Error('@body (SearchBody) is required');
122
+ return this.service.searchRaw(body, searchType);
382
123
  }
383
124
  /**
384
125
  * convert result as `QueryResult`
@@ -387,14 +128,13 @@ class Elastic6QueryService {
387
128
  * @returns QueryResult
388
129
  */
389
130
  asQueryResult(body, res) {
390
- var _a, _b, _c;
391
- const size = engine_1.$U.N(body === null || body === void 0 ? void 0 : body.size, 10);
131
+ const size = engine_1.$U.N(body?.size, 10);
392
132
  //* extract for result.
393
- const hits = res === null || res === void 0 ? void 0 : res.hits;
133
+ const hits = res?.hits;
394
134
  if (typeof hits !== 'object')
395
135
  throw new Error(`.hits (object) is required - hists:${engine_1.$U.json(hits)}`);
396
- const total = engine_1.$U.N(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, 0); // since v7.x
397
- const last = (hits === null || hits === void 0 ? void 0 : hits.hits.length) === size ? (_c = hits.hits[size - 1]) === null || _c === void 0 ? void 0 : _c.sort : undefined;
136
+ const total = engine_1.$U.N(typeof hits.total?.value === 'number' ? hits.total?.value : hits.total, 0); // since v7.x
137
+ const last = hits?.hits.length === size ? hits.hits[size - 1]?.sort : undefined;
398
138
  const list = ((hits && hits.hits) || []).map((N) => {
399
139
  const id = N && N._id; // id of elastic-search
400
140
  const score = N && N._score; // search score.
@@ -408,7 +148,7 @@ class Elastic6QueryService {
408
148
  return source;
409
149
  });
410
150
  const result = { list, total, last };
411
- if (res === null || res === void 0 ? void 0 : res.aggregations) {
151
+ if (res?.aggregations) {
412
152
  const $aggregations = res.aggregations || {};
413
153
  result.aggregations = Object.keys($aggregations).reduce((aggrs, field) => {
414
154
  const { doc_count_error_upper_bound: docCountError = 0, sum_other_doc_count: docSkippedCount = 0, buckets, } = res.aggregations[field];
@@ -472,39 +212,282 @@ class Elastic6QueryService {
472
212
  * search item in Search-as-You-Type way
473
213
  * @param param AutocompleteSearchParam
474
214
  */
475
- searchAutocomplete(param) {
476
- return __awaiter(this, void 0, void 0, function* () {
477
- const { field, query, body } = this.asSearchBody(param);
478
- const res = yield this.service.searchRaw(body);
479
- const result = this.asQueryResult(body, res);
480
- // highlighting result manually
481
- let list = result.list;
482
- if (param.$highlight) {
483
- // prepare tag name to wrap highlighted text
484
- const tagName = typeof param.$highlight == 'string' ? param.$highlight : 'em';
485
- // create a regular expression which has optional whitespaces between each character
486
- // e.g. 'COVID-19' => /C *O *V *I *D *- *1 *9/i
487
- const regexp = new RegExp([...query.replace(/\s/g, '')].join(' *'), 'i');
488
- // try to match regular expression with items found
489
- list = result.list.map((item) => {
490
- const target = `${item[field] || ''}`;
491
- const match = target.match(regexp);
492
- if (match) {
493
- item._highlight =
494
- target.slice(0, match.index) +
495
- `<${tagName}>${match[0]}</${tagName}>` +
496
- target.slice(match.index + match[0].length);
215
+ async searchAutocomplete(param) {
216
+ const { field, query, body } = this.asSearchBody(param);
217
+ const res = await this.service.searchRaw(body);
218
+ const result = this.asQueryResult(body, res);
219
+ // highlighting result manually
220
+ let list = result.list;
221
+ if (param.$highlight) {
222
+ // prepare tag name to wrap highlighted text
223
+ const tagName = typeof param.$highlight == 'string' ? param.$highlight : 'em';
224
+ // create a regular expression which has optional whitespaces between each character
225
+ // e.g. 'COVID-19' => /C *O *V *I *D *- *1 *9/i
226
+ const regexp = new RegExp([...query.replace(/\s/g, '')].join(' *'), 'i');
227
+ // try to match regular expression with items found
228
+ list = result.list.map((item) => {
229
+ const target = `${item[field] || ''}`;
230
+ const match = target.match(regexp);
231
+ if (match) {
232
+ item._highlight =
233
+ target.slice(0, match.index) +
234
+ `<${tagName}>${match[0]}</${tagName}>` +
235
+ target.slice(match.index + match[0].length);
236
+ }
237
+ else {
238
+ item._highlight = target;
239
+ }
240
+ return item;
241
+ });
242
+ }
243
+ //* finally, override list.
244
+ return { ...result, list };
245
+ }
246
+ /**
247
+ * build query parameter from search param.
248
+ */
249
+ buildQueryBody = (param) => {
250
+ //* parameters.
251
+ let $query = null;
252
+ let $source = null;
253
+ let $page = -1;
254
+ let $limit = -1;
255
+ let $A = ''; // Aggregation
256
+ let $O = ''; // OrderBy
257
+ let $H = ''; // Highlight
258
+ //* build query.
259
+ const queries = Object.keys(param).reduce((list, key) => {
260
+ let val = param[key];
261
+ // ignore internal values.
262
+ if (key.startsWith('_'))
263
+ return list;
264
+ // _log(NS, `>> param[${key}] = `, val);
265
+ if (key === '$query') {
266
+ $query = {
267
+ query: typeof val === 'object' ? val : typeof val === 'string' ? JSON.parse(val) : `${val || ''}`,
268
+ };
269
+ }
270
+ else if (key === '$limit') {
271
+ $limit = engine_1.$U.N(val, 0);
272
+ }
273
+ else if (key === '$page') {
274
+ $page = engine_1.$U.N(val, 0);
275
+ }
276
+ else if (key === '$Q') {
277
+ if (!val) {
278
+ //NOP;
279
+ }
280
+ else if (typeof val === 'object') {
281
+ // ONLY IF object. use it as raw query.
282
+ $query = val;
283
+ }
284
+ else if (typeof val === 'string' && val.startsWith('{') && val.endsWith('}')) {
285
+ // might be the json data.
286
+ $query = JSON.parse(val);
287
+ }
288
+ else if (typeof val === 'string') {
289
+ // might be query string.
290
+ //* escape queries..
291
+ // + - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /
292
+ // val = val.replace(/([\(\)])/ig,'\\$1'); //TODO - 이걸 무시하면, 중복 조건 검색에 문제가 생김, 하여 일단 안하는걸루. @180828.
293
+ list.push(`(${val})`);
294
+ }
295
+ }
296
+ else if (key === '$A') {
297
+ $A = `${val}`.trim(); // ',' delimited terms to count
298
+ }
299
+ else if (key === '$O') {
300
+ $O = `${val}`.trim(); // ',' delimited terms to order
301
+ }
302
+ else if (key === '$H') {
303
+ $H = `${val}`.trim(); // ',' delimited terms to highlight
304
+ }
305
+ else if (key === '$source') {
306
+ // returned source fields set. '*', 'obj.*', '!abc'
307
+ if (val === '*') {
308
+ // all.
309
+ $source = '*';
310
+ }
311
+ else if (typeof val === 'string' && val.indexOf !== undefined) {
312
+ // string array set.
313
+ const vals = val.split(',') || [];
314
+ const $includes = [];
315
+ const $excludes = [];
316
+ vals.forEach(val => {
317
+ val = `${val || ''}`.trim();
318
+ if (!val)
319
+ return;
320
+ if (val.startsWith('!')) {
321
+ $excludes.push(val.substr(1));
322
+ }
323
+ else {
324
+ $includes.push(val);
325
+ }
326
+ });
327
+ $source = { includes: $includes, excludes: $excludes };
328
+ }
329
+ else {
330
+ $source = val;
331
+ }
332
+ }
333
+ else if (key === '$exist' || key === '$exists') {
334
+ (Array.isArray(val) ? val : `${val}`.split(',') || []).forEach((val) => {
335
+ val = `${val || ''}`.trim();
336
+ if (!val)
337
+ return;
338
+ if (val.startsWith('!')) {
339
+ list.push('NOT _exists_:' + val.substr(1));
497
340
  }
498
341
  else {
499
- item._highlight = target;
342
+ list.push('_exists_:' + val);
500
343
  }
501
- return item;
502
344
  });
503
345
  }
504
- //* finally, override list.
505
- return Object.assign(Object.assign({}, result), { list });
506
- });
507
- }
346
+ else {
347
+ //* escape if there is ' ' except like '(a AND B)'
348
+ const escape_val = (val) => {
349
+ if (typeof val === 'string' && val === '') {
350
+ return '"' + val + '"';
351
+ }
352
+ else if (val && typeof val === 'string') {
353
+ if (val.startsWith('(') && val.endsWith(')')) {
354
+ // nop
355
+ }
356
+ else if (val.startsWith('"') && val.endsWith('"')) {
357
+ // must be string block
358
+ return val;
359
+ }
360
+ else if (val.indexOf(',') > 0) {
361
+ // list of array.
362
+ return val.split(',').map(s => {
363
+ return (s || '').trim();
364
+ });
365
+ }
366
+ else if (
367
+ // special chars
368
+ val.indexOf(' ') >= 0 ||
369
+ val.indexOf('\n') >= 0 ||
370
+ val.indexOf(':') >= 0 ||
371
+ val.indexOf('\\') >= 0 ||
372
+ val.indexOf('#') >= 0 ||
373
+ val.indexOf('^') >= 0) {
374
+ const str = val.replace(/([\"\'])/gi, '\\$1'); // replace '"' -> '\"'
375
+ return '"' + str + '"';
376
+ }
377
+ }
378
+ return val;
379
+ };
380
+ val = escape_val(val);
381
+ //* add to query-list.
382
+ if (key.startsWith('!')) {
383
+ if (val) {
384
+ if (Array.isArray(val)) {
385
+ const vals = val.map((_) => escape_val(_));
386
+ list.push(key.substr(1) + ':(NOT (' + vals.join(' OR ') + '))');
387
+ }
388
+ else {
389
+ list.push(key.substr(1) + ':(NOT ' + val + ')');
390
+ }
391
+ }
392
+ else {
393
+ list.push('_exists_:' + key.substr(1));
394
+ }
395
+ }
396
+ else if (key.startsWith('#')) {
397
+ // projection.
398
+ $source = $source || { includes: [], excludes: [] };
399
+ if ($source && $source.includes) {
400
+ $source.includes.push(key.substr(1));
401
+ }
402
+ }
403
+ else if (val === undefined) {
404
+ //* nop
405
+ }
406
+ else if (val && Array.isArray(val)) {
407
+ // list.push('(' + val.map(val => `${key}:${val}`).join(' OR ') + ')');
408
+ list.push(`${key}:` + '(' + val.map((val) => `${escape_val(val)}`).join(' OR ') + ')');
409
+ }
410
+ else {
411
+ list.push(`${key}:${val}`);
412
+ }
413
+ }
414
+ return list;
415
+ }, []);
416
+ //* prepare returned body.
417
+ const $body = $query
418
+ ? $query
419
+ : (queries.length && { query: { query_string: { query: queries.join(' AND ') } } }) || {}; // $query 이게 있으면 그냥 이걸 이용.
420
+ //* Aggregation.
421
+ if ($A) {
422
+ // const $aggs = {
423
+ // // "types_count" : { "value_count" : { "field" : "brand" } }
424
+ // "types_count" : { "terms" : { "field" : "brand" } }
425
+ // }
426
+ const $aggs = $A.split(',').reduce(($a, val) => {
427
+ val = ('' + val).trim();
428
+ if (val) {
429
+ if (val.indexOf(':') > 0) {
430
+ // must be size.
431
+ const [nm, size] = val.split(':', 2);
432
+ $a[nm] = { terms: { field: nm, size: parseInt(size) } };
433
+ }
434
+ else {
435
+ $a[val] = { terms: { field: val } };
436
+ }
437
+ }
438
+ return $a;
439
+ }, {});
440
+ $body['aggs'] = $aggs;
441
+ }
442
+ //* OrderBy.
443
+ if ($O) {
444
+ //see sorting: see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html.
445
+ const $sort = $O.split(',').reduce(($a, val) => {
446
+ val = ('' + val).trim();
447
+ if (val) {
448
+ let name = val;
449
+ let asc = true;
450
+ if (val.startsWith('!')) {
451
+ // reverse
452
+ name = val.slice(1);
453
+ asc = false;
454
+ }
455
+ if (name) {
456
+ $a.push({ [name]: { order: asc ? 'asc' : 'desc' } });
457
+ }
458
+ }
459
+ return $a;
460
+ }, []);
461
+ if ($sort.length) {
462
+ $body.sort = $sort;
463
+ }
464
+ }
465
+ //* Highlight.
466
+ if ($H) {
467
+ const $highlight = $H.split(',').reduce(($h, val) => {
468
+ val = ('' + val).trim();
469
+ if (val) {
470
+ $h[val] = { type: 'unified' };
471
+ }
472
+ return $h;
473
+ }, {});
474
+ $body['highlight'] = {};
475
+ $body['highlight']['fields'] = $highlight;
476
+ }
477
+ //* if valid limit, then paginating.
478
+ if ($limit > -1) {
479
+ $body.size = $limit;
480
+ if ($page > -1) {
481
+ // starts from 0
482
+ $body.from = $page * $limit;
483
+ }
484
+ }
485
+ //* field projection with _source parameter.
486
+ if ($source !== null)
487
+ $body._source = $source;
488
+ //* returns body.
489
+ return $body;
490
+ };
508
491
  }
509
492
  exports.Elastic6QueryService = Elastic6QueryService;
510
493
  //# sourceMappingURL=elastic6-query-service.js.map