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