@opengis/cms 0.0.31 → 0.0.32

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.
@@ -1,79 +1,80 @@
1
- import path from 'node:path';
2
- import { mkdir } from 'node:fs/promises';
3
-
4
- import { uploadMultiPart, config, getFolder, dataInsert, pgClients } from "@opengis/fastify-table/utils.js";
5
-
6
- const rootDir = getFolder(config, 'local');
7
- const dir = '/files';
8
-
9
- export default async function uploadMedia(req, reply) {
10
- const { pg = pgClients.client, user = {}, query = {} } = req;
11
-
12
- if (!pg?.pk?.['site.media']) {
13
- return reply.status(404).send('table not found');
14
- }
15
-
16
- if (query.subdir && (typeof query.subdir !== 'string' || query.subdir.includes('..'))) {
17
- return reply.status(403).send('invalid query params: subdir');
18
- }
19
-
20
- // upload assets
21
- if (req.headers['content-type']?.split?.(';')?.shift?.() === 'multipart/form-data') {
22
- const file = await uploadMultiPart(req, { subdir: query.subdir || '', originalFilename: true }).catch(err => {
23
- if (err.message === 'file with specified name already exists in directory') {
24
- err.message = 'Файл з вказаною назвою вже існує';
25
- err.statusCode = 400;
26
- }
27
- throw err;
28
- });
29
-
30
- const { originalFilename: filename, filetype, mimetype } = file;
31
- const relpath = path.join(dir, query.subdir || '', file.originalFilename).replace(/\\/g, '/');
32
-
33
- const id = await dataInsert({
34
- pg,
35
- table: 'site.media',
36
- data: {
37
- filename,
38
- filetype,
39
- subdir: query.subdir,
40
- url: relpath,
41
- mime: mimetype,
42
- filesize: file.size,
43
- },
44
- uid: user?.uid,
45
- }).then(el => el?.rows?.[0]?.media_id);
46
-
47
- return reply.status(200).send({
48
- res: 'ok',
49
- name: filename,
50
- type: 'file',
51
- mimetype,
52
- result: {
53
- file_id: id,
54
- format: file.extension,
55
- size: file.size,
56
- // entity_id: resultInsert?.entity_id,
57
- file_path: relpath,
58
- file_name: filename,
59
- dir: path.dirname(relpath).replace(/\\/g, '/'),
60
- native_file_name: filename,
61
- },
62
- });
63
- }
64
-
65
- if (!query.subdir) {
66
- return reply.status(400).send('not enough query params: subdir');
67
- }
68
-
69
- // create directory
70
- const relpath = path.join(dir, query.subdir).replace(/\\/g, '/');
71
- const dirpath = path.join(rootDir, relpath);
72
- await mkdir(dirpath, { recursive: true });
73
-
74
- return reply.status(200).send({
75
- relpath,
76
- dirname: path.basename(query.subdir),
77
- type: 'dir',
78
- });
1
+ import path from 'node:path';
2
+ import { mkdir } from 'node:fs/promises';
3
+
4
+ import { uploadMultiPart, config, getFolder, dataInsert, pgClients } from "@opengis/fastify-table/utils.js";
5
+
6
+ // path.resolve() converts POSIX paths from getFolder to valid Windows paths (Bun/Node fs require this on Windows)
7
+ const rootDir = path.resolve(getFolder(config, 'local'));
8
+ const dir = '/files';
9
+
10
+ export default async function uploadMedia(req, reply) {
11
+ const { pg = pgClients.client, user = {}, query = {} } = req;
12
+
13
+ if (!pg?.pk?.['site.media']) {
14
+ return reply.status(404).send('table not found');
15
+ }
16
+
17
+ if (query.subdir && (typeof query.subdir !== 'string' || query.subdir.includes('..'))) {
18
+ return reply.status(403).send('invalid query params: subdir');
19
+ }
20
+
21
+ // upload assets
22
+ if (req.headers['content-type']?.split?.(';')?.shift?.() === 'multipart/form-data') {
23
+ const file = await uploadMultiPart(req, { subdir: query.subdir || '', originalFilename: true }).catch(err => {
24
+ if (err.message === 'file with specified name already exists in directory') {
25
+ err.message = 'Файл з вказаною назвою вже існує';
26
+ err.statusCode = 400;
27
+ }
28
+ throw err;
29
+ });
30
+
31
+ const { originalFilename: filename, filetype, mimetype } = file;
32
+ const relpath = path.join(dir, query.subdir || '', file.originalFilename).replace(/\\/g, '/');
33
+
34
+ const id = await dataInsert({
35
+ pg,
36
+ table: 'site.media',
37
+ data: {
38
+ filename,
39
+ filetype,
40
+ subdir: query.subdir,
41
+ url: relpath,
42
+ mime: mimetype,
43
+ filesize: file.size,
44
+ },
45
+ uid: user?.uid,
46
+ }).then(el => el?.rows?.[0]?.media_id);
47
+
48
+ return reply.status(200).send({
49
+ res: 'ok',
50
+ name: filename,
51
+ type: 'file',
52
+ mimetype,
53
+ result: {
54
+ file_id: id,
55
+ format: file.extension,
56
+ size: file.size,
57
+ // entity_id: resultInsert?.entity_id,
58
+ file_path: relpath,
59
+ file_name: filename,
60
+ dir: path.dirname(relpath).replace(/\\/g, '/'),
61
+ native_file_name: filename,
62
+ },
63
+ });
64
+ }
65
+
66
+ if (!query.subdir) {
67
+ return reply.status(400).send('not enough query params: subdir');
68
+ }
69
+
70
+ // create directory
71
+ const relpath = path.join(dir, query.subdir).replace(/\\/g, '/');
72
+ const dirpath = path.join(rootDir, relpath);
73
+ await mkdir(dirpath, { recursive: true });
74
+
75
+ return reply.status(200).send({
76
+ relpath,
77
+ dirname: path.basename(query.subdir),
78
+ type: 'dir',
79
+ });
79
80
  }
@@ -52,6 +52,7 @@ export default async function getCollection({
52
52
  },
53
53
  user,
54
54
  contextQuery: cQuery,
55
+ actions: ['view']
55
56
  }, reply, true);
