@opengis/cms 0.0.42 → 0.0.44

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 (95) hide show
  1. package/README.md +98 -98
  2. package/dist/{en-CzEziHMG.js → en-OTy187va.js} +1 -0
  3. package/dist/index.html +29 -29
  4. package/dist/index.js +6266 -15660
  5. package/dist/index.umd.cjs +75 -77
  6. package/dist/{uk-TyVZmyOZ.js → uk-Dy2psXBp.js} +1 -0
  7. package/input-types.json +10 -0
  8. package/module/cms/cls/content.status.json +17 -17
  9. package/module/cms/cls/user_type.json +9 -9
  10. package/module/cms/form/admin.users.form.json +77 -77
  11. package/module/cms/select/cms.page_type.sql +1 -1
  12. package/module/cms/select/news_tag_id.sql +11 -11
  13. package/module/cms/table/admin.users.table.json +53 -53
  14. package/module/cms/table/collection.default.table.json +96 -96
  15. package/module/cms/table/single.default.table.json +116 -114
  16. package/package.json +65 -71
  17. package/plugin.js +43 -76
  18. package/server/app.js +35 -35
  19. package/server/config.js +4 -4
  20. package/server/functions/getDraftKey.js +22 -22
  21. package/server/index.js +22 -22
  22. package/server/migrations/fixes.sql +124 -124
  23. package/server/migrations/site.sql +595 -595
  24. package/server/plugins/adminHook.js +78 -78
  25. package/server/plugins/hook.js +59 -59
  26. package/server/plugins/vite.js +75 -75
  27. package/server/routes/category/controllers/cms.category.delete.js +21 -21
  28. package/server/routes/category/controllers/cms.category.get.js +17 -17
  29. package/server/routes/category/controllers/cms.category.list.js +16 -16
  30. package/server/routes/category/controllers/cms.category.post.js +21 -21
  31. package/server/routes/category/controllers/cms.category.put.js +23 -23
  32. package/server/routes/category/index.mjs +22 -22
  33. package/server/routes/cms/controllers/cmsStat.js +55 -55
  34. package/server/routes/cms/controllers/cmsSuggest.js +57 -57
  35. package/server/routes/cms/controllers/deleteContent.js +113 -113
  36. package/server/routes/cms/controllers/getContent.js +110 -110
  37. package/server/routes/cms/controllers/getContentBySlug.js +93 -95
  38. package/server/routes/cms/controllers/getPermissions.js +15 -15
  39. package/server/routes/cms/controllers/insertContent.js +217 -218
  40. package/server/routes/cms/controllers/properties.get.js +53 -53
  41. package/server/routes/cms/controllers/properties.post.js +99 -99
  42. package/server/routes/cms/controllers/searchContent.js +205 -205
  43. package/server/routes/cms/controllers/setPermissions.js +49 -49
  44. package/server/routes/cms/controllers/translate.js +89 -89
  45. package/server/routes/cms/controllers/updateContent.js +238 -240
  46. package/server/routes/cms/index.mjs +112 -114
  47. package/server/routes/cms/utils/additionalData.js +35 -35
  48. package/server/routes/cms/utils/getCollection.js +82 -82
  49. package/server/routes/cms/utils/getSingle.js +187 -189
  50. package/server/routes/cms/utils/inputTypes.js +6 -0
  51. package/server/routes/cms/utils/insertContentLocalization.js +86 -86
  52. package/server/routes/cms/utils/requestTranslation.js +85 -85
  53. package/server/routes/cms/utils/updateLocalization.js +47 -47
  54. package/server/routes/cmsSpace/controllers/deleteSpace.js +25 -25
  55. package/server/routes/cmsSpace/controllers/getSpaces.js +27 -27
  56. package/server/routes/cmsSpace/controllers/insertSpace.js +21 -21
  57. package/server/routes/cmsSpace/controllers/updateSpace.js +23 -23
  58. package/server/routes/cmsSpace/index.mjs +20 -20
  59. package/server/routes/contentType/controllers/addContentType.js +162 -162
  60. package/server/routes/contentType/controllers/contentTypeList.js +54 -54
  61. package/server/routes/contentType/controllers/delContentType.js +75 -75
  62. package/server/routes/contentType/controllers/editContentType.js +61 -61
  63. package/server/routes/contentType/controllers/getContentType.js +37 -37
  64. package/server/routes/contentType/index.mjs +35 -35
  65. package/server/routes/contentType/utils/updateContents.js +28 -28
  66. package/server/routes/contentType/utils/updateCustomContentTable.js +53 -55
  67. package/server/routes/feedback/controllers/email.list.js +24 -24
  68. package/server/routes/feedback/controllers/feedback.js +48 -48
  69. package/server/routes/feedback/controllers/feedback.list.js +37 -37
  70. package/server/routes/feedback/controllers/news.subscriptions.js +44 -44
  71. package/server/routes/feedback/index.mjs +71 -71
  72. package/server/routes/logs/controllers/export.user.logs.js +77 -77
  73. package/server/routes/logs/controllers/user.logs.js +44 -44
  74. package/server/routes/logs/index.mjs +9 -9
  75. package/server/routes/menu/controllers/addMenu.js +37 -37
  76. package/server/routes/menu/controllers/delMenu.js +31 -31
  77. package/server/routes/menu/controllers/editMenu.js +41 -41
  78. package/server/routes/menu/controllers/getMenu.js +42 -42
  79. package/server/routes/menu/index.mjs +13 -13
  80. package/server/routes/migration/controllers/collectionToCustom.js +137 -137
  81. package/server/routes/migration/index.mjs +8 -8
  82. package/server/routes/root.mjs +8 -8
  83. package/server/routes/tags/controllers/add.tags.js +24 -24
  84. package/server/routes/tags/controllers/del.tags.js +19 -19
  85. package/server/routes/tags/controllers/edit.tags.js +25 -25
  86. package/server/routes/tags/controllers/get.tags.js +15 -15
  87. package/server/routes/tags/index.mjs +14 -14
  88. package/server/templates/cls/cms.category_type.json +9 -9
  89. package/server/templates/cls/cms.content_review_status.json +9 -9
  90. package/server/templates/cls/cms.content_status.json +9 -9
  91. package/server/templates/cls/cms.content_type.json +9 -9
  92. package/server/templates/cls/cms.lang.json +9 -9
  93. package/server/templates/page/login.html +126 -126
  94. package/server/templates/select/core.user_mentioned.sql +1 -1
  95. package/dist/index-W-qQIppj-DRzFSjU1.js +0 -2452
