@opengis/cms 0.0.47 → 0.0.49
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/dist/ArticlesPage-BcR1hbds.js +286 -0
- package/dist/BuilderPage-CK_osM89.js +386 -0
- package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-CnOe9ORD.js +45 -0
- package/dist/CollectionsPage-JfmrHNR_.js +110 -0
- package/dist/CreateForm-BMOBeP4G.js +125 -0
- package/dist/EditCollectionPage-DtgvKGm-.js +803 -0
- package/dist/EmptyData-DaZt_nAm.js +72 -0
- package/dist/MenuAddPage-Bf48Z-ah.js +115 -0
- package/dist/MenuItemPage-BSwUW8tv.js +1365 -0
- package/dist/MenuPage-tJZtK46W.js +106 -0
- package/dist/MonacoEditor.vue_vue_type_script_setup_true_lang-B1DrxmQX.js +84 -0
- package/dist/UniversalTable.vue_vue_type_script_setup_true_lang-CJGTsd1V.js +210 -0
- package/dist/UniversalTablePagination.vue_vue_type_script_setup_true_lang-GYZd_gkA.js +89 -0
- package/dist/_plugin-vue_export-helper-CHgC5LLL.js +9 -0
- package/dist/contentForm-NcG15_5z.js +553 -0
- package/dist/getField-C7EZs-YQ.js +2920 -0
- package/dist/index.js +1710 -13356
- package/dist/vuedraggable-CoAPPFYd.js +1742 -0
- package/package.json +4 -4
- package/server/functions/getContent.js +21 -11
- package/server/functions/getSearchData.js +41 -0
- package/server/functions/getUser.js +4 -3
- package/server/migrations/fixes.sql +5 -0
- package/server/routes/cms/controllers/getContent.js +5 -4
- package/server/routes/cms/controllers/getPermissions.js +15 -15
- package/server/routes/cms/controllers/searchContent.js +7 -5
- package/server/routes/cms/controllers/setPermissions.js +49 -49
- package/server/routes/cms/functions/getSettings.js +4 -2
- package/server/routes/cms/utils/getCollection.js +10 -3
- package/server/routes/cms/utils/updateLocalization.js +4 -4
- package/server/routes/contentType/controllers/addContentType.js +0 -2
- package/server/routes/contentType/utils/updateCustomContentTable.js +5 -5
- package/server/routes/menu/functions/getMenu.js +4 -2
- package/server/templates/select/core.user_mentioned.sql +1 -1
- package/utils.d.ts +49 -13
- package/utils.js +1 -0
- package/dist/MenuAddPage-DJPQEn2D.js +0 -4
- package/dist/MenuItemPage-EH8svyv5.js +0 -4
- package/dist/MenuPage-BgE0yNpY.js +0 -4
- package/dist/en-sWmaB9uu.js +0 -787
- package/dist/index.umd.cjs +0 -272
- package/dist/uk-rH4IPxG5.js +0 -805
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengis/cms",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.49",
|
|
4
4
|
"description": "cms",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Softpro",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@fastify/compress": "^8.1.0",
|
|
42
42
|
"@opengis/core": "^0.0.30",
|
|
43
|
-
"@opengis/fastify-table": "^2.0.
|
|
43
|
+
"@opengis/fastify-table": "^2.0.137",
|
|
44
44
|
"@opengis/filter": "^0.1.31",
|
|
45
|
-
"@opengis/form": "^0.0.
|
|
45
|
+
"@opengis/form": "^0.0.109",
|
|
46
46
|
"@opengis/richtext": "0.0.38",
|
|
47
47
|
"@vueuse/head": "2.0.0",
|
|
48
48
|
"js-yaml": "^4.1.0",
|
|
@@ -64,4 +64,4 @@
|
|
|
64
64
|
"vitest": "3.2.4",
|
|
65
65
|
"vue-tsc": "^2.2.10"
|
|
66
66
|
}
|
|
67
|
-
}
|
|
67
|
+
}
|
|
@@ -4,6 +4,7 @@ import { config, getRedis, pgClients } from '@opengis/fastify-table/utils.js';
|
|
|
4
4
|
|
|
5
5
|
import getContent from '../routes/cms/controllers/getContent.js';
|
|
6
6
|
|
|
7
|
+
const pg = pgClients.client;
|
|
7
8
|
const rclient = getRedis();
|
|
8
9
|
|
|
9
10
|
const mockReply = {
|
|
@@ -18,27 +19,36 @@ const mockReply = {
|
|
|
18
19
|
},
|
|
19
20
|
};
|
|
20
21
|
|
|
21
|
-
export default async function getContentBySlug(slug,
|
|
22
|
+
export default async function getContentBySlug({ slug, filter, tags, state, locale, contextQuery, collection = 'pages', ttl = 3600, fields, limit = 12, page = 1 } = {}) {
|
|
22
23
|
if (!slug) {
|
|
23
|
-
return { error: 'not enough params: slug', code: 400 };
|
|
24
|
+
// return { error: 'not enough params: slug', code: 400 };
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
const
|
|
27
|
+
const tables = await pg.queryCache('select json_object_agg(name, \'data.\'||table_name) from site.content_types', { table: 'site.content_types' }).then(el => el.rows?.[0]?.json_object_agg || {});
|
|
27
28
|
|
|
28
|
-
const
|
|
29
|
+
const table = collection === 'pages' ? 'site.contents' : tables[collection];
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return { cache: true, ...JSON.parse(cache) };
|
|
31
|
+
if (!table) {
|
|
32
|
+
return { error: 'invalid params: collection', code: 400 };
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
// check if any crud operations performed, if not - return cached response
|
|
36
|
+
const crudInc = await rclient.get(`pg:${table}:crud`) || 0;
|
|
35
37
|
|
|
36
|
-
const
|
|
38
|
+
const cacheKey = createHash('md5').update([config.pg?.database, 'cms:content', slug, crudInc, filter, tags, state, locale, contextQuery, collection, fields, limit, page, fields && typeof fields !== 'string' ? JSON.stringify(fields) : fields].join(':')).digest('hex');
|
|
39
|
+
const cacheData = ttl === 0 ? null : JSON.parse(await rclient.get(cacheKey));
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
// return from cache
|
|
42
|
+
if (cacheData) {
|
|
43
|
+
return { cache: true, ...cacheData };
|
|
44
|
+
}
|
|
40
45
|
|
|
41
|
-
|
|
46
|
+
const req = { pg: pgClients.client, params: { type: collection, id: slug }, query: { filter, tags, state, contextQuery, locale, fields, limit, page } };
|
|
47
|
+
const result = await getContent(req, mockReply, true);
|
|
48
|
+
|
|
49
|
+
if (ttl) {
|
|
50
|
+
await rclient.set(cacheKey, JSON.stringify(result), 'EX', ttl);
|
|
51
|
+
}
|
|
42
52
|
|
|
43
53
|
return result;
|
|
44
54
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
import { config, getRedis, pgClients } from '@opengis/fastify-table/utils.js';
|
|
4
|
+
|
|
5
|
+
import searchContent from '../routes/cms/controllers/searchContent.js';
|
|
6
|
+
|
|
7
|
+
const pg = pgClients.client;
|
|
8
|
+
const rclient = getRedis();
|
|
9
|
+
|
|
10
|
+
const mockReply = {
|
|
11
|
+
response: {},
|
|
12
|
+
status: (statusCode) => {
|
|
13
|
+
Object.assign(mockReply.response, { status: statusCode });
|
|
14
|
+
return mockReply;
|
|
15
|
+
},
|
|
16
|
+
send: (result) => {
|
|
17
|
+
Object.assign(mockReply.response, typeof result === 'object' ? result : { message: result });
|
|
18
|
+
return { ...mockReply.response };
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default async function getSearchData({ page = 1, limit = 12, ttl = 3600, search, locale, tags, filter, contentType, asc } = {}) {
|
|
23
|
+
// check if any crud operations performed, if not - return cached response
|
|
24
|
+
const crudInc = await rclient.get(`pg:site.contents:crud`) || 0;
|
|
25
|
+
|
|
26
|
+
const cacheKey = createHash('md5').update([config.pg?.database, 'cms:search', crudInc, page, limit, ttl, locale, tags, filter, contentType, asc].join(':')).digest('hex');
|
|
27
|
+
const cacheData = ttl === 0 ? null : JSON.parse(await rclient.get(cacheKey));
|
|
28
|
+
|
|
29
|
+
// return from cache
|
|
30
|
+
if (cacheData) {
|
|
31
|
+
return { cache: true, ...cacheData };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const result = await searchContent({ pg, query: { search, locale, page, limit, tags, filter, contentType } }, mockReply);
|
|
35
|
+
|
|
36
|
+
if (ttl) {
|
|
37
|
+
await rclient.set(cacheKey, JSON.stringify(result), 'EX', ttl);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
@@ -4,10 +4,11 @@ import { config, getRedis } from "@opengis/fastify-table/utils.js";
|
|
|
4
4
|
|
|
5
5
|
const rclient2 = getRedis({ db: 2 });
|
|
6
6
|
|
|
7
|
-
// const test = await getUser(req.cookies);
|
|
7
|
+
// const test = await getUser(req.cookies); - as object from request
|
|
8
|
+
// const test = await getUser('_ga=GA...; session_auth=e0tQkaEI9yGab7pv--fZxbUJqTNmbqh; _dd_s=...'); - as string via astro
|
|
8
9
|
|
|
9
10
|
export default async function getUser(cookies) {
|
|
10
|
-
const rawCookie = cookies?.['session_auth'];
|
|
11
|
+
const rawCookie = typeof cookies === 'string' ? decodeURIComponent(cookies.match(/(?:^|;\s*)session_auth=([^;]+)/)?.[1]) : cookies?.['session_auth'];
|
|
11
12
|
|
|
12
13
|
// unauthorized
|
|
13
14
|
if (!rawCookie) {
|
|
@@ -22,5 +23,5 @@ export default async function getUser(cookies) {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
const str = await rclient2.get(`session_auth:${config.pg?.database || 'db'}:${sessionId}`);
|
|
25
|
-
return str ? JSON.parse(str)
|
|
26
|
+
return str ? JSON.parse(str)?.passport?.user : null;
|
|
26
27
|
}
|
|
@@ -41,6 +41,11 @@ left join lateral (select content_type_id from site.content_types b where a.type
|
|
|
41
41
|
*/
|
|
42
42
|
-- seamless migration finish
|
|
43
43
|
|
|
44
|
+
ALTER TABLE if exists site.content_types add column if not exists template text;
|
|
45
|
+
ALTER TABLE if exists site.content_types add column if not exists uid text;
|
|
46
|
+
ALTER TABLE if exists site.contents add column if not exists template text;
|
|
47
|
+
ALTER TABLE if exists site.contents add column if not exists uid text;
|
|
48
|
+
|
|
44
49
|
--- insert default content types start
|
|
45
50
|
insert into site.content_types(content_type_id,name,title,type,columns,template,uid)
|
|
46
51
|
values('pages','pages','Сторінки','collection',
|
|
@@ -35,7 +35,7 @@ addHook('preFilter', async ({ pg = pgClients.client, table }) => {
|
|
|
35
35
|
|
|
36
36
|
const defaultFields = ['title', 'slug', 'status', 'created_at', 'updated_at', 'main_image', 'published_at'];
|
|
37
37
|
|
|
38
|
-
export default async function getContent(req, reply) {
|
|
38
|
+
export default async function getContent(req, reply, called = false) {
|
|
39
39
|
const { pg = pgClients.client, params = {}, query = {}, headers = {} } = req;
|
|
40
40
|
const user = req.user || {};
|
|
41
41
|
const { type, id } = params;
|
|
@@ -46,7 +46,7 @@ export default async function getContent(req, reply) {
|
|
|
46
46
|
|
|
47
47
|
const { draftKey } = await getDraftKey();
|
|
48
48
|
const showDrafts = query.draftKey && query.draftKey === draftKey;
|
|
49
|
-
const statusQuery = !!req.user?.uid || showDrafts ? '1=1' : `status='published'`;
|
|
49
|
+
const statusQuery = !!req.user?.uid || showDrafts || called ? '1=1' : `status='published'`;
|
|
50
50
|
|
|
51
51
|
// headers.authorization = 'Bearer tokenExample'
|
|
52
52
|
const isValidToken = await pg.query(
|
|
@@ -54,7 +54,7 @@ export default async function getContent(req, reply) {
|
|
|
54
54
|
[headers.authorization?.split(' ')?.pop?.() || '']
|
|
55
55
|
).then(el => el.rows?.[0]?.isvalid);
|
|
56
56
|
|
|
57
|
-
if (!config.local && !isValidToken && config.mode !== 'cms') {
|
|
57
|
+
if (!config.local && !isValidToken && config.mode !== 'cms' && !called) {
|
|
58
58
|
return reply.status(403).send('access restricted: token');
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -91,7 +91,8 @@ export default async function getContent(req, reply) {
|
|
|
91
91
|
const result = contentType === 'collection' && table
|
|
92
92
|
? await getCollection({
|
|
93
93
|
table, id, limit, maxLimit, tags, order, search, filter, state, page, desc,
|
|
94
|
-
sql, locale, contextQuery, statusQuery, columns, preview, user, defaultColumns,
|
|
94
|
+
sql, locale, contextQuery, statusQuery, columns, preview, user, defaultColumns,
|
|
95
|
+
fields, defaultFields, defaultFilters, called,
|
|
95
96
|
}, reply, pg)
|
|
96
97
|
: await getSingle({
|
|
97
98
|
contentId, id, limit, maxLimit, tags, search, filter, locale, statusQuery, user, sql, page, defaultColumns, fields, defaultFields, defaultFilters,
|
|
@@ -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
|
}
|
|
@@ -25,16 +25,17 @@ const matchFilterType = {
|
|
|
25
25
|
const maxLimit = 100;
|
|
26
26
|
|
|
27
27
|
export default async function searchContent({
|
|
28
|
-
pg = pgClients.client, query = {},
|
|
28
|
+
pg = pgClients.client, query = {},
|
|
29
29
|
}, reply) {
|
|
30
30
|
if (!pg?.pk?.['site.contents']) {
|
|
31
|
-
return reply.status(404).send('table not found');
|
|
31
|
+
return reply.status(404).send({ error: 'table not found', code: 404 });
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
const t1 = Date.now();
|
|
35
35
|
|
|
36
36
|
const {
|
|
37
37
|
locale, // to do?
|
|
38
|
+
search,
|
|
38
39
|
filter,
|
|
39
40
|
contentType,
|
|
40
41
|
asc,
|
|
@@ -42,11 +43,11 @@ export default async function searchContent({
|
|
|
42
43
|
} = query;
|
|
43
44
|
|
|
44
45
|
if (contentType && typeof contentType !== 'string') {
|
|
45
|
-
return reply.status(400).send('invalid query params: contentType must be a string');
|
|
46
|
+
return reply.status(400).send({ error: 'invalid query params: contentType must be a string', code: 400 });
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
if (tags && typeof tags !== 'string') {
|
|
49
|
-
return reply.status(400).send('invalid query params: tags must be a string');
|
|
50
|
+
return reply.status(400).send({ error: 'invalid query params: tags must be a string', code: 400 });
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
// add for singletone offset
|
|
@@ -58,6 +59,7 @@ export default async function searchContent({
|
|
|
58
59
|
pg,
|
|
59
60
|
table: 'site.contents',
|
|
60
61
|
filter,
|
|
62
|
+
search,
|
|
61
63
|
query: `status='published'`,
|
|
62
64
|
filterList,
|
|
63
65
|
}) : { q: `status='published'` };
|
|
@@ -82,7 +84,7 @@ export default async function searchContent({
|
|
|
82
84
|
}) || {};
|
|
83
85
|
|
|
84
86
|
if (!contents.length) {
|
|
85
|
-
return reply.status(404).send('content not found');
|
|
87
|
+
return reply.status(404).send({ error: 'content not found', code: 404 });
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
const singles = contents.filter(el => el.content_type === 'single');
|
|
@@ -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
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { config, pgClients, getRedis } from "@opengis/fastify-table/utils.js";
|
|
2
2
|
|
|
3
|
+
const pg = pgClients.client;
|
|
3
4
|
const rclient = getRedis();
|
|
4
5
|
|
|
5
|
-
export default async function getSettings({ entity = 'app', keys = ['cms'], uid = 0, ttl = 3600
|
|
6
|
+
export default async function getSettings({ entity = 'app', keys = ['cms'], uid = 0, ttl = 3600 } = {}) {
|
|
6
7
|
if (!pg) {
|
|
7
8
|
return { error: "empty pg", code: 500 };
|
|
8
9
|
}
|
|
@@ -11,7 +12,8 @@ export default async function getSettings({ entity = 'app', keys = ['cms'], uid
|
|
|
11
12
|
return { error: "properties table not found", code: 404 };
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
+
const crudInc = await rclient.get(`pg:admin.properties:crud`) || 0;
|
|
16
|
+
const cacheKey = [config.pg?.database, "cms:settings", crudInc, entity, keys, uid].filter(Boolean).join(":");
|
|
15
17
|
const cache = ttl === 0 ? null : await rclient.get(cacheKey);
|
|
16
18
|
|
|
17
19
|
// return from cache
|
|
@@ -3,9 +3,11 @@ import { pgClients, getData, getMeta } from "@opengis/fastify-table/utils.js";
|
|
|
3
3
|
import additionalData from "./additionalData.js";
|
|
4
4
|
|
|
5
5
|
export default async function getCollection({
|
|
6
|
-
table, id, limit, maxLimit, order, search, tags, filter, state, page, desc, sql, locale, contextQuery, statusQuery, columns, preview, user, defaultColumns, fields, defaultFields = [], defaultFilters = []
|
|
6
|
+
table, id, limit, maxLimit, order, search, tags, filter, state, page, desc, sql, locale, contextQuery, statusQuery, columns, preview, user, defaultColumns, fields, defaultFields = [], defaultFilters = [], called = false,
|
|
7
7
|
}, reply, pg = pgClients.client) {
|
|
8
|
-
|
|
8
|
+
const meta = table ? await getMeta({ pg, table: 'data.' + table }) : {};
|
|
9
|
+
|
|
10
|
+
if (!table || !meta?.pk) {
|
|
9
11
|
return { message: 'content table not found', status: 404 };
|
|
10
12
|
}
|
|
11
13
|
|
|
@@ -60,7 +62,7 @@ export default async function getCollection({
|
|
|
60
62
|
// Apply localization and tags etc.
|
|
61
63
|
if (res?.rows?.length) {
|
|
62
64
|
await additionalData(pg, res.rows, locale, id ? null : existingFields);
|
|
63
|
-
}
|
|
65
|
+
}
|
|
64
66
|
|
|
65
67
|
const columns1 = !id
|
|
66
68
|
? columns?.map(col => Object.assign(col, { type: col.name === 'published_at' ? 'date' : col.type }))?.filter?.(el => !el.hidden)
|
|
@@ -79,5 +81,10 @@ export default async function getCollection({
|
|
|
79
81
|
Object.assign(res, { type: 'collection', locales, preview_path: preview, columns: finalColumns });
|
|
80
82
|
}
|
|
81
83
|
|
|
84
|
+
// add table name for cache via getContent function
|
|
85
|
+
if (called) {
|
|
86
|
+
Object.assign(res, { table: 'data.' + `"${table}"` });
|
|
87
|
+
}
|
|
88
|
+
|
|
82
89
|
return res;
|
|
83
90
|
}
|
|
@@ -8,11 +8,11 @@ export default async function updateLocalization(pg, id, body, contentTypeId, ui
|
|
|
8
8
|
// const contentColumns = await pg.query('select columns from site.content_types where content_type_id=$1', [contentTypeId])
|
|
9
9
|
// .then(el => el.rows?.[0]?.columns || []);
|
|
10
10
|
|
|
11
|
-
const loadTable = contentTypeId === 'pages'
|
|
11
|
+
const loadTable = contentTypeId === 'pages'
|
|
12
|
+
? await getTemplate('table', 'single.default.table')
|
|
13
|
+
: await getTemplate('table', 'collection.default.table');
|
|
12
14
|
|
|
13
|
-
const columns =
|
|
14
|
-
? (loadTable?.columns || []).concat(contentColumns.filter(col => loadTable?.columns.findIndex(el => el.name === col.name) === -1))
|
|
15
|
-
: contentColumns;
|
|
15
|
+
const columns = (loadTable?.columns || []).concat(contentColumns.filter(col => loadTable?.columns.findIndex(el => el.name === col.name) === -1));
|
|
16
16
|
|
|
17
17
|
const locales = await pg.query('select locales from site.spaces where space_id = $1 limit 1', ['default']).then(el => el.rows?.[0]?.locales || []);
|
|
18
18
|
|
|
@@ -43,12 +43,12 @@ export default async function updateCustomContentTable({ pg, id, columns = [] })
|
|
|
43
43
|
await pg.query(`alter table data."${tablename}" drop constraint if exists c${id}_slug_unique;alter table data."${tablename}" add constraint c${id}_slug_unique UNIQUE (slug);`);
|
|
44
44
|
|
|
45
45
|
// force meta columns refresh to avoid crud skips
|
|
46
|
-
getMeta({ pg, table: `data.${tablename}` }, true);
|
|
46
|
+
await getMeta({ pg, table: `data.${tablename}` }, true);
|
|
47
47
|
|
|
48
|
-
if (pg?.pk && pg.tlist && !pg.tlist.find(el => el === `data.${tablename}`)) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
48
|
+
// if (pg?.pk && pg.tlist && !pg.tlist.find(el => el === `data.${tablename}`)) {
|
|
49
|
+
// pg.pk[`data.${tablename}`] = 'id';
|
|
50
|
+
// pg.tlist?.push?.(`data.${tablename}`);
|
|
51
|
+
// }
|
|
52
52
|
|
|
53
53
|
return null;
|
|
54
54
|
}
|
|
@@ -2,9 +2,10 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
|
|
3
3
|
import { config, pgClients, getRedis } from "@opengis/fastify-table/utils.js";
|
|
4
4
|
|
|
5
|
+
const pg = pgClients.client;
|
|
5
6
|
const rclient = getRedis();
|
|
6
7
|
|
|
7
|
-
export default async function getMenu(name, { locale, ttl = 3600, page, limit = 16, sql
|
|
8
|
+
export default async function getMenu(name, { locale, ttl = 3600, page, limit = 16, sql } = {}) {
|
|
8
9
|
if (!pg?.pk) {
|
|
9
10
|
return { error: 'empty pg', code: 400 };
|
|
10
11
|
}
|
|
@@ -13,7 +14,8 @@ export default async function getMenu(name, { locale, ttl = 3600, page, limit =
|
|
|
13
14
|
return { error: 'table not found', code: 404 };
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
const
|
|
17
|
+
const crudInc = await rclient.get(`pg:site.menus:crud`) || 0;
|
|
18
|
+
const cacheKey = createHash('md5').update([config.pg?.database, 'cms:menu', crudInc, name, locale].filter(Boolean).join(':')).digest('hex');
|
|
17
19
|
|
|
18
20
|
const cache = ttl === 0 ? null : await rclient.get(cacheKey);
|
|
19
21
|
|
|
@@ -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,'')
|
package/utils.d.ts
CHANGED
|
@@ -1,16 +1,52 @@
|
|
|
1
|
-
interface
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
interface ContentParam {
|
|
2
|
+
slug?: string;
|
|
3
|
+
locale?: string;
|
|
4
|
+
ttl?: number;
|
|
5
|
+
page?: number;
|
|
6
|
+
fields?: string;
|
|
7
|
+
limit?: number;
|
|
8
|
+
filter?: string;
|
|
9
|
+
tags?: any;
|
|
10
|
+
state?: string;
|
|
11
|
+
contextQuery?: string;
|
|
12
|
+
collection?: string;
|
|
7
13
|
}
|
|
14
|
+
|
|
15
|
+
interface MenuParam {
|
|
16
|
+
locale?: string;
|
|
17
|
+
ttl?: number;
|
|
18
|
+
page?: number;
|
|
19
|
+
limit?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface SettingParam {
|
|
23
|
+
entity?: string;
|
|
24
|
+
keys?: string;
|
|
25
|
+
uid?: number;
|
|
26
|
+
ttl?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
8
29
|
interface Setting {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
30
|
+
entity?: string;
|
|
31
|
+
keys?: string;
|
|
32
|
+
uid?: number;
|
|
33
|
+
ttl?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface SearchParam {
|
|
37
|
+
contentType?: string;
|
|
38
|
+
filter?: string;
|
|
39
|
+
search?: string;
|
|
40
|
+
locale?: string;
|
|
41
|
+
tags?: string;
|
|
42
|
+
page?: number;
|
|
43
|
+
limit?: number;
|
|
44
|
+
asc?: number;
|
|
45
|
+
ttl?: number;
|
|
13
46
|
}
|
|
14
|
-
|
|
15
|
-
export function
|
|
16
|
-
export function
|
|
47
|
+
|
|
48
|
+
export function getContent(param?: ContentParam): any;
|
|
49
|
+
export function getMenu(slug: string, param?: MenuParam): any;
|
|
50
|
+
export function getSettings(param?: SettingParam): any;
|
|
51
|
+
export function getUser(cookies: string | Record<string, any>): any;
|
|
52
|
+
export function getSearchData(param: SearchParam): any;
|
package/utils.js
CHANGED
|
@@ -2,5 +2,6 @@ export { default as getMenu } from "./server/routes/menu/functions/getMenu.js";
|
|
|
2
2
|
export { default as getContent } from "./server/functions/getContent.js";
|
|
3
3
|
export { default as getSettings } from "./server/routes/cms/functions/getSettings.js";
|
|
4
4
|
export { default as getUser } from "./server/functions/getUser.js";
|
|
5
|
+
export { default as getSearchData } from "./server/functions/getSearchData.js";
|
|
5
6
|
|
|
6
7
|
export default null;
|