56
57
 
57
58
  const locales = await pg.query(`select array_agg(distinct REVERSE(split_part(REVERSE(field_key), ':', 1))) from site.localization where object_id in (select id from ${'data.' + `"${table}"`})`).then(el => el.rows?.[0]?.array_agg || []);
@@ -1,4 +1,4 @@
1
- import { config, pgClients } from '@opengis/fastify-table/utils.js';
1
+ import { logger, pgClients } from '@opengis/fastify-table/utils.js';
2
2
 
3
3
  const maxLimit = 100;
4
4
 
@@ -15,7 +15,7 @@ export default async function builderList({ pg = pgClients.client, query = {} },
15
15
  where ${query.type === 'collection' ? `type='collection'` : (query.type === 'single' ? `type='single'` : '1=1')}`;
16
16
 
17
17
  const where = query.search?.replace ? `(name ilike '%${query.search.replace(/'/, "''")}%' or title ilike '%${query.search.replace(/'/, "''")}%')` : '1=1';
18
- const q1 = q + `and ${where} order by case when status='archived' then true else false end limit ${limit} offset ${offset}`;
18
+ const q1 = q + ` and ${where} order by case when status='archived' then true else false end limit ${limit} offset ${offset}`;
19
19
 
20
20
  if (query.sql) return q1;
21
21
 
@@ -39,13 +39,13 @@ export default async function builderList({ pg = pgClients.client, query = {} },
39
39
  ? `select count(*) from data."${row.table}" where $1=$1`
40
40
  : `select count(*) from site.contents where $1=$1 and ${row.id === 'pages' ? `slug <> 'pages' and content_type_id in (select content_type_id from site.content_types where type = 'single' or content_type_id='pages')` : 'content_type_id=$1'}`;
41
41
 
42
- const q1 = row.table
42
+ const q3 = row.table
43
43
  ? `select updated_at from data."${row.table}" where $1=$1 order by updated_at desc limit 1`
44
44
  : `select updated_at from site.content_data where content_id in ( select content_id from site.contents where content_type_id=$1 limit 1) order by updated_at desc limit 1`;
45
45
 
46
46
  const count = await pg.queryCache(q2, { table: row.table ? `data.${row.table}` : 'site.content_data', args: [row.id] }).then(el => el.rows?.[0]?.count || '0');
47
47
 
48
- const lastEdit = await pg.queryCache(q1, { table: row.table ? `data.${row.table}` : 'site.content_data', args: [row.id] }).then(el => el.rows?.[0]?.updated_at);
48
+ const lastEdit = await pg.queryCache(q3, { table: row.table ? `data.${row.table}` : 'site.content_data', args: [row.id] }).then(el => el.rows?.[0]?.updated_at);
49
49
 
50
50
  Object.assign(row, { columns: undefined, fields: row.columns?.length || '0', entries: +count, last_edit: lastEdit });
51
51
  }));