@opengis/cms 0.0.56 → 0.0.58

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 (149) hide show
  1. package/README.md +131 -131
  2. package/dist/AddNewItemInTree-05PSSEFi.js +76 -0
  3. package/dist/ArticlesPage-CFjE_cw_.js +298 -0
  4. package/dist/CollectionsBreadcrumb-BCxeRikP.js +4 -0
  5. package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-umRzB5mY.js +53 -0
  6. package/dist/CollectionsPage-DHfPNql6.js +124 -0
  7. package/dist/{CreateForm-BMOBeP4G.js → CreateForm-5FvT45vH.js} +1 -1
  8. package/dist/Dashboard-C1eGscNd.js +358 -0
  9. package/dist/EditCollectionPage-DIr1tdtn.js +187 -0
  10. package/dist/{EmptyData-DaZt_nAm.js → EmptyData-DxPrSXhV.js} +1 -1
  11. package/dist/{MenuAddPage-Bf48Z-ah.js → MenuAddPage-D-p3gFgm.js} +40 -35
  12. package/dist/MenuBody-rN5j4YBu.js +125 -0
  13. package/dist/MenuItemPage-BoJw885D.js +1027 -0
  14. package/dist/MenuList-DFEBS0NB.js +172 -0
  15. package/dist/MenuPage-BCZB_S8j.js +107 -0
  16. package/dist/MenuWrapper-AZ_8s-zd.js +12 -0
  17. package/dist/MonacoEditor-Db-3Jc3E.js +4 -0
  18. package/dist/{UniversalTable.vue_vue_type_script_setup_true_lang-CJGTsd1V.js → UniversalTable-CzqPG-tY.js} +12 -12
  19. package/dist/{UniversalTablePagination.vue_vue_type_script_setup_true_lang-GYZd_gkA.js → UniversalTablePagination-4gL47A7I.js} +1 -1
  20. package/dist/VsFormTags-CMjiu9sY.js +114 -0
  21. package/dist/VsPreview-DwETkOpb.js +63 -0
  22. package/dist/contentForm-CtMhQTG0.js +489 -0
  23. package/dist/getField-CpwVE28P.js +179 -0
  24. package/dist/index.d.ts +8 -0
  25. package/dist/index.html +29 -29
  26. package/dist/index.js +72 -71
  27. package/dist/style.css +1 -1
  28. package/dist/vs-builder-edit-D-q1o8tF.js +604 -0
  29. package/dist/vs-builder-monaco-B3Jj0V31.js +33 -0
  30. package/dist/vs-builder-preview-BH4VAM3a.js +44 -0
  31. package/dist/vs-form-custom-datatable-BDZo48w3.js +317 -0
  32. package/dist/vs-form-integer-BZ855R3g.js +61 -0
  33. package/dist/vs-form-media-select-NY27EaG1.js +837 -0
  34. package/dist/vs-form-reference-list-Dtv8fJJU.js +1536 -0
  35. package/dist/vs-form-reletion-link-BhzNQszm.js +34 -0
  36. package/dist/vs-form-tiptap-DDFQjRjY.js +4 -0
  37. package/dist/vs-form-tiptap.vue_vue_type_script_setup_true_lang-DGgsqXwg.js +11 -0
  38. package/dist/vs-richtext-md-C098v_6Q.js +4 -0
  39. package/dist/vs-richtext-md.vue_vue_type_script_setup_true_lang-Ct8uTV-J.js +14 -0
  40. package/input-types.json +9 -9
  41. package/locales/en.json +815 -814
  42. package/locales/uk.json +813 -812
  43. package/module/cms/cls/content.status.json +17 -17
  44. package/module/cms/cls/user_type.json +9 -9
  45. package/module/cms/form/admin.users.form.json +77 -77
  46. package/module/cms/select/cms.page_type.sql +1 -1
  47. package/module/cms/select/news_tag_id.sql +11 -11
  48. package/module/cms/table/admin.users.table.json +53 -53
  49. package/module/cms/table/collection.default.table.json +96 -96
  50. package/module/cms/table/single.default.table.json +116 -116
  51. package/package.json +68 -68
  52. package/plugin.js +43 -43
  53. package/server/app.js +35 -35
  54. package/server/config.js +4 -4
  55. package/server/functions/getContent.js +45 -45
  56. package/server/functions/getDraftKey.js +22 -22
  57. package/server/functions/getSearchData.js +31 -31
  58. package/server/functions/getTags.js +30 -30
  59. package/server/functions/getUser.js +27 -27
  60. package/server/functions/utils/mock.reply.js +55 -55
  61. package/server/index.js +22 -22
  62. package/server/migrations/fixes.sql +129 -129
  63. package/server/migrations/site.sql +595 -595
  64. package/server/plugins/adminHook.js +78 -78
  65. package/server/plugins/hook.js +59 -59
  66. package/server/plugins/vite.js +75 -75
  67. package/server/routes/category/controllers/cms.category.delete.js +21 -21
  68. package/server/routes/category/controllers/cms.category.get.js +17 -17
  69. package/server/routes/category/controllers/cms.category.list.js +16 -16
  70. package/server/routes/category/controllers/cms.category.post.js +21 -21
  71. package/server/routes/category/controllers/cms.category.put.js +23 -23
  72. package/server/routes/category/index.mjs +22 -22
  73. package/server/routes/cms/controllers/cmsStat.js +55 -55
  74. package/server/routes/cms/controllers/cmsSuggest.js +57 -57
  75. package/server/routes/cms/controllers/deleteContent.js +113 -113
  76. package/server/routes/cms/controllers/deleteMedia.js +76 -76
  77. package/server/routes/cms/controllers/downloadMedia.js +84 -84
  78. package/server/routes/cms/controllers/getContent.js +113 -113
  79. package/server/routes/cms/controllers/getContentBySlug.js +93 -93
  80. package/server/routes/cms/controllers/insertContent.js +217 -217
  81. package/server/routes/cms/controllers/listMedia.js +155 -155
  82. package/server/routes/cms/controllers/metadataMedia.js +39 -39
  83. package/server/routes/cms/controllers/properties.get.js +18 -18
  84. package/server/routes/cms/controllers/properties.post.js +99 -99
  85. package/server/routes/cms/controllers/searchContent.js +214 -214
  86. package/server/routes/cms/controllers/translate.js +89 -89
  87. package/server/routes/cms/controllers/updateContent.js +266 -264
  88. package/server/routes/cms/controllers/uploadMedia.js +79 -79
  89. package/server/routes/cms/functions/getSettings.js +48 -48
  90. package/server/routes/cms/index.mjs +112 -112
  91. package/server/routes/cms/utils/additionalData.js +35 -35
  92. package/server/routes/cms/utils/getCollection.js +89 -89
  93. package/server/routes/cms/utils/getSingle.js +188 -183
  94. package/server/routes/cms/utils/inputTypes.js +5 -5
  95. package/server/routes/cms/utils/insertContentLocalization.js +104 -104
  96. package/server/routes/cms/utils/requestTranslation.js +85 -85
  97. package/server/routes/cms/utils/updateLocalization.js +47 -47
  98. package/server/routes/cmsSpace/controllers/deleteSpace.js +25 -25
  99. package/server/routes/cmsSpace/controllers/getSpaces.js +27 -27
  100. package/server/routes/cmsSpace/controllers/insertSpace.js +21 -21
  101. package/server/routes/cmsSpace/controllers/updateSpace.js +23 -23
  102. package/server/routes/cmsSpace/index.mjs +20 -20
  103. package/server/routes/contentType/controllers/addContentType.js +160 -160
  104. package/server/routes/contentType/controllers/contentTypeList.js +54 -54
  105. package/server/routes/contentType/controllers/delContentType.js +75 -75
  106. package/server/routes/contentType/controllers/editContentType.js +88 -81
  107. package/server/routes/contentType/controllers/getContentType.js +65 -57
  108. package/server/routes/contentType/index.mjs +35 -35
  109. package/server/routes/contentType/utils/updateContents.js +44 -44
  110. package/server/routes/contentType/utils/updateCustomContentTable.js +53 -53
  111. package/server/routes/feedback/controllers/email.list.js +24 -24
  112. package/server/routes/feedback/controllers/feedback.js +48 -48
  113. package/server/routes/feedback/controllers/feedback.list.js +37 -37
  114. package/server/routes/feedback/controllers/news.subscriptions.js +44 -44
  115. package/server/routes/feedback/index.mjs +71 -71
  116. package/server/routes/logs/controllers/export.user.logs.js +77 -77
  117. package/server/routes/logs/controllers/user.logs.js +44 -44
  118. package/server/routes/logs/index.mjs +9 -9
  119. package/server/routes/menu/controllers/addMenu.js +37 -37
  120. package/server/routes/menu/controllers/delMenu.js +31 -31
  121. package/server/routes/menu/controllers/editMenu.js +41 -41
  122. package/server/routes/menu/controllers/getMenu.js +24 -24
  123. package/server/routes/menu/functions/getMenu.js +50 -50
  124. package/server/routes/menu/index.mjs +13 -13
  125. package/server/routes/migration/controllers/collectionToCustom.js +137 -137
  126. package/server/routes/migration/index.mjs +8 -8
  127. package/server/routes/root.mjs +8 -8
  128. package/server/routes/tags/controllers/add.tags.js +24 -24
  129. package/server/routes/tags/controllers/del.tags.js +19 -19
  130. package/server/routes/tags/controllers/edit.tags.js +25 -25
  131. package/server/routes/tags/controllers/get.tags.js +15 -15
  132. package/server/routes/tags/index.mjs +14 -14
  133. package/server/templates/cls/cms.category_type.json +9 -9
  134. package/server/templates/cls/cms.content_review_status.json +9 -9
  135. package/server/templates/cls/cms.content_status.json +9 -9
  136. package/server/templates/cls/cms.content_type.json +9 -9
  137. package/server/templates/cls/cms.lang.json +9 -9
  138. package/server/templates/page/login.html +126 -126
  139. package/utils.d.ts +52 -52
  140. package/utils.js +8 -8
  141. package/dist/ArticlesPage-BcR1hbds.js +0 -286
  142. package/dist/BuilderPage-CK_osM89.js +0 -386
  143. package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-CnOe9ORD.js +0 -45
  144. package/dist/CollectionsPage-JfmrHNR_.js +0 -110
  145. package/dist/EditCollectionPage-Cw3GQYRe.js +0 -809
  146. package/dist/MenuItemPage-CXn5HC8j.js +0 -1366
  147. package/dist/MenuPage-tJZtK46W.js +0 -106
  148. package/dist/contentForm-B6gHgGkz.js +0 -586
  149. package/dist/getField-Y5WXnRR0.js +0 -2948
