@opengis/fastify-table 1.3.20 → 1.3.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -86
- package/index.js +17 -6
- package/package.json +6 -3
- package/server/helpers/format/formatAuto.js +13 -0
- package/server/helpers/format/formatDate.js +258 -0
- package/server/helpers/format/formatDigit.js +21 -0
- package/server/helpers/format/formatNum.js +361 -0
- package/server/helpers/format/formatNumber.js +54 -0
- package/server/helpers/format/formatRelative.js +106 -0
- package/server/helpers/format/formatUnit.js +38 -0
- package/server/helpers/format/num_format.js +42 -0
- package/server/helpers/format/set.js +26 -0
- package/server/helpers/funcs/_math.js +50 -0
- package/server/helpers/funcs/contentList.js +58 -0
- package/server/helpers/funcs/empty.js +21 -0
- package/server/helpers/funcs/ifCond.js +106 -0
- package/server/helpers/funcs/ifCondAnd.js +96 -0
- package/server/helpers/funcs/ifCondOr.js +98 -0
- package/server/helpers/funcs/inc.js +21 -0
- package/server/helpers/funcs/json.js +3 -0
- package/server/helpers/funcs/qrcode.js +66 -0
- package/server/helpers/funcs/round.js +28 -0
- package/server/helpers/funcs/select.js +50 -0
- package/server/helpers/index.js +70 -3
- package/server/helpers/string/coalesce.js +31 -0
- package/server/helpers/string/concat.js +28 -0
- package/server/helpers/string/split.js +20 -0
- package/server/helpers/string/str_replace.js +61 -0
- package/server/helpers/string/substr.js +32 -0
- package/server/helpers/string/translit.js +23 -0
- package/server/helpers/string/utils/alphabet.js +76 -0
- package/server/plugins/cron/funcs/addCron.js +52 -52
- package/server/plugins/cron/index.js +74 -74
- package/server/plugins/crud/funcs/getOpt.js +13 -13
- package/server/plugins/crud/funcs/setOpt.js +21 -21
- package/server/plugins/crud/funcs/setToken.js +44 -44
- package/server/plugins/crud/funcs/utils/getFolder.js +11 -11
- package/server/plugins/crud/index.js +23 -23
- package/server/plugins/hook/index.js +8 -8
- package/server/plugins/logger/errorStatus.js +19 -19
- package/server/plugins/logger/index.js +26 -26
- package/server/plugins/migration/index.js +7 -7
- package/server/plugins/pg/funcs/getMeta.js +1 -1
- package/server/plugins/policy/sqlInjection.js +33 -33
- package/server/plugins/redis/client.js +8 -8
- package/server/plugins/redis/funcs/redisClients.js +3 -3
- package/server/plugins/redis/index.js +17 -17
- package/server/plugins/table/funcs/getFilterSQL/util/getCustomQuery.js +13 -13
- package/server/plugins/table/funcs/getFilterSQL/util/getTableSql.js +34 -34
- package/server/plugins/table/funcs/getTemplates.js +19 -19
- package/server/plugins/table/funcs/gisIRColumn.js +82 -82
- package/server/plugins/table/funcs/loadTemplate.js +1 -1
- package/server/plugins/table/funcs/loadTemplatePath.js +1 -1
- package/server/plugins/table/funcs/metaFormat/index.js +1 -1
- package/server/plugins/table/funcs/userTemplateDir.js +1 -1
- package/server/plugins/table/index.js +13 -13
- package/server/plugins/util/index.js +7 -7
- package/server/routes/cron/index.js +14 -14
- package/server/routes/logger/controllers/logger.file.js +92 -92
- package/server/routes/logger/controllers/utils/checkUserAccess.js +19 -19
- package/server/routes/logger/controllers/utils/getRootDir.js +26 -26
- package/server/routes/logger/index.js +17 -17
- package/server/routes/properties/controllers/properties.add.js +55 -55
- package/server/routes/properties/controllers/properties.get.js +17 -17
- package/server/routes/properties/index.js +16 -16
- package/server/routes/table/controllers/filter.js +1 -1
- package/server/routes/table/controllers/form.js +42 -42
- package/server/routes/table/controllers/search.js +74 -74
- package/server/routes/table/schema.js +64 -64
- package/server/routes/util/controllers/status.monitor.js +8 -8
- package/utils.js +2 -2
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Об'єднання декількох вихідних змінних в одній строці
|
|
3
|
+
*
|
|
4
|
+
* @summary Об'єднання в одну строку декількох архументів. Можна використовувати для побудови посилань.
|
|
5
|
+
* @priority 4
|
|
6
|
+
* @alias concat
|
|
7
|
+
* @type helper
|
|
8
|
+
* @tag string
|
|
9
|
+
* @example
|
|
10
|
+
* {{concat 'https://spending.gov.ua/new/disposers/' edrpou '/agreements/' id}}
|
|
11
|
+
* @descr Результат: https://spending.gov.ua/new/disposers/1234567890/agreements/3721893718937819 (edrpou та id - змінні)
|
|
12
|
+
* @param {Array} args Масив аргуметів, які потрібно з'єднати
|
|
13
|
+
* @returns {String} Returns HTML
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export default function concat(...args) {
|
|
17
|
+
if (args.length === 0) return '';
|
|
18
|
+
|
|
19
|
+
let result = '';
|
|
20
|
+
|
|
21
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
22
|
+
if (['string', 'number'].includes(typeof args[i])) {
|
|
23
|
+
result += args[i];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return result;
|
|
28
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Метод split() разбивает объект String на массив строк путём разделения строки указанной подстрокой.
|
|
3
|
+
*
|
|
4
|
+
* @summary Метод split() разбивает объект String на массив строк путём разделения строки указанной подстрокой.
|
|
5
|
+
* @priority 4
|
|
6
|
+
* @alias split
|
|
7
|
+
* @tag string
|
|
8
|
+
* @type helper
|
|
9
|
+
* @example
|
|
10
|
+
|
|
11
|
+
* @param {String} separator Символ по якому ділиться объект String
|
|
12
|
+
* @param {String} data Строка або число яке обрізається
|
|
13
|
+
* @returns {Array} Returns HTML
|
|
14
|
+
*/
|
|
15
|
+
export default function split(data, options) {
|
|
16
|
+
const fullString = data ? `${data}` : '';
|
|
17
|
+
const separator = options || ',';
|
|
18
|
+
|
|
19
|
+
return fullString.split(separator);
|
|
20
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Виконує заміну символів у строці. Є можливість заміни регулярного виразу нової строки на тег <br>
|
|
3
|
+
*
|
|
4
|
+
* @summary Виконання заміни частини строки на значення з останнього аргументу.
|
|
5
|
+
* @priority 3
|
|
6
|
+
* @type helper
|
|
7
|
+
* @alias strReplace
|
|
8
|
+
* @tag string
|
|
9
|
+
* @example
|
|
10
|
+
* {{str_replace 'This Is Alias' ' ' ''}}
|
|
11
|
+
* @example
|
|
12
|
+
* {{{str_replace '<p>Перший рядок</p><p>Наступний рядок</p>' br=1}}}
|
|
13
|
+
* @example
|
|
14
|
+
* {{{str_replace 'Перший рядок<br>Наступний рядок' br=1}}}
|
|
15
|
+
* @param {Object} br
|
|
16
|
+
* @param {Object} newline
|
|
17
|
+
* @param {Object} html
|
|
18
|
+
* @param {Object} last
|
|
19
|
+
* @param {Array} args[0]]
|
|
20
|
+
* @param {Array} args[1]]
|
|
21
|
+
* @param {Array} args[2]]
|
|
22
|
+
* @returns {String} Returns HTML
|
|
23
|
+
*/
|
|
24
|
+
export default function strReplace(...args) {
|
|
25
|
+
const options = args.pop();
|
|
26
|
+
const [str, from, to] = args;
|
|
27
|
+
|
|
28
|
+
if (!str) return '';
|
|
29
|
+
|
|
30
|
+
if (options.hash.br) {
|
|
31
|
+
return str.replace(/\n/g, '<br>');
|
|
32
|
+
}
|
|
33
|
+
if (options.hash.newline) {
|
|
34
|
+
return str.replace(/\n/g, ' ');
|
|
35
|
+
}
|
|
36
|
+
if (options.hash.html) {
|
|
37
|
+
return str
|
|
38
|
+
.replace(/<br>/g, '\n')
|
|
39
|
+
.replace(/<\/p>/g, '\n')
|
|
40
|
+
.replace(/<\/li>/g, '\n')
|
|
41
|
+
.replace(/(<[^>]+>|<[^>]>|<\/[^>]>)/g, '')
|
|
42
|
+
.replace(/\n/g, ' ');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (options.hash.last) {
|
|
46
|
+
return replaceLast(str, from, to);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (typeof from !== 'string' || typeof to !== 'string') {
|
|
50
|
+
return 'Invalid replacement parameters';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return str.replace(new RegExp(from, 'g'), to);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function replaceLast(str, what, replacement) {
|
|
57
|
+
if (!str?.split) return str;
|
|
58
|
+
const pcs = str?.split(what);
|
|
59
|
+
const lastPc = pcs.pop();
|
|
60
|
+
return pcs.join(what) + replacement + lastPc;
|
|
61
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Зменшення строки за значеням із змінної. Можна отримати частину строки за першим та останнім символом.
|
|
3
|
+
*
|
|
4
|
+
* @summary Обрізання строки. За замовчуванням до 100 символів. Є можливість вказання точної кількості.
|
|
5
|
+
* @priority 4
|
|
6
|
+
* @alias substr
|
|
7
|
+
* @tag string
|
|
8
|
+
* @type helper
|
|
9
|
+
* @example
|
|
10
|
+
* {{substr @root.domain from=5}}
|
|
11
|
+
* @example
|
|
12
|
+
* {{substr req.headers.host max=15}}
|
|
13
|
+
* @param {Object} from Число з якого обрізати строку
|
|
14
|
+
* @param {Object} max Число до якого обрізати строку
|
|
15
|
+
* @param {Object} args[1]] Використовуэться, якщо не дано opt.max
|
|
16
|
+
* @param {String|Number} data Строка або число яке обрізається
|
|
17
|
+
* @returns {String} Returns HTML
|
|
18
|
+
*/
|
|
19
|
+
export default function substr(data, { hash }) {
|
|
20
|
+
const fullString = data ? String(data) : '';
|
|
21
|
+
|
|
22
|
+
const max = typeof hash?.max === 'number' ? hash.max : 100;
|
|
23
|
+
const from = typeof hash?.from === 'number' ? hash.from : 0;
|
|
24
|
+
|
|
25
|
+
const result = fullString.substr(from, max);
|
|
26
|
+
|
|
27
|
+
if (hash?.unit && fullString.length > max) {
|
|
28
|
+
return `${result}${hash.unit}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return result;
|
|
32
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import L from './utils/alphabet.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Форматування символів з кирилиці на латиницю
|
|
5
|
+
*
|
|
6
|
+
* @summary Форматування символів з кирилиці на латиницю
|
|
7
|
+
* @priority 0
|
|
8
|
+
* @deprecated true
|
|
9
|
+
* @tag string
|
|
10
|
+
* @type helper
|
|
11
|
+
* @alias translit
|
|
12
|
+
* @example
|
|
13
|
+
* {{translit data_name}}
|
|
14
|
+
* @param {String} data Перетворення букв з строки з укр на англ
|
|
15
|
+
* @returns {String} Returns HTML
|
|
16
|
+
*/
|
|
17
|
+
export default function translit({ data }) {
|
|
18
|
+
const rKey = Object.keys(L).join('');
|
|
19
|
+
|
|
20
|
+
const reg = new RegExp(`[${rKey}]`, 'g');
|
|
21
|
+
|
|
22
|
+
return (data || '').replace(reg, (a) => (a in L ? L[a] : ''));
|
|
23
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
А: 'A',
|
|
3
|
+
а: 'a',
|
|
4
|
+
Б: 'B',
|
|
5
|
+
б: 'b',
|
|
6
|
+
В: 'V',
|
|
7
|
+
в: 'v',
|
|
8
|
+
Г: 'H',
|
|
9
|
+
г: 'h',
|
|
10
|
+
Д: 'D',
|
|
11
|
+
д: 'd',
|
|
12
|
+
Е: 'E',
|
|
13
|
+
е: 'e',
|
|
14
|
+
Ё: 'Yo',
|
|
15
|
+
ё: 'yo',
|
|
16
|
+
Ж: 'Zh',
|
|
17
|
+
ж: 'zh',
|
|
18
|
+
З: 'Z',
|
|
19
|
+
з: 'z',
|
|
20
|
+
И: 'Y',
|
|
21
|
+
и: 'y',
|
|
22
|
+
Й: 'Y',
|
|
23
|
+
й: 'i',
|
|
24
|
+
К: 'K',
|
|
25
|
+
к: 'k',
|
|
26
|
+
Л: 'L',
|
|
27
|
+
л: 'l',
|
|
28
|
+
М: 'M',
|
|
29
|
+
м: 'm',
|
|
30
|
+
Н: 'N',
|
|
31
|
+
н: 'n',
|
|
32
|
+
О: 'O',
|
|
33
|
+
о: 'o',
|
|
34
|
+
П: 'P',
|
|
35
|
+
п: 'p',
|
|
36
|
+
Р: 'R',
|
|
37
|
+
р: 'r',
|
|
38
|
+
С: 'S',
|
|
39
|
+
с: 's',
|
|
40
|
+
Т: 'T',
|
|
41
|
+
т: 't',
|
|
42
|
+
У: 'U',
|
|
43
|
+
у: 'u',
|
|
44
|
+
Ф: 'F',
|
|
45
|
+
ф: 'f',
|
|
46
|
+
Х: 'Kh',
|
|
47
|
+
х: 'kh',
|
|
48
|
+
Ц: 'Ts',
|
|
49
|
+
ц: 'ts',
|
|
50
|
+
Ч: 'Ch',
|
|
51
|
+
ч: 'ch',
|
|
52
|
+
Ш: 'Sh',
|
|
53
|
+
ш: 'sh',
|
|
54
|
+
Щ: 'Shch',
|
|
55
|
+
щ: 'shch',
|
|
56
|
+
Ъ: '',
|
|
57
|
+
ъ: '',
|
|
58
|
+
Ы: 'Y',
|
|
59
|
+
ы: 'y',
|
|
60
|
+
Ь: '',
|
|
61
|
+
ь: '',
|
|
62
|
+
Э: 'E',
|
|
63
|
+
э: 'e',
|
|
64
|
+
Ю: 'Yu',
|
|
65
|
+
ю: 'yu',
|
|
66
|
+
Я: 'Ya',
|
|
67
|
+
я: 'ia',
|
|
68
|
+
І: 'I',
|
|
69
|
+
і: 'i',
|
|
70
|
+
Ї: 'Yi',
|
|
71
|
+
ї: 'i',
|
|
72
|
+
Є: 'Ye',
|
|
73
|
+
є: 'ie',
|
|
74
|
+
Ґ: 'G',
|
|
75
|
+
ґ: 'g',
|
|
76
|
+
};
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
import config from '../../../../config.js';
|
|
2
|
-
|
|
3
|
-
import logger from '../../logger/getLogger.js';
|
|
4
|
-
import pgClients from '../../pg/pgClients.js';
|
|
5
|
-
|
|
6
|
-
import cronList from '../cronList.js';
|
|
7
|
-
import runCron from './runCron.js';
|
|
8
|
-
import interval2ms from './interval2ms.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* interval:
|
|
12
|
-
* - 02:54 - every day
|
|
13
|
-
* - 2:03 - every day
|
|
14
|
-
* - *1:43 - 2 times a day
|
|
15
|
-
* - *12:03 - 2 times a day
|
|
16
|
-
* - **:54 - every hour
|
|
17
|
-
* - **:*3 - every 10 minutes
|
|
18
|
-
* - 60 - every minute
|
|
19
|
-
* - 10 * 60 - every 10 minutes
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
export default async function addCron(func, interval, pg = pgClients.client) {
|
|
23
|
-
const { time = {}, disabled = [] } = config.cron || {};
|
|
24
|
-
|
|
25
|
-
const name = func.name || func.toString().split('/').at(-1).split('\'')[0];
|
|
26
|
-
|
|
27
|
-
// if (!config.isServer) return;
|
|
28
|
-
|
|
29
|
-
if (disabled.includes(name)) {
|
|
30
|
-
logger.file('cron', { name, message: 'cron disabled' });
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
cronList[name] = func;
|
|
35
|
-
|
|
36
|
-
const userInterval = time[name] || interval;
|
|
37
|
-
const [waitMs, intervalMs] = interval2ms[typeof interval](userInterval);
|
|
38
|
-
|
|
39
|
-
if (intervalMs < 1000) {
|
|
40
|
-
logger.file('cron', { name, error: `interval ${interval} too small` });
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// setTimeout to w8 for the time to start
|
|
45
|
-
setTimeout(() => {
|
|
46
|
-
runCron({ pg, func, name });
|
|
47
|
-
// interval
|
|
48
|
-
setInterval(() => {
|
|
49
|
-
runCron({ pg, func, name });
|
|
50
|
-
}, intervalMs);
|
|
51
|
-
}, waitMs);
|
|
52
|
-
}
|
|
1
|
+
import config from '../../../../config.js';
|
|
2
|
+
|
|
3
|
+
import logger from '../../logger/getLogger.js';
|
|
4
|
+
import pgClients from '../../pg/pgClients.js';
|
|
5
|
+
|
|
6
|
+
import cronList from '../cronList.js';
|
|
7
|
+
import runCron from './runCron.js';
|
|
8
|
+
import interval2ms from './interval2ms.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* interval:
|
|
12
|
+
* - 02:54 - every day
|
|
13
|
+
* - 2:03 - every day
|
|
14
|
+
* - *1:43 - 2 times a day
|
|
15
|
+
* - *12:03 - 2 times a day
|
|
16
|
+
* - **:54 - every hour
|
|
17
|
+
* - **:*3 - every 10 minutes
|
|
18
|
+
* - 60 - every minute
|
|
19
|
+
* - 10 * 60 - every 10 minutes
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export default async function addCron(func, interval, pg = pgClients.client) {
|
|
23
|
+
const { time = {}, disabled = [] } = config.cron || {};
|
|
24
|
+
|
|
25
|
+
const name = func.name || func.toString().split('/').at(-1).split('\'')[0];
|
|
26
|
+
|
|
27
|
+
// if (!config.isServer) return;
|
|
28
|
+
|
|
29
|
+
if (disabled.includes(name)) {
|
|
30
|
+
logger.file('cron', { name, message: 'cron disabled' });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
cronList[name] = func;
|
|
35
|
+
|
|
36
|
+
const userInterval = time[name] || interval;
|
|
37
|
+
const [waitMs, intervalMs] = interval2ms[typeof interval](userInterval);
|
|
38
|
+
|
|
39
|
+
if (intervalMs < 1000) {
|
|
40
|
+
logger.file('cron', { name, error: `interval ${interval} too small` });
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// setTimeout to w8 for the time to start
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
runCron({ pg, func, name });
|
|
47
|
+
// interval
|
|
48
|
+
setInterval(() => {
|
|
49
|
+
runCron({ pg, func, name });
|
|
50
|
+
}, intervalMs);
|
|
51
|
+
}, waitMs);
|
|
52
|
+
}
|
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
|
-
|
|
3
|
-
import config from "../../../config.js";
|
|
4
|
-
|
|
5
|
-
import getPG from "../pg/funcs/getPG.js";
|
|
6
|
-
import pgClients from "../pg/pgClients.js";
|
|
7
|
-
import getRedis from '../redis/funcs/getRedis.js';
|
|
8
|
-
import logger from "../logger/getLogger.js";
|
|
9
|
-
import interval2ms from "./funcs/interval2ms.js";
|
|
10
|
-
|
|
11
|
-
const rclient = getRedis();
|
|
12
|
-
|
|
13
|
-
async function runCron({
|
|
14
|
-
pg = pgClients.client, query, name,
|
|
15
|
-
}) {
|
|
16
|
-
const db = pg.options.database;
|
|
17
|
-
|
|
18
|
-
// verifyUnique
|
|
19
|
-
const key = `cron:unique:${name}`;
|
|
20
|
-
const unique = await rclient.setnx(key, 1);
|
|
21
|
-
const ttl = await rclient.ttl(key);
|
|
22
|
-
|
|
23
|
-
if (!unique && ttl !== -1) {
|
|
24
|
-
// if (config.trace) console.log(name, db, query, 'skip unique');
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
await rclient.expire(key, 20);
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
if (!pg.pk) await pg.init();
|
|
32
|
-
|
|
33
|
-
if (config.trace) console.time(`${db}:${query}`);
|
|
34
|
-
const { command, rows = [], rowCount } = await pg.query(query);
|
|
35
|
-
if (config.trace) console.timeEnd(`${db}:${query}`);
|
|
36
|
-
|
|
37
|
-
logger.file('cron', { db, name, result: { command, rows, rowCount } });
|
|
38
|
-
}
|
|
39
|
-
catch (err) {
|
|
40
|
-
if (config.trace) console.error(name, err.toString());
|
|
41
|
-
logger.file('cron/error', { db, name, error: err.toString() });
|
|
42
|
-
logger.error(err);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async function plugin(fastify) {
|
|
47
|
-
if (config.cronList?.length) {
|
|
48
|
-
config.cronList?.filter(el => el.query && !el.disabled)?.forEach?.((el, idx) => {
|
|
49
|
-
const { interval, db, query } = el;
|
|
50
|
-
const name = createHash('md5').update(`${config.port || 3000}:${db}:${query}`).digest('hex');
|
|
51
|
-
const pg = getPG(db);
|
|
52
|
-
|
|
53
|
-
if (config.trace) console.log('cron-list: init', db, idx);
|
|
54
|
-
|
|
55
|
-
const [waitMs, intervalMs] = interval2ms[typeof interval](interval);
|
|
56
|
-
|
|
57
|
-
if (intervalMs < 1000) {
|
|
58
|
-
if (config.trace) console.error('cron-list: skip too small interval', db, idx);
|
|
59
|
-
logger.file('cron', { name, error: `interval ${interval} too small` });
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// setTimeout to w8 for the time to start
|
|
64
|
-
setTimeout(() => {
|
|
65
|
-
runCron({ pg, query, name });
|
|
66
|
-
// interval
|
|
67
|
-
setInterval(() => {
|
|
68
|
-
runCron({ pg, query, name });
|
|
69
|
-
}, intervalMs);
|
|
70
|
-
}, waitMs);
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
export default plugin;
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
import config from "../../../config.js";
|
|
4
|
+
|
|
5
|
+
import getPG from "../pg/funcs/getPG.js";
|
|
6
|
+
import pgClients from "../pg/pgClients.js";
|
|
7
|
+
import getRedis from '../redis/funcs/getRedis.js';
|
|
8
|
+
import logger from "../logger/getLogger.js";
|
|
9
|
+
import interval2ms from "./funcs/interval2ms.js";
|
|
10
|
+
|
|
11
|
+
const rclient = getRedis();
|
|
12
|
+
|
|
13
|
+
async function runCron({
|
|
14
|
+
pg = pgClients.client, query, name,
|
|
15
|
+
}) {
|
|
16
|
+
const db = pg.options.database;
|
|
17
|
+
|
|
18
|
+
// verifyUnique
|
|
19
|
+
const key = `cron:unique:${name}`;
|
|
20
|
+
const unique = await rclient.setnx(key, 1);
|
|
21
|
+
const ttl = await rclient.ttl(key);
|
|
22
|
+
|
|
23
|
+
if (!unique && ttl !== -1) {
|
|
24
|
+
// if (config.trace) console.log(name, db, query, 'skip unique');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
await rclient.expire(key, 20);
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
if (!pg.pk) await pg.init();
|
|
32
|
+
|
|
33
|
+
if (config.trace) console.time(`${db}:${query}`);
|
|
34
|
+
const { command, rows = [], rowCount } = await pg.query(query);
|
|
35
|
+
if (config.trace) console.timeEnd(`${db}:${query}`);
|
|
36
|
+
|
|
37
|
+
logger.file('cron', { db, name, result: { command, rows, rowCount } });
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
if (config.trace) console.error(name, err.toString());
|
|
41
|
+
logger.file('cron/error', { db, name, error: err.toString() });
|
|
42
|
+
logger.error(err);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function plugin(fastify) {
|
|
47
|
+
if (config.cronList?.length) {
|
|
48
|
+
config.cronList?.filter(el => el.query && !el.disabled)?.forEach?.((el, idx) => {
|
|
49
|
+
const { interval, db, query } = el;
|
|
50
|
+
const name = createHash('md5').update(`${config.port || 3000}:${db}:${query}`).digest('hex');
|
|
51
|
+
const pg = getPG(db);
|
|
52
|
+
|
|
53
|
+
if (config.trace) console.log('cron-list: init', db, idx);
|
|
54
|
+
|
|
55
|
+
const [waitMs, intervalMs] = interval2ms[typeof interval](interval);
|
|
56
|
+
|
|
57
|
+
if (intervalMs < 1000) {
|
|
58
|
+
if (config.trace) console.error('cron-list: skip too small interval', db, idx);
|
|
59
|
+
logger.file('cron', { name, error: `interval ${interval} too small` });
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// setTimeout to w8 for the time to start
|
|
64
|
+
setTimeout(() => {
|
|
65
|
+
runCron({ pg, query, name });
|
|
66
|
+
// interval
|
|
67
|
+
setInterval(() => {
|
|
68
|
+
runCron({ pg, query, name });
|
|
69
|
+
}, intervalMs);
|
|
70
|
+
}, waitMs);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export default plugin;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import getRedis from '../../redis/funcs/getRedis.js';
|
|
2
|
-
|
|
3
|
-
// import { getRedis } from '../../../../utils.js';
|
|
4
|
-
|
|
5
|
-
export default async function getOpt(token, uid = 0) {
|
|
6
|
-
const rclient = getRedis({ db: 0 });
|
|
7
|
-
|
|
8
|
-
const key = `opt:${uid}:${token}`;
|
|
9
|
-
// console.log(key);
|
|
10
|
-
const data = await rclient.get(key);
|
|
11
|
-
if (!data) return null;
|
|
12
|
-
return JSON.parse(data);
|
|
13
|
-
}
|
|
1
|
+
import getRedis from '../../redis/funcs/getRedis.js';
|
|
2
|
+
|
|
3
|
+
// import { getRedis } from '../../../../utils.js';
|
|
4
|
+
|
|
5
|
+
export default async function getOpt(token, uid = 0) {
|
|
6
|
+
const rclient = getRedis({ db: 0 });
|
|
7
|
+
|
|
8
|
+
const key = `opt:${uid}:${token}`;
|
|
9
|
+
// console.log(key);
|
|
10
|
+
const data = await rclient.get(key);
|
|
11
|
+
if (!data) return null;
|
|
12
|
+
return JSON.parse(data);
|
|
13
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { createHash, randomUUID } from 'crypto';
|
|
2
|
-
|
|
3
|
-
const random = randomUUID();
|
|
4
|
-
|
|
5
|
-
import getRedis from '../../redis/funcs/getRedis.js';
|
|
6
|
-
|
|
7
|
-
// import { getRedis } from '../../../../utils.js';
|
|
8
|
-
|
|
9
|
-
function md5(string) {
|
|
10
|
-
return createHash('md5').update(string).digest('hex');
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export default function setOpt(params, uid = 0) {
|
|
14
|
-
const token = Buffer.from(md5(typeof params === 'object' ? JSON.stringify(params) : params) + random, 'hex').toString('base64').replace(/[+-=]+/g, '');
|
|
15
|
-
// const token = md5(params);
|
|
16
|
-
const key = `opt:${uid}:${token}`;
|
|
17
|
-
|
|
18
|
-
const rclient = getRedis({ db: 0 });
|
|
19
|
-
rclient.set(key, JSON.stringify(params), 'EX', 60 * 60);
|
|
20
|
-
return token;
|
|
21
|
-
}
|
|
1
|
+
import { createHash, randomUUID } from 'crypto';
|
|
2
|
+
|
|
3
|
+
const random = randomUUID();
|
|
4
|
+
|
|
5
|
+
import getRedis from '../../redis/funcs/getRedis.js';
|
|
6
|
+
|
|
7
|
+
// import { getRedis } from '../../../../utils.js';
|
|
8
|
+
|
|
9
|
+
function md5(string) {
|
|
10
|
+
return createHash('md5').update(string).digest('hex');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default function setOpt(params, uid = 0) {
|
|
14
|
+
const token = Buffer.from(md5(typeof params === 'object' ? JSON.stringify(params) : params) + random, 'hex').toString('base64').replace(/[+-=]+/g, '');
|
|
15
|
+
// const token = md5(params);
|
|
16
|
+
const key = `opt:${uid}:${token}`;
|
|
17
|
+
|
|
18
|
+
const rclient = getRedis({ db: 0 });
|
|
19
|
+
rclient.set(key, JSON.stringify(params), 'EX', 60 * 60);
|
|
20
|
+
return token;
|
|
21
|
+
}
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import { createHash, randomUUID } from 'crypto';
|
|
2
|
-
|
|
3
|
-
import config from '../../../../config.js';
|
|
4
|
-
|
|
5
|
-
import getRedis from '../../redis/funcs/getRedis.js';
|
|
6
|
-
|
|
7
|
-
const rclient = getRedis({ db: 0 });
|
|
8
|
-
|
|
9
|
-
// import { config, getRedis } from '../../../../utils.js';
|
|
10
|
-
|
|
11
|
-
const generateCodes = (ids, userToken) => {
|
|
12
|
-
const token = userToken || randomUUID();
|
|
13
|
-
const notNullIds = ids.filter((el) => el);
|
|
14
|
-
const obj = {};
|
|
15
|
-
const codes = notNullIds.reduce((acc, id) => {
|
|
16
|
-
const newToken = createHash('sha1').update(token + id).digest('base64url').replace(/-/g, '');
|
|
17
|
-
acc[newToken] = id; obj[id] = newToken;
|
|
18
|
-
return acc;
|
|
19
|
-
}, {});
|
|
20
|
-
return { codes, obj };
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
function setToken({
|
|
24
|
-
ids: idsOrigin, uid, array,
|
|
25
|
-
}) {
|
|
26
|
-
// const rclient5 = getRedis({ db: 0, funcs });
|
|
27
|
-
|
|
28
|
-
if (!uid) return { user: 'empty' };
|
|
29
|
-
if (!Object.keys(idsOrigin).length) return { ids: 'empty' };
|
|
30
|
-
|
|
31
|
-
const ids = idsOrigin.map((el) => (typeof el === 'object' ? JSON.stringify(el) : el));
|
|
32
|
-
|
|
33
|
-
// TODO generate salt
|
|
34
|
-
const { codes, obj } = generateCodes(ids, uid);
|
|
35
|
-
|
|
36
|
-
if (!Object.keys(codes).length) return { ids: 'empty' };
|
|
37
|
-
|
|
38
|
-
rclient.hmset(`${config.pg.database}:token:edit:${uid}`, codes);
|
|
39
|
-
// console.log(`${config.pg.database}:token:edit:${uid}`, idsOrigin, Object.values(obj));
|
|
40
|
-
// TODO дополнительно писать в hset token -> uid
|
|
41
|
-
return array ? Object.values(obj) : obj;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export default setToken;
|
|
1
|
+
import { createHash, randomUUID } from 'crypto';
|
|
2
|
+
|
|
3
|
+
import config from '../../../../config.js';
|
|
4
|
+
|
|
5
|
+
import getRedis from '../../redis/funcs/getRedis.js';
|
|
6
|
+
|
|
7
|
+
const rclient = getRedis({ db: 0 });
|
|
8
|
+
|
|
9
|
+
// import { config, getRedis } from '../../../../utils.js';
|
|
10
|
+
|
|
11
|
+
const generateCodes = (ids, userToken) => {
|
|
12
|
+
const token = userToken || randomUUID();
|
|
13
|
+
const notNullIds = ids.filter((el) => el);
|
|
14
|
+
const obj = {};
|
|
15
|
+
const codes = notNullIds.reduce((acc, id) => {
|
|
16
|
+
const newToken = createHash('sha1').update(token + id).digest('base64url').replace(/-/g, '');
|
|
17
|
+
acc[newToken] = id; obj[id] = newToken;
|
|
18
|
+
return acc;
|
|
19
|
+
}, {});
|
|
20
|
+
return { codes, obj };
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function setToken({
|
|
24
|
+
ids: idsOrigin, uid, array,
|
|
25
|
+
}) {
|
|
26
|
+
// const rclient5 = getRedis({ db: 0, funcs });
|
|
27
|
+
|
|
28
|
+
if (!uid) return { user: 'empty' };
|
|
29
|
+
if (!Object.keys(idsOrigin).length) return { ids: 'empty' };
|
|
30
|
+
|
|
31
|
+
const ids = idsOrigin.map((el) => (typeof el === 'object' ? JSON.stringify(el) : el));
|
|
32
|
+
|
|
33
|
+
// TODO generate salt
|
|
34
|
+
const { codes, obj } = generateCodes(ids, uid);
|
|
35
|
+
|
|
36
|
+
if (!Object.keys(codes).length) return { ids: 'empty' };
|
|
37
|
+
|
|
38
|
+
rclient.hmset(`${config.pg.database}:token:edit:${uid}`, codes);
|
|
39
|
+
// console.log(`${config.pg.database}:token:edit:${uid}`, idsOrigin, Object.values(obj));
|
|
40
|
+
// TODO дополнительно писать в hset token -> uid
|
|
41
|
+
return array ? Object.values(obj) : obj;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default setToken;
|