@questwork/q-utilities 0.1.12 → 0.1.14
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/dist/index.min.cjs +1076 -583
- package/dist/{index.min.js → q-utilities.esm.js} +1068 -651
- package/dist/q-utilities.min.js +1076 -583
- package/package.json +14 -19
package/dist/index.min.cjs
CHANGED
|
@@ -56,22 +56,64 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
56
56
|
Repo: () => (/* reexport */ Repo),
|
|
57
57
|
Service: () => (/* reexport */ Service),
|
|
58
58
|
TemplateCompiler: () => (/* reexport */ TemplateCompiler),
|
|
59
|
+
TenantAwareEntity: () => (/* reexport */ TenantAwareEntity),
|
|
60
|
+
TrackedEntity: () => (/* reexport */ TrackedEntity),
|
|
59
61
|
UniqueKeyGenerator: () => (/* reexport */ UniqueKeyGenerator),
|
|
62
|
+
authorize: () => (/* reexport */ authorize),
|
|
60
63
|
concatStringByArray: () => (/* reexport */ concatStringByArray),
|
|
61
64
|
convertString: () => (/* reexport */ convertString),
|
|
62
65
|
formatDate: () => (/* reexport */ formatDate),
|
|
63
66
|
generalPost: () => (/* reexport */ generalPost),
|
|
64
67
|
getValidation: () => (/* reexport */ getValidation),
|
|
65
68
|
getValueByKeys: () => (/* reexport */ getValueByKeys_getValueByKeys),
|
|
69
|
+
init: () => (/* reexport */ init),
|
|
70
|
+
initFromArray: () => (/* reexport */ initFromArray),
|
|
71
|
+
initOnlyValidFromArray: () => (/* reexport */ initOnlyValidFromArray),
|
|
66
72
|
makeApiResponse: () => (/* reexport */ makeApiResponse),
|
|
67
73
|
makeService: () => (/* reexport */ makeService),
|
|
68
74
|
objectHelper: () => (/* reexport */ objectHelper),
|
|
69
75
|
pReduce: () => (/* reexport */ pReduce),
|
|
70
76
|
padZeros: () => (/* reexport */ padZeros),
|
|
71
77
|
stringFormatter: () => (/* reexport */ stringFormatter),
|
|
72
|
-
stringHelper: () => (/* reexport */ stringHelper)
|
|
78
|
+
stringHelper: () => (/* reexport */ stringHelper),
|
|
79
|
+
trackingPlugin: () => (/* reexport */ trackingPlugin)
|
|
73
80
|
});
|
|
74
81
|
|
|
82
|
+
;// ./lib/helpers/authorize/authorize.js
|
|
83
|
+
function authorize({ allowOwner, query = {}, required, user }) {
|
|
84
|
+
if (!user) {
|
|
85
|
+
throw new Error('Require login.')
|
|
86
|
+
}
|
|
87
|
+
if (!user.permission) {
|
|
88
|
+
throw new Error('You do not have any permission.')
|
|
89
|
+
}
|
|
90
|
+
const scopes = user.permission.getScopes(required || {})
|
|
91
|
+
if (!scopes || scopes.length === 0) {
|
|
92
|
+
throw new Error('You are not allowed in this scope.')
|
|
93
|
+
}
|
|
94
|
+
if (!scopes.includes('*')) {
|
|
95
|
+
query.tenantCode = user.tenantCode
|
|
96
|
+
}
|
|
97
|
+
if (!scopes.includes('TENANT')) {
|
|
98
|
+
query.eventShortCode = user.eventShortCode
|
|
99
|
+
}
|
|
100
|
+
if (!scopes.includes('EVENT')) {
|
|
101
|
+
query.eventRegistrationCode = user.eventRegistrationCode
|
|
102
|
+
}
|
|
103
|
+
if (allowOwner) {
|
|
104
|
+
query.__ALLOW_OWNER = true
|
|
105
|
+
}
|
|
106
|
+
// not good, just use it as example
|
|
107
|
+
if (user.hasExcludedFields) {
|
|
108
|
+
query.__EXCLUDED_FIELDS = user.getExcludedFields(required)
|
|
109
|
+
}
|
|
110
|
+
query.__LOGIN_SUBJECT_CODE = user.loginSubjectCode
|
|
111
|
+
return query
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
;// ./lib/helpers/authorize/index.js
|
|
115
|
+
|
|
116
|
+
|
|
75
117
|
;// ./lib/helpers/getValidation/getValidation.js
|
|
76
118
|
function getValidation(rule, data, getDataByKey, KeyValueObject) {
|
|
77
119
|
if (!rule) {
|
|
@@ -289,7 +331,6 @@ function getValueByKeys_getValueByKeys(keys, data) {
|
|
|
289
331
|
});
|
|
290
332
|
|
|
291
333
|
|
|
292
|
-
|
|
293
334
|
;// ./lib/helpers/getValueByKeys/index.js
|
|
294
335
|
|
|
295
336
|
|
|
@@ -317,7 +358,26 @@ class TemplateCompilerException extends Error {
|
|
|
317
358
|
;// ./lib/models/templateCompiler/constants.js
|
|
318
359
|
const _EMPTY = '_EMPTY'
|
|
319
360
|
const _FN_NAMES = [
|
|
320
|
-
'
|
|
361
|
+
'concatIf',
|
|
362
|
+
'divide',
|
|
363
|
+
'eq',
|
|
364
|
+
'exec',
|
|
365
|
+
'filterAll',
|
|
366
|
+
'filterOne',
|
|
367
|
+
'formatDate',
|
|
368
|
+
'get',
|
|
369
|
+
'gt',
|
|
370
|
+
'gte',
|
|
371
|
+
'isEmpty',
|
|
372
|
+
'isNotEmpty',
|
|
373
|
+
'join',
|
|
374
|
+
'lt',
|
|
375
|
+
'lte',
|
|
376
|
+
'map',
|
|
377
|
+
'neq',
|
|
378
|
+
'removeHtml',
|
|
379
|
+
'toLowerCase',
|
|
380
|
+
'toUpperCase',
|
|
321
381
|
]
|
|
322
382
|
const _HIDE = '_HIDE'
|
|
323
383
|
const _NOT_EMPTY = '_NOT_EMPTY'
|
|
@@ -358,6 +418,20 @@ function _concatIf(data, args) {
|
|
|
358
418
|
|
|
359
419
|
|
|
360
420
|
|
|
421
|
+
;// ./lib/models/templateCompiler/helpers/_divide.js
|
|
422
|
+
function _divide(value, divisor) {
|
|
423
|
+
try {
|
|
424
|
+
if (Number.isNaN(value)) {
|
|
425
|
+
return value
|
|
426
|
+
}
|
|
427
|
+
return (value / divisor)
|
|
428
|
+
} catch (e) {
|
|
429
|
+
throw e
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
|
|
361
435
|
;// ./lib/models/templateCompiler/helpers/_eq.js
|
|
362
436
|
|
|
363
437
|
|
|
@@ -890,6 +964,66 @@ function _neq(data, args) {
|
|
|
890
964
|
|
|
891
965
|
|
|
892
966
|
|
|
967
|
+
;// ./lib/models/templateCompiler/helpers/_removeHtml.js
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
function _removeHtml(html, args) {
|
|
971
|
+
if (html === null || html === undefined) {
|
|
972
|
+
return null
|
|
973
|
+
}
|
|
974
|
+
if (!Array.isArray(args)) {
|
|
975
|
+
throw new TemplateCompilerException(`_removeHtml: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: args parts must be array`)
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
return _htmlToPlainText(html, args[0])
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
function _htmlToPlainText(html, delimiter = '\n') {
|
|
982
|
+
if (typeof delimiter !== 'string') {
|
|
983
|
+
delimiter = '\n'; // Fallback to default if not a string
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// First decode HTML entities and normalize whitespace
|
|
987
|
+
const decodedHtml = html
|
|
988
|
+
.replace(/ /g, ' ')
|
|
989
|
+
.replace(/\s+/g, ' '); // Collapse all whitespace to single spaces
|
|
990
|
+
|
|
991
|
+
// Process HTML tags
|
|
992
|
+
let text = decodedHtml
|
|
993
|
+
// Replace block tags with temporary marker (~~~)
|
|
994
|
+
.replace(/<\/?(p|div|h[1-6]|ul|ol|li|pre|section|article|table|tr|td|th)(\s[^>]*)?>/gi, '~~~')
|
|
995
|
+
// Replace <br> tags with temporary marker (~~~)
|
|
996
|
+
.replace(/<br\s*\/?>/gi, '~~~')
|
|
997
|
+
// Remove all other tags
|
|
998
|
+
.replace(/<[^>]+>/g, '')
|
|
999
|
+
// Convert markers to specified delimiter
|
|
1000
|
+
.replace(/~~~+/g, delimiter)
|
|
1001
|
+
// Trim and clean whitespace
|
|
1002
|
+
.trim();
|
|
1003
|
+
|
|
1004
|
+
// Special handling for empty delimiter
|
|
1005
|
+
if (delimiter === '') {
|
|
1006
|
+
// Collapse all whitespace to single space
|
|
1007
|
+
text = text.replace(/\s+/g, ' ');
|
|
1008
|
+
} else {
|
|
1009
|
+
|
|
1010
|
+
|
|
1011
|
+
// Collapse multiple delimiters to single
|
|
1012
|
+
text = text.replace(new RegExp(`${escapeRegExp(delimiter)}+`, 'g'), delimiter);
|
|
1013
|
+
// Remove leading/trailing delimiters
|
|
1014
|
+
text = text.replace(new RegExp(`^${escapeRegExp(delimiter)}|${escapeRegExp(delimiter)}$`, 'g'), '');
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
return text;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
|
|
1021
|
+
function escapeRegExp(string) {
|
|
1022
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
|
|
893
1027
|
;// ./lib/models/templateCompiler/helpers/_toLowerCase.js
|
|
894
1028
|
|
|
895
1029
|
|
|
@@ -942,6 +1076,8 @@ function _toUpperCase(data, args) {
|
|
|
942
1076
|
|
|
943
1077
|
|
|
944
1078
|
|
|
1079
|
+
|
|
1080
|
+
|
|
945
1081
|
|
|
946
1082
|
|
|
947
1083
|
|
|
@@ -969,6 +1105,9 @@ class TemplateCompiler {
|
|
|
969
1105
|
static concatIf(data, args) {
|
|
970
1106
|
return _concatIf(data, args)
|
|
971
1107
|
}
|
|
1108
|
+
static divide(data, args) {
|
|
1109
|
+
return _divide(data, args)
|
|
1110
|
+
}
|
|
972
1111
|
static eq(data, args) {
|
|
973
1112
|
return _eq(data, args)
|
|
974
1113
|
}
|
|
@@ -980,7 +1119,6 @@ class TemplateCompiler {
|
|
|
980
1119
|
static formatDate(data, args) {
|
|
981
1120
|
return _formatDate(data, args)
|
|
982
1121
|
}
|
|
983
|
-
|
|
984
1122
|
static get(data, key, failover = null) {
|
|
985
1123
|
return _get(data, key, failover)
|
|
986
1124
|
}
|
|
@@ -1011,6 +1149,9 @@ class TemplateCompiler {
|
|
|
1011
1149
|
static neq(data, args) {
|
|
1012
1150
|
return _neq(data, args)
|
|
1013
1151
|
}
|
|
1152
|
+
static removeHtml(data, args) {
|
|
1153
|
+
return _removeHtml(data, args)
|
|
1154
|
+
}
|
|
1014
1155
|
static toLowerCase(data, args) {
|
|
1015
1156
|
return _toLowerCase(data, args)
|
|
1016
1157
|
}
|
|
@@ -1020,6 +1161,9 @@ class TemplateCompiler {
|
|
|
1020
1161
|
static parseFunction(expression) {
|
|
1021
1162
|
return _parseFunction(expression, _FN_NAMES)
|
|
1022
1163
|
}
|
|
1164
|
+
static parseParams(parameters) {
|
|
1165
|
+
return _parseParams(parameters)
|
|
1166
|
+
}
|
|
1023
1167
|
|
|
1024
1168
|
pipe(expression = '') {
|
|
1025
1169
|
this.delimiters = expression.substring(0, 2) === '{{' ? TAGS_HANDLEBAR : TAGS_EJS
|
|
@@ -1102,6 +1246,10 @@ function _parseSinglePart(input) {
|
|
|
1102
1246
|
// 去掉双引号,返回
|
|
1103
1247
|
return input.substring(1, input.length - 1)
|
|
1104
1248
|
}
|
|
1249
|
+
if (input.startsWith("'") && input.endsWith("'")) {
|
|
1250
|
+
// 去掉双引号,返回
|
|
1251
|
+
return input.substring(1, input.length - 1)
|
|
1252
|
+
}
|
|
1105
1253
|
|
|
1106
1254
|
const _input = _toBasicType(input)
|
|
1107
1255
|
|
|
@@ -1129,6 +1277,10 @@ function _toBasicType(input) {
|
|
|
1129
1277
|
// 去掉双引号,返回
|
|
1130
1278
|
return input.substring(1, input.length - 1)
|
|
1131
1279
|
}
|
|
1280
|
+
if (input.startsWith("'") && input.endsWith("'")) {
|
|
1281
|
+
// 去掉双引号,返回
|
|
1282
|
+
return input.substring(1, input.length - 1)
|
|
1283
|
+
}
|
|
1132
1284
|
if (input === 'true') {
|
|
1133
1285
|
return true
|
|
1134
1286
|
}
|
|
@@ -1151,8 +1303,20 @@ function _callFunction(data, functionName, parameters) {
|
|
|
1151
1303
|
try {
|
|
1152
1304
|
let failover
|
|
1153
1305
|
switch (functionName) {
|
|
1306
|
+
case 'concatIf':
|
|
1307
|
+
return _concatIf(data, parameters)
|
|
1308
|
+
case 'divide':
|
|
1309
|
+
return _divide(data, parameters)
|
|
1310
|
+
case 'eq':
|
|
1311
|
+
return _eq(data, parameters)
|
|
1154
1312
|
case 'exec':
|
|
1155
1313
|
return _exec(data, parameters)
|
|
1314
|
+
case 'filterAll':
|
|
1315
|
+
return _filterAll(data, parameters)
|
|
1316
|
+
case 'filterOne':
|
|
1317
|
+
return _filterOne(data, parameters)
|
|
1318
|
+
case 'formatDate':
|
|
1319
|
+
return _formatDate(data, parameters)
|
|
1156
1320
|
case 'get':
|
|
1157
1321
|
if (parameters.length > 2) {
|
|
1158
1322
|
throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException)
|
|
@@ -1161,34 +1325,26 @@ function _callFunction(data, functionName, parameters) {
|
|
|
1161
1325
|
failover = parameters[parameters.length - 1]
|
|
1162
1326
|
}
|
|
1163
1327
|
return _get(data, parameters[0], failover)
|
|
1164
|
-
case 'join':
|
|
1165
|
-
return _join(data, parameters[0])
|
|
1166
|
-
case 'map':
|
|
1167
|
-
return _map(data, parameters)
|
|
1168
|
-
case 'concatIf':
|
|
1169
|
-
return _concatIf(data, parameters)
|
|
1170
|
-
case 'filterOne':
|
|
1171
|
-
return _filterOne(data, parameters)
|
|
1172
|
-
case 'filterAll':
|
|
1173
|
-
return _filterAll(data, parameters)
|
|
1174
|
-
case 'formatDate':
|
|
1175
|
-
return _formatDate(data, parameters)
|
|
1176
|
-
case 'eq':
|
|
1177
|
-
return _eq(data, parameters)
|
|
1178
|
-
case 'neq':
|
|
1179
|
-
return _neq(data, parameters)
|
|
1180
1328
|
case 'gt':
|
|
1181
1329
|
return _gt(data, parameters)
|
|
1182
1330
|
case 'gte':
|
|
1183
1331
|
return _gte(data, parameters)
|
|
1184
|
-
case 'lt':
|
|
1185
|
-
return _lt(data, parameters)
|
|
1186
|
-
case 'lte':
|
|
1187
|
-
return _lte(data, parameters)
|
|
1188
1332
|
case 'isEmpty':
|
|
1189
1333
|
return _isEmpty(data, parameters)
|
|
1190
1334
|
case 'isNotEmpty':
|
|
1191
1335
|
return _isNotEmpty(data, parameters)
|
|
1336
|
+
case 'join':
|
|
1337
|
+
return _join(data, parameters[0])
|
|
1338
|
+
case 'lt':
|
|
1339
|
+
return _lt(data, parameters)
|
|
1340
|
+
case 'lte':
|
|
1341
|
+
return _lte(data, parameters)
|
|
1342
|
+
case 'map':
|
|
1343
|
+
return _map(data, parameters)
|
|
1344
|
+
case 'neq':
|
|
1345
|
+
return _neq(data, parameters)
|
|
1346
|
+
case 'removeHtml':
|
|
1347
|
+
return _removeHtml(data, parameters)
|
|
1192
1348
|
case 'toLowerCase':
|
|
1193
1349
|
return _toLowerCase(data)
|
|
1194
1350
|
case 'toUpperCase':
|
|
@@ -1337,42 +1493,59 @@ const objectHelper = {
|
|
|
1337
1493
|
},
|
|
1338
1494
|
merge,
|
|
1339
1495
|
set(obj, path, value) {
|
|
1340
|
-
const parts = path.split('.')
|
|
1341
|
-
let current = obj
|
|
1496
|
+
const parts = path.split('.');
|
|
1497
|
+
let current = obj;
|
|
1498
|
+
|
|
1499
|
+
// 处理所有中间部分
|
|
1342
1500
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
1343
|
-
const part = parts[i]
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1501
|
+
const part = parts[i];
|
|
1502
|
+
let key, index;
|
|
1503
|
+
|
|
1504
|
+
// 检查是否是数组索引格式,如key[0]
|
|
1505
|
+
const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/);
|
|
1506
|
+
if (arrayMatch) {
|
|
1507
|
+
key = arrayMatch[1];
|
|
1508
|
+
index = parseInt(arrayMatch[2], 10);
|
|
1509
|
+
// 确保当前层级的数组存在
|
|
1510
|
+
if (!current[key] || !Array.isArray(current[key])) {
|
|
1511
|
+
current[key] = [];
|
|
1349
1512
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
if (
|
|
1356
|
-
|
|
1357
|
-
const index = arrayMatch[2]
|
|
1358
|
-
if (Array.isArray(current[key]) && current[key][index]) {
|
|
1359
|
-
current = current[key][index]
|
|
1360
|
-
} else {
|
|
1361
|
-
return // 如果数组或索引不存在,直接返回
|
|
1362
|
-
}
|
|
1513
|
+
// 扩展数组到足够大
|
|
1514
|
+
while (current[key].length <= index) {
|
|
1515
|
+
current[key].push(undefined);
|
|
1516
|
+
}
|
|
1517
|
+
// 如果当前位置未定义或为null,初始化为对象
|
|
1518
|
+
if (current[key][index] == null) {
|
|
1519
|
+
current[key][index] = {};
|
|
1363
1520
|
}
|
|
1521
|
+
current = current[key][index];
|
|
1364
1522
|
} else {
|
|
1365
1523
|
// 处理普通属性
|
|
1366
1524
|
if (!current[part]) {
|
|
1367
|
-
current[part] = {}
|
|
1525
|
+
current[part] = {};
|
|
1368
1526
|
}
|
|
1369
|
-
current = current[part]
|
|
1527
|
+
current = current[part];
|
|
1370
1528
|
}
|
|
1371
1529
|
}
|
|
1372
|
-
|
|
1373
|
-
//
|
|
1374
|
-
const lastPart = parts[parts.length - 1]
|
|
1375
|
-
|
|
1530
|
+
|
|
1531
|
+
// 处理最后一部分
|
|
1532
|
+
const lastPart = parts[parts.length - 1];
|
|
1533
|
+
const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/);
|
|
1534
|
+
if (arrayMatch) {
|
|
1535
|
+
const key = arrayMatch[1];
|
|
1536
|
+
const index = parseInt(arrayMatch[2], 10);
|
|
1537
|
+
// 确保数组存在
|
|
1538
|
+
if (!current[key] || !Array.isArray(current[key])) {
|
|
1539
|
+
current[key] = [];
|
|
1540
|
+
}
|
|
1541
|
+
// 扩展数组到所需索引
|
|
1542
|
+
while (current[key].length <= index) {
|
|
1543
|
+
current[key].push(undefined);
|
|
1544
|
+
}
|
|
1545
|
+
current[key][index] = value;
|
|
1546
|
+
} else {
|
|
1547
|
+
current[lastPart] = value;
|
|
1548
|
+
}
|
|
1376
1549
|
}
|
|
1377
1550
|
}
|
|
1378
1551
|
|
|
@@ -1440,113 +1613,728 @@ async function pReduce(iterable, reducer, initialValue) {
|
|
|
1440
1613
|
|
|
1441
1614
|
|
|
1442
1615
|
|
|
1443
|
-
;// ./lib/models/
|
|
1444
|
-
|
|
1445
|
-
|
|
1616
|
+
;// ./lib/models/repo/repo.js
|
|
1617
|
+
|
|
1618
|
+
|
|
1619
|
+
class Repo {
|
|
1620
|
+
constructor(options) {
|
|
1446
1621
|
options = options || {}
|
|
1447
|
-
this.
|
|
1448
|
-
this.
|
|
1449
|
-
this.
|
|
1450
|
-
this.
|
|
1451
|
-
this.
|
|
1452
|
-
|
|
1622
|
+
this.model = options.model
|
|
1623
|
+
this._sharedOptions = options._sharedOptions // { session: this.dbTransaction }
|
|
1624
|
+
this._queryOptions = options._queryOptions
|
|
1625
|
+
this._saveOptions = options._saveOptions
|
|
1626
|
+
this._Class = options._constructor && options._constructor._Class
|
|
1627
|
+
? options._constructor._Class
|
|
1628
|
+
: null
|
|
1453
1629
|
}
|
|
1454
|
-
|
|
1455
1630
|
static init(options = {}) {
|
|
1456
|
-
|
|
1457
|
-
return options
|
|
1458
|
-
}
|
|
1459
|
-
const instance = new this(options)
|
|
1460
|
-
return instance
|
|
1631
|
+
return init(this, options)
|
|
1461
1632
|
}
|
|
1462
1633
|
static get _classname() {
|
|
1463
|
-
return '
|
|
1634
|
+
return 'Repo'
|
|
1464
1635
|
}
|
|
1465
1636
|
static get _superclass() {
|
|
1466
|
-
return '
|
|
1637
|
+
return 'Repo'
|
|
1467
1638
|
}
|
|
1468
1639
|
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
if (this._instanceBuilder && (typeof this._instanceBuilder === 'function')) {
|
|
1472
|
-
return this._data.map(this._instanceBuilder)
|
|
1473
|
-
}
|
|
1474
|
-
return this._data
|
|
1640
|
+
get _classname() {
|
|
1641
|
+
return 'Repo'
|
|
1475
1642
|
}
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1478
1643
|
|
|
1644
|
+
get _superclass() {
|
|
1645
|
+
return 'Repo'
|
|
1646
|
+
}
|
|
1479
1647
|
|
|
1480
|
-
|
|
1481
|
-
|
|
1648
|
+
get isValid() {
|
|
1649
|
+
return this.model
|
|
1650
|
+
&& (typeof this.model.deleteOne === 'function')
|
|
1651
|
+
&& (typeof this.model.findAll === 'function')
|
|
1652
|
+
&& (typeof this.model.saveOne === 'function')
|
|
1653
|
+
}
|
|
1482
1654
|
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
return repo.init(i)
|
|
1655
|
+
get queryOptions() {
|
|
1656
|
+
return {
|
|
1657
|
+
...this._sharedOptions,
|
|
1658
|
+
...this._queryOptions,
|
|
1488
1659
|
}
|
|
1489
|
-
})
|
|
1490
|
-
}
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
;// ./lib/models/apiResponse/index.js
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
;// ./lib/models/keyValueObject/keyValueObject.js
|
|
1501
|
-
class KeyValueObject {
|
|
1502
|
-
constructor(options = {}) {
|
|
1503
|
-
options = options || {}
|
|
1504
|
-
this.key = options.key || null
|
|
1505
|
-
this.value = (typeof options.value !== 'undefined') ? options.value : ''
|
|
1506
1660
|
}
|
|
1507
1661
|
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1662
|
+
get saveOptions() {
|
|
1663
|
+
return {
|
|
1664
|
+
...this._sharedOptions,
|
|
1665
|
+
...this._saveOptions,
|
|
1512
1666
|
}
|
|
1513
|
-
const instance = new this(options)
|
|
1514
|
-
return instance.isValid ? instance : null
|
|
1515
1667
|
}
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1668
|
+
|
|
1669
|
+
init(options) {
|
|
1670
|
+
if (this._Class && typeof this._Class.init === 'function') {
|
|
1671
|
+
return this._Class.init(options)
|
|
1519
1672
|
}
|
|
1520
|
-
return
|
|
1521
|
-
}
|
|
1522
|
-
static initOnlyValidFromArray(arr = []) {
|
|
1523
|
-
return this.initFromArray(arr).filter((i) => i)
|
|
1524
|
-
}
|
|
1525
|
-
static get _classname() {
|
|
1526
|
-
return 'KeyValueObject'
|
|
1527
|
-
}
|
|
1528
|
-
static get _superclass() {
|
|
1529
|
-
return 'KeyValueObject'
|
|
1673
|
+
return options
|
|
1530
1674
|
}
|
|
1531
1675
|
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1676
|
+
async deleteOne({ id }) {
|
|
1677
|
+
try {
|
|
1678
|
+
const result = await this.model.deleteOne({ _id: id })
|
|
1679
|
+
return {
|
|
1680
|
+
...result, // { message: 'ok', total }
|
|
1681
|
+
isNew: false,
|
|
1682
|
+
data: []
|
|
1683
|
+
}
|
|
1684
|
+
} catch (err) {
|
|
1685
|
+
throw err
|
|
1538
1686
|
}
|
|
1539
|
-
return arr
|
|
1540
1687
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1688
|
+
|
|
1689
|
+
// systemLog is optional
|
|
1690
|
+
findAll({ query, systemLog }) {
|
|
1691
|
+
const log = _makeLog({
|
|
1692
|
+
systemLog,
|
|
1693
|
+
label: 'REPO_READ',
|
|
1694
|
+
message: `fn ${this._classname}.prototype.findAll`,
|
|
1695
|
+
input: [{ query: { ...query }, systemLog: { ...systemLog } }]
|
|
1547
1696
|
})
|
|
1548
|
-
|
|
1549
|
-
|
|
1697
|
+
return new Promise((resolve, reject) => {
|
|
1698
|
+
this.model.findAll(query, this.queryOptions, (err, data, total) => {
|
|
1699
|
+
if (err) {
|
|
1700
|
+
log({ level: 'warn', output: err.toString() })
|
|
1701
|
+
reject(err)
|
|
1702
|
+
} else {
|
|
1703
|
+
const result = {
|
|
1704
|
+
isNew: false,
|
|
1705
|
+
data,
|
|
1706
|
+
total: total || data.length
|
|
1707
|
+
}
|
|
1708
|
+
log({ level: 'info', output: { ...result } })
|
|
1709
|
+
resolve(result)
|
|
1710
|
+
}
|
|
1711
|
+
})
|
|
1712
|
+
})
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
findOne({ query, systemLog }) {
|
|
1716
|
+
const log = _makeLog({
|
|
1717
|
+
systemLog,
|
|
1718
|
+
label: 'REPO_READ',
|
|
1719
|
+
message: `fn ${this._classname}.prototype.findOne`,
|
|
1720
|
+
input: [{ query: { ...query }, systemLog: { ...systemLog } }]
|
|
1721
|
+
})
|
|
1722
|
+
return new Promise((resolve, reject) => {
|
|
1723
|
+
this.model.findAll(query, this.queryOptions, (err, data) => {
|
|
1724
|
+
if (err) {
|
|
1725
|
+
reject(err)
|
|
1726
|
+
} else if (data.length === 1) {
|
|
1727
|
+
const result = {
|
|
1728
|
+
isNew: false,
|
|
1729
|
+
data,
|
|
1730
|
+
total: 1
|
|
1731
|
+
}
|
|
1732
|
+
log({ level: 'info', output: { ...result } })
|
|
1733
|
+
resolve(result)
|
|
1734
|
+
} else if (data.length === 0) {
|
|
1735
|
+
reject(new Error('record not found'))
|
|
1736
|
+
} else {
|
|
1737
|
+
reject(new Error('more than one is found'))
|
|
1738
|
+
}
|
|
1739
|
+
})
|
|
1740
|
+
})
|
|
1741
|
+
.catch((err) => {
|
|
1742
|
+
log({ level: 'warn', output: err.toString() })
|
|
1743
|
+
throw err
|
|
1744
|
+
})
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
saveAll({ docs, systemLog }) {
|
|
1748
|
+
let isNew
|
|
1749
|
+
const log = _makeLog({
|
|
1750
|
+
systemLog,
|
|
1751
|
+
label: 'REPO_WRITE',
|
|
1752
|
+
message: `fn ${this._classname}.prototype.saveAll`,
|
|
1753
|
+
input: [{ docs: [...docs], systemLog: { ...systemLog } }]
|
|
1754
|
+
})
|
|
1755
|
+
const promise = typeof this.model.saveAll === 'function'
|
|
1756
|
+
? this.model.saveAll({ docs })
|
|
1757
|
+
: Promise.all(docs.map(async (doc) => {
|
|
1758
|
+
if (doc) {
|
|
1759
|
+
const result = await this.saveOne({ doc })
|
|
1760
|
+
isNew = result.isNew
|
|
1761
|
+
const _data = result._data || result.data
|
|
1762
|
+
return _data[0]
|
|
1763
|
+
}
|
|
1764
|
+
return null
|
|
1765
|
+
}))
|
|
1766
|
+
return promise.then((savedData) => {
|
|
1767
|
+
if (savedData.length !== 1) isNew = null
|
|
1768
|
+
const result = {
|
|
1769
|
+
data: savedData,
|
|
1770
|
+
isNew,
|
|
1771
|
+
total: savedData.length
|
|
1772
|
+
}
|
|
1773
|
+
log({ level: 'info', output: { ...result } })
|
|
1774
|
+
return result
|
|
1775
|
+
}).catch((err) => {
|
|
1776
|
+
log({ level: 'warn', output: err.toString() })
|
|
1777
|
+
throw err
|
|
1778
|
+
})
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
saveOne({ doc, systemLog }) {
|
|
1782
|
+
const log = _makeLog({
|
|
1783
|
+
systemLog,
|
|
1784
|
+
label: 'REPO_WRITE',
|
|
1785
|
+
message: `fn ${this._classname}.prototype.saveOne`,
|
|
1786
|
+
input: [{ doc: { ...doc }, systemLog: { ...systemLog } }]
|
|
1787
|
+
})
|
|
1788
|
+
return new Promise((resolve, reject) => {
|
|
1789
|
+
this.model.saveOne(doc, this.saveOptions, (err, result) => {
|
|
1790
|
+
if (err) {
|
|
1791
|
+
log({ level: 'warn', output: err.toString() })
|
|
1792
|
+
reject(err)
|
|
1793
|
+
} else {
|
|
1794
|
+
log({ level: 'info', output: { ...result } })
|
|
1795
|
+
resolve(result)
|
|
1796
|
+
}
|
|
1797
|
+
})
|
|
1798
|
+
})
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
function _makeLog({ systemLog, label, message: message1, input } = {}) {
|
|
1803
|
+
return ({ level, messgae: massage2, output } = {}) => {
|
|
1804
|
+
if (systemLog && systemLog.systemLogHelper) {
|
|
1805
|
+
systemLog.systemLogHelper.log({
|
|
1806
|
+
batchId: systemLog.batchId,
|
|
1807
|
+
label,
|
|
1808
|
+
level,
|
|
1809
|
+
message: massage2 || message1,
|
|
1810
|
+
data: {
|
|
1811
|
+
payload: {
|
|
1812
|
+
input,
|
|
1813
|
+
output
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
})
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
|
|
1822
|
+
|
|
1823
|
+
;// ./lib/models/repo/index.js
|
|
1824
|
+
|
|
1825
|
+
|
|
1826
|
+
|
|
1827
|
+
|
|
1828
|
+
;// ./lib/models/apiResponse/apiResponse.js
|
|
1829
|
+
class ApiResponse {
|
|
1830
|
+
constructor(options = {}) {
|
|
1831
|
+
options = options || {}
|
|
1832
|
+
this._data = options.data || options._data || []
|
|
1833
|
+
this.err = options.err
|
|
1834
|
+
this.isNew = options.isNew || false
|
|
1835
|
+
this.message = options.message
|
|
1836
|
+
this.total = options.total || 0
|
|
1837
|
+
this._instanceBuilder = options._instanceBuilder
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
static init(options = {}) {
|
|
1841
|
+
if (options instanceof this) {
|
|
1842
|
+
return options
|
|
1843
|
+
}
|
|
1844
|
+
const instance = new this(options)
|
|
1845
|
+
return instance
|
|
1846
|
+
}
|
|
1847
|
+
static get _classname() {
|
|
1848
|
+
return 'ApiResponse'
|
|
1849
|
+
}
|
|
1850
|
+
static get _superclass() {
|
|
1851
|
+
return 'ApiResponse'
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
// getters
|
|
1855
|
+
get data() {
|
|
1856
|
+
if (this._instanceBuilder && (typeof this._instanceBuilder === 'function')) {
|
|
1857
|
+
return this._data.map(this._instanceBuilder)
|
|
1858
|
+
}
|
|
1859
|
+
return this._data
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
|
|
1864
|
+
|
|
1865
|
+
;// ./lib/models/apiResponse/makeApiResponse.js
|
|
1866
|
+
|
|
1867
|
+
|
|
1868
|
+
function makeApiResponse({ repo, result }) {
|
|
1869
|
+
return ApiResponse.init({
|
|
1870
|
+
...result,
|
|
1871
|
+
_instanceBuilder: (i) => {
|
|
1872
|
+
return repo.init(i)
|
|
1873
|
+
}
|
|
1874
|
+
})
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
|
|
1878
|
+
|
|
1879
|
+
;// ./lib/models/service/service.js
|
|
1880
|
+
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+
class Service {
|
|
1884
|
+
constructor({ repo }) {
|
|
1885
|
+
this.repo = repo
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
static get _classname() {
|
|
1889
|
+
return 'Service'
|
|
1890
|
+
}
|
|
1891
|
+
static get _superclass() {
|
|
1892
|
+
return 'Service'
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
deleteOne({ id }) {
|
|
1896
|
+
return this.repo.deleteOne({ id })
|
|
1897
|
+
.catch(() => {
|
|
1898
|
+
throw new Error(`Not found for query: ${id}`)
|
|
1899
|
+
})
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
async findAll({ query = {}, systemLog } = {}) {
|
|
1903
|
+
const result = await this.repo.findAll({ query, systemLog })
|
|
1904
|
+
return makeApiResponse({
|
|
1905
|
+
repo: this.repo,
|
|
1906
|
+
result
|
|
1907
|
+
})
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
async findOne({ query = {}, systemLog } = {}) {
|
|
1911
|
+
const result = await this.repo.findOne({ query, systemLog })
|
|
1912
|
+
return makeApiResponse({
|
|
1913
|
+
repo: this.repo,
|
|
1914
|
+
result
|
|
1915
|
+
})
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
init(options) {
|
|
1919
|
+
return this.repo.init(options)
|
|
1920
|
+
}
|
|
1921
|
+
initFromArray(arr = []) {
|
|
1922
|
+
if (Array.isArray(arr)) {
|
|
1923
|
+
return arr.map((a) => this.init(a))
|
|
1924
|
+
}
|
|
1925
|
+
return []
|
|
1926
|
+
}
|
|
1927
|
+
initOnlyValidFromArray(arr = []) {
|
|
1928
|
+
return this.initFromArray(arr).filter((i) => i)
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
async saveAll({ docs = [], config = {}, systemLog } = {}) {
|
|
1932
|
+
const copies = docs.map((doc) => {
|
|
1933
|
+
return config.skipInit ? doc : this.init(doc)
|
|
1934
|
+
})
|
|
1935
|
+
const result = await this.repo.saveAll({ docs: copies, systemLog })
|
|
1936
|
+
return makeApiResponse({
|
|
1937
|
+
repo: this.repo,
|
|
1938
|
+
result
|
|
1939
|
+
})
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
// set skipInit to true if we want to use POST for query
|
|
1943
|
+
async saveOne({ doc = {}, config = {}, systemLog } = {}) {
|
|
1944
|
+
const copy = config.skipInit ? doc : this.init(doc)
|
|
1945
|
+
if (copy) {
|
|
1946
|
+
const result = await this.repo.saveOne({ doc: copy, systemLog })
|
|
1947
|
+
return makeApiResponse({
|
|
1948
|
+
repo: this.repo,
|
|
1949
|
+
result
|
|
1950
|
+
})
|
|
1951
|
+
}
|
|
1952
|
+
return {
|
|
1953
|
+
isNew: null,
|
|
1954
|
+
data: [],
|
|
1955
|
+
err: new Error('doc is not a valid instance')
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
function makeService({ repo }) {
|
|
1961
|
+
if (repo === undefined) {
|
|
1962
|
+
throw new Error('repo is required.')
|
|
1963
|
+
}
|
|
1964
|
+
if (repo._superclass !== Repo._superclass) {
|
|
1965
|
+
throw new Error('repo is not an instance of Repo.')
|
|
1966
|
+
}
|
|
1967
|
+
return new Service({ repo })
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
|
|
1971
|
+
|
|
1972
|
+
;// ./lib/models/service/index.js
|
|
1973
|
+
|
|
1974
|
+
|
|
1975
|
+
|
|
1976
|
+
|
|
1977
|
+
;// ./lib/helpers/generalPost/generalPost.js
|
|
1978
|
+
|
|
1979
|
+
|
|
1980
|
+
|
|
1981
|
+
|
|
1982
|
+
|
|
1983
|
+
async function generalPost({ body = {}, GeneralModel, UniqueKeyGenerator, resourceInfo }) {
|
|
1984
|
+
const { resources, data, globalShared = {}, shared = {}, relationship = {} } = body
|
|
1985
|
+
const _resourceInfo = resourceInfo || body.resourceInfo
|
|
1986
|
+
_attachShared(data, globalShared, shared)
|
|
1987
|
+
const obj = await pReduce(resources, async (acc, resource) => {
|
|
1988
|
+
const service = _makeService(resource, _resourceInfo, UniqueKeyGenerator, GeneralModel)
|
|
1989
|
+
_createRelationship(data, relationship[resource], acc)
|
|
1990
|
+
const _data = data[resource]
|
|
1991
|
+
const result = await service.saveAll({ docs: [].concat(_data) })
|
|
1992
|
+
acc[resource] = Array.isArray(_data) ? result._data : result._data[0]
|
|
1993
|
+
return acc
|
|
1994
|
+
}, {})
|
|
1995
|
+
return obj
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
function _attachShared(data, globalShared = {}, shared = {}) {
|
|
1999
|
+
Object.keys(shared).forEach((key) => {
|
|
2000
|
+
const _data = data[key]
|
|
2001
|
+
if (Array.isArray(_data)) {
|
|
2002
|
+
data[key] = _data.map((_dataItem) => {
|
|
2003
|
+
return objectHelper.merge({}, _dataItem, globalShared, shared[key] || {})
|
|
2004
|
+
})
|
|
2005
|
+
} else {
|
|
2006
|
+
data[key] = objectHelper.merge({}, _data, globalShared, shared[key] || {})
|
|
2007
|
+
}
|
|
2008
|
+
})
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
function _createRelationship(data, relationship = {}, object) {
|
|
2012
|
+
Object.keys(relationship).forEach((key) => {
|
|
2013
|
+
const path = relationship[key]
|
|
2014
|
+
const val = objectHelper.get(object, path)
|
|
2015
|
+
objectHelper.set(data, key, val)
|
|
2016
|
+
})
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
function _makeService(resource, resourceInfo, UniqueKeyGenerator, GeneralModel) {
|
|
2020
|
+
const { collectionName, fields } = resourceInfo[resource]
|
|
2021
|
+
const uniqueKeyGenerator = UniqueKeyGenerator.makeGenerator(fields)
|
|
2022
|
+
const model = new GeneralModel({ collectionName, uniqueKeyGenerator })
|
|
2023
|
+
return makeService({
|
|
2024
|
+
repo: new Repo({ model })
|
|
2025
|
+
})
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
|
|
2029
|
+
|
|
2030
|
+
;// ./lib/helpers/generalPost/index.js
|
|
2031
|
+
|
|
2032
|
+
|
|
2033
|
+
|
|
2034
|
+
|
|
2035
|
+
;// ./lib/helpers/init/init.js
|
|
2036
|
+
function init(_class, options) {
|
|
2037
|
+
if (options instanceof _class) {
|
|
2038
|
+
return options
|
|
2039
|
+
}
|
|
2040
|
+
try {
|
|
2041
|
+
const instance = new _class(options)
|
|
2042
|
+
return instance.isValid !== false ? instance : null
|
|
2043
|
+
} catch (e) {
|
|
2044
|
+
console.log(`init failed for class: ${_class._classname || 'no _classname'}`, e)
|
|
2045
|
+
return null
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
;// ./lib/helpers/init/index.js
|
|
2050
|
+
|
|
2051
|
+
|
|
2052
|
+
;// ./lib/helpers/initFromArray/initFromArray.js
|
|
2053
|
+
|
|
2054
|
+
|
|
2055
|
+
function initFromArray(_class, arr) {
|
|
2056
|
+
if (Array.isArray(arr)) {
|
|
2057
|
+
return arr.map((a) => init(_class, a))
|
|
2058
|
+
}
|
|
2059
|
+
return []
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
;// ./lib/helpers/initFromArray/index.js
|
|
2063
|
+
|
|
2064
|
+
|
|
2065
|
+
;// ./lib/helpers/initOnlyValidFromArray/initOnlyValidFromArray.js
|
|
2066
|
+
|
|
2067
|
+
|
|
2068
|
+
function initOnlyValidFromArray(_class, arr) {
|
|
2069
|
+
return initFromArray(_class, arr).filter((i) => i)
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
;// ./lib/helpers/initOnlyValidFromArray/index.js
|
|
2073
|
+
|
|
2074
|
+
|
|
2075
|
+
;// ./lib/helpers/padZeros/padZeros.js
|
|
2076
|
+
function padZeros(num, minLength = 6) {
|
|
2077
|
+
num = num.toString()
|
|
2078
|
+
if (num.length < minLength) {
|
|
2079
|
+
return padZeros('0' + num, minLength)
|
|
2080
|
+
}
|
|
2081
|
+
return num
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
|
|
2085
|
+
|
|
2086
|
+
;// ./lib/helpers/padZeros/index.js
|
|
2087
|
+
|
|
2088
|
+
|
|
2089
|
+
|
|
2090
|
+
|
|
2091
|
+
;// ./lib/helpers/pReduce/index.js
|
|
2092
|
+
|
|
2093
|
+
|
|
2094
|
+
|
|
2095
|
+
|
|
2096
|
+
;// ./lib/helpers/stringFormatter/stringFormatter.js
|
|
2097
|
+
function stringFormatter(str, delimiter = '_') {
|
|
2098
|
+
if (str === null || typeof str === 'undefined' || typeof str.toString === 'undefined') {
|
|
2099
|
+
return null
|
|
2100
|
+
}
|
|
2101
|
+
return str.toString()
|
|
2102
|
+
.trim()
|
|
2103
|
+
.toUpperCase()
|
|
2104
|
+
.replace('-', delimiter)
|
|
2105
|
+
.replace(' ', delimiter)
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
|
|
2109
|
+
|
|
2110
|
+
;// ./lib/helpers/stringFormatter/index.js
|
|
2111
|
+
|
|
2112
|
+
|
|
2113
|
+
|
|
2114
|
+
|
|
2115
|
+
;// ./lib/helpers/stringHelper/stringHelper.js
|
|
2116
|
+
function baseXEncode(num, base = 34) {
|
|
2117
|
+
const charset = getBaseCharset(base)
|
|
2118
|
+
return encode(num, charset)
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
function encode(int, charset) {
|
|
2122
|
+
const { byCode } = charset
|
|
2123
|
+
if (int === 0) {
|
|
2124
|
+
return byCode[0]
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
let res = ''
|
|
2128
|
+
const max = charset.length
|
|
2129
|
+
while (int > 0) {
|
|
2130
|
+
res = byCode[int % max] + res
|
|
2131
|
+
int = Math.floor(int / max)
|
|
2132
|
+
}
|
|
2133
|
+
return res
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
function getBaseCharset(base) {
|
|
2137
|
+
let charset = '9876543210ABCDEFGHJKLMNPQRSTUVWXYZ'
|
|
2138
|
+
if (base === 58) {
|
|
2139
|
+
charset = '9876543210ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz'
|
|
2140
|
+
}
|
|
2141
|
+
return indexCharset(charset)
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
function indexCharset(str) {
|
|
2145
|
+
const byCode = {}
|
|
2146
|
+
const byChar = {}
|
|
2147
|
+
const { length } = str
|
|
2148
|
+
let char
|
|
2149
|
+
for (let i = 0; i < length; i++) {
|
|
2150
|
+
char = str[i]
|
|
2151
|
+
byCode[i] = char
|
|
2152
|
+
byChar[char] = i;
|
|
2153
|
+
}
|
|
2154
|
+
return { byCode, byChar, length }
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
function isSame(str1, str2) {
|
|
2158
|
+
if (typeof str1 !== 'string' || typeof str2 !== 'string') {
|
|
2159
|
+
return false
|
|
2160
|
+
}
|
|
2161
|
+
return str1.trim().toUpperCase() === str2.trim().toUpperCase()
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
function randomString({ len = 16, pattern = 'a1' } = {}) {
|
|
2165
|
+
const A = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
2166
|
+
const a = 'abcdefghijklmnopqrstuvwxyz'
|
|
2167
|
+
const num = '1234567890'
|
|
2168
|
+
const mark = '~!@#$%^&*_+-='
|
|
2169
|
+
let str = ''
|
|
2170
|
+
if (pattern.includes('A')) {
|
|
2171
|
+
str += A
|
|
2172
|
+
}
|
|
2173
|
+
if (pattern.includes('a')) {
|
|
2174
|
+
str += a
|
|
2175
|
+
}
|
|
2176
|
+
if (pattern.includes('1')) {
|
|
2177
|
+
str += num
|
|
2178
|
+
}
|
|
2179
|
+
if (pattern.includes('#')) {
|
|
2180
|
+
str += mark
|
|
2181
|
+
}
|
|
2182
|
+
const chars = [...str]
|
|
2183
|
+
return [...Array(len)].map(i => {
|
|
2184
|
+
return chars[(Math.random() * chars.length) | 0]
|
|
2185
|
+
}).join``
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
function reverse(str) {
|
|
2189
|
+
const _str = (typeof str !== 'string') ? str.toString() : str
|
|
2190
|
+
const splitString = _str.split('')
|
|
2191
|
+
const reverseArray = splitString.reverse()
|
|
2192
|
+
return reverseArray.join('')
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
function setCode(base = 34) {
|
|
2196
|
+
const now = (new Date()).valueOf()
|
|
2197
|
+
const random = randomString({
|
|
2198
|
+
len: 8,
|
|
2199
|
+
pattern: '1'
|
|
2200
|
+
})
|
|
2201
|
+
const str = reverse(`${now}${random}`)
|
|
2202
|
+
// const str = `${now}${random}`
|
|
2203
|
+
return baseXEncode(str, base)
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
function toCamelCase(str) {
|
|
2207
|
+
if (!str) return ''
|
|
2208
|
+
return str
|
|
2209
|
+
.trim()
|
|
2210
|
+
.split(/\s+/)
|
|
2211
|
+
.map((word, index) => {
|
|
2212
|
+
if (!word) return ''
|
|
2213
|
+
if (index === 0) {
|
|
2214
|
+
return word.toLowerCase()
|
|
2215
|
+
}
|
|
2216
|
+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
|
|
2217
|
+
})
|
|
2218
|
+
.join('')
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
const stringHelper = {
|
|
2222
|
+
isSame,
|
|
2223
|
+
setCode,
|
|
2224
|
+
toCamelCase,
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
|
|
2228
|
+
|
|
2229
|
+
;// ./lib/helpers/stringHelper/index.js
|
|
2230
|
+
|
|
2231
|
+
|
|
2232
|
+
|
|
2233
|
+
|
|
2234
|
+
;// ./lib/helpers/trackingPlugin/trackingPlugin.js
|
|
2235
|
+
function trackingPlugin(schema, options) {
|
|
2236
|
+
// Add meta fields
|
|
2237
|
+
schema.add({
|
|
2238
|
+
meta: {
|
|
2239
|
+
active: { type: Boolean, default: true },
|
|
2240
|
+
created: { type: Number },
|
|
2241
|
+
creator: { type: String },
|
|
2242
|
+
deleted: { type: Boolean, default: false },
|
|
2243
|
+
modified: { type: Number },
|
|
2244
|
+
owner: { type: String },
|
|
2245
|
+
}
|
|
2246
|
+
})
|
|
2247
|
+
|
|
2248
|
+
// Auto-update hook
|
|
2249
|
+
schema.pre('save', function(next) {
|
|
2250
|
+
this.meta.modified = Date.now()
|
|
2251
|
+
next()
|
|
2252
|
+
})
|
|
2253
|
+
|
|
2254
|
+
// Optional: Add helper methods
|
|
2255
|
+
// schema.methods.touch = function(userId) {
|
|
2256
|
+
// this.meta.updatedAt = new Date()
|
|
2257
|
+
// this.meta.updatedBy = userId
|
|
2258
|
+
// }
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
;// ./lib/helpers/trackingPlugin/index.js
|
|
2262
|
+
|
|
2263
|
+
|
|
2264
|
+
;// ./lib/helpers/index.js
|
|
2265
|
+
|
|
2266
|
+
|
|
2267
|
+
|
|
2268
|
+
|
|
2269
|
+
|
|
2270
|
+
|
|
2271
|
+
|
|
2272
|
+
|
|
2273
|
+
|
|
2274
|
+
|
|
2275
|
+
|
|
2276
|
+
|
|
2277
|
+
|
|
2278
|
+
|
|
2279
|
+
|
|
2280
|
+
|
|
2281
|
+
|
|
2282
|
+
;// ./lib/models/apiResponse/index.js
|
|
2283
|
+
|
|
2284
|
+
|
|
2285
|
+
|
|
2286
|
+
|
|
2287
|
+
|
|
2288
|
+
;// ./lib/models/keyValueObject/keyValueObject.js
|
|
2289
|
+
class KeyValueObject {
|
|
2290
|
+
constructor(options = {}) {
|
|
2291
|
+
options = options || {}
|
|
2292
|
+
this.key = options.key || null
|
|
2293
|
+
this.value = (typeof options.value !== 'undefined') ? options.value : ''
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
// Class methods
|
|
2297
|
+
static init(options = {}) {
|
|
2298
|
+
if (options instanceof this) {
|
|
2299
|
+
return options
|
|
2300
|
+
}
|
|
2301
|
+
const instance = new this(options)
|
|
2302
|
+
return instance.isValid ? instance : null
|
|
2303
|
+
}
|
|
2304
|
+
static initFromArray(arr = []) {
|
|
2305
|
+
if (Array.isArray(arr)) {
|
|
2306
|
+
return arr.map((a) => this.init(a))
|
|
2307
|
+
}
|
|
2308
|
+
return []
|
|
2309
|
+
}
|
|
2310
|
+
static initOnlyValidFromArray(arr = []) {
|
|
2311
|
+
return this.initFromArray(arr).filter((i) => i)
|
|
2312
|
+
}
|
|
2313
|
+
static get _classname() {
|
|
2314
|
+
return 'KeyValueObject'
|
|
2315
|
+
}
|
|
2316
|
+
static get _superclass() {
|
|
2317
|
+
return 'KeyValueObject'
|
|
2318
|
+
}
|
|
2319
|
+
|
|
2320
|
+
static addItem(arr, key, value) {
|
|
2321
|
+
arr.push(this.init({ key, value }))
|
|
2322
|
+
}
|
|
2323
|
+
static addRecord(arr = [], key, value) {
|
|
2324
|
+
if (!this.hasKeyValue(arr, key, value)) {
|
|
2325
|
+
arr.push(this.init({ key, value }))
|
|
2326
|
+
}
|
|
2327
|
+
return arr
|
|
2328
|
+
}
|
|
2329
|
+
static appendRecord(arr = [], key, value) {
|
|
2330
|
+
return arr.map((item) => {
|
|
2331
|
+
if (this.sameKey(item, key)) {
|
|
2332
|
+
item.value = [...item.value, ...value]
|
|
2333
|
+
}
|
|
2334
|
+
return item
|
|
2335
|
+
})
|
|
2336
|
+
}
|
|
2337
|
+
static appendValueArray(arr = [], key, value) {
|
|
1550
2338
|
return arr.map((item) => {
|
|
1551
2339
|
if (this.sameKey(item, key)) {
|
|
1552
2340
|
item.value = [...item.value, ...value]
|
|
@@ -1720,20 +2508,6 @@ function _isSame(key1, key2) {
|
|
|
1720
2508
|
|
|
1721
2509
|
|
|
1722
2510
|
|
|
1723
|
-
;// ./lib/helpers/stringFormatter/stringFormatter.js
|
|
1724
|
-
function stringFormatter(str, delimiter = '_') {
|
|
1725
|
-
if (str === null || typeof str === 'undefined' || typeof str.toString === 'undefined') {
|
|
1726
|
-
return null
|
|
1727
|
-
}
|
|
1728
|
-
return str.toString()
|
|
1729
|
-
.trim()
|
|
1730
|
-
.toUpperCase()
|
|
1731
|
-
.replace('-', delimiter)
|
|
1732
|
-
.replace(' ', delimiter)
|
|
1733
|
-
}
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
2511
|
;// ./lib/models/metadata/metadata.js
|
|
1738
2512
|
|
|
1739
2513
|
|
|
@@ -1845,314 +2619,218 @@ class QMeta {
|
|
|
1845
2619
|
|
|
1846
2620
|
|
|
1847
2621
|
|
|
1848
|
-
;// ./lib/models/
|
|
1849
|
-
|
|
1850
|
-
|
|
2622
|
+
;// ./lib/models/trackedEntity/trackedEntity.js
|
|
2623
|
+
|
|
2624
|
+
|
|
2625
|
+
class TrackedEntity {
|
|
2626
|
+
constructor(options = {}) {
|
|
1851
2627
|
options = options || {}
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
:
|
|
1859
|
-
|
|
1860
|
-
static init(options = {}) {
|
|
1861
|
-
if (options instanceof this) {
|
|
1862
|
-
return options
|
|
2628
|
+
const timestamp = Date.now()
|
|
2629
|
+
const _tracking = {
|
|
2630
|
+
active: options.active ?? true,
|
|
2631
|
+
created: options.created ?? timestamp,
|
|
2632
|
+
creator: options.creator ?? '',
|
|
2633
|
+
deleted: options.deleted ?? false,
|
|
2634
|
+
modified: options.modified ?? timestamp,
|
|
2635
|
+
owner: options.owner ?? '',
|
|
1863
2636
|
}
|
|
1864
|
-
|
|
1865
|
-
|
|
2637
|
+
|
|
2638
|
+
this.meta = { ..._tracking, ...options.meta }
|
|
2639
|
+
|
|
2640
|
+
// if (trackFlat) {
|
|
2641
|
+
// Object.assign(this, _tracking)
|
|
2642
|
+
// } else {
|
|
2643
|
+
// this.meta = { ..._tracking, ...options.meta }
|
|
2644
|
+
// }
|
|
1866
2645
|
}
|
|
2646
|
+
|
|
2647
|
+
// Class methods
|
|
1867
2648
|
static get _classname() {
|
|
1868
|
-
return '
|
|
2649
|
+
return 'TrackedEntity'
|
|
1869
2650
|
}
|
|
1870
2651
|
static get _superclass() {
|
|
1871
|
-
return '
|
|
2652
|
+
return 'TrackedEntity'
|
|
1872
2653
|
}
|
|
1873
2654
|
|
|
1874
|
-
|
|
1875
|
-
return
|
|
2655
|
+
static init(options = {}) {
|
|
2656
|
+
return init(this, options)
|
|
1876
2657
|
}
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
2658
|
+
static initFromArray(arr = []) {
|
|
2659
|
+
return initFromArray(this, arr)
|
|
2660
|
+
}
|
|
2661
|
+
static initOnlyValidFromArray(arr = []) {
|
|
2662
|
+
return initOnlyValidFromArray(this, arr)
|
|
1880
2663
|
}
|
|
2664
|
+
// static nest(entity) {
|
|
2665
|
+
// const { active, created, creator, deleted, modified, owner, ...rest } = entity
|
|
2666
|
+
// return { ...rest, meta: { active, created, creator, deleted, modified, owner } }
|
|
2667
|
+
// }
|
|
1881
2668
|
|
|
2669
|
+
// getters
|
|
1882
2670
|
get isValid() {
|
|
1883
|
-
return this
|
|
1884
|
-
&& (typeof this.model.deleteOne === 'function')
|
|
1885
|
-
&& (typeof this.model.findAll === 'function')
|
|
1886
|
-
&& (typeof this.model.saveOne === 'function')
|
|
2671
|
+
return !!this
|
|
1887
2672
|
}
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
return {
|
|
1891
|
-
...this._sharedOptions,
|
|
1892
|
-
...this._queryOptions,
|
|
1893
|
-
}
|
|
2673
|
+
get active() {
|
|
2674
|
+
return this.meta?.active ?? this.active
|
|
1894
2675
|
}
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
return {
|
|
1898
|
-
...this._sharedOptions,
|
|
1899
|
-
...this._saveOptions,
|
|
1900
|
-
}
|
|
2676
|
+
get created() {
|
|
2677
|
+
return this.meta?.created ?? this.created
|
|
1901
2678
|
}
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
2679
|
+
get creator() {
|
|
2680
|
+
return this.meta?.creator ?? this.creator
|
|
2681
|
+
}
|
|
2682
|
+
get deleted() {
|
|
2683
|
+
return this.meta?.deleted ?? this.deleted
|
|
2684
|
+
}
|
|
2685
|
+
get modified() {
|
|
2686
|
+
return this.meta?.modified ?? this.modified
|
|
2687
|
+
}
|
|
2688
|
+
get owner() {
|
|
2689
|
+
return this.meta?.owner ?? this.owner
|
|
2690
|
+
}
|
|
2691
|
+
delete() {
|
|
2692
|
+
return this.setDeleted()
|
|
2693
|
+
}
|
|
2694
|
+
setActive() {
|
|
2695
|
+
if (this.meta) {
|
|
2696
|
+
this.meta.active = true
|
|
2697
|
+
} else {
|
|
2698
|
+
this.active = true
|
|
1906
2699
|
}
|
|
1907
|
-
return
|
|
2700
|
+
return this
|
|
1908
2701
|
}
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
...result, // { message: 'ok', total }
|
|
1915
|
-
isNew: false,
|
|
1916
|
-
data: []
|
|
1917
|
-
}
|
|
1918
|
-
} catch (err) {
|
|
1919
|
-
throw err
|
|
2702
|
+
setDeleted() {
|
|
2703
|
+
if (this.meta) {
|
|
2704
|
+
this.meta.deleted = true
|
|
2705
|
+
} else {
|
|
2706
|
+
this.deleted = true
|
|
1920
2707
|
}
|
|
2708
|
+
return this
|
|
1921
2709
|
}
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
})
|
|
1931
|
-
return new Promise((resolve, reject) => {
|
|
1932
|
-
this.model.findAll(query, this.queryOptions, (err, data, total) => {
|
|
1933
|
-
if (err) {
|
|
1934
|
-
log({ level: 'warn', output: err.toString() })
|
|
1935
|
-
reject(err)
|
|
1936
|
-
} else {
|
|
1937
|
-
const result = {
|
|
1938
|
-
isNew: false,
|
|
1939
|
-
data,
|
|
1940
|
-
total: total || data.length
|
|
1941
|
-
}
|
|
1942
|
-
log({ level: 'info', output: { ...result } })
|
|
1943
|
-
resolve(result)
|
|
1944
|
-
}
|
|
1945
|
-
})
|
|
1946
|
-
})
|
|
2710
|
+
setModified() {
|
|
2711
|
+
const timestamp = Date.now()
|
|
2712
|
+
if (this.meta) {
|
|
2713
|
+
this.meta.modified = timestamp
|
|
2714
|
+
} else {
|
|
2715
|
+
this.modified = timestamp
|
|
2716
|
+
}
|
|
2717
|
+
return this
|
|
1947
2718
|
}
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
if (err) {
|
|
1959
|
-
reject(err)
|
|
1960
|
-
} else if (data.length === 1) {
|
|
1961
|
-
const result = {
|
|
1962
|
-
isNew: false,
|
|
1963
|
-
data,
|
|
1964
|
-
total: 1
|
|
1965
|
-
}
|
|
1966
|
-
log({ level: 'info', output: { ...result } })
|
|
1967
|
-
resolve(result)
|
|
1968
|
-
} else if (data.length === 0) {
|
|
1969
|
-
reject(new Error('record not found'))
|
|
1970
|
-
} else {
|
|
1971
|
-
reject(new Error('more than one is found'))
|
|
1972
|
-
}
|
|
1973
|
-
})
|
|
1974
|
-
})
|
|
1975
|
-
.catch((err) => {
|
|
1976
|
-
log({ level: 'warn', output: err.toString() })
|
|
1977
|
-
throw err
|
|
1978
|
-
})
|
|
2719
|
+
setOwner(owner) {
|
|
2720
|
+
if (!owner) {
|
|
2721
|
+
return this
|
|
2722
|
+
}
|
|
2723
|
+
if (this.meta) {
|
|
2724
|
+
this.meta.owner = owner
|
|
2725
|
+
} else {
|
|
2726
|
+
this.owner = owner
|
|
2727
|
+
}
|
|
2728
|
+
return this
|
|
1979
2729
|
}
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
input: [{ docs: [...docs], systemLog: { ...systemLog } }]
|
|
1988
|
-
})
|
|
1989
|
-
const promise = typeof this.model.saveAll === 'function'
|
|
1990
|
-
? this.model.saveAll({ docs })
|
|
1991
|
-
: Promise.all(docs.map(async (doc) => {
|
|
1992
|
-
if (doc) {
|
|
1993
|
-
const result = await this.saveOne({ doc })
|
|
1994
|
-
isNew = result.isNew
|
|
1995
|
-
const _data = result._data || result.data
|
|
1996
|
-
return _data[0]
|
|
1997
|
-
}
|
|
1998
|
-
return null
|
|
1999
|
-
}))
|
|
2000
|
-
return promise.then((savedData) => {
|
|
2001
|
-
if (savedData.length !== 1) isNew = null
|
|
2002
|
-
const result = {
|
|
2003
|
-
data: savedData,
|
|
2004
|
-
isNew,
|
|
2005
|
-
total: savedData.length
|
|
2006
|
-
}
|
|
2007
|
-
log({ level: 'info', output: { ...result } })
|
|
2008
|
-
return result
|
|
2009
|
-
}).catch((err) => {
|
|
2010
|
-
log({ level: 'warn', output: err.toString() })
|
|
2011
|
-
throw err
|
|
2012
|
-
})
|
|
2730
|
+
unsetActive() {
|
|
2731
|
+
if (this.meta) {
|
|
2732
|
+
this.meta.active = false
|
|
2733
|
+
} else {
|
|
2734
|
+
this.active = false
|
|
2735
|
+
}
|
|
2736
|
+
return this
|
|
2013
2737
|
}
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
})
|
|
2022
|
-
return new Promise((resolve, reject) => {
|
|
2023
|
-
this.model.saveOne(doc, this.saveOptions, (err, result) => {
|
|
2024
|
-
if (err) {
|
|
2025
|
-
log({ level: 'warn', output: err.toString() })
|
|
2026
|
-
reject(err)
|
|
2027
|
-
} else {
|
|
2028
|
-
log({ level: 'info', output: { ...result } })
|
|
2029
|
-
resolve(result)
|
|
2030
|
-
}
|
|
2031
|
-
})
|
|
2032
|
-
})
|
|
2738
|
+
unsetDeleted() {
|
|
2739
|
+
if (this.meta) {
|
|
2740
|
+
this.meta.deleted = false
|
|
2741
|
+
} else {
|
|
2742
|
+
this.deleted = false
|
|
2743
|
+
}
|
|
2744
|
+
return this
|
|
2033
2745
|
}
|
|
2034
|
-
}
|
|
2035
2746
|
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
systemLog.systemLogHelper.log({
|
|
2040
|
-
batchId: systemLog.batchId,
|
|
2041
|
-
label,
|
|
2042
|
-
level,
|
|
2043
|
-
message: massage2 || message1,
|
|
2044
|
-
data: {
|
|
2045
|
-
payload: {
|
|
2046
|
-
input,
|
|
2047
|
-
output
|
|
2048
|
-
}
|
|
2049
|
-
}
|
|
2050
|
-
})
|
|
2747
|
+
update(update) {
|
|
2748
|
+
if (update.meta) {
|
|
2749
|
+
this.meta = { ...this.meta, ...update.meta }
|
|
2051
2750
|
}
|
|
2751
|
+
return this.setModified()
|
|
2052
2752
|
}
|
|
2053
2753
|
}
|
|
2054
2754
|
|
|
2755
|
+
;// ./lib/models/trackedEntity/index.js
|
|
2055
2756
|
|
|
2757
|
+
// Explicit named export (optional)
|
|
2056
2758
|
|
|
2057
|
-
;// ./lib/models/
|
|
2759
|
+
;// ./lib/models/tenantAwareEntity/tenantAwareEntity.js
|
|
2058
2760
|
|
|
2059
2761
|
|
|
2060
2762
|
|
|
2061
2763
|
|
|
2062
|
-
|
|
2764
|
+
class TenantAwareEntity extends TrackedEntity {
|
|
2765
|
+
constructor(options = {}) {
|
|
2766
|
+
options = options || {}
|
|
2063
2767
|
|
|
2768
|
+
/**
|
|
2769
|
+
* instead of throw error, we choose to implement the isValid checking
|
|
2770
|
+
*/
|
|
2771
|
+
// if (!options.tenantCode) {
|
|
2772
|
+
// throw new Error('tenantCode required')
|
|
2773
|
+
// }
|
|
2064
2774
|
|
|
2775
|
+
super(options)
|
|
2065
2776
|
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
this.
|
|
2777
|
+
this._tenant = options._tenant
|
|
2778
|
+
|
|
2779
|
+
this.metadata = Metadata.initOnlyValidFromArray(options.metadata)
|
|
2780
|
+
this.remarks = KeyValueObject.initOnlyValidFromArray(options.remarks)
|
|
2781
|
+
this.tenantCode = options.tenantCode // Required for multi-tenancy
|
|
2069
2782
|
}
|
|
2070
2783
|
|
|
2784
|
+
// Class methods
|
|
2071
2785
|
static get _classname() {
|
|
2072
|
-
return '
|
|
2786
|
+
return 'TenantAwareEntity'
|
|
2073
2787
|
}
|
|
2074
2788
|
static get _superclass() {
|
|
2075
|
-
return '
|
|
2789
|
+
return 'TenantAwareEntity'
|
|
2076
2790
|
}
|
|
2077
2791
|
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
throw new Error(`Not found for query: ${id}`)
|
|
2082
|
-
})
|
|
2792
|
+
// getters
|
|
2793
|
+
get isValid() {
|
|
2794
|
+
return super.isValid && !!this.tenantCode // Required for multi-tenancy
|
|
2083
2795
|
}
|
|
2084
2796
|
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
return
|
|
2088
|
-
repo: this.repo,
|
|
2089
|
-
result
|
|
2090
|
-
})
|
|
2797
|
+
// instance methods
|
|
2798
|
+
getMetadata() {
|
|
2799
|
+
return this.metadata
|
|
2091
2800
|
}
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
const result = await this.repo.findOne({ query, systemLog })
|
|
2095
|
-
return makeApiResponse({
|
|
2096
|
-
repo: this.repo,
|
|
2097
|
-
result
|
|
2098
|
-
})
|
|
2801
|
+
getMetadataByKey(key) {
|
|
2802
|
+
return Metadata.foundByKey(this.metadata, key)
|
|
2099
2803
|
}
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
return
|
|
2804
|
+
getMetadataValueByKey(key) {
|
|
2805
|
+
const found = this.getMetadataByKey(key)
|
|
2806
|
+
return found ? found.value : null
|
|
2103
2807
|
}
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
return arr.map((a) => this.init(a))
|
|
2107
|
-
}
|
|
2108
|
-
return []
|
|
2808
|
+
getRemarks() {
|
|
2809
|
+
return this.remarks
|
|
2109
2810
|
}
|
|
2110
|
-
|
|
2111
|
-
return
|
|
2811
|
+
getRemarkByKey(key) {
|
|
2812
|
+
return KeyValueObject.foundByKey(this.remarks, key)
|
|
2112
2813
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
return makeApiResponse({
|
|
2120
|
-
repo: this.repo,
|
|
2121
|
-
result
|
|
2122
|
-
})
|
|
2814
|
+
getRemarksValueByKey(key) {
|
|
2815
|
+
const found = this.getRemarkByKey(key)
|
|
2816
|
+
return found ? found.value : null
|
|
2817
|
+
}
|
|
2818
|
+
getTenantCode() {
|
|
2819
|
+
return this.tenantCode
|
|
2123
2820
|
}
|
|
2124
2821
|
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
const result = await this.repo.saveOne({ doc: copy, systemLog })
|
|
2129
|
-
return makeApiResponse({
|
|
2130
|
-
repo: this.repo,
|
|
2131
|
-
result
|
|
2132
|
-
})
|
|
2822
|
+
update(update) {
|
|
2823
|
+
if (update.metadata && Array.isArray(update.metadata)) {
|
|
2824
|
+
this.metadata = Metadata.initOnlyValidFromArray(update.metadata)
|
|
2133
2825
|
}
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
data: [],
|
|
2137
|
-
err: new Error('doc is not a valid instance')
|
|
2826
|
+
if (update.remarks && Array.isArray(update.remarks)) {
|
|
2827
|
+
this.remarks = KeyValueObject.initOnlyValidFromArray(update.remarks)
|
|
2138
2828
|
}
|
|
2829
|
+
return super.update(update)
|
|
2139
2830
|
}
|
|
2140
2831
|
}
|
|
2141
2832
|
|
|
2142
|
-
|
|
2143
|
-
if (repo === undefined) {
|
|
2144
|
-
throw new Error('repo is required.')
|
|
2145
|
-
}
|
|
2146
|
-
if (repo._superclass !== Repo._superclass) {
|
|
2147
|
-
throw new Error('repo is not an instance of Repo.')
|
|
2148
|
-
}
|
|
2149
|
-
return new Service({ repo })
|
|
2150
|
-
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
;// ./lib/models/service/index.js
|
|
2155
|
-
|
|
2833
|
+
;// ./lib/models/tenantAwareEntity/index.js
|
|
2156
2834
|
|
|
2157
2835
|
|
|
2158
2836
|
|
|
@@ -2214,191 +2892,6 @@ function _makeSetCode(fieldName, options) {
|
|
|
2214
2892
|
|
|
2215
2893
|
|
|
2216
2894
|
|
|
2217
|
-
;// ./lib/helpers/generalPost/generalPost.js
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
async function generalPost({ body = {}, GeneralModel, UniqueKeyGenerator, resourceInfo }) {
|
|
2223
|
-
const { resources, data, globalShared = {}, shared = {}, relationship = {} } = body
|
|
2224
|
-
const _resourceInfo = resourceInfo || body.resourceInfo
|
|
2225
|
-
_attachShared(data, globalShared, shared)
|
|
2226
|
-
const obj = await pReduce(resources, async (acc, resource) => {
|
|
2227
|
-
const service = _makeService(resource, _resourceInfo, UniqueKeyGenerator, GeneralModel)
|
|
2228
|
-
_createRelationship(data, relationship[resource], acc)
|
|
2229
|
-
const _data = data[resource]
|
|
2230
|
-
const result = await service.saveAll({ docs: [].concat(_data) })
|
|
2231
|
-
acc[resource] = Array.isArray(_data) ? result._data : result._data[0]
|
|
2232
|
-
return acc
|
|
2233
|
-
}, {})
|
|
2234
|
-
return obj
|
|
2235
|
-
}
|
|
2236
|
-
|
|
2237
|
-
function _attachShared(data, globalShared = {}, shared = {}) {
|
|
2238
|
-
Object.keys(shared).forEach((key) => {
|
|
2239
|
-
const _data = data[key]
|
|
2240
|
-
data[key] = objectHelper.merge({}, _data, globalShared, shared[key] || {})
|
|
2241
|
-
})
|
|
2242
|
-
}
|
|
2243
|
-
|
|
2244
|
-
function _createRelationship(data, relationship = {}, object) {
|
|
2245
|
-
Object.keys(relationship).forEach((key) => {
|
|
2246
|
-
const path = relationship[key]
|
|
2247
|
-
const val = objectHelper.get(object, path)
|
|
2248
|
-
objectHelper.set(data, key, val)
|
|
2249
|
-
})
|
|
2250
|
-
}
|
|
2251
|
-
|
|
2252
|
-
function _makeService(resource, resourceInfo, UniqueKeyGenerator, GeneralModel) {
|
|
2253
|
-
const { collectionName, fields } = resourceInfo[resource]
|
|
2254
|
-
const uniqueKeyGenerator = UniqueKeyGenerator.makeGenerator(fields)
|
|
2255
|
-
const model = new GeneralModel({ collectionName, uniqueKeyGenerator })
|
|
2256
|
-
return makeService({
|
|
2257
|
-
repo: new Repo({ model })
|
|
2258
|
-
})
|
|
2259
|
-
}
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
;// ./lib/helpers/generalPost/index.js
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
;// ./lib/helpers/padZeros/padZeros.js
|
|
2269
|
-
function padZeros(num, minLength = 6) {
|
|
2270
|
-
num = num.toString()
|
|
2271
|
-
if (num.length < minLength) {
|
|
2272
|
-
return padZeros('0' + num, minLength)
|
|
2273
|
-
}
|
|
2274
|
-
return num
|
|
2275
|
-
}
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
;// ./lib/helpers/padZeros/index.js
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
;// ./lib/helpers/pReduce/index.js
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
;// ./lib/helpers/stringFormatter/index.js
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
;// ./lib/helpers/stringHelper/stringHelper.js
|
|
2295
|
-
function baseXEncode(num, base = 34) {
|
|
2296
|
-
const charset = getBaseCharset(base)
|
|
2297
|
-
return encode(num, charset)
|
|
2298
|
-
}
|
|
2299
|
-
|
|
2300
|
-
function encode(int, charset) {
|
|
2301
|
-
let byCode = charset.byCode;
|
|
2302
|
-
if (int === 0) {
|
|
2303
|
-
return byCode[0];
|
|
2304
|
-
}
|
|
2305
|
-
|
|
2306
|
-
var res = "",
|
|
2307
|
-
max = charset.length;
|
|
2308
|
-
while (int > 0) {
|
|
2309
|
-
res = byCode[int % max] + res;
|
|
2310
|
-
int = Math.floor(int / max);
|
|
2311
|
-
}
|
|
2312
|
-
return res;
|
|
2313
|
-
}
|
|
2314
|
-
|
|
2315
|
-
function getBaseCharset(base) {
|
|
2316
|
-
let charset = '9876543210ABCDEFGHJKLMNPQRSTUVWXYZ'
|
|
2317
|
-
if (base === 58) {
|
|
2318
|
-
charset = '9876543210ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz'
|
|
2319
|
-
}
|
|
2320
|
-
return indexCharset(charset)
|
|
2321
|
-
}
|
|
2322
|
-
|
|
2323
|
-
function indexCharset(str) {
|
|
2324
|
-
var byCode = {},
|
|
2325
|
-
byChar = {},
|
|
2326
|
-
length = str.length,
|
|
2327
|
-
i, char;
|
|
2328
|
-
for (i = 0; i < length; i++) {
|
|
2329
|
-
char = str[i];
|
|
2330
|
-
byCode[i] = char;
|
|
2331
|
-
byChar[char] = i;
|
|
2332
|
-
}
|
|
2333
|
-
return { byCode: byCode, byChar: byChar, length: length };
|
|
2334
|
-
}
|
|
2335
|
-
|
|
2336
|
-
function randomString({ len = 16, pattern = 'a1' } = {}) {
|
|
2337
|
-
const A = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
2338
|
-
const a = 'abcdefghijklmnopqrstuvwxyz'
|
|
2339
|
-
const num = '1234567890'
|
|
2340
|
-
const mark = '~!@#$%^&*_+-='
|
|
2341
|
-
let str = ''
|
|
2342
|
-
if (pattern.includes('A')) {
|
|
2343
|
-
str += A
|
|
2344
|
-
}
|
|
2345
|
-
if (pattern.includes('a')) {
|
|
2346
|
-
str += a
|
|
2347
|
-
}
|
|
2348
|
-
if (pattern.includes('1')) {
|
|
2349
|
-
str += num
|
|
2350
|
-
}
|
|
2351
|
-
if (pattern.includes('#')) {
|
|
2352
|
-
str += mark
|
|
2353
|
-
}
|
|
2354
|
-
const chars = [...str]
|
|
2355
|
-
return [...Array(len)].map(i => {
|
|
2356
|
-
return chars[(Math.random() * chars.length) | 0]
|
|
2357
|
-
}).join``
|
|
2358
|
-
}
|
|
2359
|
-
|
|
2360
|
-
function reverse(str) {
|
|
2361
|
-
if (typeof str !== 'string') {
|
|
2362
|
-
str = str.toString()
|
|
2363
|
-
}
|
|
2364
|
-
const splitString = str.split('')
|
|
2365
|
-
const reverseArray = splitString.reverse()
|
|
2366
|
-
return reverseArray.join('')
|
|
2367
|
-
}
|
|
2368
|
-
|
|
2369
|
-
function setCode(base = 34) {
|
|
2370
|
-
const now = (new Date()).valueOf()
|
|
2371
|
-
const random = randomString({
|
|
2372
|
-
len: 8,
|
|
2373
|
-
pattern: '1'
|
|
2374
|
-
})
|
|
2375
|
-
const str = reverse(`${now}${random}`)
|
|
2376
|
-
// const str = `${now}${random}`
|
|
2377
|
-
return baseXEncode(str, base)
|
|
2378
|
-
}
|
|
2379
|
-
|
|
2380
|
-
const stringHelper = {
|
|
2381
|
-
setCode
|
|
2382
|
-
}
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
;// ./lib/helpers/stringHelper/index.js
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
;// ./lib/helpers/index.js
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
2895
|
|
|
2403
2896
|
|
|
2404
2897
|
;// ./lib/index.js
|