@@ -1,111 +1,111 @@
1
- import { config, pgClients, addHook, getTemplate } from '@opengis/fastify-table/utils.js';
2
-
3
- import getCollection from '../utils/getCollection.js';
4
- import getSingle from '../utils/getSingle.js';
5
- import getDraftKey from '../../../functions/getDraftKey.js';
6
-
7
- const maxLimit = 100;
8
-
9
- addHook('preFilter', async ({ pg = pgClients.client, table }) => {
10
- if (config.trace) console.log('preFilter', table);
11
- if (!pg || !table) return null;
12
-
13
- if (!table.startsWith('data.') && ['site.contents', 'single.default.table'].includes(table)) {
14
- const { filters = [] } = await getTemplate('table', 'single.default.table') || {};
15
- return { table: 'site.contents', filters };
16
- }
17
-
18
- // default filters, same as pages collection
19
- const { filters = [] } = await getTemplate('table', 'collection.default.table') || {};
20
-
21
- if (['site.contents', 'collection.default.table'].includes(table)) {
22
- return { table: 'site.contents', filters };
23
- }
24
-
25
- if (table.startsWith('data.') && pg?.pk?.[table.replace(/"/g, '')]) {
26
- const { ctid, columns } = await pg.query(
27
- `select content_type_id as ctid, columns from site.content_types where 'data.' || table_name = $1`,
28
- [table.replace(/"/g, '')]
29
- ).then(el => el.rows?.[0] || {});
30
- if (!ctid) return null;
31
-
32
- return { table, filters: filters.concat((columns || []).filter(el => !el.hidden && el.filter && el.name && filters.map(item => item.name).includes(el.name))) };
33
- }
34
- });
35
-
36
- const defaultFields = ['title', 'slug', 'status', 'created_at', 'updated_at', 'main_image', 'published_at'];
37
-
38
- export default async function getContent(req, reply) {
39
- const { pg = pgClients.client, params = {}, query = {}, headers = {} } = req;
40
- const user = req.user || {};
41
- const { type, id } = params;
42
- const { filter, state, limit = 16, page, sql, contextQuery, locale, tags, fields } = query;
43
- const search = filter ? filter?.split?.('search=')?.[1]?.split?.('|')?.[0] : undefined;
44
- const [order, ord] = query.order?.split?.('-') || [];
45
- const desc = query.desc || ord === 'desc';
46
-
47
- const { draftKey } = await getDraftKey();
48
- const showDrafts = query.draftKey && query.draftKey === draftKey;
49
- const statusQuery = !!req.user?.uid || showDrafts ? '1=1' : `status='published'`;
50
-
51
- // headers.authorization = 'Bearer tokenExample'
52
- const isValidToken = await pg.query(
53
- `select count(*) = 1 as isvalid from site.tokens where token_value=$1 and token_status = 'Active'`,
54
- [headers.authorization?.split(' ')?.pop?.() || '']
55
- ).then(el => el.rows?.[0]?.isvalid);
56
-
57
- if (!config.local && !isValidToken && config.mode !== 'cms') {
58
- return reply.status(403).send('access restricted: token');
59
- }
60
-
61
- if (!type) {
62
- return reply.status(400).send('not enough params: type');
63
- }
64
-
65
- const { contentId, contentTypeId, meta } = params.type === 'pages'
66
- ? await pg.query(`select content_id as "contentId", content_type_id as "contentTypeId", meta from site.contents where content_id=$1`, [params.type]).then(el => el.rows?.[0] || {})
67
- : await pg.query(`select content_id as "contentId", content_type_id as "contentTypeId", meta from site.contents where $1 in (slug, content_id, content_type_id)`, [params.type]).then(el => el.rows?.[0] || {});
68
-
69
- if (!contentId) {
70
- return reply.status(404).send('content not found');
71
- }
72
-
73
- const { table, contentType, preview, columns: columns1 } = await pg.query(
74
- 'select table_name as table, type as "contentType", preview_path as preview, columns from site.content_types where content_type_id=$1',
75
- [contentTypeId],
76
- ).then(el => el.rows?.[0] || {});
77
-
78
- if (!contentType) {
79
- return reply.status(404).send('content type not found');
80
- }
81
-
82
- const loadTable = contentType === 'collection' && table
83
- ? await getTemplate('table', 'collection.default.table')
84
- : await getTemplate('table', 'single.default.table');
85
- const { columns: defaultColumns = [], filters: defaultFilters = [] } = loadTable || {};
86
-
87
- defaultColumns.forEach(col => Object.assign(col, { default: true }));
88
-
89
- const columns = columns1.filter(col => !defaultColumns.map(el => el.name).includes(col.name));
90
-
91
- const result = contentType === 'collection' && table
92
- ? await getCollection({
93
- table, id, limit, maxLimit, tags, order, search, filter, state, page, desc,
94
- sql, locale, contextQuery, statusQuery, columns, preview, user, defaultColumns, fields, defaultFields, defaultFilters,
95
- }, reply, pg)
96
- : await getSingle({
97
- contentId, id, limit, maxLimit, tags, search, filter, locale, statusQuery, user, sql, page, defaultColumns, fields, defaultFields, defaultFilters,
98
- }, pg);
99
-
100
- if (!result) {
101
- return reply.status(404).send('empty content data');
102
- }
103
-
104
- if (result?.message) {
105
- return reply.status(result.status || 500).send(result.message);
106
- }
107
-
108
- Object.assign(result, { meta });
109
-
110
- return reply.status(200).send(result);
1
+ import { config, pgClients, addHook, getTemplate } from '@opengis/fastify-table/utils.js';
2
+
3
+ import getCollection from '../utils/getCollection.js';
4
+ import getSingle from '../utils/getSingle.js';
5
+ import getDraftKey from '../../../functions/getDraftKey.js';
6
+
7
+ const maxLimit = 100;
8
+
9
+ addHook('preFilter', async ({ pg = pgClients.client, table }) => {
10
+ if (config.trace) console.log('preFilter', table);
11
+ if (!pg || !table) return null;
12
+
13
+ if (!table.startsWith('data.') && ['site.contents', 'single.default.table'].includes(table)) {
14
+ const { filters = [] } = await getTemplate('table', 'single.default.table') || {};
15
+ return { table: 'site.contents', filters };
16
+ }
17
+
18
+ // default filters, same as pages collection
19
+ const { filters = [] } = await getTemplate('table', 'collection.default.table') || {};
20
+
21
+ if (['site.contents', 'collection.default.table'].includes(table)) {
22
+ return { table: 'site.contents', filters };
23
+ }
24
+
25
+ if (table.startsWith('data.') && pg?.pk?.[table.replace(/"/g, '')]) {
26
+ const { ctid, columns } = await pg.query(
27
+ `select content_type_id as ctid, columns from site.content_types where 'data.' || table_name = $1`,
28
+ [table.replace(/"/g, '')]
29
+ ).then(el => el.rows?.[0] || {});
30
+ if (!ctid) return null;
31
+
32
+ return { table, filters: filters.concat((columns || []).filter(el => !el.hidden && el.filter && el.name && filters.map(item => item.name).includes(el.name))) };
33
+ }
34
+ });
35
+
36
+ const defaultFields = ['title', 'slug', 'status', 'created_at', 'updated_at', 'main_image', 'published_at'];
37
+
38
+ export default async function getContent(req, reply) {
39
+ const { pg = pgClients.client, params = {}, query = {}, headers = {} } = req;
40
+ const user = req.user || {};
41
+ const { type, id } = params;
42
+ const { filter, state, limit = 16, page, sql, contextQuery, locale, tags, fields } = query;
43
+ const search = filter ? filter?.split?.('search=')?.[1]?.split?.('|')?.[0] : undefined;
44
+ const [order, ord] = query.order?.split?.('-') || [];
45
+ const desc = query.desc || ord === 'desc';
46
+
47
+ const { draftKey } = await getDraftKey();
48
+ const showDrafts = query.draftKey && query.draftKey === draftKey;
49
+ const statusQuery = !!req.user?.uid || showDrafts ? '1=1' : `status='published'`;
50
+
51
+ // headers.authorization = 'Bearer tokenExample'
52
+ const isValidToken = await pg.query(
53
+ `select count(*) = 1 as isvalid from site.tokens where token_value=$1 and token_status = 'Active'`,
54
+ [headers.authorization?.split(' ')?.pop?.() || '']
55
+ ).then(el => el.rows?.[0]?.isvalid);
56
+
57
+ if (!config.local && !isValidToken && config.mode !== 'cms') {
58
+ return reply.status(403).send('access restricted: token');
59
+ }
60
+
61
+ if (!type) {
62
+ return reply.status(400).send('not enough params: type');
63
+ }
64
+
65
+ const { contentId, contentTypeId, meta } = params.type === 'pages'
66
+ ? await pg.query(`select content_id as "contentId", content_type_id as "contentTypeId", meta from site.contents where content_id=$1`, [params.type]).then(el => el.rows?.[0] || {})
67
+ : await pg.query(`select content_id as "contentId", content_type_id as "contentTypeId", meta from site.contents where $1 in (slug, content_id, content_type_id)`, [params.type]).then(el => el.rows?.[0] || {});
68
+
69
+ if (!contentId) {
70
+ return reply.status(404).send('content not found');
71
+ }
72
+
73
+ const { table, contentType, preview, columns: columns1 } = await pg.query(
74
+ 'select table_name as table, type as "contentType", preview_path as preview, columns from site.content_types where content_type_id=$1',
75
+ [contentTypeId],
76
+ ).then(el => el.rows?.[0] || {});
77
+
78
+ if (!contentType) {
79
+ return reply.status(404).send('content type not found');
80
+ }
81
+
82
+ const loadTable = contentType === 'collection' && table
83
+ ? await getTemplate('table', 'collection.default.table')
84
+ : await getTemplate('table', 'single.default.table');
85
+ const { columns: defaultColumns = [], filters: defaultFilters = [] } = loadTable || {};
86
+
87
+ defaultColumns.forEach(col => Object.assign(col, { default: true }));
88
+
89
+ const columns = columns1.filter(col => !defaultColumns.map(el => el.name).includes(col.name));
90
+
91
+ const result = contentType === 'collection' && table
92
+ ? await getCollection({
93
+ table, id, limit, maxLimit, tags, order, search, filter, state, page, desc,
94
+ sql, locale, contextQuery, statusQuery, columns, preview, user, defaultColumns, fields, defaultFields, defaultFilters,
95
+ }, reply, pg)
96
+ : await getSingle({
97
+ contentId, id, limit, maxLimit, tags, search, filter, locale, statusQuery, user, sql, page, defaultColumns, fields, defaultFields, defaultFilters,
98
+ }, pg);
99
+
100
+ if (!result) {
101
+ return reply.status(404).send('empty content data');
102
+ }
103
+
104
+ if (result?.message) {
105
+ return reply.status(result.status || 500).send(result.message);
106
+ }
107
+
108
+ Object.assign(result, { meta });
109
+
110
+ return reply.status(200).send(result);
111
111
  }
@@ -1,95 +1,93 @@
1
- import { existsSync, readFileSync } from 'node:fs';
2
-
3
- import { config, pgClients } from '@opengis/fastify-table/utils.js';
4
-
5
- const inputTypes = existsSync('input-types.json') ? JSON.parse(readFileSync('input-types.json') || '{}') : {};
6
-
7
- export default async function getContentBySlug({ pg = pgClients.client, params = {}, headers = {} }, reply) {
8
- if (!params.slug) {
9
- return reply.status(400).send('not enough params: slug');
10
- }
11
-
12
- if (!pg?.pk?.['site.content_types']) {
13
- return reply.status(404).send('table not found');
14
- }
15
-
16
- // headers.authorization = 'Bearer tokenExample'
17
- const isValidToken = await pg.query(
18
- `select count(*) = 1 as isvalid from site.tokens where token_value=$1 and token_status = 'Active'`,
19
- [headers.authorization?.split(' ')?.pop?.() || '']
20
- ).then(el => el.rows?.[0]?.isvalid);
21
-
22
- if (!config.local && !isValidToken && config.mode !== 'cms') {
23
- return reply.status(403).send('access restricted: token');
24
- }
25
-
26
- const { cid } = await pg.query(
27
- `select content_id as cid from site.contents where $1 in (content_id,slug) limit 1`,
28
- [params.slug],
29
- ).then(el => el.rows?.[0] || {});
30
-
31
- if (cid) {
32
- const { rows: data = [] } = await pg.query(
33
- `select field_key, field_type, field_value, field_value_object, content_id from site.content_data where content_id=$1`, [cid]
34
- );
35
-
36
- const meta = await pg.query(
37
- 'select title, status, revision, locale, slug, content_type_id, (select columns from site.content_types where content_type_id=a.content_type_id limit 1) as columns from site.contents a where content_id=$1 limit 1',
38
- [cid],
39
- ).then(el => el.rows?.[0] || {});
40
-
41
- const rows = meta.content_type_id ? [{
42
- ...meta,
43
- columns: undefined,
44
- ...Object.fromEntries(
45
- data.map(k =>
46
- [k.field_key, inputTypes[k.field_type] === 'json' || k.field_key === 'meta'
47
- ? k.field_value_object
48
- : k.field_value]
49
- ) || []
50
- )
51
- }] : [];
52
-
53
- const meta1 = meta.content_type_id ? await pg.query(
54
- 'select type from site.content_types where content_type_id=$1',
55
- [meta.content_type_id],
56
- ).then(el => el.rows?.[0] || {}) : {};
57
-
58
- return reply.status(200).send({
59
- ...meta,
60
- ...meta1,
61
- rows,
62
- });
63
- }
64
-
65
- const { rows: contentTypes = [] } = await pg.query(`select content_type_id as ctid, table_name as table, type from site.content_types where table_name is not null and type='collection' `);
66
-
67
- if (!contentTypes.length || contentTypes.find(row => row.table && pg.pk[row.table])) {
68
- return reply.status(404).send('content not found');
69
- }
70
-
71
- const tlist = await pg.query(`select array_agg((select nspname from pg_namespace where oid=relnamespace)||'.'||relname) tlist
72
- from pg_class where relkind in ('r','v')`).then((d) => d.rows[0].tlist);
73
-
74
- const q = contentTypes.filter(row => row.table && tlist.includes(`data.${row.table}`)).map(row => `select id as dataid, '${row.ctid}' as ctid from data."${row.table}" where slug='${params.slug.replace(/'/g, "''")}'`).join(' union all ');
75
-
76
- const { dataid, ctid } = await pg.query(q).then(el => el.rows?.[0] || {});
77
-
78
- if (!dataid) {
79
- return reply.status(404).send('content not found: 2');
80
- }
81
-
82
- if (!ctid) {
83
- return reply.status(404).send('content not found: 3');
84
- }
85
-
86
- const meta = await pg.query('select content_type_id, type, table_name as table, title, status, name as slug, columns from site.content_types where content_type_id=$1', [ctid]).then(el => el.rows?.[0] || {});
87
-
88
- if (!meta?.table) {
89
- return reply.status(404).send('content not found: 4');
90
- }
91
-
92
- const { rows = [] } = await pg.query(`select * from data.${meta.table} where id=$1`, [dataid]);
93
-
94
- return reply.status(200).send({ ...meta, custom: true, rows });
95
- }
1
+ import { config, pgClients } from '@opengis/fastify-table/utils.js';
2
+
3
+ import inputTypes from '../utils/inputTypes.js';
4
+
5
+ export default async function getContentBySlug({ pg = pgClients.client, params = {}, headers = {} }, reply) {
6
+ if (!params.slug) {
7
+ return reply.status(400).send('not enough params: slug');
8
+ }
9
+
10
+ if (!pg?.pk?.['site.content_types']) {
11
+ return reply.status(404).send('table not found');
12
+ }
13
+
14
+ // headers.authorization = 'Bearer tokenExample'
15
+ const isValidToken = await pg.query(
16
+ `select count(*) = 1 as isvalid from site.tokens where token_value=$1 and token_status = 'Active'`,
17
+ [headers.authorization?.split(' ')?.pop?.() || '']
18
+ ).then(el => el.rows?.[0]?.isvalid);
19
+
20
+ if (!config.local && !isValidToken && config.mode !== 'cms') {
21
+ return reply.status(403).send('access restricted: token');
22
+ }
23
+
24
+ const { cid } = await pg.query(
25
+ `select content_id as cid from site.contents where $1 in (content_id,slug) limit 1`,
26
+ [params.slug],
27
+ ).then(el => el.rows?.[0] || {});
28
+
29
+ if (cid) {
30
+ const { rows: data = [] } = await pg.query(
31
+ `select field_key, field_type, field_value, field_value_object, content_id from site.content_data where content_id=$1`, [cid]
32
+ );
33
+
34
+ const meta = await pg.query(
35
+ 'select title, status, revision, locale, slug, content_type_id, (select columns from site.content_types where content_type_id=a.content_type_id limit 1) as columns from site.contents a where content_id=$1 limit 1',
36
+ [cid],
37
+ ).then(el => el.rows?.[0] || {});
38
+
39
+ const rows = meta.content_type_id ? [{
40
+ ...meta,
41
+ columns: undefined,
42
+ ...Object.fromEntries(
43
+ data.map(k =>
44
+ [k.field_key, inputTypes[k.field_type] === 'json' || k.field_key === 'meta'
45
+ ? k.field_value_object
46
+ : k.field_value]
47
+ ) || []
48
+ )
49
+ }] : [];
50
+
51
+ const meta1 = meta.content_type_id ? await pg.query(
52
+ 'select type from site.content_types where content_type_id=$1',
53
+ [meta.content_type_id],
54
+ ).then(el => el.rows?.[0] || {}) : {};
55
+
56
+ return reply.status(200).send({
57
+ ...meta,
58
+ ...meta1,
59
+ rows,
60
+ });
61
+ }
62
+
63
+ const { rows: contentTypes = [] } = await pg.query(`select content_type_id as ctid, table_name as table, type from site.content_types where table_name is not null and type='collection' `);
64
+
65
+ if (!contentTypes.length || contentTypes.find(row => row.table && pg.pk[row.table])) {
66
+ return reply.status(404).send('content not found');
67
+ }
68
+
69
+ const tlist = await pg.query(`select array_agg((select nspname from pg_namespace where oid=relnamespace)||'.'||relname) tlist
70
+ from pg_class where relkind in ('r','v')`).then((d) => d.rows[0].tlist);
71
+
72
+ const q = contentTypes.filter(row => row.table && tlist.includes(`data.${row.table}`)).map(row => `select id as dataid, '${row.ctid}' as ctid from data."${row.table}" where slug='${params.slug.replace(/'/g, "''")}'`).join(' union all ');
73
+
74
+ const { dataid, ctid } = await pg.query(q).then(el => el.rows?.[0] || {});
75
+
76
+ if (!dataid) {
77
+ return reply.status(404).send('content not found: 2');
78
+ }
79
+
80
+ if (!ctid) {
81
+ return reply.status(404).send('content not found: 3');
82
+ }
83
+
84
+ const meta = await pg.query('select content_type_id, type, table_name as table, title, status, name as slug, columns from site.content_types where content_type_id=$1', [ctid]).then(el => el.rows?.[0] || {});
85
+
86
+ if (!meta?.table) {
87
+ return reply.status(404).send('content not found: 4');
88
+ }
89
+
90
+ const { rows = [] } = await pg.query(`select * from data.${meta.table} where id=$1`, [dataid]);
91
+
92
+ return reply.status(200).send({ ...meta, custom: true, rows });
93
+ }
@@ -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
  }