@@ -1,22 +1,22 @@
1
- import { randomUUID } from "node:crypto";
2
-
3
- import { config, getRedis } from "@opengis/fastify-table/utils.js";
4
-
5
- const rclient = getRedis();
6
- const redisKey = [config.pg?.database, "draftKey"].filter(Boolean).join(":");
7
-
8
- // allow users to view content in draft status if passed as query param
9
- export default async function getDraftKey(nocache = false) {
10
- const cacheKey = await rclient.get(redisKey);
11
- const ttl = await rclient.ttl(redisKey) || 0;
12
-
13
- if (cacheKey && !nocache) {
14
- return { draftKey: cacheKey, ttl: (ttl / 60).toFixed(0) + " minutes" };
15
- }
16
-
17
- const draftKey = randomUUID().replace(/-/g, "").substring(0, 10);
18
-
19
- // refresh every hour
20
- await rclient.set(redisKey, draftKey, "EX", 60 * 60);
21
- return { draftKey };
22
- }
1
+ import { randomUUID } from "node:crypto";
2
+
3
+ import { config, getRedis } from "@opengis/fastify-table/utils.js";
4
+
5
+ const rclient = getRedis();
6
+ const redisKey = [config.pg?.database, "draftKey"].filter(Boolean).join(":");
7
+
8
+ // allow users to view content in draft status if passed as query param
9
+ export default async function getDraftKey(nocache = false) {
10
+ const cacheKey = await rclient.get(redisKey);
11
+ const ttl = await rclient.ttl(redisKey) || 0;
12
+
13
+ if (cacheKey && !nocache) {
14
+ return { draftKey: cacheKey, ttl: (ttl / 60).toFixed(0) + " minutes" };
15
+ }
16
+
17
+ const draftKey = randomUUID().replace(/-/g, "").substring(0, 10);
18
+
19
+ // refresh every hour
20
+ await rclient.set(redisKey, draftKey, "EX", 60 * 60);
21
+ return { draftKey };
22
+ }
@@ -1,31 +1,31 @@
1
- import { createHash } from 'node:crypto';
2
-
3
- import { config, getRedis, pgClients } from '@opengis/fastify-table/utils.js';
4
- import { createMockReply } from './utils/mock.reply.js';
5
-
6
- import searchContent from '../routes/cms/controllers/searchContent.js';
7
-
8
- const pg = pgClients.client;
9
- const rclient = getRedis();
10
-
11
- export default async function getSearchData({ page = 1, limit = 12, ttl = 3600, search, locale, tags, filter, contentType, asc } = {}) {
12
- // check if any crud operations performed, if not - return cached response
13
- const crudInc = await rclient.get(`pg:${config.pg?.database}:site.contents:crud`) || 0;
14
-
15
- const cacheKey = createHash('md5').update([config.pg?.database, 'cms:search', crudInc, page, limit, search, locale, tags, filter, contentType, asc].join(':')).digest('hex');
16
- const cacheData = ttl === 0 ? null : JSON.parse(await rclient.get(cacheKey));
17
-
18
- // return from cache
19
- if (cacheData) {
20
- return { cache: true, ...cacheData };
21
- }
22
-
23
- const mockReply = createMockReply();
24
- const result = await searchContent({ pg, query: { search, locale, page, limit, tags, filter, contentType } }, mockReply);
25
-
26
- if (ttl) {
27
- await rclient.set(cacheKey, JSON.stringify(result), 'EX', ttl);
28
- }
29
-
30
- return result;
31
- }
1
+ import { createHash } from 'node:crypto';
2
+
3
+ import { config, getRedis, pgClients } from '@opengis/fastify-table/utils.js';
4
+ import { createMockReply } from './utils/mock.reply.js';
5
+
6
+ import searchContent from '../routes/cms/controllers/searchContent.js';
7
+
8
+ const pg = pgClients.client;
9
+ const rclient = getRedis();
10
+
11
+ export default async function getSearchData({ page = 1, limit = 12, ttl = 3600, search, locale, tags, filter, contentType, asc } = {}) {
12
+ // check if any crud operations performed, if not - return cached response
13
+ const crudInc = await rclient.get(`pg:${config.pg?.database}:site.contents:crud`) || 0;
14
+
15
+ const cacheKey = createHash('md5').update([config.pg?.database, 'cms:search', crudInc, page, limit, search, locale, tags, filter, contentType, asc].join(':')).digest('hex');
16
+ const cacheData = ttl === 0 ? null : JSON.parse(await rclient.get(cacheKey));
17
+
18
+ // return from cache
19
+ if (cacheData) {
20
+ return { cache: true, ...cacheData };
21
+ }
22
+
23
+ const mockReply = createMockReply();
24
+ const result = await searchContent({ pg, query: { search, locale, page, limit, tags, filter, contentType } }, mockReply);
25
+
26
+ if (ttl) {
27
+ await rclient.set(cacheKey, JSON.stringify(result), 'EX', ttl);
28
+ }
29
+
30
+ return result;
31
+ }
@@ -1,30 +1,30 @@
1
- import { createHash } from 'node:crypto';
2
-
3
- import { config, getRedis, pgClients } from '@opengis/fastify-table/utils.js';
4
- import { createMockReply } from './utils/mock.reply.js';
5
-
6
- import getTagsApi from '../routes/tags/controllers/get.tags.js';
7
-
8
- const pg = pgClients.client;
9
- const rclient = getRedis();
10
-
11
- export default async function getTags({ page = 1, limit = 16, search, ttl = 3600 } = {}) {
12
-
13
- const crudInc = await rclient.get(`pg:site.contents:tags`) || 0;
14
-
15
- const cacheKey = createHash('md5').update([config.pg?.database, 'cms:tags', crudInc, page, limit, search].join(':')).digest('hex');
16
- const cacheData = ttl === 0 ? null : JSON.parse(await rclient.get(cacheKey));
17
-
18
- if (cacheData) {
19
- return { cache: true, ...cacheData };
20
- }
21
-
22
- const mockReply = createMockReply();
23
- const result = await getTagsApi({ pg, query: { page, limit, search } }, mockReply);
24
-
25
- if (ttl) {
26
- await rclient.set(cacheKey, JSON.stringify(result), 'EX', ttl);
27
- }
28
-
29
- return result;
30
- }
1
+ import { createHash } from 'node:crypto';
2
+
3
+ import { config, getRedis, pgClients } from '@opengis/fastify-table/utils.js';
4
+ import { createMockReply } from './utils/mock.reply.js';
5
+
6
+ import getTagsApi from '../routes/tags/controllers/get.tags.js';
7
+
8
+ const pg = pgClients.client;
9
+ const rclient = getRedis();
10
+
11
+ export default async function getTags({ page = 1, limit = 16, search, ttl = 3600 } = {}) {
12
+
13
+ const crudInc = await rclient.get(`pg:site.contents:tags`) || 0;
14
+
15
+ const cacheKey = createHash('md5').update([config.pg?.database, 'cms:tags', crudInc, page, limit, search].join(':')).digest('hex');
16
+ const cacheData = ttl === 0 ? null : JSON.parse(await rclient.get(cacheKey));
17
+
18
+ if (cacheData) {
19
+ return { cache: true, ...cacheData };
20
+ }
21
+
22
+ const mockReply = createMockReply();
23
+ const result = await getTagsApi({ pg, query: { page, limit, search } }, mockReply);
24
+
25
+ if (ttl) {
26
+ await rclient.set(cacheKey, JSON.stringify(result), 'EX', ttl);
27
+ }
28
+
29
+ return result;
30
+ }
@@ -1,27 +1,27 @@
1
- import { unsign } from "@fastify/cookie";
2
-
3
- import { config, getRedis } from "@opengis/fastify-table/utils.js";
4
-
5
- const rclient2 = getRedis({ db: 2 });
6
-
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
9
-
10
- export default async function getUser(cookies) {
11
- const rawCookie = typeof cookies === 'string' ? decodeURIComponent(cookies.match(/(?:^|;\s*)session_auth=([^;]+)/)?.[1]) : cookies?.['session_auth'];
12
-
13
- // unauthorized
14
- if (!rawCookie) {
15
- return null;
16
- }
17
-
18
- const { valid, value: sessionId } = unsign(rawCookie, config.auth?.secret || "61b820e12858570a4b0633020d4394a17903d9a9");
19
-
20
- // invalid cookie
21
- if (!valid) {
22
- return null;
23
- }
24
-
25
- const str = await rclient2.get(`session_auth:${config.pg?.database || 'db'}:${sessionId}`);
26
- return str ? JSON.parse(str)?.passport?.user : null;
27
- }
1
+ import { unsign } from "@fastify/cookie";
2
+
3
+ import { config, getRedis } from "@opengis/fastify-table/utils.js";
4
+
5
+ const rclient2 = getRedis({ db: 2 });
6
+
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
9
+
10
+ export default async function getUser(cookies) {
11
+ const rawCookie = typeof cookies === 'string' ? decodeURIComponent(cookies.match(/(?:^|;\s*)session_auth=([^;]+)/)?.[1]) : cookies?.['session_auth'];
12
+
13
+ // unauthorized
14
+ if (!rawCookie) {
15
+ return null;
16
+ }
17
+
18
+ const { valid, value: sessionId } = unsign(rawCookie, config.auth?.secret || "61b820e12858570a4b0633020d4394a17903d9a9");
19
+
20
+ // invalid cookie
21
+ if (!valid) {
22
+ return null;
23
+ }
24
+
25
+ const str = await rclient2.get(`session_auth:${config.pg?.database || 'db'}:${sessionId}`);
26
+ return str ? JSON.parse(str)?.passport?.user : null;
27
+ }
@@ -1,56 +1,56 @@
1
- /**
2
- * @template T
3
- * @typedef {Object} MockReplyResponse
4
- * @property {number} [status] - HTTP статус-код
5
- * @property {T} [data] - Дані відповіді (якщо передано об'єкт)
6
- * @property {string} [message] - Повідомлення (якщо передано рядок)
7
- */
8
-
9
- /**
10
- * Створює ізольований mock-об'єкт reply для тестування Fastify-хендлерів.
11
- * Імітує методи `status()` та `send()`.
12
- *
13
- * @template T
14
- * @returns {{
15
- * status: (statusCode: number) => any,
16
- * send: (result: T | string) => MockReplyResponse<T>
17
- * }}
18
- */
19
- export function createMockReply() {
20
- /** @type {MockReplyResponse<any>} */
21
-
22
- let response = {};
23
-
24
- return {
25
- /**
26
- * Встановлює HTTP статус-код.
27
- * Повертає той самий reply для чейнінгу.
28
- *
29
- * @param {number} statusCode
30
- * @returns {any}
31
- */
32
- status(statusCode) {
33
- response.status = statusCode;
34
- return this;
35
- },
36
-
37
- /**
38
- * Імітує Fastify reply.send().
39
- * Якщо передано об'єкт — він додається як data.
40
- * Якщо передано рядок — додається як message.
41
- *
42
- * @param {T | string} result
43
- * @returns {MockReplyResponse<T>}
44
- */
45
- send(result) {
46
- response = {
47
- ...response,
48
- ...(typeof result === 'object'
49
- ? { data: result }
50
- : { message: result }),
51
- };
52
-
53
- return response;
54
- },
55
- };
1
+ /**
2
+ * @template T
3
+ * @typedef {Object} MockReplyResponse
4
+ * @property {number} [status] - HTTP статус-код
5
+ * @property {T} [data] - Дані відповіді (якщо передано об'єкт)
6
+ * @property {string} [message] - Повідомлення (якщо передано рядок)
7
+ */
8
+
9
+ /**
10
+ * Створює ізольований mock-об'єкт reply для тестування Fastify-хендлерів.
11
+ * Імітує методи `status()` та `send()`.
12
+ *
13
+ * @template T
14
+ * @returns {{
15
+ * status: (statusCode: number) => any,
16
+ * send: (result: T | string) => MockReplyResponse<T>
17
+ * }}
18
+ */
19
+ export function createMockReply() {
20
+ /** @type {MockReplyResponse<any>} */
21
+
22
+ const response = {};
23
+
24
+ return {
25
+ /**
26
+ * Встановлює HTTP статус-код.
27
+ * Повертає той самий reply для чейнінгу.
28
+ *
29
+ * @param {number} statusCode
30
+ * @returns {any}
31
+ */
32
+ status(statusCode) {
33
+ response.status = statusCode;
34
+ return this;
35
+ },
36
+
37
+ /**
38
+ * Імітує Fastify reply.send().
39
+ * Якщо передано об'єкт — він додається як data.
40
+ * Якщо передано рядок — додається як message.
41
+ *
42
+ * @param {T | string} result
43
+ * @returns {MockReplyResponse<T>}
44
+ */
45
+ send(result) {
46
+
47
+ if (typeof result !== 'object') return { ...response, message: result }
48
+
49
+ return {
50
+ ...response,
51
+ ...result
52
+ };
53
+
54
+ },
55
+ };
56
56
  }
package/server/index.js CHANGED
@@ -1,22 +1,22 @@
1
- import Fastify from 'fastify';
2
-
3
- import appService from './app.js';
4
-
5
- import { config, logger } from '@opengis/fastify-table/utils.js';
6
-
7
- // Instantiate Fastify with some config
8
- const app = Fastify({ loggerInstance: logger, maxParamLength: config.maxParamLength || 500 });
9
-
10
- // Register your application as a normal plugin.
11
-
12
- app.register(appService);
13
-
14
- process.env.PORT = process.env.PORT || config.port || 3000;
15
- // Start listening.
16
- app.listen({ host: '0.0.0.0', port: process.env.PORT }, (err) => {
17
- if (err) {
18
- console.error(err.toString());
19
- logger.error(err);
20
- process.exit(1);
21
- }
22
- });
1
+ import Fastify from 'fastify';
2
+
3
+ import appService from './app.js';
4
+
5
+ import { config, logger } from '@opengis/fastify-table/utils.js';
6
+
7
+ // Instantiate Fastify with some config
8
+ const app = Fastify({ loggerInstance: logger, maxParamLength: config.maxParamLength || 500 });
9
+
10
+ // Register your application as a normal plugin.
11
+
12
+ app.register(appService);
13
+
14
+ process.env.PORT = process.env.PORT || config.port || 3000;
15
+ // Start listening.
16
+ app.listen({ host: '0.0.0.0', port: process.env.PORT }, (err) => {
17
+ if (err) {
18
+ console.error(err.toString());
19
+ logger.error(err);
20
+ process.exit(1);
21
+ }
22
+ });
@@ -1,130 +1,130 @@
1
- create schema if not exists site;
2
-
3
- ALTER TABLE if exists site.spaces add column if not exists locales text[];
4
- ALTER TABLE IF exists site.spaces add column if not exists default_locale text;
5
- ALTER TABLE if exists site.spaces alter column default_locale set default 'ua';
6
- update site.spaces set default_locale = 'ua' where default_locale is null;
7
- ALTER TABLE if exists site.spaces alter column default_locale set not null;
8
-
9
- ALTER TABLE if exists site.media ADD COLUMN IF NOT EXISTS subdir TEXT;
10
- COMMENT ON COLUMN site.media.subdir is 'Піддиректорія';
11
-
12
- -- deprecated tables
13
- -- drop table if exists site.articles cascade;
14
- drop table if exists site.article_media cascade;
15
- drop table if exists site.content_attributes cascade;
16
- drop table if exists site.article_translations cascade;
17
- drop table if exists site.menu_items cascade;
18
-
19
- -- redundant columns / constraints
20
- ALTER TABLE if exists site.content_types DROP CONSTRAINT if exists content_types_slug_key;
21
- ALTER TABLE if exists site.content_types drop column if exists slug;
22
- ALTER TABLE if exists site.content_types drop column if exists display_name;
23
- ALTER TABLE if exists site.contents drop column if exists fields;
24
-
25
- DROP FUNCTION if exists site.getmenu(text);
26
-
27
- -- seamless migration start
28
- /*
29
- insert into site.contents(content_id, space_id, content_type_id, slug)
30
- select content_type_id, 'default', content_type_id, min(type_name) from site.single_type_values a
31
- left join lateral (select content_type_id from site.content_types b where a.type_name=b.name limit 1)b on 1=1
32
- where content_type_id not in (select content_id from site.contents) and content_type_id is not null
33
- group by content_type_id;
34
- insert into site.content_data(field_id, content_id, object_id, field_key, field_type, field_value)
35
- select distinct single_type_value_id, content_type_id, type_name, key,
36
- coalesce(value_type,case when substring(value from 1 for 1) = '[' then 'datalist' else 'text' end), value from site.single_type_values a
37
- left join lateral (select content_type_id from site.content_types b where a.type_name=b.name limit 1)b on 1=1
38
- where single_type_value_id not in (select field_id from site.content_data) and content_type_id is not null
39
- and case when key = 'slug' then value not in ( select field_value from site.content_data where field_key='slug') else true end;
40
- -- drop table if exists site.single_type_values cascade;
41
- */
42
- -- seamless migration finish
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
-
49
- --- insert default content types start
50
- insert into site.content_types(content_type_id,name,title,type,columns,template,uid)
51
- values('pages','pages','Сторінки','collection',
52
- '[{"name":"slug","label":"Slug","type":"slug","parent":"title","required":true},{"name":"title","label":"Title","type":"text","required":true},{"name":"status","label":"Status","type":"select","options":[{"id":"draft","text":"Draft"},{"id":"published","text":"Published"},{"id":"archived","text":"Archived"},{"id":"delayPublished","text":"Delay Published"}],"required":true},{"name":"published_at","label":"Publish at","type":"datetime","required":true}]'::json
53
- ,'','1') on conflict(content_type_id) do update set columns=excluded.columns, type = excluded.type;
54
- insert into site.contents(content_id,content_type_id,space_id,template,uid)
55
- values('pages','pages','default','','1') on conflict(content_id) do nothing;
56
- --- insert default content types finish
57
-
58
- alter table site.contents add column if not exists meta json;
59
- alter table site.contents add column if not exists main_image text;
60
- /*
61
- ALTER TABLE if exists site.contents drop column if exists publish_at;
62
- ALTER TABLE if exists site.contents add column if not exists published_at timestamp without time zone;
63
- update site.contents set published_at=now() where published_at is null;
64
- ALTER TABLE if exists site.contents alter column published_at set not null;
65
- ALTER TABLE if exists site.contents alter column published_at set default now();
66
- */
67
-
68
- alter table site.content_data add column if not exists created_by text;
69
- alter table site.content_data add column if not exists updated_by text;
70
- alter table site.content_data add column if not exists field_value_object json;
71
-
72
- --- seamless migration for content_data start
73
- update site.content_data
74
- set field_value_object=field_value::json
75
- where field_value_object is null
76
- and field_value is not null
77
- and field_type in ('reference-list', 'reference', 'datalist', 'filelist', 'array');
78
- --- seamless migration for content_data finish
79
-
80
-
81
- -- delete accidental dupes
82
- delete from site.content_data where object_id in ( select min(object_id) from site.content_data where field_key= 'slug' group by field_value having count(*) > 1 );
83
-
84
- alter table site.content_types ADD COLUMN if not exists preview_path text;
85
-
86
- -- get rid of naming inconsistency
87
- update site.content_types
88
- set columns=replace(columns::text,'publish_at', 'published_at')::json
89
- where columns::text like '%publish_at%';
90
-
91
- ALTER TABLE site.contents DROP CONSTRAINT if exists contents_status_check;
92
- -- select * from site.contents where not status = ANY (ARRAY['draft'::text, 'published'::text, 'archived'::text, 'delayPublished'::text])
93
- ALTER TABLE site.contents ADD CONSTRAINT contents_status_check CHECK (status = ANY (ARRAY['draft'::text, 'published'::text, 'archived'::text, 'delayPublished'::text]));
94
-
95
- UPDATE site.content_types
96
- SET columns = (
97
- SELECT jsonb_agg(elem)
98
- FROM jsonb_array_elements(columns::jsonb) elem
99
- WHERE elem->>'name' <> 'status'
100
- )
101
- WHERE columns IS NOT NULL;
102
-
103
-
104
- UPDATE site.content_types
105
- SET columns = columns::jsonb || '{"name": "status", "type": "select", "label": "Status", "options": [{"id": "draft", "text": "Draft"}, {"id": "published", "text": "Published"}, {"id": "archived", "text": "Archived"}, {"id": "delayPublished", "text": "Delay Published"}], "required": true}
106
- '::jsonb
107
- WHERE columns is not null;
108
-
109
- -- remove dupes, make slug unique
110
- update site.content_data set content_id='pages' where content_id<>'pages' and content_id in (
111
- select content_id from site.contents where content_id<>'pages' and slug='pages'
112
- );
113
-
114
- delete from site.contents where content_id<>'pages' and slug='pages';
115
-
116
- delete from site.contents a
117
- where slug in (select slug from site.contents group by slug having count(*) > 1)
118
- and (select count(*) from site.content_data where content_id=a.content_id) = 0;
119
-
120
- alter table site.contents drop constraint if exists site_contents_slug_unique;
121
- alter table site.contents add constraint site_contents_slug_unique UNIQUE (slug);
122
-
123
- alter table site.contents add column if not exists space_id text;
124
- alter table site.contents alter column space_id drop not null;
125
- update site.spaces set locales='{ua,en,de}'::text[] where space_id='default';
126
-
127
- alter table site.content_data drop constraint if exists content_data_content_id_fkey;
128
- alter table site.content_data add constraint content_data_content_id_fkey foreign key (content_id) references site.contents(content_id) on delete cascade;
129
-
1
+ create schema if not exists site;
2
+
3
+ ALTER TABLE if exists site.spaces add column if not exists locales text[];
4
+ ALTER TABLE IF exists site.spaces add column if not exists default_locale text;
5
+ ALTER TABLE if exists site.spaces alter column default_locale set default 'ua';
6
+ update site.spaces set default_locale = 'ua' where default_locale is null;
7
+ ALTER TABLE if exists site.spaces alter column default_locale set not null;
8
+
9
+ ALTER TABLE if exists site.media ADD COLUMN IF NOT EXISTS subdir TEXT;
10
+ COMMENT ON COLUMN site.media.subdir is 'Піддиректорія';
11
+
12
+ -- deprecated tables
13
+ -- drop table if exists site.articles cascade;
14
+ drop table if exists site.article_media cascade;
15
+ drop table if exists site.content_attributes cascade;
16
+ drop table if exists site.article_translations cascade;
17
+ drop table if exists site.menu_items cascade;
18
+
19
+ -- redundant columns / constraints
20
+ ALTER TABLE if exists site.content_types DROP CONSTRAINT if exists content_types_slug_key;
21
+ ALTER TABLE if exists site.content_types drop column if exists slug;
22
+ ALTER TABLE if exists site.content_types drop column if exists display_name;
23
+ ALTER TABLE if exists site.contents drop column if exists fields;
24
+
25
+ DROP FUNCTION if exists site.getmenu(text);
26
+
27
+ -- seamless migration start
28
+ /*
29
+ insert into site.contents(content_id, space_id, content_type_id, slug)
30
+ select content_type_id, 'default', content_type_id, min(type_name) from site.single_type_values a
31
+ left join lateral (select content_type_id from site.content_types b where a.type_name=b.name limit 1)b on 1=1
32
+ where content_type_id not in (select content_id from site.contents) and content_type_id is not null
33
+ group by content_type_id;
34
+ insert into site.content_data(field_id, content_id, object_id, field_key, field_type, field_value)
35
+ select distinct single_type_value_id, content_type_id, type_name, key,
36
+ coalesce(value_type,case when substring(value from 1 for 1) = '[' then 'datalist' else 'text' end), value from site.single_type_values a
37
+ left join lateral (select content_type_id from site.content_types b where a.type_name=b.name limit 1)b on 1=1
38
+ where single_type_value_id not in (select field_id from site.content_data) and content_type_id is not null
39
+ and case when key = 'slug' then value not in ( select field_value from site.content_data where field_key='slug') else true end;
40
+ -- drop table if exists site.single_type_values cascade;
41
+ */
42
+ -- seamless migration finish
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
+
49
+ --- insert default content types start
50
+ insert into site.content_types(content_type_id,name,title,type,columns,template,uid)
51
+ values('pages','pages','Сторінки','collection',
52
+ '[{"name":"slug","label":"Slug","type":"slug","parent":"title","required":true},{"name":"title","label":"Title","type":"text","required":true},{"name":"status","label":"Status","type":"select","options":[{"id":"draft","text":"Draft"},{"id":"published","text":"Published"},{"id":"archived","text":"Archived"},{"id":"delayPublished","text":"Delay Published"}],"required":true},{"name":"published_at","label":"Publish at","type":"datetime","required":true}]'::json
53
+ ,'','1') on conflict(content_type_id) do update set columns=excluded.columns, type = excluded.type;
54
+ insert into site.contents(content_id,content_type_id,space_id,template,uid)
55
+ values('pages','pages','default','','1') on conflict(content_id) do nothing;
56
+ --- insert default content types finish
57
+
58
+ alter table site.contents add column if not exists meta json;
59
+ alter table site.contents add column if not exists main_image text;
60
+ /*
61
+ ALTER TABLE if exists site.contents drop column if exists publish_at;
62
+ ALTER TABLE if exists site.contents add column if not exists published_at timestamp without time zone;
63
+ update site.contents set published_at=now() where published_at is null;
64
+ ALTER TABLE if exists site.contents alter column published_at set not null;
65
+ ALTER TABLE if exists site.contents alter column published_at set default now();
66
+ */
67
+
68
+ alter table site.content_data add column if not exists created_by text;
69
+ alter table site.content_data add column if not exists updated_by text;
70
+ alter table site.content_data add column if not exists field_value_object json;
71
+
72
+ --- seamless migration for content_data start
73
+ update site.content_data
74
+ set field_value_object=field_value::json
75
+ where field_value_object is null
76
+ and field_value is not null
77
+ and field_type in ('reference-list', 'reference', 'datalist', 'filelist', 'array');
78
+ --- seamless migration for content_data finish
79
+
80
+
81
+ -- delete accidental dupes
82
+ delete from site.content_data where object_id in ( select min(object_id) from site.content_data where field_key= 'slug' group by field_value having count(*) > 1 );
83
+
84
+ alter table site.content_types ADD COLUMN if not exists preview_path text;
85
+
86
+ -- get rid of naming inconsistency
87
+ update site.content_types
88
+ set columns=replace(columns::text,'publish_at', 'published_at')::json
89
+ where columns::text like '%publish_at%';
90
+
91
+ ALTER TABLE site.contents DROP CONSTRAINT if exists contents_status_check;
92
+ -- select * from site.contents where not status = ANY (ARRAY['draft'::text, 'published'::text, 'archived'::text, 'delayPublished'::text])
93
+ ALTER TABLE site.contents ADD CONSTRAINT contents_status_check CHECK (status = ANY (ARRAY['draft'::text, 'published'::text, 'archived'::text, 'delayPublished'::text]));
94
+
95
+ UPDATE site.content_types
96
+ SET columns = (
97
+ SELECT jsonb_agg(elem)
98
+ FROM jsonb_array_elements(columns::jsonb) elem
99
+ WHERE elem->>'name' <> 'status'
100
+ )
101
+ WHERE columns IS NOT NULL;
102
+
103
+
104
+ UPDATE site.content_types
105
+ SET columns = columns::jsonb || '{"name": "status", "type": "select", "label": "Status", "options": [{"id": "draft", "text": "Draft"}, {"id": "published", "text": "Published"}, {"id": "archived", "text": "Archived"}, {"id": "delayPublished", "text": "Delay Published"}], "required": true}
106
+ '::jsonb
107
+ WHERE columns is not null;
108
+
109
+ -- remove dupes, make slug unique
110
+ update site.content_data set content_id='pages' where content_id<>'pages' and content_id in (
111
+ select content_id from site.contents where content_id<>'pages' and slug='pages'
112
+ );
113
+
114
+ delete from site.contents where content_id<>'pages' and slug='pages';
115
+
116
+ delete from site.contents a
117
+ where slug in (select slug from site.contents group by slug having count(*) > 1)
118
+ and (select count(*) from site.content_data where content_id=a.content_id) = 0;
119
+
120
+ alter table site.contents drop constraint if exists site_contents_slug_unique;
121
+ alter table site.contents add constraint site_contents_slug_unique UNIQUE (slug);
122
+
123
+ alter table site.contents add column if not exists space_id text;
124
+ alter table site.contents alter column space_id drop not null;
125
+ update site.spaces set locales='{ua,en,de}'::text[] where space_id='default';
126
+
127
+ alter table site.content_data drop constraint if exists content_data_content_id_fkey;
128
+ alter table site.content_data add constraint content_data_content_id_fkey foreign key (content_id) references site.contents(content_id) on delete cascade;
129
+
130
130
  alter table site.tags add column if not exists locale jsonb;