@opengis/fastify-table 1.4.38 → 1.4.40

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.
Files changed (62) hide show
  1. package/README.md +86 -86
  2. package/package.json +1 -1
  3. package/server/helpers/core/token.js +18 -18
  4. package/server/helpers/format/formatAuto.js +13 -13
  5. package/server/helpers/format/formatDate.js +258 -258
  6. package/server/helpers/format/formatDigit.js +20 -20
  7. package/server/helpers/format/formatNum.js +361 -361
  8. package/server/helpers/format/formatNumber.js +54 -54
  9. package/server/helpers/format/formatRelative.js +106 -106
  10. package/server/helpers/format/formatUnit.js +38 -38
  11. package/server/helpers/format/num_format.js +41 -41
  12. package/server/helpers/funcs/_math.js +49 -49
  13. package/server/helpers/funcs/empty.js +21 -21
  14. package/server/helpers/funcs/ifCond.js +106 -106
  15. package/server/helpers/funcs/ifCondAnd.js +96 -96
  16. package/server/helpers/funcs/ifCondOr.js +98 -98
  17. package/server/helpers/funcs/inc.js +20 -20
  18. package/server/helpers/funcs/json.js +2 -2
  19. package/server/helpers/funcs/round.js +27 -27
  20. package/server/helpers/list/buttonHelper.js +21 -21
  21. package/server/helpers/list/utils/button.js +5 -5
  22. package/server/helpers/string/coalesce.js +31 -31
  23. package/server/helpers/string/concat.js +28 -28
  24. package/server/helpers/string/split.js +19 -19
  25. package/server/helpers/string/str_replace.js +60 -60
  26. package/server/helpers/string/substr.js +31 -31
  27. package/server/helpers/string/translit.js +23 -23
  28. package/server/helpers/string/utils/alphabet.js +75 -75
  29. package/server/helpers/utils/button.js +5 -5
  30. package/server/helpers/utils/mdToHTML.js +17 -17
  31. package/server/plugins/cron/funcs/addCron.js +52 -52
  32. package/server/plugins/cron/index.js +76 -76
  33. package/server/plugins/crud/funcs/dataDelete.js +2 -2
  34. package/server/plugins/crud/funcs/dataInsert.js +1 -1
  35. package/server/plugins/crud/funcs/getOpt.js +14 -14
  36. package/server/plugins/crud/funcs/setOpt.js +21 -21
  37. package/server/plugins/crud/funcs/setToken.js +43 -43
  38. package/server/plugins/crud/funcs/utils/getFolder.js +11 -11
  39. package/server/plugins/crud/index.js +23 -23
  40. package/server/plugins/file/uploadMultiPart.js +15 -5
  41. package/server/plugins/hook/index.js +8 -8
  42. package/server/plugins/logger/errorStatus.js +19 -19
  43. package/server/plugins/logger/index.js +26 -26
  44. package/server/plugins/migration/index.js +7 -7
  45. package/server/plugins/pg/funcs/getMeta.js +5 -4
  46. package/server/plugins/policy/sqlInjection.js +33 -33
  47. package/server/plugins/redis/client.js +8 -8
  48. package/server/plugins/redis/funcs/redisClients.js +3 -3
  49. package/server/plugins/redis/index.js +17 -17
  50. package/server/plugins/table/funcs/getFilterSQL/util/getCustomQuery.js +13 -13
  51. package/server/plugins/table/funcs/getFilterSQL/util/getTableSql.js +34 -34
  52. package/server/plugins/table/funcs/getTemplates.js +19 -19
  53. package/server/plugins/table/funcs/gisIRColumn.js +82 -82
  54. package/server/plugins/table/funcs/loadTemplate.js +1 -1
  55. package/server/plugins/table/funcs/loadTemplatePath.js +1 -1
  56. package/server/plugins/table/funcs/userTemplateDir.js +1 -1
  57. package/server/plugins/util/index.js +7 -7
  58. package/server/routes/file/controllers/resize.js +4 -0
  59. package/server/routes/logger/controllers/utils/getRootDir.js +26 -26
  60. package/server/routes/table/controllers/form.js +42 -42
  61. package/server/routes/table/controllers/search.js +74 -74
  62. package/server/routes/util/controllers/status.monitor.js +8 -8
