@opengis/cms 0.0.31 → 0.0.33

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/cms",
3
- "version": "0.0.31",
3
+ "version": "0.0.33",
4
4
  "description": "cms",
5
5
  "type": "module",
6
6
  "author": "Softpro",
@@ -12,6 +12,7 @@
12
12
  "plugin.js"
13
13
  ],
14
14
  "scripts": {
15
+ "patch": "npm version patch && git push && npm publish",
15
16
  "test": "node --test test/**/*.test.js",
16
17
  "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
17
18
  "build": "vite build admin",
@@ -31,17 +32,17 @@
31
32
  "demo": "node --env-file=.env.demo --env-file=.env server",
32
33
  "i18n:sync": "node i18n-sync.cjs",
33
34
  "prepublishOnly": "bun build:lib",
34
- "softpro": "bun --env-file=.env.softpro server"
35
- },
36
- "dependencies": {
35
+ "softpro": "bun --env-file=.env.softpro server",
36
+ "softpro1": "bun --env-file=.env.prod-softpro.local server"
37
37
  },
38
+ "dependencies": {},
38
39
  "resolutions": {
39
40
  "rollup": "4.30.0"
40
41
  },
41
42
  "devDependencies": {
42
43
  "@fastify/compress": "^8.1.0",
43
44
  "@opengis/core": "^0.0.30",
44
- "@opengis/fastify-table": "^2.0.118",
45
+ "@opengis/fastify-table": "^2.0.128",
45
46
  "@opengis/filter": "^0.1.10",
46
47
  "@opengis/form": "^0.0.70",
47
48
  "@opengis/richtext": "0.0.38",
@@ -6,6 +6,8 @@ import { config } from '@opengis/fastify-table/utils.js';
6
6
 
7
7
  const dir = dirname(fileURLToPath(import.meta.url));
8
8
  const root = `${dir}/../..`;
9
+ const adminRoot = path.join(root, 'admin');
10
+
9
11
  const isProduction = process.env.NODE_ENV === 'production' || config.production;
10
12
  console.log({ isProduction })
11
13
  async function plugin(fastify) {
@@ -14,7 +16,8 @@ async function plugin(fastify) {
14
16
  const vite = await import('vite');
15
17
 
16
18
  const viteServer = await vite.createServer({
17
- root: `${root}`,
19
+ root: adminRoot,
20
+ configFile: path.join(adminRoot, 'vite.config.js'),
18
21
  server: {
19
22
  middlewareMode: true,
20
23
  },
@@ -4,7 +4,8 @@ import { rm, stat, readdir } from 'node:fs/promises';
4
4
 
5
5
  import { config, dataDelete, getFolder, pgClients } from "@opengis/fastify-table/utils.js";
6
6
 
7
- const rootDir = getFolder(config, 'local');
7
+ // path.resolve() converts POSIX paths from getFolder to valid Windows paths (Bun/Node fs require this on Windows)
8
+ const rootDir = path.resolve(getFolder(config, 'local'));
8
9
  const dir = '/files';
9
10
 
10
11
  export default async function deleteMedia({
@@ -4,7 +4,8 @@ import { readFile } from 'node:fs/promises';
4
4
 
5
5
  import { config, getFolder, pgClients } from "@opengis/fastify-table/utils.js";
6
6
 
7
- const rootDir = getFolder(config, 'local');
7
+ // path.resolve() converts POSIX paths from getFolder to valid Windows paths (Bun/Node fs require this on Windows)
8
+ const rootDir = path.resolve(getFolder(config, 'local'));
8
9
 
9
10
  export default async function downloadMedia({
10
11
  pg = pgClients.client, params = {},
@@ -1,16 +1,16 @@
1
- import { pgClients } from '@opengis/fastify-table/utils.js';
2
-
3
- export default async function getPermissions(req, reply) {
4
- const { pg = pgClients.client, params = {}, user = {} } = req;
5
-
6
- if (!user?.uid) {
7
- return reply.status(401).send('unauthorized');
8
- }
9
-
10
- const { rows = [] } = await pg.query(
11
- `select * from site.permissions where ${params.id ? 'user_id=$1' : 'true'}`,
12
- [params.id].filter(Boolean),
13
- );
14
-
15
- return { permissions: rows };
1
+ import { pgClients } from '@opengis/fastify-table/utils.js';
2
+
3
+ export default async function getPermissions(req, reply) {
4
+ const { pg = pgClients.client, params = {}, user = {} } = req;
5
+
6
+ if (!user?.uid) {
7
+ return reply.status(401).send('unauthorized');
8
+ }
9
+
10
+ const { rows = [] } = await pg.query(
11
+ `select * from site.permissions where ${params.id ? 'user_id=$1' : 'true'}`,
12
+ [params.id].filter(Boolean),
13
+ );
14
+
15
+ return { permissions: rows };
16
16
  }
@@ -42,12 +42,6 @@ export default async function insertContent(req, reply) {
42
42
  left join pg_namespace b on a.relnamespace=b.oid
43
43
  where a.relam=2 and b.nspname='data'`).then(el => el.rows?.[0]?.array_agg || []) : [];
44
44
 
45
- if (!arr.length) {
46
- return reply.status(400).send('empty schema: data');
47
- }
48
-
49
- const table = arr.find(el => el === params.type);
50
-
51
45
  const { content_id: contentId, type: contentType } = await pg.query(
52
46
  'select content_id, (select type from site.content_types where content_type_id=t.content_type_id) from site.contents t where slug=$1',
53
47
  [['single', 'pages'].includes(type) ? id : type],
@@ -58,6 +52,12 @@ export default async function insertContent(req, reply) {
58
52
  [contentId],
59
53
  ).then(el => el.rows?.[0]?.content_type_id) : null;
60
54
 
55
+ if (!arr.length && (ctypeId || type) !== 'pages') {
56
+ return reply.status(400).send('empty schema: data');
57
+ }
58
+
59
+ const table = arr.find(el => el === params.type);
60
+
61
61
  const { ctid, dbtable, columns: contentColumns } = await pg.query(
62
62
  'select content_type_id as ctid, table_name as dbtable, columns from site.content_types where $1 in (content_type_id, name)',
63
63
  [type === 'single' && id ? id : (ctypeId || type)],
@@ -70,7 +70,7 @@ export default async function insertContent(req, reply) {
70
70
  : contentColumns;
71
71
 
72
72
  // site.content_data, includes singletone
73
- if (((!table && !dbtable) || type === 'pages')) {
73
+ if (((!table && !dbtable) || (ctypeId || type) === 'pages')) {
74
74
  const cid = await pg.query(
75
75
  'select content_id from site.contents where content_type_id=$1 limit 1',
76
76
  [ctid || 'pages'],
@@ -5,7 +5,8 @@ import { readdir, stat } from 'node:fs/promises';
5
5
  import { config, getFolder, pgClients, getMimeType } from '@opengis/fastify-table/utils.js';
6
6
  import { createHash } from 'node:crypto';
7
7
 
8
- const rootDir = getFolder(config, 'local');
8
+ // path.resolve() converts POSIX paths from getFolder to valid Windows paths (Bun/Node fs require this on Windows)
9
+ const rootDir = path.resolve(getFolder(config, 'local'));
9
10
  const dir = '/files';
10
11
 
11
12
  mkdirSync(path.join(rootDir, dir), { recursive: true });
@@ -3,7 +3,8 @@ import { existsSync } from 'node:fs';
3
3
 
4
4
  import { config, getFolder, pgClients } from "@opengis/fastify-table/utils.js";
5
5
 
6
- const rootDir = getFolder(config, 'local');
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'));
7
8
 
8
9
  export default async function metadataMedia({
9
10
  routeOptions = {}, pg = pgClients.client, params = {},
@@ -1,50 +1,50 @@
1
- import { logger, pgClients, dataInsert } from '@opengis/fastify-table/utils.js';
2
-
3
- export default async function setPermissions(req, reply) {
4
- const { pg = pgClients.client, params = {}, user = {}, body = {} } = req;
5
-
6
- if (!user?.uid) {
7
- return reply.status(401).send('unauthorized');
8
- }
9
-
10
- if (!params.id) {
11
- return reply.status(400).send('not enough params: id');
12
- }
13
-
14
- const client = await pg.connect()
15
- const result = {};
16
- try {
17
- await client.query('BEGIN');
18
-
19
- const { rowCount = 0 } = await client.query(
20
- `delete from site.permissions where user_id=$1`,
21
- [params.id].filter(Boolean),
22
- );
23
-
24
- Object.assign(result, { deleted: rowCount });
25
-
26
- if (Array.isArray(body.permissions) && body.permissions?.length) {
27
- body.permissions.forEach((el) => {
28
- Object.assign(el, { user_id: el.user_id || params.id });
29
- });
30
-
31
- await Promise.all(body.permissions.map(async (el) => dataInsert({
32
- pg: client,
33
- table: 'site.permissions',
34
- data: el,
35
- uid: user.uid,
36
- })));
37
-
38
- Object.assign(result, { inserted: body.permissions.length });
39
- }
40
-
41
- await client.query('COMMIT');
42
- return reply.status(200).send(result);
43
- } catch (err) {
44
- await client.query('ROLLBACK');
45
- logger.file('cms/permissions', { error: err.toString(), stack: err.stack });
46
- return reply.status(500).send('set permissions error');
47
- } finally {
48
- client.release();
49
- }
1
+ import { logger, pgClients, dataInsert } from '@opengis/fastify-table/utils.js';
2
+
3
+ export default async function setPermissions(req, reply) {
4
+ const { pg = pgClients.client, params = {}, user = {}, body = {} } = req;
5
+
6
+ if (!user?.uid) {
7
+ return reply.status(401).send('unauthorized');
8
+ }
9
+
10
+ if (!params.id) {
11
+ return reply.status(400).send('not enough params: id');
12
+ }
13
+
14
+ const client = await pg.connect()
15
+ const result = {};
16
+ try {
17
+ await client.query('BEGIN');
18
+
19
+ const { rowCount = 0 } = await client.query(
20
+ `delete from site.permissions where user_id=$1`,
21
+ [params.id].filter(Boolean),
22
+ );
23
+
24
+ Object.assign(result, { deleted: rowCount });
25
+
26
+ if (Array.isArray(body.permissions) && body.permissions?.length) {
27
+ body.permissions.forEach((el) => {
28
+ Object.assign(el, { user_id: el.user_id || params.id });
29
+ });
30
+
31
+ await Promise.all(body.permissions.map(async (el) => dataInsert({
32
+ pg: client,
33
+ table: 'site.permissions',
34
+ data: el,
35
+ uid: user.uid,
36
+ })));
37
+
38
+ Object.assign(result, { inserted: body.permissions.length });
39
+ }
40
+
41
+ await client.query('COMMIT');
42
+ return reply.status(200).send(result);
43
+ } catch (err) {
44
+ await client.query('ROLLBACK');
45
+ logger.file('cms/permissions', { error: err.toString(), stack: err.stack });
46
+ return reply.status(500).send('set permissions error');
47
+ } finally {
48
+ client.release();
49
+ }
50
50
  }
@@ -3,7 +3,8 @@ import { mkdir } from 'node:fs/promises';
3
3
 
4
4
  import { uploadMultiPart, config, getFolder, dataInsert, pgClients } from "@opengis/fastify-table/utils.js";
5
5
 
6
- const rootDir = getFolder(config, 'local');
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'));
7
8
  const dir = '/files';
8
9
 
9
10
  export default async function uploadMedia(req, reply) {
@@ -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
  }));
@@ -1,2 +1,2 @@
1
- select uid, coalesce(sur_name,'')||coalesce(' '||user_name,'') as text, email from admin.users
1
+ select uid, coalesce(sur_name,'')||coalesce(' '||user_name,'') as text, email from admin.users
2
2
  where enabled order by coalesce(sur_name,'')||coalesce(' '||user_name,'')