lemon-core 3.0.0 → 3.1.1
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 +13 -21
- package/dist/common/test-helper.js +19 -11
- package/dist/common/test-helper.js.map +1 -1
- package/dist/controllers/dummy-controller.d.ts +1 -1
- package/dist/controllers/dummy-controller.js +2 -2
- package/dist/controllers/dummy-controller.js.map +1 -1
- package/dist/controllers/general-api-controller.d.ts +1 -1
- package/dist/controllers/general-api-controller.js +5 -5
- package/dist/controllers/general-api-controller.js.map +1 -1
- package/dist/controllers/general-controller.js +2 -1
- package/dist/controllers/general-controller.js.map +1 -1
- package/dist/controllers/index.js +6 -2
- package/dist/controllers/index.js.map +1 -1
- package/dist/cores/api/api-service.d.ts +239 -0
- package/dist/cores/api/api-service.js +674 -0
- package/dist/cores/api/api-service.js.map +1 -0
- package/dist/cores/api/index.d.ts +10 -0
- package/dist/cores/api/index.js +27 -0
- package/dist/cores/api/index.js.map +1 -0
- package/dist/cores/api-service.js +19 -18
- package/dist/cores/api-service.js.map +1 -1
- package/dist/cores/aws/aws-kms-service.d.ts +53 -2
- package/dist/cores/aws/aws-kms-service.js +112 -29
- package/dist/cores/aws/aws-kms-service.js.map +1 -1
- package/dist/cores/aws/aws-s3-service.js +19 -18
- package/dist/cores/aws/aws-s3-service.js.map +1 -1
- package/dist/cores/aws/aws-sns-service.js +10 -10
- package/dist/cores/aws/aws-sns-service.js.map +1 -1
- package/dist/cores/aws/aws-sqs-service.js +12 -12
- package/dist/cores/aws/aws-sqs-service.js.map +1 -1
- package/dist/cores/aws/index.js +1 -1
- package/dist/cores/cache/cache-service.d.ts +440 -0
- package/dist/cores/cache/cache-service.js +967 -0
- package/dist/cores/cache/cache-service.js.map +1 -0
- package/dist/cores/cache/index.d.ts +10 -0
- package/dist/cores/cache/index.js +27 -0
- package/dist/cores/cache/index.js.map +1 -0
- package/dist/cores/cache-service.d.ts +54 -18
- package/dist/cores/cache-service.js +56 -45
- package/dist/cores/cache-service.js.map +1 -1
- package/dist/cores/config/config-service.js +11 -10
- package/dist/cores/config/config-service.js.map +1 -1
- package/dist/cores/core-services.js +6 -2
- package/dist/cores/core-services.js.map +1 -1
- package/dist/cores/core-types.d.ts +42 -12
- package/dist/cores/dynamo/dynamo-query-service.d.ts +52 -0
- package/dist/cores/dynamo/dynamo-query-service.js +127 -0
- package/dist/cores/dynamo/dynamo-query-service.js.map +1 -0
- package/dist/cores/dynamo/dynamo-scan-service.d.ts +70 -0
- package/dist/cores/dynamo/dynamo-scan-service.js +164 -0
- package/dist/cores/dynamo/dynamo-scan-service.js.map +1 -0
- package/dist/cores/dynamo/dynamo-service.d.ts +192 -0
- package/dist/cores/dynamo/dynamo-service.js +525 -0
- package/dist/cores/dynamo/dynamo-service.js.map +1 -0
- package/dist/cores/dynamo/index.d.ts +12 -0
- package/dist/cores/dynamo/index.js +29 -0
- package/dist/cores/dynamo/index.js.map +1 -0
- package/dist/cores/dynamo-query-service.js +7 -7
- package/dist/cores/dynamo-query-service.js.map +1 -1
- package/dist/cores/dynamo-scan-service.js +8 -8
- package/dist/cores/dynamo-scan-service.js.map +1 -1
- package/dist/cores/dynamo-service.js +19 -19
- package/dist/cores/dynamo-service.js.map +1 -1
- package/dist/cores/elastic/elastic6-query-service.d.ts +104 -0
- package/dist/cores/elastic/elastic6-query-service.js +510 -0
- package/dist/cores/elastic/elastic6-query-service.js.map +1 -0
- package/dist/cores/elastic/elastic6-service.d.ts +273 -0
- package/dist/cores/elastic/elastic6-service.js +903 -0
- package/dist/cores/elastic/elastic6-service.js.map +1 -0
- package/dist/cores/elastic/hangul-service.d.ts +102 -0
- package/dist/cores/elastic/hangul-service.js +205 -0
- package/dist/cores/elastic/hangul-service.js.map +1 -0
- package/dist/cores/elastic/index.d.ts +12 -0
- package/dist/cores/elastic/index.js +29 -0
- package/dist/cores/elastic/index.js.map +1 -0
- package/dist/cores/elastic6-query-service.js +7 -7
- package/dist/cores/elastic6-query-service.js.map +1 -1
- package/dist/cores/elastic6-service.js +57 -65
- package/dist/cores/elastic6-service.js.map +1 -1
- package/dist/cores/hangul-service.d.ts +17 -3
- package/dist/cores/hangul-service.js +17 -8
- package/dist/cores/hangul-service.js.map +1 -1
- package/dist/cores/http-storage-service.js +1 -1
- package/dist/cores/http-storage-service.js.map +1 -1
- package/dist/cores/index.d.ts +9 -15
- package/dist/cores/index.js +14 -15
- package/dist/cores/index.js.map +1 -1
- package/dist/cores/lambda/index.js +8 -4
- package/dist/cores/lambda/index.js.map +1 -1
- package/dist/cores/lambda/lambda-cognito-handler.js +2 -2
- package/dist/cores/lambda/lambda-cognito-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-cron-handler.js +2 -2
- package/dist/cores/lambda/lambda-cron-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-dynamo-stream-handler.d.ts +2 -2
- package/dist/cores/lambda/lambda-dynamo-stream-handler.js +20 -20
- package/dist/cores/lambda/lambda-dynamo-stream-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-handler.js +12 -11
- package/dist/cores/lambda/lambda-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-notification-handler.js +10 -10
- package/dist/cores/lambda/lambda-notification-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-sns-handler.js +13 -13
- package/dist/cores/lambda/lambda-sns-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-sqs-handler.js +13 -13
- package/dist/cores/lambda/lambda-sqs-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-web-handler.d.ts +158 -8
- package/dist/cores/lambda/lambda-web-handler.js +330 -119
- package/dist/cores/lambda/lambda-web-handler.js.map +1 -1
- package/dist/cores/lambda/lambda-wss-handler.js +16 -12
- package/dist/cores/lambda/lambda-wss-handler.js.map +1 -1
- package/dist/cores/model-manager.js +11 -11
- package/dist/cores/model-manager.js.map +1 -1
- package/dist/cores/protocol/protocol-service.d.ts +4 -0
- package/dist/cores/protocol/protocol-service.js +46 -40
- package/dist/cores/protocol/protocol-service.js.map +1 -1
- package/dist/cores/proxy-storage-service.js +7 -10
- package/dist/cores/proxy-storage-service.js.map +1 -1
- package/dist/cores/redis-storage-service.js +13 -13
- package/dist/cores/redis-storage-service.js.map +1 -1
- package/dist/cores/storage/http-storage-service.d.ts +22 -0
- package/dist/cores/storage/http-storage-service.js +129 -0
- package/dist/cores/storage/http-storage-service.js.map +1 -0
- package/dist/cores/storage/index.d.ts +14 -0
- package/dist/cores/storage/index.js +31 -0
- package/dist/cores/storage/index.js.map +1 -0
- package/dist/cores/storage/model-manager.d.ts +93 -0
- package/dist/cores/storage/model-manager.js +192 -0
- package/dist/cores/storage/model-manager.js.map +1 -0
- package/dist/cores/storage/proxy-storage-service.d.ts +573 -0
- package/dist/cores/storage/proxy-storage-service.js +913 -0
- package/dist/cores/storage/proxy-storage-service.js.map +1 -0
- package/dist/cores/storage/redis-storage-service.d.ts +183 -0
- package/dist/cores/storage/redis-storage-service.js +391 -0
- package/dist/cores/storage/redis-storage-service.js.map +1 -0
- package/dist/cores/storage/storage-service.d.ts +169 -0
- package/dist/cores/storage/storage-service.js +374 -0
- package/dist/cores/storage/storage-service.js.map +1 -0
- package/dist/cores/storage-service.d.ts +1 -1
- package/dist/cores/storage-service.js +10 -8
- package/dist/cores/storage-service.js.map +1 -1
- package/dist/engine/builder.js +27 -20
- package/dist/engine/builder.js.map +1 -1
- package/dist/engine/engine.js +53 -44
- package/dist/engine/engine.js.map +1 -1
- package/dist/engine/index.js +8 -4
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/utilities.d.ts +4 -3
- package/dist/engine/utilities.js +32 -37
- package/dist/engine/utilities.js.map +1 -1
- package/dist/environ.d.ts +2 -2
- package/dist/environ.js +20 -10
- package/dist/environ.js.map +1 -1
- package/dist/exec-cli.js +26 -26
- package/dist/exec-cli.js.map +1 -1
- package/dist/extended/abstract-service.d.ts +533 -0
- package/dist/extended/abstract-service.js +915 -0
- package/dist/extended/abstract-service.js.map +1 -0
- package/dist/extended/index.d.ts +10 -0
- package/dist/extended/index.js +27 -0
- package/dist/extended/index.js.map +1 -0
- package/dist/helpers/helpers.d.ts +273 -0
- package/dist/helpers/helpers.js +613 -0
- package/dist/helpers/helpers.js.map +1 -0
- package/dist/helpers/index.d.ts +10 -0
- package/dist/helpers/index.js +27 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.js +11 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/dynamo/expressions.js +35 -27
- package/dist/lib/dynamo/expressions.js.map +1 -1
- package/dist/lib/dynamo/query.js +24 -20
- package/dist/lib/dynamo/query.js.map +1 -1
- package/dist/lib/dynamo/scan.js +17 -13
- package/dist/lib/dynamo/scan.js.map +1 -1
- package/dist/lib/dynamo/serializer.js +11 -7
- package/dist/lib/dynamo/serializer.js.map +1 -1
- package/dist/lib/dynamo/utils.js +19 -14
- package/dist/lib/dynamo/utils.js.map +1 -1
- package/dist/lib/dynamodb-value.js +3 -3
- package/dist/lib/dynamodb-value.js.map +1 -1
- package/dist/lib/index.js +6 -2
- package/dist/lib/index.js.map +1 -1
- package/dist/tools/express.js +21 -15
- package/dist/tools/express.js.map +1 -1
- package/dist/tools/index.js +6 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/shared.js +12 -6
- package/dist/tools/shared.js.map +1 -1
- package/package.json +16 -15
|
@@ -0,0 +1,915 @@
|
|
|
1
|
+
"use strict";
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
35
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
36
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
37
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
38
|
+
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
39
|
+
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
|
|
40
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
41
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
42
|
+
function fulfill(value) { resume("next", value); }
|
|
43
|
+
function reject(value) { resume("throw", value); }
|
|
44
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
45
|
+
};
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.$ES6 = exports.sourceToItem = exports.Elastic6Instance = exports.Elastic6Synchronizer = exports.AbstractProxy = exports.ManagerProxy = exports.CoreManager = exports.CoreService = exports.filterFields = exports.asIdentityId = void 0;
|
|
48
|
+
/**
|
|
49
|
+
* `abstract-service.ts`
|
|
50
|
+
* - common service design pattern to build micro-service backend.
|
|
51
|
+
*
|
|
52
|
+
* @author Tim Hong <tim@lemoncloud.io>
|
|
53
|
+
* @date 2021-02-23 initial version
|
|
54
|
+
* @author Steve <steve@lemoncloud.io>
|
|
55
|
+
* @date 2022-02-18 optimized search w/ ES6.8
|
|
56
|
+
* @date 2022-02-22 optimized w/ `lemon-core#3.0` and `@elastic/elasticsearch`
|
|
57
|
+
* @date 2022-02-24 use `$id` in elastic-search as `_id` in dynamo-table.
|
|
58
|
+
* @date 2022-03-15 optimized w/ `AbstractProxy`
|
|
59
|
+
* @date 2022-03-17 optimized w/ `lemon-core#3.0.2` and use `env.ES6_DOCTYPE`
|
|
60
|
+
* @date 2022-03-31 optimized w/ unit test spec.
|
|
61
|
+
* @date 2022-05-19 optimized `CacheService` w/ typed key.
|
|
62
|
+
*
|
|
63
|
+
* @origin see `lemon-accounts-api/src/service/core-service.ts`
|
|
64
|
+
* @copyright (C) 2021 LemonCloud Co Ltd. - All Rights Reserved.
|
|
65
|
+
*/
|
|
66
|
+
const cores_1 = __importStar(require("../cores/"));
|
|
67
|
+
const engine_1 = require("../engine/");
|
|
68
|
+
const test_helper_1 = require("../common/test-helper");
|
|
69
|
+
const helpers_1 = require("../helpers");
|
|
70
|
+
const NS = engine_1.$U.NS('back', 'blue'); // NAMESPACE TO BE PRINTED.
|
|
71
|
+
/**
|
|
72
|
+
* authentication helper - get identity-id from context
|
|
73
|
+
* @param context the current request context.
|
|
74
|
+
*/
|
|
75
|
+
function asIdentityId(context) {
|
|
76
|
+
var _a;
|
|
77
|
+
return (_a = context === null || context === void 0 ? void 0 : context.identity) === null || _a === void 0 ? void 0 : _a.identityId;
|
|
78
|
+
}
|
|
79
|
+
exports.asIdentityId = asIdentityId;
|
|
80
|
+
/**
|
|
81
|
+
* extract field names from models
|
|
82
|
+
* - only fields start with lowercase, or all upper.
|
|
83
|
+
*/
|
|
84
|
+
const filterFields = (fields, base = []) => fields
|
|
85
|
+
.filter(field => /^[a-z]+/.test(field) || /^[A-Z_]+$/.test(field))
|
|
86
|
+
.reduce((L, k) => {
|
|
87
|
+
if (k && !L.includes(k))
|
|
88
|
+
L.push(k);
|
|
89
|
+
return L;
|
|
90
|
+
}, [...base]);
|
|
91
|
+
exports.filterFields = filterFields;
|
|
92
|
+
/**
|
|
93
|
+
* abstract class `CoreService`
|
|
94
|
+
* - common abstract to build user service
|
|
95
|
+
*
|
|
96
|
+
* @abstract
|
|
97
|
+
*/
|
|
98
|
+
class CoreService extends cores_1.GeneralKeyMaker {
|
|
99
|
+
/**
|
|
100
|
+
* constructor
|
|
101
|
+
* @param tableName target table-name (or .yml dummy file-name)
|
|
102
|
+
* @param ns namespace of dataset
|
|
103
|
+
* @param idName must be `_id` unless otherwise
|
|
104
|
+
*/
|
|
105
|
+
constructor(tableName, ns, idName) {
|
|
106
|
+
super(ns || engine_1.$U.env('NS', 'TT'));
|
|
107
|
+
/** (optional) current timestamp */
|
|
108
|
+
this.current = 0; // for unit-test. set the current time-stamp.
|
|
109
|
+
/**
|
|
110
|
+
* override current time
|
|
111
|
+
*/
|
|
112
|
+
this.setCurrent = (current) => (this.current = current);
|
|
113
|
+
this.tableName = tableName || engine_1.$U.env('MY_DYNAMO_TABLE', 'Test');
|
|
114
|
+
this.idName = idName || '_id';
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* get the current dynamo-options.
|
|
118
|
+
*/
|
|
119
|
+
get dynamoOptions() {
|
|
120
|
+
return {
|
|
121
|
+
tableName: this.tableName,
|
|
122
|
+
idName: this.idName,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* create storage-service w/ fields list.
|
|
127
|
+
*/
|
|
128
|
+
makeStorageService(type, fields, filter) {
|
|
129
|
+
//! use proxy-storage-service for both dynamo-table and dummy-data.
|
|
130
|
+
const storage = new cores_1.ProxyStorageService(this, this.tableName, fields, filter, this.idName);
|
|
131
|
+
storage.setTimer(() => (this.current ? this.current : new Date().getTime()));
|
|
132
|
+
return storage.makeTypedStorageService(type);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
exports.CoreService = CoreService;
|
|
136
|
+
/**
|
|
137
|
+
* class: `CoreManager`
|
|
138
|
+
* - shared core manager for all model
|
|
139
|
+
*
|
|
140
|
+
* @abstract
|
|
141
|
+
*/
|
|
142
|
+
class CoreManager extends cores_1.AbstractManager {
|
|
143
|
+
/**
|
|
144
|
+
* constructor
|
|
145
|
+
* @protected
|
|
146
|
+
*/
|
|
147
|
+
constructor(type, parent, fields, uniqueField) {
|
|
148
|
+
super(type, parent, fields, uniqueField);
|
|
149
|
+
/**
|
|
150
|
+
* say hello()
|
|
151
|
+
*/
|
|
152
|
+
this.hello = () => `${this.storage.hello()}`;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* get existence of model
|
|
156
|
+
* @param id
|
|
157
|
+
*/
|
|
158
|
+
exists(id) {
|
|
159
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
160
|
+
return (yield this.find(id)) !== null;
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* find model - retrieve or null
|
|
165
|
+
* @param id model-id
|
|
166
|
+
*/
|
|
167
|
+
find(id) {
|
|
168
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
169
|
+
return this.retrieve(id).catch(e => {
|
|
170
|
+
if ((0, test_helper_1.GETERR)(e).startsWith('404 NOT FOUND'))
|
|
171
|
+
return null;
|
|
172
|
+
throw e;
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* get model by key
|
|
178
|
+
* @param key global id(like primary-key)
|
|
179
|
+
*/
|
|
180
|
+
findByKey(key) {
|
|
181
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
182
|
+
return this.storage.storage.read(key).catch(e => {
|
|
183
|
+
if ((0, test_helper_1.GETERR)(e).startsWith('404 NOT FOUND'))
|
|
184
|
+
return null;
|
|
185
|
+
throw e;
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* batch get models
|
|
191
|
+
* - retrieve multi models per each id
|
|
192
|
+
* - must be matched with idList in sequence order.
|
|
193
|
+
*
|
|
194
|
+
* @param idList list of id
|
|
195
|
+
* @param parrallel (optional) in parrallel size
|
|
196
|
+
*/
|
|
197
|
+
getMulti(idList, parrallel) {
|
|
198
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
const $map = yield this.getMulti$(idList, 'id', parrallel);
|
|
200
|
+
return idList.map(id => { var _a; return (_a = $map[id]) !== null && _a !== void 0 ? _a : null; }).map(N => { var _a; return (((_a = N === null || N === void 0 ? void 0 : N.error) === null || _a === void 0 ? void 0 : _a.startsWith('404 NOT FOUND')) ? null : N); });
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* batch get models in map by idName
|
|
205
|
+
*/
|
|
206
|
+
getMulti$(idList, idName = 'id', parrallel) {
|
|
207
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
208
|
+
// 1. find items in unique
|
|
209
|
+
const ids = idList.reduce((L, id) => {
|
|
210
|
+
if (id && !L.includes(id))
|
|
211
|
+
L.push(id);
|
|
212
|
+
return L;
|
|
213
|
+
}, []);
|
|
214
|
+
// 2. find from storage.
|
|
215
|
+
const list = yield (0, helpers_1.my_parrallel)(ids.map(id => ({ id })), N => this.retrieve(N.id), parrallel);
|
|
216
|
+
// 3. convert to map
|
|
217
|
+
return helpers_1.$T.asMap(list, idName);
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* get by unique field value
|
|
222
|
+
* @param uniqueValue
|
|
223
|
+
*/
|
|
224
|
+
getByUniqueField(uniqueValue) {
|
|
225
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
226
|
+
return this.$unique.findOrCreate(uniqueValue);
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* find model by unique field value - retrieve or null
|
|
231
|
+
* @param uniqueValue
|
|
232
|
+
*/
|
|
233
|
+
findByUniqueField(uniqueValue) {
|
|
234
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
235
|
+
return this.getByUniqueField(uniqueValue).catch(e => {
|
|
236
|
+
if ((0, test_helper_1.GETERR)(e).startsWith('404 NOT FOUND'))
|
|
237
|
+
return null;
|
|
238
|
+
throw e;
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* prepare model
|
|
244
|
+
* - override `AbstractManager.prepare()`
|
|
245
|
+
*/
|
|
246
|
+
prepare(id, $def, isCreate = true) {
|
|
247
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
248
|
+
const $org = yield this.find(id);
|
|
249
|
+
if ($org)
|
|
250
|
+
return $org;
|
|
251
|
+
if (!isCreate || $def === undefined)
|
|
252
|
+
throw new Error(`404 NOT FOUND - ${this.type}:${id}`);
|
|
253
|
+
const model = this.prepareDefault($def);
|
|
254
|
+
// create or update lookup
|
|
255
|
+
if (this.$unique)
|
|
256
|
+
yield this.updateLookup(id, model, $org);
|
|
257
|
+
// save target model
|
|
258
|
+
const $saved = yield this.storage.save(id, Object.assign(Object.assign({}, model), { id }));
|
|
259
|
+
return Object.assign(Object.assign(Object.assign({}, model), $saved), { id });
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* update model
|
|
264
|
+
* - override 'AbstractManager.insert()'
|
|
265
|
+
*
|
|
266
|
+
* @deprecated use `AbstractProxy`
|
|
267
|
+
*/
|
|
268
|
+
insert(model, initSeq) {
|
|
269
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
270
|
+
const id = helpers_1.$T.S(yield this.storage.storage.nextSeq(this.type, initSeq));
|
|
271
|
+
return this.save(id, model);
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* create or update model
|
|
276
|
+
* @param id model id
|
|
277
|
+
* @param model model data
|
|
278
|
+
*/
|
|
279
|
+
save(id, model) {
|
|
280
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
281
|
+
if (!id)
|
|
282
|
+
throw new Error(`@id is requird - save()`);
|
|
283
|
+
const $org = yield this.find(id);
|
|
284
|
+
if (!$org)
|
|
285
|
+
model = this.prepareDefault(model);
|
|
286
|
+
// create or update lookup
|
|
287
|
+
if (this.$unique)
|
|
288
|
+
yield this.updateLookup(id, model, $org);
|
|
289
|
+
// save target model
|
|
290
|
+
const $saved = yield this.storage.save(id, model);
|
|
291
|
+
return Object.assign(Object.assign(Object.assign({}, $org), $saved), { id });
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* update model
|
|
296
|
+
* - override 'AbstractManager.update()'
|
|
297
|
+
*/
|
|
298
|
+
update(id, model, $inc) {
|
|
299
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
300
|
+
if (!id)
|
|
301
|
+
throw new Error(`@id is requird - update()`);
|
|
302
|
+
const $org = yield this.retrieve(id);
|
|
303
|
+
// update lookup
|
|
304
|
+
if (this.$unique)
|
|
305
|
+
yield this.updateLookup(id, model, $org);
|
|
306
|
+
// update target model
|
|
307
|
+
model = this.beforeSave(model, $org);
|
|
308
|
+
const $updated = yield this.storage.update(id, model, $inc);
|
|
309
|
+
return Object.assign(Object.assign(Object.assign({}, $org), $updated), { id });
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* update or create model
|
|
314
|
+
* - override 'AbstractManager.updateOrCreate()'
|
|
315
|
+
*/
|
|
316
|
+
updateOrCreate(id, model, $inc) {
|
|
317
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
318
|
+
if (!id)
|
|
319
|
+
throw new Error(`@id is requird - updateOrCreate()`);
|
|
320
|
+
const $org = yield this.prepare(id, model);
|
|
321
|
+
// update lookup
|
|
322
|
+
if (this.$unique)
|
|
323
|
+
yield this.updateLookup(id, model, $org);
|
|
324
|
+
// update target model
|
|
325
|
+
model = this.beforeSave(model, $org);
|
|
326
|
+
const $updated = yield this.storage.update(id, model, $inc);
|
|
327
|
+
return Object.assign(Object.assign(Object.assign({}, $org), $updated), { id });
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* delete model
|
|
332
|
+
* - override 'AbstractManager.delete()'
|
|
333
|
+
*/
|
|
334
|
+
delete(id, destroy) {
|
|
335
|
+
const _super = Object.create(null, {
|
|
336
|
+
delete: { get: () => super.delete }
|
|
337
|
+
});
|
|
338
|
+
var _a;
|
|
339
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
340
|
+
if (!id)
|
|
341
|
+
throw new Error(`@id is requird - delete()`);
|
|
342
|
+
// delete target model
|
|
343
|
+
const $org = yield _super.delete.call(this, id, destroy);
|
|
344
|
+
// delete lookup
|
|
345
|
+
const uniqueField = (_a = this.$unique) === null || _a === void 0 ? void 0 : _a.field;
|
|
346
|
+
const uniqueValue = uniqueField && $org[uniqueField];
|
|
347
|
+
if (uniqueValue)
|
|
348
|
+
yield this.storage.delete(this.$unique.asLookupId(uniqueValue));
|
|
349
|
+
return $org;
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* prepare default-model when creation
|
|
354
|
+
* @param $def base-model
|
|
355
|
+
*/
|
|
356
|
+
prepareDefault($def) {
|
|
357
|
+
return Object.assign({}, $def);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* update lookup and delete old one if exists
|
|
361
|
+
*/
|
|
362
|
+
updateLookup(id, model, $org) {
|
|
363
|
+
var _a;
|
|
364
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
365
|
+
const uniqueField = (_a = this.$unique) === null || _a === void 0 ? void 0 : _a.field;
|
|
366
|
+
const newUniqueValue = uniqueField && model[uniqueField];
|
|
367
|
+
const oldUniqueValue = uniqueField && ($org === null || $org === void 0 ? void 0 : $org[uniqueField]);
|
|
368
|
+
// update lookup.
|
|
369
|
+
if (newUniqueValue && newUniqueValue !== oldUniqueValue) {
|
|
370
|
+
yield this.$unique.updateLookup(Object.assign({ id }, model));
|
|
371
|
+
// remove old lookup
|
|
372
|
+
if (oldUniqueValue) {
|
|
373
|
+
yield this.storage.delete(this.$unique.asLookupId(oldUniqueValue));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
exports.CoreManager = CoreManager;
|
|
380
|
+
/**
|
|
381
|
+
* proxy of manager
|
|
382
|
+
* - save model internally, and update only if changed properties.
|
|
383
|
+
* Model extends CoreModel<ModelType>, ModelType extends string
|
|
384
|
+
*/
|
|
385
|
+
// export class ManagerProxy<T, U extends CoreManager<T, any, any>> {
|
|
386
|
+
class ManagerProxy {
|
|
387
|
+
constructor(proxy, mgr) {
|
|
388
|
+
/**
|
|
389
|
+
* store the origin model.
|
|
390
|
+
* - `null` means `404 not found`
|
|
391
|
+
*/
|
|
392
|
+
this._org = {};
|
|
393
|
+
/**
|
|
394
|
+
* store the updated one.
|
|
395
|
+
*/
|
|
396
|
+
this._new = {};
|
|
397
|
+
/**
|
|
398
|
+
* 객체 정규화 시킴.
|
|
399
|
+
* - null 에 대해서는 특별히 처리.
|
|
400
|
+
*/
|
|
401
|
+
this.normal = (N) => Object.keys(N || {}).reduce((M, k) => {
|
|
402
|
+
if (k.startsWith('_') || k.startsWith('$'))
|
|
403
|
+
return M;
|
|
404
|
+
const v = N[k];
|
|
405
|
+
//! `null` 은 DynamoDB에서 비어있는 문자임.
|
|
406
|
+
M[k] = v === null ? '' : v;
|
|
407
|
+
return M;
|
|
408
|
+
}, {});
|
|
409
|
+
/**
|
|
410
|
+
* override w/ model
|
|
411
|
+
* @param $org the origin model by `.get(id)`
|
|
412
|
+
* @param model the new model.
|
|
413
|
+
*/
|
|
414
|
+
this.override = ($org, model) => {
|
|
415
|
+
const fields = this.$mgr.FIELDS;
|
|
416
|
+
//! update(set) all properties.
|
|
417
|
+
Object.entries(model).forEach(([key, val]) => {
|
|
418
|
+
if (!fields || fields.includes(key)) {
|
|
419
|
+
$org[key] = val;
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
return $org;
|
|
423
|
+
};
|
|
424
|
+
this.$mgr = mgr;
|
|
425
|
+
proxy.register(this);
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* get storage linked.
|
|
429
|
+
*/
|
|
430
|
+
get storage() {
|
|
431
|
+
return this.$mgr.storage;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* read the origin node (cloned not to change).
|
|
435
|
+
*/
|
|
436
|
+
org(id, raw = false) {
|
|
437
|
+
const O = this._org[id];
|
|
438
|
+
return O === undefined ? null : raw ? O : Object.assign({}, O);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* check if already read.
|
|
442
|
+
*/
|
|
443
|
+
has(id) {
|
|
444
|
+
return this.org(id) ? true : false;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* read the node.
|
|
448
|
+
* @param id object-id
|
|
449
|
+
* @param defaultOrThrow (optional) create if not exists, or flag to throw error
|
|
450
|
+
*/
|
|
451
|
+
get(id, defaultOrThrow) {
|
|
452
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
453
|
+
const err404 = `404 NOT FOUND - proxy/${this.$mgr.type}/id:${id}`;
|
|
454
|
+
const throwable = typeof defaultOrThrow === 'boolean' ? defaultOrThrow : true;
|
|
455
|
+
const $def = typeof defaultOrThrow === 'boolean' ? null : defaultOrThrow;
|
|
456
|
+
// STEP.0 validate if null (404 error)
|
|
457
|
+
if (this._org[id] === null && !$def) {
|
|
458
|
+
if (throwable)
|
|
459
|
+
throw new Error(err404);
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
// STEP.1 find from `new`
|
|
463
|
+
const N = this._new[id];
|
|
464
|
+
if (N !== undefined)
|
|
465
|
+
return N;
|
|
466
|
+
// OR, READ (or CREATE) from storage.
|
|
467
|
+
const M = !$def ? yield this.$mgr.retrieve(id).catch(test_helper_1.NUL404) : yield this.$mgr.prepare(id, $def, true);
|
|
468
|
+
if (M === null) {
|
|
469
|
+
this._org[id] = null; //! null 로 저장해두고, 다음에 호출할때 에러 발생.
|
|
470
|
+
if (throwable)
|
|
471
|
+
throw new Error(err404);
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
const M2 = this.normal(M);
|
|
475
|
+
this._org[id] = M2; //! 원본 저장.
|
|
476
|
+
// const M3 = { ...M2 }; //! 클론 생성.
|
|
477
|
+
const M3 = JSON.parse(engine_1.$U.json(M2)); //! deep clone.
|
|
478
|
+
this._new[id] = M3; //! 클론 저장.
|
|
479
|
+
return M3;
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* update the node.
|
|
484
|
+
*/
|
|
485
|
+
set(id, model) {
|
|
486
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
487
|
+
if (!model)
|
|
488
|
+
throw new Error(`@model (object) is required - proxy/${this.$mgr.type}/id:${id}!`);
|
|
489
|
+
const O = yield this.get(id);
|
|
490
|
+
return this.override(O, model);
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* increment the field of Object[id]
|
|
495
|
+
* !WARN! this incremented properties should NOT be updated later.
|
|
496
|
+
*/
|
|
497
|
+
inc(id, model) {
|
|
498
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
499
|
+
if (!model)
|
|
500
|
+
throw new Error(`@model (object) is required - proxy/${this.$mgr.type}/id:${id}!`);
|
|
501
|
+
const $inc = Object.entries(model).reduce((M, [k, v]) => {
|
|
502
|
+
if (typeof v === 'number')
|
|
503
|
+
M[k] = v;
|
|
504
|
+
return M;
|
|
505
|
+
}, {});
|
|
506
|
+
const keys = Object.keys($inc);
|
|
507
|
+
if (!keys.length)
|
|
508
|
+
throw new Error(`@model (object) is empty to inc() - proxy/${this.$mgr.type}/id:${id}!`);
|
|
509
|
+
//! try to increment, and update the latest to both org and new.
|
|
510
|
+
const $res = yield this.$mgr.storage.update(id, null, $inc);
|
|
511
|
+
const $new = yield this.get(id);
|
|
512
|
+
const $org = this.org(id, true);
|
|
513
|
+
return keys.reduce((N, k) => {
|
|
514
|
+
const key = k;
|
|
515
|
+
N[key] = $org[key] = $res[key];
|
|
516
|
+
return N;
|
|
517
|
+
}, $new);
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* get all the updated node.
|
|
522
|
+
*
|
|
523
|
+
* @param onlyUpdated flag to return the only updated set. (useful to check whether to update really!)
|
|
524
|
+
*/
|
|
525
|
+
alls(onlyUpdated = true, onlyValid = true) {
|
|
526
|
+
const ids = Object.keys(this._new).sort();
|
|
527
|
+
return ids.reduce((M, id) => {
|
|
528
|
+
const O = this._org[id];
|
|
529
|
+
const N = this._new[id];
|
|
530
|
+
const N2 = this.$mgr.onBeforeSave(Object.assign({}, N), O);
|
|
531
|
+
const N3 = onlyUpdated ? helpers_1.$T.diff(O, N2, onlyValid) : N2;
|
|
532
|
+
M[id] = N3;
|
|
533
|
+
return M;
|
|
534
|
+
}, {});
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
exports.ManagerProxy = ManagerProxy;
|
|
538
|
+
/**
|
|
539
|
+
* class: `AbstractProxy`
|
|
540
|
+
* - common abstract based class for Proxy
|
|
541
|
+
*/
|
|
542
|
+
class AbstractProxy {
|
|
543
|
+
/**
|
|
544
|
+
* constructor of proxy.
|
|
545
|
+
* @param service user service instance
|
|
546
|
+
* @param parrallel parrallel count (default 2)
|
|
547
|
+
* @param cacheScope prefix of cache-key (like `lemon:SS:` or `lemon:SS:user`)
|
|
548
|
+
*/
|
|
549
|
+
constructor(context, service, parrallel = 2, cacheScope) {
|
|
550
|
+
/**
|
|
551
|
+
* say hello().
|
|
552
|
+
*/
|
|
553
|
+
this.hello = () => `manager-proxy:${this.service.NS}/${this.service.tableName}`;
|
|
554
|
+
/**
|
|
555
|
+
* list of manager-proxy
|
|
556
|
+
*/
|
|
557
|
+
this._proxies = [];
|
|
558
|
+
/**
|
|
559
|
+
* report via slack.
|
|
560
|
+
*/
|
|
561
|
+
this.report = (title, data) => __awaiter(this, void 0, void 0, function* () {
|
|
562
|
+
const context = this.context;
|
|
563
|
+
return (0, helpers_1.$slack)(title, data, null, { context }).catch(e => `ERR:${(0, test_helper_1.GETERR)(e)}`);
|
|
564
|
+
});
|
|
565
|
+
/**
|
|
566
|
+
* the cached identity model
|
|
567
|
+
*/
|
|
568
|
+
this._identity = {};
|
|
569
|
+
this.context = context;
|
|
570
|
+
this.service = service;
|
|
571
|
+
this.parrallel = parrallel;
|
|
572
|
+
// create cache
|
|
573
|
+
const endpoint = engine_1.$U.env('CACHE_ENDPOINT', '');
|
|
574
|
+
if (cacheScope && endpoint.startsWith('redis:')) {
|
|
575
|
+
this.cache = cores_1.CacheService.create({ type: 'redis', endpoint, ns: cacheScope });
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* get all proxies in list.
|
|
580
|
+
*/
|
|
581
|
+
get allProxies() {
|
|
582
|
+
return this._proxies;
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* register this.
|
|
586
|
+
*/
|
|
587
|
+
register(mgr) {
|
|
588
|
+
this._proxies.push(mgr);
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* 업데이트할 항목을 모두 저장함
|
|
592
|
+
*/
|
|
593
|
+
saveAllUpdates(parrallel) {
|
|
594
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
595
|
+
parrallel = engine_1.$U.N(parrallel, this.parrallel);
|
|
596
|
+
// STEP.1 prepare the list of updater.
|
|
597
|
+
const list = this.allProxies.reduce((L, $p) => {
|
|
598
|
+
const $set = $p.alls(true);
|
|
599
|
+
return Object.entries($set).reduce((L, [id, N]) => {
|
|
600
|
+
const hasUpdate = Object.keys(N).length > 0;
|
|
601
|
+
if (hasUpdate) {
|
|
602
|
+
(0, engine_1._log)(NS, `>> ${$p.$mgr.type}/${id} =`, engine_1.$U.json(N));
|
|
603
|
+
const _ = () => $p.$mgr.storage.update(id, N);
|
|
604
|
+
L.push({ id, N, _ });
|
|
605
|
+
}
|
|
606
|
+
return L;
|
|
607
|
+
}, L);
|
|
608
|
+
}, []);
|
|
609
|
+
// STEP.2 finally update storage.
|
|
610
|
+
return (0, helpers_1.my_parrallel)(list, (N) => __awaiter(this, void 0, void 0, function* () {
|
|
611
|
+
return typeof N._ === 'function' ? N._() : null;
|
|
612
|
+
}), parrallel);
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* featch identity-acess from `lemon-accounts-api`
|
|
617
|
+
*/
|
|
618
|
+
fetchIdentityAccess(identityId, domain) {
|
|
619
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
620
|
+
domain = helpers_1.$T.S(domain, this.context.domain);
|
|
621
|
+
if (!identityId)
|
|
622
|
+
throw new Error(`.identityId (string) is required - fetchAccess(${domain})`);
|
|
623
|
+
// 1. get user detail by invoking 'lemon-accounts-api/pack-context'
|
|
624
|
+
const service = '//lemon-accounts-api/oauth/0/pack-context';
|
|
625
|
+
const body = { domain, identityId };
|
|
626
|
+
const $identity = yield (0, helpers_1.$protocol)(this.context, service)
|
|
627
|
+
.execute({}, body, 'POST')
|
|
628
|
+
.catch(test_helper_1.NUL404);
|
|
629
|
+
(0, engine_1._log)(NS, `> identity[${domain}] =`, engine_1.$U.json($identity));
|
|
630
|
+
//WARN! - $identity can be null (or .Account can be null)
|
|
631
|
+
// if (!$identity?.Account)
|
|
632
|
+
// throw new Error(`.Account(NextIdentityAccess) is invalid - fetchAccess(${domain}/${identityId})`);
|
|
633
|
+
return { identityId, $identity };
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
getIdentity$(identityId) {
|
|
637
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
638
|
+
// STEP.1 check if in stock.
|
|
639
|
+
const val = this._identity[identityId];
|
|
640
|
+
if (val !== undefined)
|
|
641
|
+
return val;
|
|
642
|
+
// STEP.2 fetch remotely, and save
|
|
643
|
+
const { $identity } = yield this.fetchIdentityAccess(identityId);
|
|
644
|
+
this._identity[identityId] = $identity;
|
|
645
|
+
return $identity;
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* get current identity-id
|
|
650
|
+
*/
|
|
651
|
+
getCurrentIdentityId(throwable = true) {
|
|
652
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
653
|
+
const identityId = asIdentityId(this.context) || '';
|
|
654
|
+
if (!identityId && throwable)
|
|
655
|
+
throw new Error(`400 NOT ALLOWED - getCurrentIdentity(${identityId || ''})`);
|
|
656
|
+
return identityId;
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* get the current identity object (or throw access-error)
|
|
661
|
+
*/
|
|
662
|
+
getCurrentIdentity$(throwable = true) {
|
|
663
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
664
|
+
const identityId = yield this.getCurrentIdentityId(throwable);
|
|
665
|
+
if (!identityId && !throwable)
|
|
666
|
+
return null;
|
|
667
|
+
return this.getIdentity$(identityId);
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
exports.AbstractProxy = AbstractProxy;
|
|
672
|
+
/**
|
|
673
|
+
* class `Elastic6Synchronizer`
|
|
674
|
+
* - listen DynamoDBStream events and index into Elasticsearch
|
|
675
|
+
*/
|
|
676
|
+
class Elastic6Synchronizer {
|
|
677
|
+
/**
|
|
678
|
+
* constructor
|
|
679
|
+
* @param elastic elastic6-service instance
|
|
680
|
+
* @param dynamoOptions dynamo options
|
|
681
|
+
*/
|
|
682
|
+
constructor(elastic, dynamoOptions) {
|
|
683
|
+
/**
|
|
684
|
+
* internal callback for filtering
|
|
685
|
+
* @private
|
|
686
|
+
*/
|
|
687
|
+
this.filter = (id, item) => {
|
|
688
|
+
var _a, _b;
|
|
689
|
+
const handler = this.synchronizerMap.get(item.type);
|
|
690
|
+
if (handler)
|
|
691
|
+
return (_b = (_a = handler.filter) === null || _a === void 0 ? void 0 : _a.call(handler, id, item)) !== null && _b !== void 0 ? _b : true; // 핸들러를 등록했다면 filter 메서드를 정의하지 않았더라도 sync 한다.
|
|
692
|
+
return false; // 핸들러가 등록되지 않았다면 sync하지 않는다.
|
|
693
|
+
};
|
|
694
|
+
/**
|
|
695
|
+
* internal callback on before synchronization
|
|
696
|
+
* @private
|
|
697
|
+
*/
|
|
698
|
+
this.onBeforeSync = (id, eventName, item, diff, prev) => __awaiter(this, void 0, void 0, function* () {
|
|
699
|
+
var _a;
|
|
700
|
+
const handler = this.synchronizerMap.get(item.type);
|
|
701
|
+
if (handler)
|
|
702
|
+
yield ((_a = handler.onBeforeSync) === null || _a === void 0 ? void 0 : _a.call(handler, id, eventName, item, diff, prev));
|
|
703
|
+
});
|
|
704
|
+
/**
|
|
705
|
+
* internal callback on after synchronization
|
|
706
|
+
* @private
|
|
707
|
+
*/
|
|
708
|
+
this.onAfterSync = (id, eventName, item, diff, prev) => __awaiter(this, void 0, void 0, function* () {
|
|
709
|
+
var _b;
|
|
710
|
+
const handler = this.synchronizerMap.get(item.type);
|
|
711
|
+
if (handler)
|
|
712
|
+
yield ((_b = handler.onAfterSync) === null || _b === void 0 ? void 0 : _b.call(handler, id, eventName, item, diff, prev));
|
|
713
|
+
});
|
|
714
|
+
if (!elastic)
|
|
715
|
+
throw new Error(`@elastic (elastic-service) is required!`);
|
|
716
|
+
if (!dynamoOptions)
|
|
717
|
+
throw new Error(`@dynamoOptions (object) is required!`);
|
|
718
|
+
//! build dynamo-options as default.
|
|
719
|
+
const options = Object.assign(Object.assign({}, dynamoOptions), { idName: dynamoOptions.idName || '_id' });
|
|
720
|
+
//! create sync-handler w/ this.
|
|
721
|
+
const listener = cores_1.LambdaDynamoStreamHandler.createSyncToElastic6(options, elastic, this.filter.bind(this), this.onBeforeSync.bind(this), this.onAfterSync.bind(this));
|
|
722
|
+
cores_1.default.lambda.dynamos.addListener(listener); // register DynamoStream event listener
|
|
723
|
+
//! prepare default synchro
|
|
724
|
+
this.synchronizerMap = new Map();
|
|
725
|
+
this.defModelSynchronizer = new (class {
|
|
726
|
+
filter(id, item) {
|
|
727
|
+
const type = `${(item === null || item === void 0 ? void 0 : item.type) || ''}`;
|
|
728
|
+
const stereo = `${(item === null || item === void 0 ? void 0 : item.stereo) || ''}`;
|
|
729
|
+
return !(type.startsWith('#') || stereo.startsWith('#')); // special purpose item. do not index.
|
|
730
|
+
}
|
|
731
|
+
})();
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* set synchronizer for the model
|
|
735
|
+
* @param type the model-type
|
|
736
|
+
* @param handler (optional) custom synchronizer.
|
|
737
|
+
*/
|
|
738
|
+
enableSynchronization(type, handler) {
|
|
739
|
+
this.synchronizerMap.set(type, handler !== null && handler !== void 0 ? handler : this.defModelSynchronizer);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
exports.Elastic6Synchronizer = Elastic6Synchronizer;
|
|
743
|
+
/**
|
|
744
|
+
* class `ElasticInstance`
|
|
745
|
+
* - to manipulate the shared Elasticsearch resources.
|
|
746
|
+
*/
|
|
747
|
+
class Elastic6Instance {
|
|
748
|
+
/**
|
|
749
|
+
* default constructor
|
|
750
|
+
*/
|
|
751
|
+
constructor({ endpoint, indexName, esVersion, esDocType, tableName, autocompleteFields, }) {
|
|
752
|
+
// const endpoint = $U.env('ES6_ENDPOINT', '');
|
|
753
|
+
// const indexName = $U.env('ES6_INDEX', 'test-v1');
|
|
754
|
+
// const esVersion = $U.env('ES6_VERSION', '6.8'); //! version of elastic server (default 6.8)
|
|
755
|
+
// const esDocType = $U.env('ES6_DOCTYPE', ''); //! version of elastic server (default `_doc`)
|
|
756
|
+
// const tableName = $U.env('MY_DYNAMO_TABLE', 'Test');
|
|
757
|
+
// const autocompleteFields = $T.SS($U.env('ES6_AUTOCOMPLETE_FIELDS', ''));
|
|
758
|
+
// initialize Elasticsearch only if valid endpoint.
|
|
759
|
+
if (endpoint && indexName) {
|
|
760
|
+
const options = {
|
|
761
|
+
endpoint,
|
|
762
|
+
indexName,
|
|
763
|
+
version: esVersion,
|
|
764
|
+
autocompleteFields,
|
|
765
|
+
};
|
|
766
|
+
if (esDocType)
|
|
767
|
+
options.docType = esDocType;
|
|
768
|
+
this.elastic = new cores_1.Elastic6Service(options);
|
|
769
|
+
this.client = this.elastic.client;
|
|
770
|
+
this.query = new cores_1.Elastic6QueryService(this.elastic);
|
|
771
|
+
this.synchronizer = new Elastic6Synchronizer(this.elastic, { tableName });
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* read the current elastic6-option.
|
|
776
|
+
*/
|
|
777
|
+
get options() {
|
|
778
|
+
if (!this.elastic)
|
|
779
|
+
return null;
|
|
780
|
+
return this.elastic.options;
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* create Elasticsearch index w/ custom settings
|
|
784
|
+
*/
|
|
785
|
+
createIndex() {
|
|
786
|
+
var _a, _b;
|
|
787
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
788
|
+
if (this.elastic) {
|
|
789
|
+
const { docType, idName } = this.options;
|
|
790
|
+
const settings = cores_1.Elastic6Service.prepareSettings({ docType, idName }); // default setting
|
|
791
|
+
const { version } = this.elastic.options;
|
|
792
|
+
// force set type of 'score_' field
|
|
793
|
+
const ver = engine_1.$U.F(version, 7.0);
|
|
794
|
+
const $set = { score_: { type: 'half_float' } };
|
|
795
|
+
if (ver < 7.0) {
|
|
796
|
+
settings.mappings[docType].properties = Object.assign(Object.assign({}, (((_a = settings.mappings[docType]) === null || _a === void 0 ? void 0 : _a.properties) || {})), $set);
|
|
797
|
+
}
|
|
798
|
+
else {
|
|
799
|
+
settings.mappings.properties = Object.assign(Object.assign({}, (((_b = settings.mappings) === null || _b === void 0 ? void 0 : _b.properties) || {})), $set);
|
|
800
|
+
}
|
|
801
|
+
return this.elastic.createIndex(settings);
|
|
802
|
+
}
|
|
803
|
+
return null;
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* destroy Elasticsearch index
|
|
808
|
+
*/
|
|
809
|
+
destroyIndex() {
|
|
810
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
811
|
+
return this.elastic && (yield this.elastic.destroyIndex());
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* display index settings and mappings
|
|
816
|
+
*/
|
|
817
|
+
describeIndex() {
|
|
818
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
819
|
+
return this.elastic && (yield this.elastic.describe());
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* multi get
|
|
824
|
+
* @param _ids _id list
|
|
825
|
+
*/
|
|
826
|
+
mget(_ids) {
|
|
827
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
828
|
+
const $res = yield this.client.mget({
|
|
829
|
+
index: this.options.indexName,
|
|
830
|
+
type: this.options.docType,
|
|
831
|
+
body: {
|
|
832
|
+
docs: _ids.map(_id => ({ _id })),
|
|
833
|
+
},
|
|
834
|
+
});
|
|
835
|
+
// _log(NS, `> res =`, $U.json({ ...$res, meta: undefined }));
|
|
836
|
+
const { docs } = $res.body;
|
|
837
|
+
const idName = this.options.idName;
|
|
838
|
+
return docs.map((doc) => (doc.found ? sourceToItem(doc._source, idName) : null));
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* search raw query
|
|
843
|
+
* @param body Elasticsearch Query DSL
|
|
844
|
+
* @param params see 'search_type' in Elasticsearch documentation
|
|
845
|
+
*/
|
|
846
|
+
search(body, params) {
|
|
847
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
848
|
+
if (!this.elastic)
|
|
849
|
+
throw new Error(`Could not read Elasticsearch endpoint or index setting.`);
|
|
850
|
+
const searchType = params === null || params === void 0 ? void 0 : params.searchType;
|
|
851
|
+
const elastic = (params === null || params === void 0 ? void 0 : params.indexName)
|
|
852
|
+
? new cores_1.Elastic6Service(Object.assign(Object.assign({}, this.options), { indexName: params.indexName }))
|
|
853
|
+
: this.elastic;
|
|
854
|
+
return elastic.search(body, searchType);
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* create async generator that yields items queried until last
|
|
859
|
+
* @param body Elasticsearch Query DSL
|
|
860
|
+
* @param searchType see 'search_type' in Elasticsearch documentation
|
|
861
|
+
*/
|
|
862
|
+
generateSearchResult(body, searchType) {
|
|
863
|
+
return __asyncGenerator(this, arguments, function* generateSearchResult_1() {
|
|
864
|
+
if (!body.sort)
|
|
865
|
+
body.sort = '_doc';
|
|
866
|
+
do {
|
|
867
|
+
const { list, last } = yield __await(this.search(body, { searchType }));
|
|
868
|
+
body.search_after = last;
|
|
869
|
+
yield yield __await(list);
|
|
870
|
+
} while (body.search_after);
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
exports.Elastic6Instance = Elastic6Instance;
|
|
875
|
+
/**
|
|
876
|
+
* from Elasticsearch document to model item
|
|
877
|
+
* - replace the elastic's `$id` field to `_id` of dynamo-table.
|
|
878
|
+
*
|
|
879
|
+
* @param _source from elastic-search
|
|
880
|
+
* @param idName (optional) global id of elastic. (default is `$id`)
|
|
881
|
+
*/
|
|
882
|
+
function sourceToItem(_source, idName = '$id') {
|
|
883
|
+
const item = Object.assign({}, _source);
|
|
884
|
+
if (idName in item) {
|
|
885
|
+
item._id = item[idName];
|
|
886
|
+
delete item[idName];
|
|
887
|
+
}
|
|
888
|
+
return item;
|
|
889
|
+
}
|
|
890
|
+
exports.sourceToItem = sourceToItem;
|
|
891
|
+
/**
|
|
892
|
+
* const `$ES6`
|
|
893
|
+
* - default instance as a singleton by env configuration.
|
|
894
|
+
*/
|
|
895
|
+
exports.$ES6 = new (class extends Elastic6Instance {
|
|
896
|
+
constructor() {
|
|
897
|
+
// 0. load from env configuration.
|
|
898
|
+
const endpoint = engine_1.$U.env('ES6_ENDPOINT', '');
|
|
899
|
+
const indexName = engine_1.$U.env('ES6_INDEX', 'test-v1');
|
|
900
|
+
const esVersion = engine_1.$U.env('ES6_VERSION', '6.8'); //! version of elastic server (default 6.8)
|
|
901
|
+
const esDocType = engine_1.$U.env('ES6_DOCTYPE', ''); //! version of elastic server (default `_doc`)
|
|
902
|
+
const tableName = engine_1.$U.env('MY_DYNAMO_TABLE', 'Test');
|
|
903
|
+
const autocompleteFields = helpers_1.$T.SS(engine_1.$U.env('ES6_AUTOCOMPLETE_FIELDS', ''));
|
|
904
|
+
// 1. initialize instance.
|
|
905
|
+
super({
|
|
906
|
+
endpoint,
|
|
907
|
+
indexName,
|
|
908
|
+
esVersion,
|
|
909
|
+
esDocType,
|
|
910
|
+
tableName,
|
|
911
|
+
autocompleteFields,
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
})();
|
|
915
|
+
//# sourceMappingURL=abstract-service.js.map
|