@@ -1,6 +1,6 @@
1
-
2
-
3
- export default function button(token, title) {
4
- return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
5
- 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>`;
1
+
2
+
3
+ export default function button(token, title) {
4
+ return `<button onclick="window.v3plugin.$form({ token: '${token}' })"
5
+ 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>`;
6
6
  }
@@ -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, options) {
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, options) {
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,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,76 +1,76 @@
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 = config.redis ? await rclient.setnx(key, 1) : null;
21
- const ttl = config.redis ? await rclient.ttl(key) : -1;
22
-
23
- if (!unique && ttl !== -1) {
24
- // if (config.trace) console.log(name, db, query, 'skip unique');
25
- return;
26
- }
27
-
28
- if (config.redis) {
29
- await rclient.expire(key, 20);
30
- }
31
-
32
- try {
33
- if (!pg.pk && config.pg) { await pg.init(); }
34
-
35
- if (config.trace) console.time(`${db}:${query}`);
36
- const { command, rows = [], rowCount } = pg?.pk ? await pg.query(query) : {};
37
- if (config.trace) console.timeEnd(`${db}:${query}`);
38
-
39
- logger.file('cron', { db, name, result: { command, rows, rowCount } });
40
- }
41
- catch (err) {
42
- if (config.trace) console.error(name, err.toString());
43
- logger.file('cron/error', { db, name, error: err.toString() });
44
- logger.error(err);
45
- }
46
- }
47
-
48
- async function plugin(fastify) {
49
- if (config.cronList?.length) {
50
- config.cronList?.filter?.(el => el.query && !el.disabled)?.forEach?.((el, idx) => {
51
- const { interval, db, query } = el;
52
- const name = createHash('md5').update(`${config.port || 3000}:${db}:${query}`).digest('hex');
53
- const pg = getPG(db);
54
-
55
- if (config.trace) console.log('cron-list: init', db, idx);
56
-
57
- const [waitMs, intervalMs] = interval2ms[typeof interval](interval);
58
-
59
- if (intervalMs < 1000) {
60
- if (config.trace) console.error('cron-list: skip too small interval', db, idx);
61
- logger.file('cron', { name, error: `interval ${interval} too small` });
62
- return;
63
- }
64
-
65
- // setTimeout to w8 for the time to start
66
- setTimeout(() => {
67
- runCron({ pg, query, name });
68
- // interval
69
- setInterval(() => {
70
- runCron({ pg, query, name });
71
- }, intervalMs);
72
- }, waitMs);
73
- });
74
- }
75
- }
76
- 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 = config.redis ? await rclient.setnx(key, 1) : null;
21
+ const ttl = config.redis ? await rclient.ttl(key) : -1;
22
+
23
+ if (!unique && ttl !== -1) {
24
+ // if (config.trace) console.log(name, db, query, 'skip unique');
25
+ return;
26
+ }
27
+
28
+ if (config.redis) {
29
+ await rclient.expire(key, 20);
30
+ }
31
+
32
+ try {
33
+ if (!pg.pk && config.pg) { await pg.init(); }
34
+
35
+ if (config.trace) console.time(`${db}:${query}`);
36
+ const { command, rows = [], rowCount } = pg?.pk ? await pg.query(query) : {};
37
+ if (config.trace) console.timeEnd(`${db}:${query}`);
38
+
39
+ logger.file('cron', { db, name, result: { command, rows, rowCount } });
40
+ }
41
+ catch (err) {
42
+ if (config.trace) console.error(name, err.toString());
43
+ logger.file('cron/error', { db, name, error: err.toString() });
44
+ logger.error(err);
45
+ }
46
+ }
47
+
48
+ async function plugin(fastify) {
49
+ if (config.cronList?.length) {
50
+ config.cronList?.filter?.(el => el.query && !el.disabled)?.forEach?.((el, idx) => {
51
+ const { interval, db, query } = el;
52
+ const name = createHash('md5').update(`${config.port || 3000}:${db}:${query}`).digest('hex');
53
+ const pg = getPG(db);
54
+
55
+ if (config.trace) console.log('cron-list: init', db, idx);
56
+
57
+ const [waitMs, intervalMs] = interval2ms[typeof interval](interval);
58
+
59
+ if (intervalMs < 1000) {
60
+ if (config.trace) console.error('cron-list: skip too small interval', db, idx);
61
+ logger.file('cron', { name, error: `interval ${interval} too small` });
62
+ return;
63
+ }
64
+
65
+ // setTimeout to w8 for the time to start
66
+ setTimeout(() => {
67
+ runCron({ pg, query, name });
68
+ // interval
69
+ setInterval(() => {
70
+ runCron({ pg, query, name });
71
+ }, intervalMs);
72
+ }, waitMs);
73
+ });
74
+ }
75
+ }
76
+ export default plugin;
@@ -24,11 +24,11 @@ export default async function dataDelete({
24
24
  pg.pk = pgClients.client?.pk;
25
25
  }
26
26
 
27
- const table = table1.replace(/"/g, '');
27
+ const table = pg.pk[table1] ? table1 : table1.replace(/"/g, '');
28
28
 
29
29
  const { pk } = await getMeta({ pg, table });
30
30
 
31
- if (!pg.tlist?.includes(table1)) return 'table not exist';
31
+ if (!pg.tlist?.includes(table)) return 'table not exist';
32
32
 
33
33
  const delQuery = `delete from ${table} WHERE ${pk}::text = $1::text returning *`;
34
34
 
@@ -60,7 +60,7 @@ export default async function dataInsert({
60
60
  }
61
61
  const res = await client.query(insertQuery, args).then(el => el || {});
62
62
 
63
- const id1 = res.rows?.[0]?.[pg.pk[table1]];
63
+ const id1 = res.rows?.[0]?.[pg.pk[table]];
64
64
 
65
65
  if (!id1) return null;
66
66
 
@@ -1,14 +1,14 @@
1
- import config from '../../../../config.js';
2
- import getRedis from '../../redis/funcs/getRedis.js';
3
-
4
- const rclient = getRedis({ db: 0 });
5
-
6
- export default async function getOpt(token, uid = 0) {
7
- if (!config.redis) return null;
8
-
9
- const key = `opt:${uid}:${token}`;
10
- // console.log(key);
11
- const data = await rclient.get(key);
12
- if (!data) return null;
13
- return JSON.parse(data);
14
- }
1
+ import config from '../../../../config.js';
2
+ import getRedis from '../../redis/funcs/getRedis.js';
3
+
4
+ const rclient = getRedis({ db: 0 });
5
+
6
+ export default async function getOpt(token, uid = 0) {
7
+ if (!config.redis) return null;
8
+
9
+ const key = `opt:${uid}:${token}`;
10
+ // console.log(key);
11
+ const data = await rclient.get(key);
12
+ if (!data) return null;
13
+ return JSON.parse(data);
14
+ }
@@ -1,21 +1,21 @@
1
- import { createHash, randomUUID } from 'crypto';
2
-
3
- import config from '../../../../config.js';
4
- import getRedis from '../../redis/funcs/getRedis.js';
5
-
6
- const random = randomUUID();
7
- const rclient = getRedis({ db: 0 });
8
-
9
- function md5(string) {
10
- return createHash('md5').update(string).digest('hex');
11
- }
12
-
13
- export default function setOpt(params, uid = 0) {
14
- if (!config.redis) return null;
15
- const token = Buffer.from(md5(typeof params === 'object' ? JSON.stringify(params) : params) + random, 'hex').toString('base64').replace(/[+-=]+/g, '');
16
- // const token = md5(params);
17
- const key = `opt:${uid}:${token}`;
18
-
19
- rclient.set(key, JSON.stringify(params), 'EX', 60 * 60);
20
- return token;
21
- }
1
+ import { createHash, randomUUID } from 'crypto';
2
+
3
+ import config from '../../../../config.js';
4
+ import getRedis from '../../redis/funcs/getRedis.js';
5
+
6
+ const random = randomUUID();
7
+ const rclient = getRedis({ db: 0 });
8
+
9
+ function md5(string) {
10
+ return createHash('md5').update(string).digest('hex');
11
+ }
12
+
13
+ export default function setOpt(params, uid = 0) {
14
+ if (!config.redis) return null;
15
+ const token = Buffer.from(md5(typeof params === 'object' ? JSON.stringify(params) : params) + random, 'hex').toString('base64').replace(/[+-=]+/g, '');
16
+ // const token = md5(params);
17
+ const key = `opt:${uid}:${token}`;
18
+
19
+ rclient.set(key, JSON.stringify(params), 'EX', 60 * 60);
20
+ return token;
21
+ }
@@ -1,43 +1,43 @@
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
- if (!config.redis) return null;
27
- if (!uid) return { user: 'empty' };
28
- if (!Object.keys(idsOrigin).length) return { ids: 'empty' };
29
-
30
- const ids = idsOrigin.map((el) => (typeof el === 'object' ? JSON.stringify(el) : el));
31
-
32
- // TODO generate salt
33
- const { codes, obj } = generateCodes(ids, uid);
34
-
35
- if (!Object.keys(codes).length) return { ids: 'empty' };
36
-
37
- rclient.hmset(`${config.pg.database}:token:edit:${uid}`, codes);
38
- // console.log(`${config.pg.database}:token:edit:${uid}`, idsOrigin, Object.values(obj));
39
- // TODO дополнительно писать в hset token -> uid
40
- return array ? Object.values(obj) : obj;
41
- }
42
-
43
- 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
+ if (!config.redis) return null;
27
+ if (!uid) return { user: 'empty' };
28
+ if (!Object.keys(idsOrigin).length) return { ids: 'empty' };
29
+
30
+ const ids = idsOrigin.map((el) => (typeof el === 'object' ? JSON.stringify(el) : el));
31
+
32
+ // TODO generate salt
33
+ const { codes, obj } = generateCodes(ids, uid);
34
+
35
+ if (!Object.keys(codes).length) return { ids: 'empty' };
36
+
37
+ rclient.hmset(`${config.pg.database}:token:edit:${uid}`, codes);
38
+ // console.log(`${config.pg.database}:token:edit:${uid}`, idsOrigin, Object.values(obj));
39
+ // TODO дополнительно писать в hset token -> uid
40
+ return array ? Object.values(obj) : obj;
41
+ }
42
+
43
+ export default setToken;
@@ -1,11 +1,11 @@
1
- import path from 'node:path';
2
-
3
- import config from '../../../../../config.js';
4
-
5
- export default function getFolder(req, type = 'server') {
6
- if (!['server', 'local'].includes(type)) throw new Error('params type is invalid');
7
- const types = { local: req.root || config.root, server: req.mapServerRoot || config.mapServerRoot };
8
- const dbname = req.pg?.options?.database || req.pg?.database || config.pg?.database; // request / config params / default config params
9
- const filepath = path.posix.join(types[type] || `/data/local/${dbname || ''}`, req.folder || config.folder || '');
10
- return filepath;
11
- }
1
+ import path from 'node:path';
2
+
3
+ import config from '../../../../../config.js';
4
+
5
+ export default function getFolder(req, type = 'server') {
6
+ if (!['server', 'local'].includes(type)) throw new Error('params type is invalid');
7
+ const types = { local: req.root || config.root, server: req.mapServerRoot || config.mapServerRoot };
8
+ const dbname = req.pg?.options?.database || req.pg?.database || config.pg?.database; // request / config params / default config params
9
+ const filepath = path.posix.join(types[type] || `/data/local/${dbname || ''}`, req.folder || config.folder || '');
10
+ return filepath;
11
+ }
@@ -1,23 +1,23 @@
1
- // import getOpt from './funcs/getOpt.js';
2
- // import setOpt from './funcs/setOpt.js';
3
-
4
- // import isFileExists from './funcs/isFileExists.js';
5
-
6
- // import dataUpdate from './funcs/dataUpdate.js';
7
- // import dataInsert from './funcs/dataInsert.js';
8
-
9
- // import getAccessFunc from './funcs/getAccess.js';
10
-
11
- async function plugin(fastify) {
12
- // fastify.decorate('setOpt', setOpt);
13
- // fastify.decorate('getOpt', getOpt);
14
-
15
- // fastify.decorate('dataUpdate', dataUpdate);
16
- // fastify.decorate('dataInsert', dataInsert);
17
-
18
- // fastify.decorate('getAccess', getAccessFunc);
19
-
20
- // fastify.decorate('isFileExists', isFileExists);
21
- }
22
-
23
- export default plugin;
1
+ // import getOpt from './funcs/getOpt.js';
2
+ // import setOpt from './funcs/setOpt.js';
3
+
4
+ // import isFileExists from './funcs/isFileExists.js';
5
+
6
+ // import dataUpdate from './funcs/dataUpdate.js';
7
+ // import dataInsert from './funcs/dataInsert.js';
8
+
9
+ // import getAccessFunc from './funcs/getAccess.js';
10
+
11
+ async function plugin(fastify) {
12
+ // fastify.decorate('setOpt', setOpt);
13
+ // fastify.decorate('getOpt', getOpt);
14
+
15
+ // fastify.decorate('dataUpdate', dataUpdate);
16
+ // fastify.decorate('dataInsert', dataInsert);
17
+
18
+ // fastify.decorate('getAccess', getAccessFunc);
19
+
20
+ // fastify.decorate('isFileExists', isFileExists);
21
+ }
22
+
23
+ export default plugin;
@@ -51,11 +51,16 @@ export default async function uploadMultiPart(req, { subdir, originalFilename =
51
51
  }[req.routeOptions?.url || ''] || all;
52
52
 
53
53
  const parts = req.parts();
54
- const part = await parts.next();
54
+ // const part = await parts.next();
55
+ const { value: part, done } = await parts.next();
55
56
 
56
- const value = part?.value?.fields?.file || part?.value;
57
+ if (done) {
58
+ return null;
59
+ }
60
+
61
+ const value = part?.fields?.file || part;
57
62
 
58
- if (!value?.filename) {
63
+ if (!value?.file || !value?.filename) {
59
64
  throw new Error('upload error');
60
65
  }
61
66
 
@@ -66,13 +71,18 @@ export default async function uploadMultiPart(req, { subdir, originalFilename =
66
71
  throw new Error('file extension is not allowed');
67
72
  }
68
73
 
69
- const buffer = await value.toBuffer();
74
+ const buffer = await new Promise((res, rej) => {
75
+ const chunks = [];
76
+ part.file.on('data', chunk => chunks.push(chunk));
77
+ part.file.on('end', () => res(Buffer.concat(chunks)));
78
+ part.file.on('error', rej);
79
+ });
70
80
 
71
81
  if (!buffer?.length) {
72
82
  throw new Error('file buffer is empty');
73
83
  }
74
84
 
75
- const dir = req.params?.['*'] || subdir || 'uploads';
85
+ const dir = subdir != null ? subdir : (req.params?.['*'] || 'uploads');
76
86
  const yearMonthDay = subdir != null ? '' : (new Date()).toISOString().split('T')[0];
77
87
 
78
88
  const dbname = req.pg?.options?.database || req.pg?.database || config.pg?.database; // request / config params / default config params
@@ -1,8 +1,8 @@
1
- import addHook from './funcs/addHook.js';
2
- import applyHook from './funcs/applyHook.js';
3
-
4
- async function plugin(fastify) {
5
- // fastify.decorate('addHook', addHook);
6
- // fastify.decorate('applyHook', applyHook);
7
- }
8
- export default plugin;
1
+ import addHook from './funcs/addHook.js';
2
+ import applyHook from './funcs/applyHook.js';
3
+
4
+ async function plugin(fastify) {
5
+ // fastify.decorate('addHook', addHook);
6
+ // fastify.decorate('applyHook', applyHook);
7
+ }
8
+ export default plugin;