@opengis/fastify-table 1.4.53 → 1.4.54
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/package.json +1 -1
- package/server/helpers/core/buttonHelper.js +1 -1
- package/server/helpers/format/formatAuto.js +13 -13
- package/server/helpers/format/formatDate.js +258 -258
- package/server/helpers/format/formatDigit.js +21 -21
- package/server/helpers/format/formatNum.js +365 -365
- package/server/helpers/format/formatNumber.js +55 -55
- package/server/helpers/format/formatRelative.js +106 -106
- package/server/helpers/format/formatUnit.js +40 -40
- package/server/helpers/format/num_format.js +44 -44
- package/server/helpers/format/set.js +2 -2
- package/server/helpers/funcs/_math.js +50 -50
- package/server/helpers/funcs/empty.js +21 -21
- package/server/helpers/funcs/ifCond.js +109 -109
- package/server/helpers/funcs/ifCondAnd.js +114 -114
- package/server/helpers/funcs/ifCondOr.js +115 -115
- package/server/helpers/funcs/inc.js +20 -20
- package/server/helpers/funcs/json.js +3 -3
- package/server/helpers/funcs/qrcode.js +2 -2
- package/server/helpers/funcs/round.js +29 -29
- package/server/helpers/list/buttonHelper.js +22 -22
- package/server/helpers/list/utils/button.js +4 -4
- package/server/helpers/string/coalesce.js +39 -39
- package/server/helpers/string/concat.js +28 -28
- package/server/helpers/string/split.js +20 -20
- package/server/helpers/string/str_replace.js +62 -62
- package/server/helpers/string/substr.js +32 -32
- package/server/helpers/string/translit.js +23 -23
- package/server/helpers/string/utils/alphabet.js +76 -76
- package/server/helpers/utils/button.js +4 -4
- package/server/helpers/utils/buttonAdd.js +1 -1
- package/server/helpers/utils/buttonDel.js +1 -1
- package/server/helpers/utils/buttonDownload.js +1 -1
- package/server/helpers/utils/buttonEdit.js +2 -2
- package/server/helpers/utils/buttonPreview.js +1 -1
- package/server/helpers/utils/mdToHTML.js +17 -17
- package/server/plugins/cron/funcs/interval2ms.js +1 -1
- package/server/plugins/cron/index.js +77 -77
- package/server/plugins/crud/funcs/getAccess.js +3 -2
- package/server/plugins/crud/funcs/setOpt.js +21 -21
- package/server/plugins/crud/funcs/setToken.js +43 -43
- package/server/plugins/crud/index.js +23 -23
- package/server/plugins/hook/index.js +8 -8
- package/server/plugins/logger/index.js +33 -33
- package/server/plugins/logger/timestampWithTimeZone.js +1 -1
- package/server/plugins/migration/index.js +7 -7
- package/server/plugins/pg/funcs/getDBParams.js +3 -3
- package/server/plugins/policy/sqlInjection.js +34 -34
- package/server/plugins/redis/index.js +17 -17
- package/server/plugins/table/funcs/customTokens.js +1 -1
- package/server/plugins/table/funcs/getFilterSQL/util/getOptimizedQuery.js +2 -2
- package/server/plugins/table/funcs/userTokens.js +1 -1
- package/server/plugins/util/index.js +7 -7
- package/server/plugins/yml/funcs/json2yml.js +1 -1
- package/server/plugins/yml/funcs/yml2json.js +2 -2
- package/server/routes/file/controllers/export.js +1 -1
- package/server/routes/file/controllers/utils/jsonToXls.js +1 -2
- package/server/routes/logger/controllers/utils/getRootDir.js +27 -27
- package/server/routes/table/controllers/utils/locales.js +1 -1
- package/server/routes/util/controllers/status.monitor.js +8 -8
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
function replaceLast(str, what, replacement) {
|
|
2
|
-
if (!str?.split) return str;
|
|
3
|
-
const pcs = str?.split?.(what) || [];
|
|
4
|
-
const lastPc = pcs.pop();
|
|
5
|
-
return pcs.join(what) + replacement + lastPc;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Виконує заміну символів у строці. Є можливість заміни регулярного виразу нової строки на тег <br>
|
|
10
|
-
*
|
|
11
|
-
* @summary Виконання заміни частини строки на значення з останнього аргументу.
|
|
12
|
-
* @priority 3
|
|
13
|
-
* @type helper
|
|
14
|
-
* @alias strReplace
|
|
15
|
-
* @tag string
|
|
16
|
-
* @example
|
|
17
|
-
* {{str_replace 'This Is Alias' ' ' ''}}
|
|
18
|
-
* @example
|
|
19
|
-
* {{{str_replace '<p>Перший рядок</p><p>Наступний рядок</p>' br=1}}}
|
|
20
|
-
* @example
|
|
21
|
-
* {{{str_replace 'Перший рядок<br>Наступний рядок' br=1}}}
|
|
22
|
-
* @param {Object} br
|
|
23
|
-
* @param {Object} newline
|
|
24
|
-
* @param {Object} html
|
|
25
|
-
* @param {Object} last
|
|
26
|
-
* @param {Array} args[0]
|
|
27
|
-
* @param {Array} args[1]
|
|
28
|
-
* @param {Array} args[2]
|
|
29
|
-
* @returns {String} Returns HTML
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
export default function strReplace(...args) {
|
|
33
|
-
const options = args.pop();
|
|
34
|
-
const [str, from, to] = args;
|
|
35
|
-
|
|
36
|
-
if (!str) return '';
|
|
37
|
-
|
|
38
|
-
if (options.hash.br) {
|
|
39
|
-
return str.replace(/\n/g, '<br>');
|
|
40
|
-
}
|
|
41
|
-
if (options.hash.newline) {
|
|
42
|
-
return str.replace(/\n/g, ' ');
|
|
43
|
-
}
|
|
44
|
-
if (options.hash.html) {
|
|
45
|
-
return str
|
|
46
|
-
.replace(/<br>/g, '\n')
|
|
47
|
-
.replace(/<\/p>/g, '\n')
|
|
48
|
-
.replace(/<\/li>/g, '\n')
|
|
49
|
-
.replace(/(<[^>]+>|<[^>]>|<\/[^>]>)/g, '')
|
|
50
|
-
.replace(/\n/g, ' ');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (options.hash.last) {
|
|
54
|
-
return replaceLast(str, from, to);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (typeof from !== 'string' || typeof to !== 'string') {
|
|
58
|
-
return 'Invalid replacement parameters';
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return str.replace(new RegExp(from, 'g'), to);
|
|
62
|
-
}
|
|
1
|
+
function replaceLast(str, what, replacement) {
|
|
2
|
+
if (!str?.split) return str;
|
|
3
|
+
const pcs = str?.split?.(what) || [];
|
|
4
|
+
const lastPc = pcs.pop();
|
|
5
|
+
return pcs.join(what) + replacement + lastPc;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Виконує заміну символів у строці. Є можливість заміни регулярного виразу нової строки на тег <br>
|
|
10
|
+
*
|
|
11
|
+
* @summary Виконання заміни частини строки на значення з останнього аргументу.
|
|
12
|
+
* @priority 3
|
|
13
|
+
* @type helper
|
|
14
|
+
* @alias strReplace
|
|
15
|
+
* @tag string
|
|
16
|
+
* @example
|
|
17
|
+
* {{str_replace 'This Is Alias' ' ' ''}}
|
|
18
|
+
* @example
|
|
19
|
+
* {{{str_replace '<p>Перший рядок</p><p>Наступний рядок</p>' br=1}}}
|
|
20
|
+
* @example
|
|
21
|
+
* {{{str_replace 'Перший рядок<br>Наступний рядок' br=1}}}
|
|
22
|
+
* @param {Object} br
|
|
23
|
+
* @param {Object} newline
|
|
24
|
+
* @param {Object} html
|
|
25
|
+
* @param {Object} last
|
|
26
|
+
* @param {Array} args[0]
|
|
27
|
+
* @param {Array} args[1]
|
|
28
|
+
* @param {Array} args[2]
|
|
29
|
+
* @returns {String} Returns HTML
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
export default function strReplace(...args) {
|
|
33
|
+
const options = args.pop();
|
|
34
|
+
const [str, from, to] = args;
|
|
35
|
+
|
|
36
|
+
if (!str) return '';
|
|
37
|
+
|
|
38
|
+
if (options.hash.br) {
|
|
39
|
+
return str.replace(/\n/g, '<br>');
|
|
40
|
+
}
|
|
41
|
+
if (options.hash.newline) {
|
|
42
|
+
return str.replace(/\n/g, ' ');
|
|
43
|
+
}
|
|
44
|
+
if (options.hash.html) {
|
|
45
|
+
return str
|
|
46
|
+
.replace(/<br>/g, '\n')
|
|
47
|
+
.replace(/<\/p>/g, '\n')
|
|
48
|
+
.replace(/<\/li>/g, '\n')
|
|
49
|
+
.replace(/(<[^>]+>|<[^>]>|<\/[^>]>)/g, '')
|
|
50
|
+
.replace(/\n/g, ' ');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (options.hash.last) {
|
|
54
|
+
return replaceLast(str, from, to);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (typeof from !== 'string' || typeof to !== 'string') {
|
|
58
|
+
return 'Invalid replacement parameters';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return str.replace(new RegExp(from, 'g'), to);
|
|
62
|
+
}
|
|
@@ -1,32 +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
|
-
}
|
|
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
|
+
}
|
|
@@ -1,23 +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
|
-
}
|
|
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
|
+
}
|
|
@@ -1,76 +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
|
+
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,4 +1,4 @@
|
|
|
1
|
-
export default function button(token, title) {
|
|
2
|
-
return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
|
|
3
|
-
class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-blue-600 border border-transparent rounded-lg gap-x-2 hover:bg-blue-700 hover:text-white">${title || 'Редагувати'}</button>`;
|
|
4
|
-
}
|
|
1
|
+
export default function button(token, title) {
|
|
2
|
+
return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
|
|
3
|
+
class="inline-flex items-center px-2 py-1 text-sm font-medium text-white duration-300 bg-blue-600 border border-transparent rounded-lg gap-x-2 hover:bg-blue-700 hover:text-white">${title || 'Редагувати'}</button>`;
|
|
4
|
+
}
|
|
@@ -2,4 +2,4 @@ const newColor = 'blue';
|
|
|
2
2
|
export default function button(token, title) {
|
|
3
3
|
return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
|
|
4
4
|
class="px-2 py-1 inline-flex border-solid justify-center items-center gap-2 rounded-md font-semibold focus:outline-none text-sm transition-all border border-transparent hover:text-white ring-offset-white bg-${newColor}-100 text-${newColor}-500 hover:bg-${newColor}-500 focus:ring-${newColor}-500">${title || 'Додати'}</button>`;
|
|
5
|
-
}
|
|
5
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export default function buttonDownload(filepath) {
|
|
2
2
|
return `<a download=1 class="flex items-center gap-x-2 border py-2 px-3 shadow rounded-xl cursor-pointer w-[42px] y-[34px]" href="${filepath}" target="_blank"><img src="https://cdn.softpro.ua/assets/file-up.svg" alt="generate"></a>`;
|
|
3
|
-
}
|
|
3
|
+
}
|
|
@@ -13,5 +13,5 @@ export default function button(token, title, icon) {
|
|
|
13
13
|
</svg>`
|
|
14
14
|
: `${title || 'Редагувати'}`;
|
|
15
15
|
|
|
16
|
-
return `<button onclick="${formCall}" class="${buttonClass}">${buttonContent}</button>`;
|
|
17
|
-
}
|
|
16
|
+
return `<button onclick="${formCall}" class="${buttonClass}">${buttonContent}</button>`;
|
|
17
|
+
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import md from 'markdown-it';
|
|
2
|
-
|
|
3
|
-
const md1 = md({ html: true });
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Перетворення з файла readme.md до формату HTML.
|
|
7
|
-
* Потрабно вставити в хелпер шлях до файла або текст readme.md і за допомогою бібліотеки markdown-it перетвориться в HTML.
|
|
8
|
-
|
|
9
|
-
* @returns {String} Returns HTML
|
|
10
|
-
*/
|
|
11
|
-
export default function mdToHTML(data) {
|
|
12
|
-
// auto detect HTML or MD
|
|
13
|
-
// const result = md().render(data);
|
|
14
|
-
if (!data) return 'empty data';
|
|
15
|
-
const result = md1.render(data);
|
|
16
|
-
return result;
|
|
17
|
-
}
|
|
1
|
+
import md from 'markdown-it';
|
|
2
|
+
|
|
3
|
+
const md1 = md({ html: true });
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Перетворення з файла readme.md до формату HTML.
|
|
7
|
+
* Потрабно вставити в хелпер шлях до файла або текст readme.md і за допомогою бібліотеки markdown-it перетвориться в HTML.
|
|
8
|
+
|
|
9
|
+
* @returns {String} Returns HTML
|
|
10
|
+
*/
|
|
11
|
+
export default function mdToHTML(data) {
|
|
12
|
+
// auto detect HTML or MD
|
|
13
|
+
// const result = md().render(data);
|
|
14
|
+
if (!data) return 'empty data';
|
|
15
|
+
const result = md1.render(data);
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
import { createHash } from 'node:crypto';
|
|
3
|
-
|
|
4
|
-
import config from '../../../config.js';
|
|
5
|
-
|
|
6
|
-
import getPG from '../pg/funcs/getPG.js';
|
|
7
|
-
import pgClients from '../pg/pgClients.js';
|
|
8
|
-
import getRedis from '../redis/funcs/getRedis.js';
|
|
9
|
-
import logger from '../logger/getLogger.js';
|
|
10
|
-
import interval2ms from './funcs/interval2ms.js';
|
|
11
|
-
|
|
12
|
-
const rclient = getRedis();
|
|
13
|
-
|
|
14
|
-
async function runCron({
|
|
15
|
-
pg = pgClients.client, query, name,
|
|
16
|
-
}) {
|
|
17
|
-
const db = pg?.options?.database;
|
|
18
|
-
|
|
19
|
-
// verifyUnique
|
|
20
|
-
const key = `cron:unique:${name}`;
|
|
21
|
-
const unique = config.redis ? await rclient.setnx(key, 1) : null;
|
|
22
|
-
const ttl = config.redis ? await rclient.ttl(key) : -1;
|
|
23
|
-
|
|
24
|
-
if (!unique && ttl !== -1) {
|
|
25
|
-
// if (config.trace) console.log(name, db, query, 'skip unique');
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (config.redis) {
|
|
30
|
-
await rclient.expire(key, 20);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
if (!pg.pk && config.pg) { await pg.init(); }
|
|
35
|
-
|
|
36
|
-
if (config.trace) console.time(`${db}:${query}`);
|
|
37
|
-
const { command, rows = [], rowCount } = pg?.pk ? await pg.query(query) : {};
|
|
38
|
-
if (config.trace) console.timeEnd(`${db}:${query}`);
|
|
39
|
-
|
|
40
|
-
logger.file('cron', { db, name, result: { command, rows, rowCount } });
|
|
41
|
-
}
|
|
42
|
-
catch (err) {
|
|
43
|
-
if (config.trace) console.error(name, err.toString());
|
|
44
|
-
logger.file('cron/error', { db, name, error: err.toString() });
|
|
45
|
-
logger.error(err);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async function plugin() {
|
|
50
|
-
if (config.cronList?.length) {
|
|
51
|
-
config.cronList?.filter?.(el => el.query && !el.disabled)?.forEach?.((el, idx) => {
|
|
52
|
-
const { interval, db, query } = el;
|
|
53
|
-
const name = createHash('md5').update(`${config.port || 3000}:${db}:${query}`).digest('hex');
|
|
54
|
-
const pg = getPG(db);
|
|
55
|
-
|
|
56
|
-
if (config.trace) console.log('cron-list: init', db, idx);
|
|
57
|
-
|
|
58
|
-
const [waitMs, intervalMs] = interval2ms[typeof interval](interval);
|
|
59
|
-
|
|
60
|
-
if (intervalMs < 1000) {
|
|
61
|
-
if (config.trace) console.error('cron-list: skip too small interval', db, idx);
|
|
62
|
-
logger.file('cron', { name, error: `interval ${interval} too small` });
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// setTimeout to w8 for the time to start
|
|
67
|
-
setTimeout(() => {
|
|
68
|
-
runCron({ pg, query, name });
|
|
69
|
-
// interval
|
|
70
|
-
setInterval(() => {
|
|
71
|
-
runCron({ pg, query, name });
|
|
72
|
-
}, intervalMs);
|
|
73
|
-
}, waitMs);
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
export default plugin;
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
|
|
4
|
+
import config from '../../../config.js';
|
|
5
|
+
|
|
6
|
+
import getPG from '../pg/funcs/getPG.js';
|
|
7
|
+
import pgClients from '../pg/pgClients.js';
|
|
8
|
+
import getRedis from '../redis/funcs/getRedis.js';
|
|
9
|
+
import logger from '../logger/getLogger.js';
|
|
10
|
+
import interval2ms from './funcs/interval2ms.js';
|
|
11
|
+
|
|
12
|
+
const rclient = getRedis();
|
|
13
|
+
|
|
14
|
+
async function runCron({
|
|
15
|
+
pg = pgClients.client, query, name,
|
|
16
|
+
}) {
|
|
17
|
+
const db = pg?.options?.database;
|
|
18
|
+
|
|
19
|
+
// verifyUnique
|
|
20
|
+
const key = `cron:unique:${name}`;
|
|
21
|
+
const unique = config.redis ? await rclient.setnx(key, 1) : null;
|
|
22
|
+
const ttl = config.redis ? await rclient.ttl(key) : -1;
|
|
23
|
+
|
|
24
|
+
if (!unique && ttl !== -1) {
|
|
25
|
+
// if (config.trace) console.log(name, db, query, 'skip unique');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (config.redis) {
|
|
30
|
+
await rclient.expire(key, 20);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
if (!pg.pk && config.pg) { await pg.init(); }
|
|
35
|
+
|
|
36
|
+
if (config.trace) console.time(`${db}:${query}`);
|
|
37
|
+
const { command, rows = [], rowCount } = pg?.pk ? await pg.query(query) : {};
|
|
38
|
+
if (config.trace) console.timeEnd(`${db}:${query}`);
|
|
39
|
+
|
|
40
|
+
logger.file('cron', { db, name, result: { command, rows, rowCount } });
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
if (config.trace) console.error(name, err.toString());
|
|
44
|
+
logger.file('cron/error', { db, name, error: err.toString() });
|
|
45
|
+
logger.error(err);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function plugin() {
|
|
50
|
+
if (config.cronList?.length) {
|
|
51
|
+
config.cronList?.filter?.(el => el.query && !el.disabled)?.forEach?.((el, idx) => {
|
|
52
|
+
const { interval, db, query } = el;
|
|
53
|
+
const name = createHash('md5').update(`${config.port || 3000}:${db}:${query}`).digest('hex');
|
|
54
|
+
const pg = getPG(db);
|
|
55
|
+
|
|
56
|
+
if (config.trace) console.log('cron-list: init', db, idx);
|
|
57
|
+
|
|
58
|
+
const [waitMs, intervalMs] = interval2ms[typeof interval](interval);
|
|
59
|
+
|
|
60
|
+
if (intervalMs < 1000) {
|
|
61
|
+
if (config.trace) console.error('cron-list: skip too small interval', db, idx);
|
|
62
|
+
logger.file('cron', { name, error: `interval ${interval} too small` });
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// setTimeout to w8 for the time to start
|
|
67
|
+
setTimeout(() => {
|
|
68
|
+
runCron({ pg, query, name });
|
|
69
|
+
// interval
|
|
70
|
+
setInterval(() => {
|
|
71
|
+
runCron({ pg, query, name });
|
|
72
|
+
}, intervalMs);
|
|
73
|
+
}, waitMs);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export default plugin;
|
|
@@ -76,14 +76,15 @@ export default async function getAccess({ table, form, user = {} }, pg = pgClien
|
|
|
76
76
|
...el.rows[0] || {},
|
|
77
77
|
roles: el.rows?.map?.(row => row.role_id) || [],
|
|
78
78
|
actions: el.rows?.map?.(row => row.actions).flat() || [],
|
|
79
|
+
interface_actions: el.rows?.map?.(row => row.interface_actions).flat() || [],
|
|
79
80
|
}))
|
|
80
81
|
: {};
|
|
81
82
|
|
|
82
83
|
const query = userAccess?.scope === 'my' ? `uid='${uid}'` : '1=1';
|
|
83
84
|
const actions = userAccess?.interface_actions
|
|
84
|
-
?.filter?.((el, idx, arr) => arr.indexOf(el) === idx)
|
|
85
85
|
?.filter(el => (userAccess?.role_actions?.length ? userAccess?.role_actions.includes(el) : true))
|
|
86
|
-
?.filter(el => tableActions.includes(el))
|
|
86
|
+
?.filter(el => tableActions.includes(el))
|
|
87
|
+
?.filter?.((el, idx, arr) => arr.indexOf(el) === idx);
|
|
87
88
|
return {
|
|
88
89
|
scope: userAccess?.scope,
|
|
89
90
|
roles: userAccess?.roles,
|