lemon-core 4.2.7 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -2
- package/dist/common/lemon-error.d.ts +34 -0
- package/dist/common/lemon-error.js +52 -0
- package/dist/common/lemon-error.js.map +1 -0
- package/dist/controllers/general-api-controller.d.ts +7 -0
- package/dist/controllers/general-api-controller.js +7 -0
- package/dist/controllers/general-api-controller.js.map +1 -1
- package/dist/cores/api/api-service.js +10 -43
- package/dist/cores/api/api-service.js.map +1 -1
- package/dist/cores/aws/aws-kms-service.d.ts +13 -5
- package/dist/cores/aws/aws-kms-service.js +23 -9
- package/dist/cores/aws/aws-kms-service.js.map +1 -1
- package/dist/cores/aws/aws-s3-service.d.ts +30 -4
- package/dist/cores/aws/aws-s3-service.js +35 -15
- package/dist/cores/aws/aws-s3-service.js.map +1 -1
- package/dist/cores/aws/aws-sns-service.js +59 -9
- package/dist/cores/aws/aws-sns-service.js.map +1 -1
- package/dist/cores/aws/aws-sqs-service.d.ts +1 -1
- package/dist/cores/aws/aws-sqs-service.js +54 -12
- package/dist/cores/aws/aws-sqs-service.js.map +1 -1
- package/dist/cores/cache/cache-service.d.ts +10 -9
- package/dist/cores/cache/cache-service.js +9 -346
- package/dist/cores/cache/cache-service.js.map +1 -1
- package/dist/cores/config/config-service.d.ts +3 -15
- package/dist/cores/config/config-service.js +5 -34
- package/dist/cores/config/config-service.js.map +1 -1
- package/dist/cores/dynamo/dynamo-query-service.js +42 -2
- package/dist/cores/dynamo/dynamo-query-service.js.map +1 -1
- package/dist/cores/dynamo/dynamo-scan-service.js +42 -2
- package/dist/cores/dynamo/dynamo-scan-service.js.map +1 -1
- package/dist/cores/dynamo/dynamo-service.d.ts +45 -14
- package/dist/cores/dynamo/dynamo-service.js +48 -21
- package/dist/cores/dynamo/dynamo-service.js.map +1 -1
- package/dist/cores/dynamo/tools/expressions.js +32 -22
- package/dist/cores/dynamo/tools/expressions.js.map +1 -1
- package/dist/cores/dynamo/tools/lang.d.ts +30 -0
- package/dist/cores/dynamo/tools/lang.js +75 -0
- package/dist/cores/dynamo/tools/lang.js.map +1 -0
- package/dist/cores/dynamo/tools/query.js +20 -21
- package/dist/cores/dynamo/tools/query.js.map +1 -1
- package/dist/cores/dynamo/tools/scan.js +15 -16
- package/dist/cores/dynamo/tools/scan.js.map +1 -1
- package/dist/cores/dynamo/tools/serializer.js +40 -38
- package/dist/cores/dynamo/tools/serializer.js.map +1 -1
- package/dist/cores/dynamo/tools/utils.d.ts +6 -2
- package/dist/cores/dynamo/tools/utils.js +11 -8
- package/dist/cores/dynamo/tools/utils.js.map +1 -1
- package/dist/cores/elastic/elastic6-query-service.d.ts +1 -104
- package/dist/cores/elastic/elastic6-query-service.js +15 -489
- package/dist/cores/elastic/elastic6-query-service.js.map +1 -1
- package/dist/cores/elastic/elastic6-service.d.ts +1 -482
- package/dist/cores/elastic/elastic6-service.js +15 -1153
- package/dist/cores/elastic/elastic6-service.js.map +1 -1
- package/dist/cores/elastic/index.d.ts +2 -2
- package/dist/cores/elastic/index.js +3 -2
- package/dist/cores/elastic/index.js.map +1 -1
- package/dist/cores/elastic/os2-query-service.d.ts +104 -0
- package/dist/cores/elastic/os2-query-service.js +495 -0
- package/dist/cores/elastic/os2-query-service.js.map +1 -0
- package/dist/cores/elastic/os2-service.d.ts +372 -0
- package/dist/cores/elastic/os2-service.js +943 -0
- package/dist/cores/elastic/os2-service.js.map +1 -0
- package/dist/cores/index.d.ts +6 -1
- package/dist/cores/index.js +9 -2
- package/dist/cores/index.js.map +1 -1
- package/dist/cores/lambda/index.js +2 -1
- package/dist/cores/lambda/index.js.map +1 -1
- package/dist/cores/lambda/lambda-cron-handler.d.ts +1 -0
- package/dist/cores/lambda/lambda-cron-handler.js +5 -1
- package/dist/cores/lambda/lambda-cron-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-dynamo-stream-handler.d.ts +5 -4
- package/dist/cores/lambda/lambda-dynamo-stream-handler.js +18 -5
- package/dist/cores/lambda/lambda-dynamo-stream-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-handler.d.ts +22 -2
- package/dist/cores/lambda/lambda-handler.js +85 -23
- package/dist/cores/lambda/lambda-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-sns-handler.d.ts +1 -0
- package/dist/cores/lambda/lambda-sns-handler.js +5 -0
- package/dist/cores/lambda/lambda-sns-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-sqs-handler.d.ts +1 -0
- package/dist/cores/lambda/lambda-sqs-handler.js +20 -5
- package/dist/cores/lambda/lambda-sqs-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-web-handler.d.ts +10 -0
- package/dist/cores/lambda/lambda-web-handler.js +107 -41
- package/dist/cores/lambda/lambda-web-handler.js.map +1 -1
- package/dist/cores/protocol/aws-lambda-helper.js +58 -11
- package/dist/cores/protocol/aws-lambda-helper.js.map +1 -1
- package/dist/cores/protocol/index.js +3 -0
- package/dist/cores/protocol/index.js.map +1 -1
- package/dist/cores/protocol/protocol-service.d.ts +26 -5
- package/dist/cores/protocol/protocol-service.js +42 -12
- package/dist/cores/protocol/protocol-service.js.map +1 -1
- package/dist/cores/protocol/protocol-sign.d.ts +72 -0
- package/dist/cores/protocol/protocol-sign.js +194 -0
- package/dist/cores/protocol/protocol-sign.js.map +1 -0
- package/dist/cores/storage/index.d.ts +0 -1
- package/dist/cores/storage/index.js +0 -1
- package/dist/cores/storage/index.js.map +1 -1
- package/dist/cores/storage/model-fields.d.ts +7 -0
- package/dist/cores/storage/model-fields.js +21 -0
- package/dist/cores/storage/model-fields.js.map +1 -0
- package/dist/cores/storage/model-manager.d.ts +3 -2
- package/dist/cores/storage/model-manager.js +7 -3
- package/dist/cores/storage/model-manager.js.map +1 -1
- package/dist/engine/builder.js +20 -2
- package/dist/engine/builder.js.map +1 -1
- package/dist/engine/engine.d.ts +2 -2
- package/dist/engine/engine.js +4 -4
- package/dist/engine/engine.js.map +1 -1
- package/dist/engine/utilities.d.ts +11 -12
- package/dist/engine/utilities.js +30 -82
- package/dist/engine/utilities.js.map +1 -1
- package/dist/environ.d.ts +0 -6
- package/dist/environ.js +1 -12
- package/dist/environ.js.map +1 -1
- package/dist/esm/index.mjs +140 -0
- package/dist/esm/testing.mjs +12 -0
- package/dist/extended/abstract-service.d.ts +48 -139
- package/dist/extended/abstract-service.js +46 -382
- package/dist/extended/abstract-service.js.map +1 -1
- package/dist/extended/cores/abstract-controllers.d.ts +170 -0
- package/dist/extended/cores/abstract-controllers.js +533 -0
- package/dist/extended/cores/abstract-controllers.js.map +1 -0
- package/dist/extended/cores/abstract-rest-apis.d.ts +142 -0
- package/dist/extended/cores/abstract-rest-apis.js +203 -0
- package/dist/extended/cores/abstract-rest-apis.js.map +1 -0
- package/dist/extended/cores/abstract-services.d.ts +771 -0
- package/dist/extended/cores/abstract-services.js +2042 -0
- package/dist/extended/cores/abstract-services.js.map +1 -0
- package/dist/extended/cores/browser-cache.d.ts +2 -0
- package/dist/extended/cores/browser-cache.js +34 -0
- package/dist/extended/cores/browser-cache.js.map +1 -0
- package/dist/extended/cores/commons.d.ts +20 -0
- package/dist/extended/cores/commons.js +31 -0
- package/dist/extended/cores/commons.js.map +1 -0
- package/dist/extended/cores/index.d.ts +15 -0
- package/dist/extended/cores/index.js +32 -0
- package/dist/extended/cores/index.js.map +1 -0
- package/dist/extended/cores/types.d.ts +14 -0
- package/dist/extended/cores/types.js +31 -0
- package/dist/extended/cores/types.js.map +1 -0
- package/dist/helpers/helpers.d.ts +10 -5
- package/dist/helpers/helpers.js +46 -58
- package/dist/helpers/helpers.js.map +1 -1
- package/dist/helpers/types.d.ts +22 -10
- package/dist/index.d.ts +4 -0
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/http-fetch.d.ts +54 -0
- package/dist/lib/http-fetch.js +133 -0
- package/dist/lib/http-fetch.js.map +1 -0
- package/dist/lib/lazy.d.ts +22 -0
- package/dist/lib/lazy.js +54 -0
- package/dist/lib/lazy.js.map +1 -0
- package/dist/lib/perf.d.ts +35 -0
- package/dist/lib/perf.js +52 -0
- package/dist/lib/perf.js.map +1 -0
- package/dist/tools/tools.d.ts +15 -3
- package/dist/tools/tools.js +21 -4
- package/dist/tools/tools.js.map +1 -1
- package/package.json +96 -39
- package/dist/cores/storage/redis-storage-service.d.ts +0 -183
- package/dist/cores/storage/redis-storage-service.js +0 -377
- package/dist/cores/storage/redis-storage-service.js.map +0 -1
- package/dist/generated/field-registry.d.ts +0 -10
- package/dist/generated/field-registry.js +0 -17
- package/dist/generated/field-registry.js.map +0 -1
|
@@ -1,1157 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
4
15
|
};
|
|
5
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* `elastic6-service.ts`
|
|
9
|
-
* - common service for elastic-search v6
|
|
10
|
-
*
|
|
11
|
-
* @author Steve Jung <steve@lemoncloud.io>
|
|
12
|
-
* @date 2019-11-20 initial version via backbone
|
|
13
|
-
* @date 2022-02-21 optimized error handler, and search.
|
|
14
|
-
* @date 2022-02-22 optimized w/ elastic client (elasticsearch-js)
|
|
15
|
-
*
|
|
16
|
-
* @copyright (C) 2019 LemonCloud Co Ltd. - All Rights Reserved.
|
|
17
|
-
*/
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
19
|
-
const engine_1 = require("../../engine/");
|
|
20
|
-
const elasticsearch_1 = __importDefault(require("@elastic/elasticsearch"));
|
|
21
|
-
exports.elasticsearch = elasticsearch_1.default;
|
|
22
|
-
const hangul_service_1 = __importDefault(require("./hangul-service"));
|
|
23
|
-
exports.$hangul = hangul_service_1.default;
|
|
24
|
-
const tools_1 = require("../../tools");
|
|
25
|
-
const test_helper_1 = require("../../common/test-helper");
|
|
26
|
-
const fs_1 = __importDefault(require("fs"));
|
|
27
|
-
const path_1 = __importDefault(require("path"));
|
|
28
|
-
const NS = engine_1.$U.NS('ES6', 'green'); // NAMESPACE TO BE PRINTED.
|
|
29
|
-
/**
|
|
30
|
-
* convert to string.
|
|
31
|
-
*/
|
|
32
|
-
const _S = (v, def = '') => typeof v === 'string' ? v : v === undefined || v === null ? def : typeof v === 'object' ? engine_1.$U.json(v) : `${v}`;
|
|
33
|
-
/** ****************************************************************************************************************
|
|
34
|
-
* Elastic Index Service
|
|
35
|
-
** ****************************************************************************************************************/
|
|
36
|
-
/**
|
|
37
|
-
* abstarct class: `ElasticIndexService`
|
|
38
|
-
* - abstract class for basic Elasticsearch CRUD operations
|
|
39
|
-
* - common operations that are shared across different versions.
|
|
40
|
-
* TODO - support `Elastic` and `OpenSearch`
|
|
41
|
-
*/
|
|
42
|
-
class ElasticIndexService {
|
|
43
|
-
_options;
|
|
44
|
-
_client;
|
|
45
|
-
/**
|
|
46
|
-
* simple instance maker.
|
|
47
|
-
*
|
|
48
|
-
* ```js
|
|
49
|
-
* const { client } = ElasticIndexService.instance(endpoint);
|
|
50
|
-
* ```
|
|
51
|
-
*
|
|
52
|
-
* @param endpoint service-url
|
|
53
|
-
* @see https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/16.x/configuration.html
|
|
54
|
-
*/
|
|
55
|
-
static instance(endpoint) {
|
|
56
|
-
const client = new elasticsearch_1.default.Client({
|
|
57
|
-
node: endpoint,
|
|
58
|
-
ssl: {
|
|
59
|
-
ca: process.env.elasticsearch_certificate,
|
|
60
|
-
rejectUnauthorized: false,
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
return { client };
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* default constuctor w/ options.
|
|
67
|
-
* @param options { endpoint, indexName } is required.
|
|
68
|
-
*/
|
|
69
|
-
constructor(options) {
|
|
70
|
-
(0, engine_1._inf)(NS, `ElasticIndexService(${options.indexName}/${options.idName})...`);
|
|
71
|
-
if (!options.endpoint)
|
|
72
|
-
throw new Error('.endpoint (URL) is required');
|
|
73
|
-
if (!options.indexName)
|
|
74
|
-
throw new Error('.indexName (string) is required');
|
|
75
|
-
// default option values: docType='_doc', idName='$id'
|
|
76
|
-
const { client } = ElasticIndexService.instance(options.endpoint);
|
|
77
|
-
this._options = { docType: '_doc', idName: '$id', version: '6.8', ...options };
|
|
78
|
-
this._client = client;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* get the client instance.
|
|
82
|
-
*/
|
|
83
|
-
get client() {
|
|
84
|
-
return this._client;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* get the current options.
|
|
88
|
-
*/
|
|
89
|
-
get options() {
|
|
90
|
-
return this._options;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* get the version from options
|
|
94
|
-
*/
|
|
95
|
-
get version() {
|
|
96
|
-
const ver = engine_1.$U.F(this.options.version, 6.8);
|
|
97
|
-
return ver;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
exports.ElasticIndexService = ElasticIndexService;
|
|
101
|
-
/**
|
|
102
|
-
* class: `Elastic6Service`
|
|
103
|
-
* - extends `ElasticIndexService` and adds version-specific implementation
|
|
104
|
-
*/
|
|
105
|
-
class Elastic6Service extends ElasticIndexService {
|
|
106
|
-
// internal field name to store analyzed strings for autocomplete search
|
|
107
|
-
static DECOMPOSED_FIELD = '_decomposed';
|
|
108
|
-
static QWERTY_FIELD = '_qwerty';
|
|
109
|
-
/**
|
|
110
|
-
* default constuctor w/ options.
|
|
111
|
-
* @param options { endpoint, indexName } is required.
|
|
112
|
-
*/
|
|
113
|
-
constructor(options) {
|
|
114
|
-
super(options);
|
|
115
|
-
(0, engine_1._inf)('Elastic6Service', `Elastic6Service(${options.indexName}/${options.idName})...`);
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* say hello of identity.
|
|
119
|
-
*/
|
|
120
|
-
hello = () => `elastic6-service:${this.options.indexName}:${this.options.version}`;
|
|
121
|
-
/**
|
|
122
|
-
* get isOldES6
|
|
123
|
-
* - used when setting doctype
|
|
124
|
-
* - used when verifying mismatched error and results of search
|
|
125
|
-
*/
|
|
126
|
-
get isOldES6() {
|
|
127
|
-
return this.parsedVersion.major < 7 && this.parsedVersion.engine === 'es';
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* get isOldES71
|
|
131
|
-
* - used when verifying mismatched error
|
|
132
|
-
*/
|
|
133
|
-
get isOldES71() {
|
|
134
|
-
return this.parsedVersion.major == 7 && this.parsedVersion.minor == 1 && this.parsedVersion.engine === 'es';
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* get isLatestOS2
|
|
138
|
-
* - used when verifying results of search
|
|
139
|
-
*/
|
|
140
|
-
get isLatestOS2() {
|
|
141
|
-
return this.parsedVersion.major >= 2 && this.parsedVersion.engine === 'os';
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* get the parsedVersion
|
|
145
|
-
*/
|
|
146
|
-
get parsedVersion() {
|
|
147
|
-
return this.parseVersion(this.options.version);
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* get the root version from client
|
|
151
|
-
*
|
|
152
|
-
* @protected only for internal test.
|
|
153
|
-
*/
|
|
154
|
-
async getVersion(options) {
|
|
155
|
-
const isDump = options?.dump ?? false;
|
|
156
|
-
// it consumes about >20ms
|
|
157
|
-
const info = await this.client.info();
|
|
158
|
-
const rootVersion = engine_1.$U.S(info.body.version.number);
|
|
159
|
-
const parsedVersion = this.parseVersion(rootVersion, { throwable: true });
|
|
160
|
-
if (isDump) {
|
|
161
|
-
//* save into `info.json`.
|
|
162
|
-
const description = {
|
|
163
|
-
'!': `${this.parsedVersion?.engine}${this.options.version} client info`,
|
|
164
|
-
...info,
|
|
165
|
-
};
|
|
166
|
-
const filePath = path_1.default.resolve(__dirname, `../../../data/samples/${this.parsedVersion?.engine}${this.options.version}/info.json`);
|
|
167
|
-
await this.saveInfoToFile(description, filePath);
|
|
168
|
-
}
|
|
169
|
-
return parsedVersion;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* check whether the service version matches the version provided in the options.
|
|
173
|
-
*
|
|
174
|
-
* @protected only for internal test.
|
|
175
|
-
*/
|
|
176
|
-
async executeSelfTest() {
|
|
177
|
-
// STEP.1 read the parsed-version.
|
|
178
|
-
const optionVersion = this.parsedVersion;
|
|
179
|
-
// STEP.2 get the real version via `getVersion()`
|
|
180
|
-
const rootVersion = await this.getVersion();
|
|
181
|
-
// STEP.3 validate version
|
|
182
|
-
const isEqual = optionVersion.engine === rootVersion.engine &&
|
|
183
|
-
optionVersion.major === rootVersion.major &&
|
|
184
|
-
optionVersion.minor === rootVersion.minor;
|
|
185
|
-
// Return the comparison result
|
|
186
|
-
return {
|
|
187
|
-
isEqual: isEqual,
|
|
188
|
-
optionVersion: optionVersion,
|
|
189
|
-
rootVersion: rootVersion,
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* parse version according to Semantic Versioning (SemVer) rules.
|
|
194
|
-
*
|
|
195
|
-
* @param version The version string to parse (e.g., "1.2.3", "1.2.3-alpha.1", "1.2.3+build.001").
|
|
196
|
-
* @param options Optional configuration for throwable behavior.
|
|
197
|
-
* @returns A ParsedVersion object or null if parsing fails and throwable is false.
|
|
198
|
-
*/
|
|
199
|
-
parseVersion(version, options) {
|
|
200
|
-
const isThrowable = options?.throwable ?? true;
|
|
201
|
-
if (!version && isThrowable)
|
|
202
|
-
throw new Error(`@version (string) is required!`);
|
|
203
|
-
// RegEx to match Semantic Versioning patterns
|
|
204
|
-
const match = version?.match(/^(\d{1,2})(?:\.(\d{1,2}))?(?:\.(\d{1,2}))?(?:-([a-zA-Z0-9-.]+))?(?:\+([a-zA-Z0-9-.]+))?$/);
|
|
205
|
-
if (!match) {
|
|
206
|
-
if (isThrowable)
|
|
207
|
-
throw new Error(`@version[${version}] is invalid - fail to parse`);
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
const res = {
|
|
211
|
-
engine: engine_1.$U.N(match[1], 10) < 6 ? 'os' : 'es',
|
|
212
|
-
major: engine_1.$U.N(match[1], 10),
|
|
213
|
-
minor: match[2] !== undefined ? engine_1.$U.N(match[2], 10) : 0,
|
|
214
|
-
patch: match[3] !== undefined ? engine_1.$U.N(match[3], 10) : 0,
|
|
215
|
-
...(match[4] !== undefined ? { prerelease: match[4] } : {}),
|
|
216
|
-
...(match[5] !== undefined ? { build: match[5] } : {}),
|
|
217
|
-
};
|
|
218
|
-
return res;
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* save info to a JSON file.
|
|
222
|
-
* @param info - The information to be saved
|
|
223
|
-
* @param filePath - The file path where should be saved.
|
|
224
|
-
*/
|
|
225
|
-
async saveInfoToFile(info, filePath) {
|
|
226
|
-
try {
|
|
227
|
-
const directory = path_1.default.dirname(filePath);
|
|
228
|
-
// check whether directory exists
|
|
229
|
-
if (!fs_1.default.existsSync(directory)) {
|
|
230
|
-
fs_1.default.mkdirSync(directory, { recursive: true });
|
|
231
|
-
}
|
|
232
|
-
// write info to file
|
|
233
|
-
fs_1.default.writeFileSync(filePath, JSON.stringify(info, null, 2));
|
|
234
|
-
}
|
|
235
|
-
catch {
|
|
236
|
-
exports.$ERROR.handler('saveIntoFile', e => {
|
|
237
|
-
throw e;
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* list of index
|
|
243
|
-
*/
|
|
244
|
-
async listIndices() {
|
|
245
|
-
(0, engine_1._log)(NS, `- listIndices()`);
|
|
246
|
-
//* prepare client..
|
|
247
|
-
const client = this.client;
|
|
248
|
-
const res = await client.cat.indices({ format: 'json' });
|
|
249
|
-
(0, engine_1._log)(NS, `> indices =`, engine_1.$U.json(res));
|
|
250
|
-
// eslint-disable-next-line prettier/prettier
|
|
251
|
-
const list0 = Array.isArray(res) ? res : res?.body && Array.isArray(res?.body) ? res?.body : null;
|
|
252
|
-
if (!list0)
|
|
253
|
-
throw new Error(`@result<${typeof res}> is invalid - ${engine_1.$U.json(res)}!`);
|
|
254
|
-
// {"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"}
|
|
255
|
-
const list = list0.map(N => ({
|
|
256
|
-
pri: engine_1.$U.N(N['pri']),
|
|
257
|
-
rep: engine_1.$U.N(N['rep']),
|
|
258
|
-
docsCount: engine_1.$U.N(N['docs.count']),
|
|
259
|
-
docsDeleted: engine_1.$U.N(N['docs.deleted']),
|
|
260
|
-
health: _S(N['health']),
|
|
261
|
-
index: _S(N['index']),
|
|
262
|
-
status: _S(N['status']),
|
|
263
|
-
uuid: _S(N['uuid']),
|
|
264
|
-
priStoreSize: _S(N['pri.store.size']),
|
|
265
|
-
storeSize: _S(N['store.size']),
|
|
266
|
-
}));
|
|
267
|
-
return { list };
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* get mapping of an index
|
|
271
|
-
* @param indexName - name of the index
|
|
272
|
-
*/
|
|
273
|
-
async getIndexMapping() {
|
|
274
|
-
const client = this.client;
|
|
275
|
-
const indexName = this.options.indexName;
|
|
276
|
-
const res = await client.indices.getMapping({ index: indexName }).catch(
|
|
277
|
-
// $ERROR.throwAsJson,
|
|
278
|
-
exports.$ERROR.handler('getMapping', e => {
|
|
279
|
-
const msg = (0, test_helper_1.GETERR)(e);
|
|
280
|
-
if (msg.startsWith('404 INDEX NOT FOUND'))
|
|
281
|
-
throw new Error(`404 NOT FOUND - index:${indexName}`);
|
|
282
|
-
throw e;
|
|
283
|
-
}));
|
|
284
|
-
const mapping = res?.body ? res.body[indexName]?.mappings : null;
|
|
285
|
-
if (!mapping)
|
|
286
|
-
throw new Error(`@indexName[${indexName}] is not found - ${engine_1.$U.json(res)}!`);
|
|
287
|
-
return mapping;
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* find the index by name
|
|
291
|
-
* @param indexName - name of the index
|
|
292
|
-
*/
|
|
293
|
-
async findIndex(indexName) {
|
|
294
|
-
indexName = indexName || this.options.indexName;
|
|
295
|
-
(0, engine_1._log)(NS, `- findIndex(${indexName})`);
|
|
296
|
-
const { list } = await this.listIndices();
|
|
297
|
-
const found = list.findIndex(N => N.index == indexName);
|
|
298
|
-
return found >= 0 ? list[found] : null;
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* create index by name
|
|
302
|
-
* @param settings - creating settings
|
|
303
|
-
*/
|
|
304
|
-
async createIndex(settings) {
|
|
305
|
-
const { indexName, docType, idName, timeSeries, version } = this.options;
|
|
306
|
-
settings = settings || Elastic6Service.prepareSettings({ docType, idName, timeSeries, version });
|
|
307
|
-
if (!indexName)
|
|
308
|
-
new Error('@index is required!');
|
|
309
|
-
(0, engine_1._log)(NS, `- createIndex(${indexName})`);
|
|
310
|
-
//* prepare payload
|
|
311
|
-
const payload = {
|
|
312
|
-
settings: {
|
|
313
|
-
number_of_shards: 5,
|
|
314
|
-
number_of_replicas: 1,
|
|
315
|
-
},
|
|
316
|
-
...settings,
|
|
317
|
-
};
|
|
318
|
-
(0, engine_1._log)(NS, `> settings[${indexName}] = `, engine_1.$U.json(payload));
|
|
319
|
-
//* call create index..
|
|
320
|
-
const client = this.client;
|
|
321
|
-
const res = await client.indices.create({ index: indexName, body: payload }).catch(
|
|
322
|
-
// $ERROR.throwAsJson,
|
|
323
|
-
exports.$ERROR.handler('create', e => {
|
|
324
|
-
const msg = (0, test_helper_1.GETERR)(e);
|
|
325
|
-
if (msg.startsWith('400 RESOURCE ALREADY EXISTS'))
|
|
326
|
-
throw new Error(`400 IN USE - index:${indexName}`);
|
|
327
|
-
throw e;
|
|
328
|
-
}));
|
|
329
|
-
// if (res) throw res;
|
|
330
|
-
(0, engine_1._log)(NS, `> create[${indexName}] =`, engine_1.$U.json({ ...res, meta: undefined }));
|
|
331
|
-
//* build result.
|
|
332
|
-
return {
|
|
333
|
-
status: res.statusCode,
|
|
334
|
-
index: indexName,
|
|
335
|
-
acknowledged: res.body.shards_acknowledged,
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* destroy search index
|
|
340
|
-
*/
|
|
341
|
-
async destroyIndex() {
|
|
342
|
-
const { indexName } = this.options;
|
|
343
|
-
if (!indexName)
|
|
344
|
-
new Error('@index is required!');
|
|
345
|
-
(0, engine_1._log)(NS, `- destroyIndex(${indexName})`);
|
|
346
|
-
//* call destroy index..
|
|
347
|
-
// const { client } = instance(endpoint);
|
|
348
|
-
const client = this.client;
|
|
349
|
-
const res = await client.indices.delete({ index: indexName }).catch(
|
|
350
|
-
// $ERROR.throwAsJson,
|
|
351
|
-
exports.$ERROR.handler('destroy', e => {
|
|
352
|
-
const msg = (0, test_helper_1.GETERR)(e);
|
|
353
|
-
if (msg.startsWith('404 INDEX NOT FOUND'))
|
|
354
|
-
throw new Error(`404 NOT FOUND - index:${indexName}`);
|
|
355
|
-
throw e;
|
|
356
|
-
}));
|
|
357
|
-
// if (res) throw res;
|
|
358
|
-
(0, engine_1._log)(NS, `> destroy[${indexName}] =`, engine_1.$U.json({ ...res, meta: undefined }));
|
|
359
|
-
return {
|
|
360
|
-
status: res.statusCode,
|
|
361
|
-
index: indexName,
|
|
362
|
-
acknowledged: res.body.acknowledged,
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* refresh search index - refresh index to make all items searchable
|
|
367
|
-
*/
|
|
368
|
-
async refreshIndex() {
|
|
369
|
-
const { indexName } = this.options;
|
|
370
|
-
if (!indexName)
|
|
371
|
-
throw new Error('.indexName is required!');
|
|
372
|
-
(0, engine_1._log)(NS, `- refreshIndex(${indexName})`);
|
|
373
|
-
//* call refresh index..
|
|
374
|
-
// const { client } = instance(endpoint);
|
|
375
|
-
const client = this.client;
|
|
376
|
-
const res = await client.indices.refresh({ index: indexName }).catch(
|
|
377
|
-
// $ERROR.throwAsJson,
|
|
378
|
-
exports.$ERROR.handler('refresh', e => {
|
|
379
|
-
const msg = (0, test_helper_1.GETERR)(e);
|
|
380
|
-
if (msg.startsWith('404 INDEX NOT FOUND'))
|
|
381
|
-
throw new Error(`404 NOT FOUND - index:${indexName}`);
|
|
382
|
-
throw e;
|
|
383
|
-
}));
|
|
384
|
-
(0, engine_1._log)(NS, `> refresh[${indexName}] =`, engine_1.$U.json({ ...res, meta: undefined }));
|
|
385
|
-
return res.body;
|
|
386
|
-
}
|
|
387
|
-
/**
|
|
388
|
-
* flush search index - force store changes into search index immediately
|
|
389
|
-
*/
|
|
390
|
-
async flushIndex() {
|
|
391
|
-
const { indexName } = this.options;
|
|
392
|
-
if (!indexName)
|
|
393
|
-
throw new Error('.indexName is required!');
|
|
394
|
-
(0, engine_1._log)(NS, `- flushIndex(${indexName})`);
|
|
395
|
-
//* call flush index..
|
|
396
|
-
// const { client } = instance(endpoint);
|
|
397
|
-
const client = this.client;
|
|
398
|
-
const res = await client.indices.flush({ index: indexName }).catch(
|
|
399
|
-
// $ERROR.throwAsJson,
|
|
400
|
-
exports.$ERROR.handler('flush', e => {
|
|
401
|
-
const msg = (0, test_helper_1.GETERR)(e);
|
|
402
|
-
if (msg.startsWith('404 INDEX NOT FOUND'))
|
|
403
|
-
throw new Error(`404 NOT FOUND - index:${indexName}`);
|
|
404
|
-
throw e;
|
|
405
|
-
}));
|
|
406
|
-
(0, engine_1._log)(NS, `> flush[${indexName}] =`, engine_1.$U.json({ ...res, meta: undefined }));
|
|
407
|
-
return res.body;
|
|
408
|
-
}
|
|
409
|
-
/**
|
|
410
|
-
* describe `settings` and `mappings` of index.
|
|
411
|
-
*/
|
|
412
|
-
async describe() {
|
|
413
|
-
const { indexName } = this.options;
|
|
414
|
-
//* call create index..
|
|
415
|
-
(0, engine_1._log)(NS, `- describe(${indexName})`);
|
|
416
|
-
//* read settings.
|
|
417
|
-
// const { client } = instance(endpoint);
|
|
418
|
-
const client = this.client;
|
|
419
|
-
const res = await client.indices.getSettings({ index: indexName }).catch(
|
|
420
|
-
// $ERROR.throwAsJson,
|
|
421
|
-
exports.$ERROR.handler('describe', e => {
|
|
422
|
-
const msg = (0, test_helper_1.GETERR)(e);
|
|
423
|
-
if (msg.startsWith('404 INDEX NOT FOUND'))
|
|
424
|
-
throw new Error(`404 NOT FOUND - index:${indexName}`);
|
|
425
|
-
throw e;
|
|
426
|
-
}));
|
|
427
|
-
(0, engine_1._log)(NS, `> settings[${indexName}] =`, engine_1.$U.json({ ...res, meta: undefined }));
|
|
428
|
-
const settings = (res.body && res.body[indexName] && res.body[indexName].settings) || {};
|
|
429
|
-
(0, engine_1._log)(NS, `> number_of_shards =`, settings.index && settings.index.number_of_shards); // 5
|
|
430
|
-
(0, engine_1._log)(NS, `> number_of_replicas =`, settings.index && settings.index.number_of_replicas); // 1
|
|
431
|
-
//* read mappings.
|
|
432
|
-
const res2 = await client.indices.getMapping({ index: indexName });
|
|
433
|
-
(0, engine_1._log)(NS, `> mappings[${indexName}] =`, engine_1.$U.json(res2));
|
|
434
|
-
const mappings = (res2.body && res2.body[indexName] && res2.body[indexName].mappings) || {};
|
|
435
|
-
//* returns
|
|
436
|
-
return { settings, mappings };
|
|
437
|
-
}
|
|
438
|
-
/**
|
|
439
|
-
* save single item
|
|
440
|
-
*
|
|
441
|
-
* @param id - id
|
|
442
|
-
* @param item - item to save
|
|
443
|
-
* @param type - document type (default: doc-type given at construction time)
|
|
444
|
-
*/
|
|
445
|
-
async saveItem(id, item, type) {
|
|
446
|
-
const { indexName, docType, idName } = this.options;
|
|
447
|
-
(0, engine_1._log)(NS, `- saveItem(${id})`);
|
|
448
|
-
// const { client } = instance(endpoint);
|
|
449
|
-
const client = this.client;
|
|
450
|
-
// prepare item body and autocomplete fields
|
|
451
|
-
const body = { ...item, [idName]: id };
|
|
452
|
-
const body2 = this.popullateAutocompleteFields(body);
|
|
453
|
-
type = `${type || docType}`;
|
|
454
|
-
const params = { index: indexName, id, body: body2 };
|
|
455
|
-
// check version to include 'type' in params
|
|
456
|
-
if (this.isOldES6) {
|
|
457
|
-
params.type = type;
|
|
458
|
-
}
|
|
459
|
-
if (idName === '_id')
|
|
460
|
-
delete params.body[idName]; //WARN! `_id` is reserved in ES6.
|
|
461
|
-
(0, engine_1._log)(NS, `> params[${id}] =`, engine_1.$U.json(params));
|
|
462
|
-
//NOTE - use npm `elasticsearch#13.2.0` for avoiding error.
|
|
463
|
-
const res = await client.create(params).catch(
|
|
464
|
-
// $ERROR.throwAsJson,
|
|
465
|
-
exports.$ERROR.handler('save', e => {
|
|
466
|
-
const msg = (0, test_helper_1.GETERR)(e);
|
|
467
|
-
//* try to overwrite document..
|
|
468
|
-
if (msg.startsWith('409 VERSION CONFLICT ENGINE')) {
|
|
469
|
-
// delete body2[idName]; // do set id while update
|
|
470
|
-
// return this.updateItem(id, body2);
|
|
471
|
-
const param2 = { index: indexName, id, body: { ...body2 } };
|
|
472
|
-
if (this.isOldES6)
|
|
473
|
-
param2.type = type;
|
|
474
|
-
return client.index(param2);
|
|
475
|
-
}
|
|
476
|
-
throw e;
|
|
477
|
-
}));
|
|
478
|
-
(0, engine_1._log)(NS, `> create[${id}].res =`, engine_1.$U.json({ ...res, meta: undefined }));
|
|
479
|
-
const _version = engine_1.$U.N(res.body?._version, 0);
|
|
480
|
-
const _id = res.body?._id;
|
|
481
|
-
const res2 = { ...body, _id, _version };
|
|
482
|
-
return res2;
|
|
483
|
-
}
|
|
484
|
-
/**
|
|
485
|
-
* push item for time-series data.
|
|
486
|
-
*
|
|
487
|
-
* @param item - item to push
|
|
488
|
-
* @param type - document type (default: doc-type given at construction time)
|
|
489
|
-
*/
|
|
490
|
-
async pushItem(item, type) {
|
|
491
|
-
const { indexName, docType } = this.options;
|
|
492
|
-
const id = '';
|
|
493
|
-
type = `${type || docType}`;
|
|
494
|
-
const body = { ...item };
|
|
495
|
-
const body2 = this.popullateAutocompleteFields(body);
|
|
496
|
-
(0, engine_1._log)(NS, `- pushItem(${id})`);
|
|
497
|
-
const params = { index: indexName, type, body: body2 };
|
|
498
|
-
(0, engine_1._log)(NS, `> params[${id}] =`, engine_1.$U.json(params));
|
|
499
|
-
//NOTE - use npm `elasticsearch#13.2.0` for avoiding error.
|
|
500
|
-
// const { client } = instance(endpoint);
|
|
501
|
-
const client = this.client;
|
|
502
|
-
const res = await client.index(params).catch(
|
|
503
|
-
// $ERROR.throwAsJson,
|
|
504
|
-
exports.$ERROR.handler('index', e => {
|
|
505
|
-
(0, engine_1._err)(NS, `> index[${indexName}].err =`, e instanceof Error ? e : engine_1.$U.json(e));
|
|
506
|
-
throw e;
|
|
507
|
-
}));
|
|
508
|
-
// {"_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}
|
|
509
|
-
(0, engine_1._log)(NS, `> create[${id}].res =`, engine_1.$U.json({ ...res, meta: undefined }));
|
|
510
|
-
const _id = res.body?._id;
|
|
511
|
-
const _version = res.body?._version;
|
|
512
|
-
const res2 = { ...body, _id, _version };
|
|
513
|
-
return res2;
|
|
514
|
-
}
|
|
515
|
-
/**
|
|
516
|
-
* read item with projections
|
|
517
|
-
*
|
|
518
|
-
* @param id - item-id
|
|
519
|
-
* @param views - projections
|
|
520
|
-
*/
|
|
521
|
-
async readItem(id, views) {
|
|
522
|
-
const { indexName, docType } = this.options;
|
|
523
|
-
const type = `${docType}`;
|
|
524
|
-
(0, engine_1._log)(NS, `- readItem(${id})`);
|
|
525
|
-
const params = { index: indexName, type, id };
|
|
526
|
-
if (views) {
|
|
527
|
-
const fields = [];
|
|
528
|
-
const keys = Array.isArray(views) ? views : Object.keys(views);
|
|
529
|
-
keys.forEach((k) => {
|
|
530
|
-
fields.push(k);
|
|
531
|
-
});
|
|
532
|
-
params._source = fields;
|
|
533
|
-
}
|
|
534
|
-
(0, engine_1._log)(NS, `> params[${id}] =`, engine_1.$U.json(params));
|
|
535
|
-
// const { client } = instance(endpoint);
|
|
536
|
-
const client = this.client;
|
|
537
|
-
const res = await client.get(params).catch(
|
|
538
|
-
// $ERROR.throwAsJson,
|
|
539
|
-
exports.$ERROR.handler('read', e => {
|
|
540
|
-
const msg = (0, test_helper_1.GETERR)(e);
|
|
541
|
-
if (msg.startsWith('404 NOT FOUND'))
|
|
542
|
-
throw new Error(`404 NOT FOUND - id:${id}`);
|
|
543
|
-
if (msg.startsWith('404 INDEX NOT FOUND'))
|
|
544
|
-
throw new Error(`404 NOT FOUND - index:${indexName}`);
|
|
545
|
-
throw e;
|
|
546
|
-
}));
|
|
547
|
-
(0, engine_1._log)(NS, `> read[${id}].res =`, engine_1.$U.json({ ...res, meta: undefined }));
|
|
548
|
-
const _id = res.body?._id;
|
|
549
|
-
const _version = res.body?._version;
|
|
550
|
-
const data = res?._source || res.body?._source || {};
|
|
551
|
-
// delete internal (analyzed) field
|
|
552
|
-
delete data[Elastic6Service.DECOMPOSED_FIELD];
|
|
553
|
-
delete data[Elastic6Service.QWERTY_FIELD];
|
|
554
|
-
const res2 = { ...data, _id, _version };
|
|
555
|
-
return res2;
|
|
556
|
-
}
|
|
557
|
-
/**
|
|
558
|
-
* delete item with projections
|
|
559
|
-
*
|
|
560
|
-
* @param id - item-id
|
|
561
|
-
*/
|
|
562
|
-
async deleteItem(id) {
|
|
563
|
-
const { indexName, docType } = this.options;
|
|
564
|
-
const type = `${docType}`;
|
|
565
|
-
(0, engine_1._log)(NS, `- readItem(${id})`);
|
|
566
|
-
const params = { index: indexName, type, id };
|
|
567
|
-
(0, engine_1._log)(NS, `> params[${id}] =`, engine_1.$U.json(params));
|
|
568
|
-
// const { client } = instance(endpoint);
|
|
569
|
-
const client = this.client;
|
|
570
|
-
const res = await client.delete(params).catch(exports.$ERROR.handler('read', e => {
|
|
571
|
-
const msg = (0, test_helper_1.GETERR)(e);
|
|
572
|
-
if (msg.startsWith('404 NOT FOUND'))
|
|
573
|
-
throw new Error(`404 NOT FOUND - id:${id}`);
|
|
574
|
-
if (msg.startsWith('404 INDEX NOT FOUND'))
|
|
575
|
-
throw new Error(`404 NOT FOUND - index:${indexName}`);
|
|
576
|
-
throw e;
|
|
577
|
-
}));
|
|
578
|
-
// {"_index":"test-v3","_type":"_doc","_id":"aaa","_version":3,"result":"deleted","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":4,"_primary_term":1}
|
|
579
|
-
(0, engine_1._log)(NS, `> delete[${id}].res =`, engine_1.$U.json({ ...res, meta: undefined }));
|
|
580
|
-
const _id = res.body?._id;
|
|
581
|
-
const _version = res.body?._version;
|
|
582
|
-
const data = res.body?._source || res.body?._source || {};
|
|
583
|
-
const res2 = { ...data, _id, _version };
|
|
584
|
-
return res2;
|
|
585
|
-
}
|
|
586
|
-
/**
|
|
587
|
-
* update item (throw if not exist)
|
|
588
|
-
* `update table set a=1, b=b+2 where id='a1'`
|
|
589
|
-
* 0. no of `a1` -> 1,2 (created)
|
|
590
|
-
* 1. a,b := 10,20 -> 11,22
|
|
591
|
-
* 2. a,b := 10,null -> 11,2 (upsert)
|
|
592
|
-
* 3. a,b := null,20 -> 1,22
|
|
593
|
-
*
|
|
594
|
-
* @param id - item-id
|
|
595
|
-
* @param item - item to update
|
|
596
|
-
* @param increments - item to increase
|
|
597
|
-
* @param options - (optional) request option of client.
|
|
598
|
-
*/
|
|
599
|
-
async updateItem(id, item, increments, options) {
|
|
600
|
-
const { indexName, docType, idName } = this.options;
|
|
601
|
-
const type = `${docType}`;
|
|
602
|
-
(0, engine_1._log)(NS, `- updateItem(${id})`);
|
|
603
|
-
item = !item && increments ? undefined : item;
|
|
604
|
-
//* prepare params.
|
|
605
|
-
const params = { index: indexName, id, body: {} };
|
|
606
|
-
// check version to include 'type' in params
|
|
607
|
-
if (this.isOldES6) {
|
|
608
|
-
params.type = type;
|
|
609
|
-
}
|
|
610
|
-
const scripts = [];
|
|
611
|
-
if (increments) {
|
|
612
|
-
//* it will create if not exists.
|
|
613
|
-
params.body.upsert = { ...increments, [idName]: id };
|
|
614
|
-
Object.entries(increments).forEach(([key, val]) => {
|
|
615
|
-
if (Array.isArray(val)) {
|
|
616
|
-
// If the value is an array, append it to the existing array in the source
|
|
617
|
-
scripts.push(`if (ctx._source['${key}'] != null && ctx._source['${key}'] instanceof List) {
|
|
618
|
-
ctx._source['${key}'].addAll(params.increments['${key}']);
|
|
619
|
-
} else {
|
|
620
|
-
ctx._source['${key}'] = params.increments['${key}'];
|
|
621
|
-
}`);
|
|
622
|
-
}
|
|
623
|
-
else {
|
|
624
|
-
// If the value is a number, increment the existing field
|
|
625
|
-
scripts.push(`if (ctx._source['${key}'] != null) {
|
|
626
|
-
ctx._source['${key}'] += params.increments['${key}'];
|
|
627
|
-
} else {
|
|
628
|
-
ctx._source['${key}'] = params.increments['${key}'];
|
|
629
|
-
}`);
|
|
630
|
-
}
|
|
631
|
-
});
|
|
632
|
-
}
|
|
633
|
-
if (item) {
|
|
634
|
-
// Handle item updates in the script
|
|
635
|
-
Object.entries(item).forEach(([key]) => {
|
|
636
|
-
scripts.push(`ctx._source['${key}'] = params.item['${key}'];`);
|
|
637
|
-
});
|
|
638
|
-
}
|
|
639
|
-
params.body.script = {
|
|
640
|
-
source: scripts.join(' '),
|
|
641
|
-
lang: 'painless',
|
|
642
|
-
params: { item, increments },
|
|
643
|
-
};
|
|
644
|
-
(0, engine_1._log)(NS, `> params[${id}] =`, engine_1.$U.json(params));
|
|
645
|
-
// const { client } = instance(endpoint);
|
|
646
|
-
const client = this.client;
|
|
647
|
-
const res = await client.update(params, options).catch(exports.$ERROR.handler('update', (e, E) => {
|
|
648
|
-
const msg = (0, test_helper_1.GETERR)(e);
|
|
649
|
-
//* id 아이템이 없을 경우 발생함.
|
|
650
|
-
if (msg.startsWith('404 DOCUMENT MISSING'))
|
|
651
|
-
throw new Error(`404 NOT FOUND - id:${id}`);
|
|
652
|
-
//* 해당 속성이 없을때 업데이트 하려면 생길 수 있음.
|
|
653
|
-
if (msg.startsWith('400 REMOTE TRANSPORT'))
|
|
654
|
-
throw new Error(`400 INVALID FIELD - id:${id}`);
|
|
655
|
-
if (msg.startsWith('404 NOT FOUND'))
|
|
656
|
-
throw new Error(`404 NOT FOUND - id:${id}`);
|
|
657
|
-
if (msg.startsWith('400 ACTION REQUEST VALIDATION'))
|
|
658
|
-
throw e;
|
|
659
|
-
if (msg.startsWith('400 INVALID FIELD'))
|
|
660
|
-
throw e; // at ES6.8
|
|
661
|
-
if (msg.startsWith('400 MAPPER PARSING'))
|
|
662
|
-
throw e;
|
|
663
|
-
if (msg.startsWith('400 ILLEGAL ARGUMENT - Cannot apply') ||
|
|
664
|
-
msg.startsWith('400 ILLEGAL ARGUMENT - class_cast_exception:'))
|
|
665
|
-
throw new Error(`400 ILLEGAL ARGUMENT - failed to update due to type mismatch in item's field`); // at ES7.1
|
|
666
|
-
if (msg.startsWith('400 ILLEGAL ARGUMENT'))
|
|
667
|
-
throw e; // at ES7.1
|
|
668
|
-
throw E;
|
|
669
|
-
}));
|
|
670
|
-
// {"_index":"test-v3","_type":"_doc","_id":"aaa","_version":2,"result":"updated","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":8,"_primary_term":1}
|
|
671
|
-
// {"_index":"test-v3","_type":"_doc","_id":"aaa","_version":2,"result":"noop","_shards":{"total":0,"successful":0,"failed":0}}
|
|
672
|
-
(0, engine_1._log)(NS, `> update[${id}].res =`, engine_1.$U.json({ ...res, meta: undefined }));
|
|
673
|
-
const _id = res.body._id;
|
|
674
|
-
const _version = res.body._version;
|
|
675
|
-
const res2 = { ...item, _id, _version };
|
|
676
|
-
return res2;
|
|
677
|
-
}
|
|
678
|
-
/**
|
|
679
|
-
* run search and get the raw response.
|
|
680
|
-
* @param body - Elasticsearch Query DSL that defines the search request (e.g., size, query, filters).
|
|
681
|
-
* @param searchType - type of search (e.g., 'query_then_fetch', 'dfs_query_then_fetch').
|
|
682
|
-
*/
|
|
683
|
-
async searchRaw(body, searchType) {
|
|
684
|
-
if (!body)
|
|
685
|
-
throw new Error('@body (SearchBody) is required');
|
|
686
|
-
const { indexName, docType } = this.options;
|
|
687
|
-
(0, engine_1._log)(NS, `- search(${indexName}, ${searchType || ''})....`);
|
|
688
|
-
(0, engine_1._log)(NS, `> body =`, engine_1.$U.json(body));
|
|
689
|
-
const tmp = docType ? docType : '';
|
|
690
|
-
const type = docType ? `${docType}` : undefined;
|
|
691
|
-
const params = { index: indexName, body, searchType };
|
|
692
|
-
// check version to include 'type' in params
|
|
693
|
-
if (this.isOldES6) {
|
|
694
|
-
params.type = type;
|
|
695
|
-
}
|
|
696
|
-
(0, engine_1._log)(NS, `> params[${tmp}] =`, engine_1.$U.json({ ...params, body: undefined }));
|
|
697
|
-
// const { client } = instance(endpoint);
|
|
698
|
-
const client = this.client;
|
|
699
|
-
const $res = await client.search(params).catch(exports.$ERROR.handler('search', e => {
|
|
700
|
-
(0, engine_1._err)(NS, `> search[${indexName}].err =`, e);
|
|
701
|
-
throw e;
|
|
702
|
-
}));
|
|
703
|
-
// {"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}}]}}
|
|
704
|
-
// _log(NS, `> search[${id}].res =`, $U.json({ ...res, meta: undefined }));
|
|
705
|
-
// _log(NS, `> search[${tmp}].took =`, $res.took);
|
|
706
|
-
// _log(NS, `> search[${tmp}].hits.total =`, $res.hits?.total);
|
|
707
|
-
// _log(NS, `> search[${tmp}].hits.max_score =`, $res.hits?.max_score);
|
|
708
|
-
// _log(NS, `> search[${tmp}].hits.hits[0] =`, $res.hits && $U.json($res.hits.hits[0]));
|
|
709
|
-
//* return raw results.
|
|
710
|
-
return $res?.body;
|
|
711
|
-
}
|
|
712
|
-
/**
|
|
713
|
-
* run search, and get the formatmted response.
|
|
714
|
-
* @param body - Elasticsearch Query DSL that defines the search request (e.g., size, query, filters).
|
|
715
|
-
* @param searchType - type of search (e.g., 'query_then_fetch', 'dfs_query_then_fetch').
|
|
716
|
-
*
|
|
717
|
-
*/
|
|
718
|
-
async search(body, searchType) {
|
|
719
|
-
const size = engine_1.$U.N(body.size, 0);
|
|
720
|
-
const response = await this.searchRaw(body, searchType);
|
|
721
|
-
// return w/ transformed id
|
|
722
|
-
const hits = response.hits;
|
|
723
|
-
if (typeof hits !== 'object')
|
|
724
|
-
throw new Error(`.hits (object) is required - hits:${engine_1.$U.json(hits)}`);
|
|
725
|
-
//NOTE - ES6.8 w/ OS1.1
|
|
726
|
-
return {
|
|
727
|
-
total: typeof hits.total?.value === 'number' ? hits.total?.value : hits.total,
|
|
728
|
-
list: hits.hits.map((hit) => ({
|
|
729
|
-
...hit._source,
|
|
730
|
-
_id: hit._id,
|
|
731
|
-
_score: hit._score,
|
|
732
|
-
})),
|
|
733
|
-
last: hits.hits.length === size && size > 0 ? hits.hits[size - 1]?.sort : undefined,
|
|
734
|
-
aggregations: response.aggregations,
|
|
735
|
-
};
|
|
736
|
-
}
|
|
737
|
-
/**
|
|
738
|
-
* search all until limit (-1 means no-limit)
|
|
739
|
-
* @param body - Elasticsearch Query DSL that defines the search request (e.g., size, query, filters).
|
|
740
|
-
* @param params - parameters including search type, limit, and retry options.
|
|
741
|
-
*/
|
|
742
|
-
async searchAll(body, params) {
|
|
743
|
-
const list = [];
|
|
744
|
-
for await (const chunk of this.generateSearchResult(body, params)) {
|
|
745
|
-
chunk.forEach((N) => list.push(N));
|
|
746
|
-
}
|
|
747
|
-
return list;
|
|
748
|
-
}
|
|
749
|
-
/**
|
|
750
|
-
* create async generator that yields items queried until last
|
|
751
|
-
*
|
|
752
|
-
* @param body - Elasticsearch Query DSL that defines the search request (e.g., size, query, filters).
|
|
753
|
-
* @param params - parameters including search type, limit, and retry options.
|
|
754
|
-
*/
|
|
755
|
-
async *generateSearchResult(body, params) {
|
|
756
|
-
const doRetry = params?.retryOptions?.do ?? false;
|
|
757
|
-
const t = params?.retryOptions?.t ?? 5000;
|
|
758
|
-
const maxRetries = params?.retryOptions?.maxRetries ?? 3;
|
|
759
|
-
let limit = params?.limit ?? -1;
|
|
760
|
-
let retryCount = 0;
|
|
761
|
-
if (!body.sort)
|
|
762
|
-
body.sort = '_doc';
|
|
763
|
-
do {
|
|
764
|
-
try {
|
|
765
|
-
const { list, last } = await this.search(body, params?.searchType);
|
|
766
|
-
body.search_after = last;
|
|
767
|
-
if (list.length === 0 && !body.search_after) {
|
|
768
|
-
break;
|
|
769
|
-
}
|
|
770
|
-
yield list;
|
|
771
|
-
}
|
|
772
|
-
catch (e) {
|
|
773
|
-
const msg = (0, test_helper_1.GETERR)(e);
|
|
774
|
-
if (doRetry && msg.startsWith('429 UNKNOWN') && retryCount < maxRetries) {
|
|
775
|
-
retryCount++;
|
|
776
|
-
await (0, test_helper_1.waited)(t);
|
|
777
|
-
continue;
|
|
778
|
-
}
|
|
779
|
-
else {
|
|
780
|
-
throw e;
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
} while (body.search_after && (limit === -1 || --limit > 0));
|
|
784
|
-
}
|
|
785
|
-
/**
|
|
786
|
-
* prepare default setting
|
|
787
|
-
* - migrated from engine-v2.
|
|
788
|
-
*
|
|
789
|
-
* @param docType document type name
|
|
790
|
-
* @param idName id-name
|
|
791
|
-
* @param shards number of shards (default 4)
|
|
792
|
-
* @param replicas number of replicas (default 1)
|
|
793
|
-
* @param timeSeries flag of TIMESERIES (default false)
|
|
794
|
-
*/
|
|
795
|
-
static prepareSettings(params) {
|
|
796
|
-
const docType = params.docType === undefined ? '_doc' : params.docType;
|
|
797
|
-
const idName = params.idName === undefined ? '$id' : params.idName;
|
|
798
|
-
const version = engine_1.$U.F(params.version === undefined ? '6.8' : params.version);
|
|
799
|
-
const shards = params.shards === undefined ? 4 : params.shards;
|
|
800
|
-
const replicas = params.replicas === undefined ? 1 : params.replicas;
|
|
801
|
-
const timeSeries = params.timeSeries === undefined ? false : params.timeSeries;
|
|
802
|
-
//* core config.
|
|
803
|
-
const CONF_ES_DOCTYPE = docType;
|
|
804
|
-
const CONF_ID_NAME = idName;
|
|
805
|
-
const CONF_ES_TIMESERIES = !!timeSeries;
|
|
806
|
-
const ES_MAPPINGS = {
|
|
807
|
-
// NOTE: the order of dynamic templates are important.
|
|
808
|
-
dynamic_templates: [
|
|
809
|
-
// 1. Search-as-You-Type (autocomplete search) - apply to '_decomposed.*' fields
|
|
810
|
-
{
|
|
811
|
-
autocomplete: {
|
|
812
|
-
path_match: `${Elastic6Service.DECOMPOSED_FIELD}.*`,
|
|
813
|
-
mapping: {
|
|
814
|
-
type: 'text',
|
|
815
|
-
analyzer: 'autocomplete_case_insensitive',
|
|
816
|
-
search_analyzer: 'standard',
|
|
817
|
-
},
|
|
818
|
-
},
|
|
819
|
-
},
|
|
820
|
-
// 2. Search-as-You-Type (Korean to Alphabet sequence in QWERTY/2벌식 keyboard) - apply to '_qwerty.*' fields
|
|
821
|
-
{
|
|
822
|
-
autocomplete_qwerty: {
|
|
823
|
-
path_match: `${Elastic6Service.QWERTY_FIELD}.*`,
|
|
824
|
-
mapping: {
|
|
825
|
-
type: 'text',
|
|
826
|
-
analyzer: 'autocomplete_case_sensitive',
|
|
827
|
-
search_analyzer: 'whitespace',
|
|
828
|
-
},
|
|
829
|
-
},
|
|
830
|
-
},
|
|
831
|
-
// 3. string type ID field
|
|
832
|
-
{
|
|
833
|
-
string_id: {
|
|
834
|
-
match_mapping_type: 'string',
|
|
835
|
-
match: CONF_ID_NAME,
|
|
836
|
-
mapping: {
|
|
837
|
-
type: 'keyword',
|
|
838
|
-
ignore_above: 256,
|
|
839
|
-
},
|
|
840
|
-
},
|
|
841
|
-
},
|
|
842
|
-
// 4. any other string fields - use Hangul analyzer and create 'keyword' sub-field
|
|
843
|
-
{
|
|
844
|
-
strings: {
|
|
845
|
-
match_mapping_type: 'string',
|
|
846
|
-
mapping: {
|
|
847
|
-
type: 'text',
|
|
848
|
-
analyzer: 'hangul',
|
|
849
|
-
search_analyzer: 'hangul',
|
|
850
|
-
fields: {
|
|
851
|
-
// keyword sub-field
|
|
852
|
-
// 문자열 타입에 대한 템플릿을 지정하지 않으면 기본으로 ES가 '.keyword' 서브필드를 생성하나
|
|
853
|
-
// 문자열 타입 템플릿 재정의 시 기본으로 생성되지 않으므로 명시적으로 선언함.
|
|
854
|
-
keyword: {
|
|
855
|
-
type: 'keyword',
|
|
856
|
-
ignore_above: 256,
|
|
857
|
-
},
|
|
858
|
-
},
|
|
859
|
-
},
|
|
860
|
-
},
|
|
861
|
-
},
|
|
862
|
-
],
|
|
863
|
-
properties: {
|
|
864
|
-
'@version': {
|
|
865
|
-
type: 'keyword',
|
|
866
|
-
index: false,
|
|
867
|
-
},
|
|
868
|
-
created_at: {
|
|
869
|
-
type: 'date',
|
|
870
|
-
format: 'strict_date_optional_time||epoch_millis',
|
|
871
|
-
},
|
|
872
|
-
updated_at: {
|
|
873
|
-
type: 'date',
|
|
874
|
-
format: 'strict_date_optional_time||epoch_millis',
|
|
875
|
-
},
|
|
876
|
-
deleted_at: {
|
|
877
|
-
type: 'date',
|
|
878
|
-
format: 'strict_date_optional_time||epoch_millis',
|
|
879
|
-
},
|
|
880
|
-
},
|
|
881
|
-
};
|
|
882
|
-
//* default settings.
|
|
883
|
-
const ES_SETTINGS = {
|
|
884
|
-
settings: {
|
|
885
|
-
number_of_shards: shards,
|
|
886
|
-
number_of_replicas: replicas,
|
|
887
|
-
analysis: {
|
|
888
|
-
tokenizer: {
|
|
889
|
-
hangul: {
|
|
890
|
-
type: 'seunjeon_tokenizer',
|
|
891
|
-
decompound: true, // 복합명사 분해
|
|
892
|
-
deinflect: true, // 활용어의 원형 추출
|
|
893
|
-
index_eojeol: true, // 어절 추출
|
|
894
|
-
pos_tagging: false, // 품사 태깅
|
|
895
|
-
},
|
|
896
|
-
edge_30grams: {
|
|
897
|
-
type: 'edge_ngram',
|
|
898
|
-
min_gram: 1,
|
|
899
|
-
max_gram: 30,
|
|
900
|
-
token_chars: ['letter', 'digit', 'punctuation', 'symbol'],
|
|
901
|
-
},
|
|
902
|
-
},
|
|
903
|
-
analyzer: {
|
|
904
|
-
hangul: {
|
|
905
|
-
type: 'custom',
|
|
906
|
-
tokenizer: 'hangul',
|
|
907
|
-
filter: ['lowercase'],
|
|
908
|
-
},
|
|
909
|
-
autocomplete_case_insensitive: {
|
|
910
|
-
type: 'custom',
|
|
911
|
-
tokenizer: 'edge_30grams',
|
|
912
|
-
filter: ['lowercase'],
|
|
913
|
-
},
|
|
914
|
-
autocomplete_case_sensitive: {
|
|
915
|
-
type: 'custom',
|
|
916
|
-
tokenizer: 'edge_30grams',
|
|
917
|
-
filter: version < 7 && version >= 6 ? ['standard'] : [], //* error - The [standard] token filter has been removed.
|
|
918
|
-
},
|
|
919
|
-
},
|
|
920
|
-
},
|
|
921
|
-
},
|
|
922
|
-
//* since 7.x. no mapping for types.
|
|
923
|
-
mappings: version < 7 && version >= 6 ? { [CONF_ES_DOCTYPE]: ES_MAPPINGS } : ES_MAPPINGS,
|
|
924
|
-
};
|
|
925
|
-
//* timeseries 데이터로, 기본 timestamp 값을 넣어준다. (주의! save시 current-time 값 자동 저장)
|
|
926
|
-
if (!!CONF_ES_TIMESERIES) {
|
|
927
|
-
ES_SETTINGS.settings.refresh_interval = '5s';
|
|
928
|
-
if (version < 7 && version >= 6) {
|
|
929
|
-
ES_SETTINGS.mappings[CONF_ES_DOCTYPE].properties['@timestamp'] = { type: 'date', doc_values: true };
|
|
930
|
-
ES_SETTINGS.mappings[CONF_ES_DOCTYPE].properties['ip'] = { type: 'ip' };
|
|
931
|
-
//* clear mappings.
|
|
932
|
-
const CLEANS = '@version,created_at,updated_at,deleted_at'.split(',');
|
|
933
|
-
CLEANS.map(key => delete ES_SETTINGS.mappings[CONF_ES_DOCTYPE].properties[key]);
|
|
934
|
-
}
|
|
935
|
-
else {
|
|
936
|
-
ES_SETTINGS.mappings.properties['@timestamp'] = { type: 'date', doc_values: true };
|
|
937
|
-
ES_SETTINGS.mappings.properties['ip'] = { type: 'ip' };
|
|
938
|
-
//* clear mappings.
|
|
939
|
-
const CLEANS = '@version,created_at,updated_at,deleted_at'.split(',');
|
|
940
|
-
CLEANS.map(key => delete ES_SETTINGS.properties[key]);
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
//* returns settings.
|
|
944
|
-
return ES_SETTINGS;
|
|
945
|
-
}
|
|
946
|
-
/**
|
|
947
|
-
* generate autocomplete fields into the item body to be indexed
|
|
948
|
-
* @param body item body to be saved into ES6 index
|
|
949
|
-
* @private
|
|
950
|
-
*/
|
|
951
|
-
popullateAutocompleteFields(body) {
|
|
952
|
-
const { autocompleteFields } = this.options;
|
|
953
|
-
const isAutoComplete = autocompleteFields && Array.isArray(autocompleteFields) && autocompleteFields.length > 0;
|
|
954
|
-
if (!isAutoComplete)
|
|
955
|
-
return body;
|
|
956
|
-
return autocompleteFields.reduce((N, field) => {
|
|
957
|
-
const value = body[field];
|
|
958
|
-
if (typeof value == 'string' || value) {
|
|
959
|
-
// 한글의 경우 자모 분해 형태와 영자판 변형 형태를 제공하고, 영문의 경우 원본 텍스트만 제공한다.
|
|
960
|
-
// 다만 사용자가 공백/하이픈을 생략하고 입력하는 경우에 대응하기 위해 공백/하이픈을 제거한 형태를 공통으로 제공한다.
|
|
961
|
-
if (hangul_service_1.default.isHangul(value, true)) {
|
|
962
|
-
// 자모 분해 (e.g. '레몬' -> 'ㄹㅔㅁㅗㄴ')
|
|
963
|
-
const decomposed = hangul_service_1.default.asJamoSequence(value);
|
|
964
|
-
const recomposed = decomposed.replace(/[ -]/g, '');
|
|
965
|
-
N[Elastic6Service.DECOMPOSED_FIELD][field] = [decomposed, recomposed];
|
|
966
|
-
// 영자판 (e.g. '레몬' -> 'fpahs')
|
|
967
|
-
N[Elastic6Service.QWERTY_FIELD][field] = hangul_service_1.default.asAlphabetKeyStokes(value);
|
|
968
|
-
}
|
|
969
|
-
else {
|
|
970
|
-
const recomposed = value.replace(/[ -]/g, '');
|
|
971
|
-
N[Elastic6Service.DECOMPOSED_FIELD][field] = [value, recomposed];
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
return N;
|
|
975
|
-
}, { ...body, [Elastic6Service.DECOMPOSED_FIELD]: {}, [Elastic6Service.QWERTY_FIELD]: {} });
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
exports.Elastic6Service = Elastic6Service;
|
|
979
|
-
/**
|
|
980
|
-
* error samples
|
|
981
|
-
*/
|
|
982
|
-
exports.$ERROR = {
|
|
983
|
-
asJson: (e) => {
|
|
984
|
-
const _pack = (o) => JSON.parse(JSON.stringify(o, Object.getOwnPropertyNames(o)));
|
|
985
|
-
if (e instanceof Error) {
|
|
986
|
-
const err = e;
|
|
987
|
-
const meta = err.meta && typeof err.meta === 'object' ? err.meta : undefined;
|
|
988
|
-
const $err = _pack(err);
|
|
989
|
-
return { ...$err, meta };
|
|
990
|
-
}
|
|
991
|
-
return e;
|
|
992
|
-
},
|
|
993
|
-
throwAsJson: (e) => {
|
|
994
|
-
throw exports.$ERROR.asJson(e);
|
|
995
|
-
},
|
|
996
|
-
parseMeta: (meta) => {
|
|
997
|
-
if (typeof meta === 'string' && meta) {
|
|
998
|
-
try {
|
|
999
|
-
if (meta.startsWith('[') && meta.endsWith(']')) {
|
|
1000
|
-
const list = JSON.parse(meta);
|
|
1001
|
-
const $ret = { list };
|
|
1002
|
-
return $ret;
|
|
1003
|
-
}
|
|
1004
|
-
else if (meta.startsWith('{') && meta.endsWith('}')) {
|
|
1005
|
-
return JSON.parse(meta);
|
|
1006
|
-
}
|
|
1007
|
-
else {
|
|
1008
|
-
const $ret = { type: 'string', value: meta };
|
|
1009
|
-
return $ret;
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
catch (e) {
|
|
1013
|
-
const $ret = { type: 'string', value: meta, error: (0, test_helper_1.GETERR)(e) };
|
|
1014
|
-
return $ret;
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
else if (meta === null || meta === undefined) {
|
|
1018
|
-
return null;
|
|
1019
|
-
}
|
|
1020
|
-
else if (typeof meta === 'object') {
|
|
1021
|
-
return meta;
|
|
1022
|
-
}
|
|
1023
|
-
else {
|
|
1024
|
-
const type = typeof meta;
|
|
1025
|
-
const $ret = { type, value: meta };
|
|
1026
|
-
return $ret;
|
|
1027
|
-
}
|
|
1028
|
-
},
|
|
1029
|
-
asError: (e) => {
|
|
1030
|
-
const E = exports.$ERROR.asJson(e);
|
|
1031
|
-
const status = `${E.statusCode || ''}`;
|
|
1032
|
-
const message = `${E.message || E.msg || ''}`;
|
|
1033
|
-
const reason = ((E) => {
|
|
1034
|
-
//* from ES7.1
|
|
1035
|
-
if (E.meta && typeof E.meta == 'object') {
|
|
1036
|
-
const type = _S(E?.message).toUpperCase().split('_').slice(0, -1).join(' ');
|
|
1037
|
-
const status = engine_1.$U.N(E.meta?.statusCode, type.includes('NOT FOUND') ? 404 : 400);
|
|
1038
|
-
const $res = exports.$ERROR.parseMeta(E.meta);
|
|
1039
|
-
//* find the reason.
|
|
1040
|
-
const reason = $res.body?.error?.reason === 'failed to execute script'
|
|
1041
|
-
? $res.body?.error?.caused_by?.caused_by?.reason
|
|
1042
|
-
: $res.body?.error?.reason;
|
|
1043
|
-
const result = { status, type: type || (status === 404 ? 'NOT FOUND' : 'UNKNOWN') };
|
|
1044
|
-
if (typeof reason !== 'undefined') {
|
|
1045
|
-
result.reason = reason;
|
|
1046
|
-
}
|
|
1047
|
-
return result;
|
|
1048
|
-
}
|
|
1049
|
-
//* from ES6.2
|
|
1050
|
-
if (!E.response)
|
|
1051
|
-
return null;
|
|
1052
|
-
const $res = exports.$ERROR.parseMeta(E.response);
|
|
1053
|
-
//* find the root-cause.
|
|
1054
|
-
const pic1 = (N, i = 0) => (N && Array.isArray(N) ? N[i] : N);
|
|
1055
|
-
const cause = pic1($res?.error?.root_cause);
|
|
1056
|
-
const status = engine_1.$U.N($res.error?.status || $res.status);
|
|
1057
|
-
const reason = _S($res.error?.reason, $res.found === false || $res.result === 'not_found' ? 'NOT FOUND' : '');
|
|
1058
|
-
const type = _S(cause?.type).toUpperCase().split('_').slice(0, -1).join(' ');
|
|
1059
|
-
return { status, reason, cause, type: type || reason };
|
|
1060
|
-
})(E);
|
|
1061
|
-
//* FINAL. convert to error-object.
|
|
1062
|
-
return {
|
|
1063
|
-
status: engine_1.$U.N(status, reason?.status || 0),
|
|
1064
|
-
message: message || reason?.reason,
|
|
1065
|
-
reason,
|
|
1066
|
-
};
|
|
1067
|
-
},
|
|
1068
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1069
|
-
handler: (name, cb) => (e) => {
|
|
1070
|
-
const E = exports.$ERROR.asError(e);
|
|
1071
|
-
//* unknown error found..
|
|
1072
|
-
if (!E?.status) {
|
|
1073
|
-
(0, engine_1._err)(NS, `! err[${name}]@handler =`, e instanceof Error, engine_1.$U.json(e));
|
|
1074
|
-
throw e;
|
|
1075
|
-
}
|
|
1076
|
-
const $e = new Error(`${E.status} ${E.reason?.type ?? ''} - ${E.reason?.reason ?? E.message ?? ''}`);
|
|
1077
|
-
if (cb)
|
|
1078
|
-
return cb($e, E);
|
|
1079
|
-
throw $e;
|
|
1080
|
-
},
|
|
1081
|
-
};
|
|
1082
|
-
/** ****************************************************************************************************************
|
|
1083
|
-
* Dummy Elastic6 Service
|
|
1084
|
-
** ****************************************************************************************************************/
|
|
1085
|
-
/**
|
|
1086
|
-
* class: `DummyElastic6Service`
|
|
1087
|
-
* - service in-memory dummy data
|
|
1088
|
-
*/
|
|
1089
|
-
class DummyElastic6Service extends Elastic6Service {
|
|
1090
|
-
constructor(dataFile, options) {
|
|
1091
|
-
super(options);
|
|
1092
|
-
(0, engine_1._log)(NS, `DummyElastic6Service(${dataFile || ''})...`);
|
|
1093
|
-
if (!dataFile)
|
|
1094
|
-
throw new Error('@dataFile(string) is required!');
|
|
1095
|
-
const dummy = (0, tools_1.loadDataYml)(dataFile);
|
|
1096
|
-
this.load(dummy.data);
|
|
1097
|
-
}
|
|
1098
|
-
buffer = {};
|
|
1099
|
-
load(data) {
|
|
1100
|
-
const { idName } = this.options;
|
|
1101
|
-
if (!data || !Array.isArray(data))
|
|
1102
|
-
throw new Error('@data should be array!');
|
|
1103
|
-
data.map(item => {
|
|
1104
|
-
const id = `${item[idName] || ''}`;
|
|
1105
|
-
this.buffer[id] = item;
|
|
1106
|
-
});
|
|
1107
|
-
}
|
|
1108
|
-
/**
|
|
1109
|
-
* say hello()
|
|
1110
|
-
*/
|
|
1111
|
-
hello = () => `dummy-elastic6-service:${this.options.indexName}`;
|
|
1112
|
-
async readItem(id) {
|
|
1113
|
-
const item = this.buffer[id];
|
|
1114
|
-
if (item === undefined)
|
|
1115
|
-
throw new Error(`404 NOT FOUND - id:${id}`);
|
|
1116
|
-
return item;
|
|
1117
|
-
}
|
|
1118
|
-
async saveItem(id, item) {
|
|
1119
|
-
const { idName } = this.options;
|
|
1120
|
-
this.buffer[id] = { id, ...item };
|
|
1121
|
-
return { [idName]: id, ...item, _version: 1 };
|
|
1122
|
-
}
|
|
1123
|
-
async deleteItem(id, sort) {
|
|
1124
|
-
const org = this.buffer[id];
|
|
1125
|
-
delete this.buffer[id];
|
|
1126
|
-
return { ...org };
|
|
1127
|
-
}
|
|
1128
|
-
async updateItem(id, updates, increments) {
|
|
1129
|
-
const org = await this.readItem(id);
|
|
1130
|
-
const item = { ...org, ...updates, _version: Number(org._version || 0) + 1 };
|
|
1131
|
-
if (increments) {
|
|
1132
|
-
Object.entries(increments).forEach(([key, value]) => {
|
|
1133
|
-
if (Array.isArray(value)) {
|
|
1134
|
-
// case of arrary increment
|
|
1135
|
-
if (Array.isArray(item[key])) {
|
|
1136
|
-
item[key] = [...item[key], ...value];
|
|
1137
|
-
}
|
|
1138
|
-
else {
|
|
1139
|
-
item[key] = value;
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
else {
|
|
1143
|
-
if (typeof item[key] === 'number') {
|
|
1144
|
-
item[key] = item[key] + value;
|
|
1145
|
-
}
|
|
1146
|
-
else {
|
|
1147
|
-
item[key] = value;
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
});
|
|
1151
|
-
}
|
|
1152
|
-
this.buffer[id] = item;
|
|
1153
|
-
return { id: id, _version: Number(org._version || 0) + 1, ...updates };
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
exports.DummyElastic6Service = DummyElastic6Service;
|
|
17
|
+
//* v5 B3 shim: the file was renamed to `os2-service.ts`; this keeps the deep path `dist/cores/elastic/elastic6-service` resolving during v5 (removed with `./dist/*` in v6).
|
|
18
|
+
__exportStar(require("./os2-service"), exports);
|
|
1157
19
|
//# sourceMappingURL=elastic6-service.js.map
|