@opengis/cms 0.0.26 → 0.0.28
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/README.md +98 -98
- package/dist/index-W-qQIppj-DunG40EG.js +2452 -0
- package/dist/index.html +28 -28
- package/dist/index.js +12683 -6702
- package/dist/index.umd.cjs +87 -41
- package/dist/style.css +1 -0
- package/package.json +68 -68
- package/plugin.js +76 -76
- package/server/app.js +35 -35
- package/server/config.js +4 -4
- package/server/functions/getDraftKey.js +22 -22
- package/server/index.js +22 -22
- package/server/migrations/fixes.sql +123 -123
- package/server/migrations/site.sql +545 -545
- package/server/plugins/adminHook.js +78 -78
- package/server/plugins/hook.js +59 -59
- package/server/plugins/vite.js +84 -84
- package/server/routes/category/controllers/cms.category.delete.js +21 -21
- package/server/routes/category/controllers/cms.category.get.js +17 -17
- package/server/routes/category/controllers/cms.category.list.js +16 -16
- package/server/routes/category/controllers/cms.category.post.js +21 -21
- package/server/routes/category/controllers/cms.category.put.js +23 -23
- package/server/routes/category/index.mjs +22 -22
- package/server/routes/cms/controllers/cmsStat.js +55 -55
- package/server/routes/cms/controllers/cmsSuggest.js +57 -57
- package/server/routes/cms/controllers/deleteContent.js +114 -114
- package/server/routes/cms/controllers/deleteMedia.js +75 -75
- package/server/routes/cms/controllers/downloadMedia.js +48 -48
- package/server/routes/cms/controllers/getContent.js +110 -110
- package/server/routes/cms/controllers/getContentBySlug.js +95 -95
- package/server/routes/cms/controllers/getPermissions.js +15 -15
- package/server/routes/cms/controllers/insertContent.js +218 -218
- package/server/routes/cms/controllers/listMedia.js +93 -93
- package/server/routes/cms/controllers/metadataMedia.js +38 -38
- package/server/routes/cms/controllers/properties.get.js +53 -53
- package/server/routes/cms/controllers/properties.post.js +99 -99
- package/server/routes/cms/controllers/searchContent.js +205 -205
- package/server/routes/cms/controllers/setPermissions.js +49 -49
- package/server/routes/cms/controllers/translate.js +89 -89
- package/server/routes/cms/controllers/updateContent.js +238 -238
- package/server/routes/cms/controllers/uploadMedia.js +78 -78
- package/server/routes/cms/index.mjs +114 -114
- package/server/routes/cms/utils/additionalData.js +35 -35
- package/server/routes/cms/utils/getCollection.js +81 -81
- package/server/routes/cms/utils/getSingle.js +187 -187
- package/server/routes/cms/utils/insertContentLocalization.js +86 -86
- package/server/routes/cms/utils/requestTranslation.js +85 -85
- package/server/routes/cms/utils/updateLocalization.js +47 -47
- package/server/routes/cmsSpace/controllers/deleteSpace.js +25 -25
- package/server/routes/cmsSpace/controllers/getSpaces.js +27 -27
- package/server/routes/cmsSpace/controllers/insertSpace.js +21 -21
- package/server/routes/cmsSpace/controllers/updateSpace.js +23 -23
- package/server/routes/cmsSpace/index.mjs +20 -20
- package/server/routes/contentType/controllers/addContentType.js +162 -162
- package/server/routes/contentType/controllers/contentTypeList.js +54 -54
- package/server/routes/contentType/controllers/delContentType.js +75 -75
- package/server/routes/contentType/controllers/editContentType.js +61 -61
- package/server/routes/contentType/controllers/getContentType.js +37 -37
- package/server/routes/contentType/index.mjs +35 -35
- package/server/routes/contentType/utils/updateContents.js +28 -28
- package/server/routes/contentType/utils/updateCustomContentTable.js +55 -55
- package/server/routes/feedback/controllers/email.list.js +24 -24
- package/server/routes/feedback/controllers/feedback.js +48 -48
- package/server/routes/feedback/controllers/feedback.list.js +37 -37
- package/server/routes/feedback/controllers/news.subscriptions.js +44 -44
- package/server/routes/feedback/index.mjs +71 -71
- package/server/routes/logs/controllers/export.user.logs.js +77 -77
- package/server/routes/logs/controllers/user.logs.js +44 -44
- package/server/routes/logs/index.mjs +9 -9
- package/server/routes/menu/controllers/addMenu.js +37 -37
- package/server/routes/menu/controllers/delMenu.js +31 -31
- package/server/routes/menu/controllers/editMenu.js +41 -41
- package/server/routes/menu/controllers/getMenu.js +42 -42
- package/server/routes/menu/index.mjs +13 -13
- package/server/routes/migration/controllers/collectionToCustom.js +137 -137
- package/server/routes/migration/index.mjs +8 -8
- package/server/routes/root.mjs +8 -8
- package/server/routes/tags/controllers/add.tags.js +24 -24
- package/server/routes/tags/controllers/del.tags.js +19 -19
- package/server/routes/tags/controllers/edit.tags.js +25 -25
- package/server/routes/tags/controllers/get.tags.js +15 -15
- package/server/routes/tags/index.mjs +14 -14
- package/server/templates/cls/cms.category_type.json +9 -9
- package/server/templates/cls/cms.content_review_status.json +9 -9
- package/server/templates/cls/cms.content_status.json +9 -9
- package/server/templates/cls/cms.content_type.json +9 -9
- package/server/templates/cls/cms.lang.json +9 -9
- package/server/templates/page/login.html +126 -126
- package/server/templates/select/core.user_mentioned.sql +1 -1
- package/dist/index-W-qQIppj-DRzFSjU1.js +0 -2452
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.ui-dialog__wrapper[data-v-6d0970a6]{position:relative}.ui-dialog__modal[data-v-6d0970a6]{margin:10px;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);min-height:0;height:-moz-fit-content;height:fit-content;max-height:80vh;overflow:hidden}.ui-dialog__content[data-v-6d0970a6]{min-height:0;height:100%;overflow:auto}.ui-dialog__content[data-v-6d0970a6]::-webkit-scrollbar{width:6px;height:6px;background-color:#f5f5f5}.ui-dialog__content[data-v-6d0970a6]::-webkit-scrollbar-thumb{border-radius:10px;background-color:#d9d9d9bf}.ui-dialog__content[data-v-6d0970a6]::-webkit-scrollbar-track{background-color:#f5f5f5}@media (max-width: 650px){.ui-dialog__modal[data-v-6d0970a6]{top:50%}}.fade-enter-active[data-v-6d0970a6],.fade-leave-active[data-v-6d0970a6]{transition:opacity .2s}.fade-enter-from[data-v-6d0970a6],.fade-leave-to[data-v-6d0970a6]{opacity:0}.content-enter-active[data-v-6d0970a6],.content-leave-active[data-v-6d0970a6]{transition:transform .4s}.content-enter-from[data-v-6d0970a6],.content-leave-to[data-v-6d0970a6]{transform:translate(-50%,-50%) scale(.95)}.col-error .vs-form-text input[data-v-749b581f]{border:1px solid red}.vs-form-text[data-v-749b581f]{position:relative}.vs-form-text__input[data-v-749b581f]::-moz-placeholder{opacity:.5}.vs-form-text__input[data-v-749b581f]::placeholder{opacity:.5}.fade-enter-active,.fade-leave-active{transition:opacity .3s}.fade-enter-from,.fade-leave-to{opacity:0}.heading-level-1[data-v-ef7c378e]{font-weight:700;font-size:30px}.heading-level-2[data-v-ef7c378e]{font-weight:700;font-size:26px}.heading-level-3[data-v-ef7c378e]{font-weight:700;font-size:22px}.heading-level-4[data-v-ef7c378e]{font-weight:700;font-size:18px}.heading-level-5[data-v-ef7c378e]{font-weight:500;font-size:16px}.heading-level-6[data-v-ef7c378e]{font-weight:400;font-size:14px}.flex>button[data-v-b5a7cc5a]:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.flex>button[data-v-b5a7cc5a]:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.flex:hover button[data-v-b5a7cc5a]:first-child{border-right-color:transparent}code[data-v-72ce3024]{font-family:Courier New,monospace;font-size:11px}.vs-editor-html-mode[data-v-99a48167]{display:flex;align-items:center;gap:4px;padding:6px 8px;border:1px solid #d1d5db;border-radius:4px;background-color:#fff;color:#374151;font-size:12px;font-weight:500;cursor:pointer;transition:all .2s ease;min-width:60px;justify-content:center}.vs-editor-html-mode[data-v-99a48167]:hover{background-color:#f3f4f6;border-color:#9ca3af}.vs-editor-html-mode.is-active[data-v-99a48167]{background-color:#3b82f6;border-color:#3b82f6;color:#fff}.vs-editor-html-mode.is-active[data-v-99a48167]:hover{background-color:#2563eb;border-color:#2563eb}.vs-editor-html-mode__text[data-v-99a48167]{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.vs-editor-html-mode svg[data-v-99a48167]{flex-shrink:0}.monaco-editor-container[data-v-b1d773a1]{position:relative;width:100%;height:100%;border-radius:4px;border:1px solid #e5e7eb;overflow:visible}.monaco-editor-container[data-v-b1d773a1]:focus-within{border-color:#3b82f6;box-shadow:0 0 0 2px #3b82f61a}.dark .monaco-editor-container[data-v-b1d773a1]{border-color:#374151}.dark .monaco-editor-container[data-v-b1d773a1]:focus-within{border-color:#3b82f6;box-shadow:0 0 0 2px #3b82f61a}.monaco-editor-container .monaco-editor[data-v-b1d773a1]{position:relative!important;width:100%!important;height:100%!important}.monaco-editor-container .monaco-editor .view-lines[data-v-b1d773a1],.monaco-editor-container .monaco-editor .view-overlays[data-v-b1d773a1],.monaco-editor-container .monaco-editor .margin[data-v-b1d773a1]{position:relative}.monaco-editor .html-tag[data-v-b1d773a1]{color:#4fc1ff!important;font-weight:700}.monaco-editor .html-attribute[data-v-b1d773a1]{color:#9cdcfe!important}.monaco-editor .html-attribute-value[data-v-b1d773a1]{color:#ff6b6b!important}.monaco-editor .html-comment[data-v-b1d773a1]{color:#6a9955!important;font-style:italic}.monaco-editor .html-string[data-v-b1d773a1]{color:#ff6b6b!important}.monaco-editor .html-keyword[data-v-b1d773a1]{color:#4fc1ff!important;font-weight:700}.monaco-editor.vs .html-tag[data-v-b1d773a1]{color:#06c!important;font-weight:700}.monaco-editor.vs .html-attribute[data-v-b1d773a1]{color:#00f!important}.monaco-editor.vs .html-attribute-value[data-v-b1d773a1]{color:#c00!important}.monaco-editor.vs .html-comment[data-v-b1d773a1]{color:green!important;font-style:italic}.monaco-editor.vs .html-string[data-v-b1d773a1]{color:#c00!important}.monaco-editor.vs .html-keyword[data-v-b1d773a1]{color:#06c!important;font-weight:700}.monaco-editor .token.tag[data-v-b1d773a1]{color:#4fc1ff!important;font-weight:700}.monaco-editor .token.attribute.name[data-v-b1d773a1]{color:#9cdcfe!important}.monaco-editor .token.attribute.value[data-v-b1d773a1],.monaco-editor .token.string[data-v-b1d773a1]{color:#ff6b6b!important}.monaco-editor .token.comment[data-v-b1d773a1]{color:#6a9955!important;font-style:italic}.monaco-editor.vs .token.tag[data-v-b1d773a1]{color:#06c!important;font-weight:700}.monaco-editor.vs .token.attribute.name[data-v-b1d773a1]{color:#00f!important}.monaco-editor.vs .token.attribute.value[data-v-b1d773a1],.monaco-editor.vs .token.string[data-v-b1d773a1]{color:#c00!important}.monaco-editor.vs .token.comment[data-v-b1d773a1]{color:green!important;font-style:italic}.editor-content{min-height:160px;width:100%;overflow:auto;max-height:500px;position:relative}.fixed .editor-content{max-height:none;height:calc(100vh - 60px)}.html-source-editor{width:100%;height:100%;overflow:auto;max-height:500px}.editor-content ul{margin-left:20px}.editor-content ul>li{list-style:disc}.editor-content ol{list-style-type:decimal;margin-left:20px}.editor-content pre{background-color:#e7e7e7;border-radius:4px;padding:0 4px}.editor-content a{color:#00f;text-decoration:underline}.editor-content table{width:100%;table-layout:fixed;border-collapse:collapse;text-align:left;margin:20px 0;font-family:Arial,sans-serif;font-size:14px;position:relative}.editor-content thead{position:sticky;top:0;z-index:10}.editor-content th,.editor-content td{border:1px solid #ccc;padding:10px;position:relative}.editor-content th{background-color:#f4f4f4;font-weight:700;position:sticky;top:0;z-index:10}.editor-content tr:nth-child(2n){background-color:#f9f9f9}.editor-content tr:nth-child(odd){background-color:#fff}.editor-content .editor-image{display:inline-block;vertical-align:middle;margin:0;border:2px solid transparent;border-radius:4px;transition:border-color .2s ease}.editor-content .editor-image[width][height]{max-width:none!important;max-height:none!important;min-width:auto!important;min-height:auto!important;-o-object-fit:fill!important;object-fit:fill!important}.editor-content .editor-image[style*=width]{max-width:none!important}.editor-content .editor-image[style*=height]{max-height:none!important}.editor-content .editor-image[style*=width][style*=height]{max-width:none!important;max-height:none!important}.editor-content .editor-image[width]:not([height]){height:auto}.editor-content .editor-image[height]:not([width]){width:auto}.editor-content .editor-image:not([width]):not([height]):not([style*=width]):not([style*=height]){height:auto;width:auto;max-width:100%}.editor-content .editor-image.ProseMirror-selectednode,.editor-content .ProseMirror-selectednode.editor-image{border:2px solid #3b82f6;box-shadow:0 0 0 2px #3b82f633}.editor-content p:has(.editor-image){display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px;line-height:1.5}.editor-content p:has(.editor-image)[style*="text-align: center"],.editor-content p:has(.editor-image)[style*="text-align:center"]{justify-content:center}.editor-content p:has(.editor-image)[style*="text-align: right"],.editor-content p:has(.editor-image)[style*="text-align:right"]{justify-content:flex-end}.editor-content p:has(.editor-image)[style*="text-align: left"],.editor-content p:has(.editor-image)[style*="text-align:left"]{justify-content:flex-start}.editor-content p:has(.editor-image)[style*="text-align: justify"],.editor-content p:has(.editor-image)[style*="text-align:justify"]{justify-content:space-between}.editor-content p:has(.editor-image):not(:has(text)){margin:8px 0}.editor-content p .editor-image{flex-shrink:0;max-width:calc(50% - 4px);-o-object-fit:contain;object-fit:contain}.editor-content p .editor-image:only-child{max-width:100%}.editor-content p .editor-image:nth-child(1):nth-last-child(2),.editor-content p .editor-image:nth-child(2):nth-last-child(1){max-width:calc(50% - 4px)}.editor-content p .editor-image:nth-child(1):nth-last-child(3),.editor-content p .editor-image:nth-child(2):nth-last-child(2),.editor-content p .editor-image:nth-child(3):nth-last-child(1){max-width:calc(33.333% - 6px)}.editor-content p .editor-image:nth-child(n+4){max-width:calc(33.333% - 6px)}.ProseMirror-focused{outline:none}.editor-toolbar{background-color:#f9fafb}.editor-page-content{min-height:160px;width:100%;overflow:auto;position:relative}.fixed .editor-page-content{max-height:none;height:calc(100vh - 117px)}.html-source-editor{width:100%;height:100%;overflow:auto}.fixed .html-source-editor{height:calc(100vh - 60px);max-height:none}button{transition:background-color .2s ease;outline:none}button:focus{outline:none}.editor-page-content ul{margin-left:20px}.editor-page-content ul>li{list-style:disc}.editor-page-content ol{list-style-type:decimal;margin-left:20px}.editor-page-content pre{background-color:#e7e7e7;border-radius:4px;padding:0 4px}.editor-code{background-color:#f1f1f1;border-radius:3px;padding:2px 4px;font-family:Courier New,monospace;font-size:.9em}.editor-codeblock{background-color:#f8f8f8;border:1px solid #e1e1e1;border-radius:4px;padding:12px;margin:8px 0;font-family:Courier New,monospace;overflow-x:auto}.editor-page-content a{color:#00f;text-decoration:underline}.editor-page-content table{width:100%;table-layout:fixed;border-collapse:collapse;text-align:left;margin:20px 0;font-family:Arial,sans-serif;font-size:14px;position:relative}.editor-page-content thead{position:sticky;top:0;z-index:10}.editor-page-content th,.editor-page-content td{border:1px solid #ccc;padding:10px;position:relative}.editor-page-content th{background-color:#f4f4f4;font-weight:700;position:sticky;top:0;z-index:10}.editor-page-content tr:nth-child(2n){background-color:#f9f9f9}.editor-page-content tr:nth-child(odd){background-color:#fff}.selectedCell{background:#f0eeed}.column-resize-handle{background-color:#1d4ed8;bottom:-2px;pointer-events:none;position:absolute;right:-2px;top:0;width:4px}.resize-cursor{cursor:ew-resize;cursor:col-resize}.editor-link{color:#00f}.editor-link:hover{text-decoration:underline}blockquote{font-style:italic;quotes:"«" "»";text-indent:16px}blockquote>p{display:inline}blockquote:before{content:open-quote;display:inline;font-size:18px;margin-right:2px}blockquote:after{content:close-quote;font-size:18px;display:inline;margin-left:2px}.html-source-editor{width:100%;height:100%}.col-error .vs-number__input{border:1px solid red}.vs-number__input::-moz-placeholder{opacity:.5}.vs-number__input::placeholder{opacity:.5}
|
package/package.json
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@opengis/cms",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "cms",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"author": "Softpro",
|
|
7
|
-
"main": "dist/cms.js",
|
|
8
|
-
"license": "EULA",
|
|
9
|
-
"files": [
|
|
10
|
-
"dist",
|
|
11
|
-
"server",
|
|
12
|
-
"plugin.js"
|
|
13
|
-
],
|
|
14
|
-
"scripts": {
|
|
15
|
-
"test": "node --test test/**/*.test.js",
|
|
16
|
-
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
|
17
|
-
"build": "vite build",
|
|
18
|
-
"build:lib": "LIB=true vite build",
|
|
19
|
-
"proxy": "vite dev",
|
|
20
|
-
"build-npm": "vite build",
|
|
21
|
-
"start": "bun --env-file=.env.ip server",
|
|
22
|
-
"prod-ip1": "node server --config=ip ",
|
|
23
|
-
"prod-softpro1": "node server --config=softpro",
|
|
24
|
-
"prod": "NODE_ENV=production bun --env-file=.env.ip server ",
|
|
25
|
-
"prod-ip": "PORT=3019 node server --config=ip",
|
|
26
|
-
"prod-ip-test": "PORT=3025 node server --config=ip",
|
|
27
|
-
"dev": "node server --config=softpro",
|
|
28
|
-
"debug": "bun --watch server --config=softpro",
|
|
29
|
-
"ip-test": "node server --config=ip-test",
|
|
30
|
-
"ip": "node --env-file=.env.ip server",
|
|
31
|
-
"demo": "node --env-file=.env.demo --env-file=.env server",
|
|
32
|
-
"i18n:sync": "node i18n-sync.cjs",
|
|
33
|
-
"prepublishOnly": "bun build:lib",
|
|
34
|
-
"softpro": "bun --env-file=.env.softpro server"
|
|
35
|
-
},
|
|
36
|
-
"dependencies": {
|
|
37
|
-
"@fastify/compress": "^8.1.0",
|
|
38
|
-
"@opengis/core": "^0.0.30",
|
|
39
|
-
"@opengis/fastify-table": "^2.0.118",
|
|
40
|
-
"@opengis/filter": "^0.1.10",
|
|
41
|
-
"@opengis/form": "^0.0.70",
|
|
42
|
-
"@opengis/richtext": "0.0.38",
|
|
43
|
-
"@vueuse/head": "2.0.0",
|
|
44
|
-
"js-yaml": "^4.1.0",
|
|
45
|
-
"lucide-vue-next": "0.344.0",
|
|
46
|
-
"vite": "5.1.4",
|
|
47
|
-
"vue": "^3.5.17",
|
|
48
|
-
"vue-i18n": "11.1.5",
|
|
49
|
-
"vue-router": "4.4.3",
|
|
50
|
-
"vuedraggable": "4.1.0"
|
|
51
|
-
},
|
|
52
|
-
"resolutions": {
|
|
53
|
-
"rollup": "4.30.0"
|
|
54
|
-
},
|
|
55
|
-
"devDependencies": {
|
|
56
|
-
"@tailwindcss/typography": "0.5.10",
|
|
57
|
-
"@tsconfig/node22": "^22.0.2",
|
|
58
|
-
"@vitejs/plugin-vue": "5.0.4",
|
|
59
|
-
"autoprefixer": "10.4.18",
|
|
60
|
-
"eslint": "8.49.0",
|
|
61
|
-
"postcss": "8.4.35",
|
|
62
|
-
"sass": "^1.92.1",
|
|
63
|
-
"tailwindcss": "3.4.1",
|
|
64
|
-
"typescript": "~5.8.0",
|
|
65
|
-
"vitest": "3.2.4",
|
|
66
|
-
"vue-tsc": "^2.2.10"
|
|
67
|
-
}
|
|
68
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@opengis/cms",
|
|
3
|
+
"version": "0.0.28",
|
|
4
|
+
"description": "cms",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": "Softpro",
|
|
7
|
+
"main": "dist/cms.js",
|
|
8
|
+
"license": "EULA",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"server",
|
|
12
|
+
"plugin.js"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"test": "node --test test/**/*.test.js",
|
|
16
|
+
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
|
17
|
+
"build": "vite build",
|
|
18
|
+
"build:lib": "LIB=true vite build",
|
|
19
|
+
"proxy": "vite dev",
|
|
20
|
+
"build-npm": "vite build",
|
|
21
|
+
"start": "bun --env-file=.env.ip server",
|
|
22
|
+
"prod-ip1": "node server --config=ip ",
|
|
23
|
+
"prod-softpro1": "node server --config=softpro",
|
|
24
|
+
"prod": "NODE_ENV=production bun --env-file=.env.ip server ",
|
|
25
|
+
"prod-ip": "PORT=3019 node server --config=ip",
|
|
26
|
+
"prod-ip-test": "PORT=3025 node server --config=ip",
|
|
27
|
+
"dev": "node server --config=softpro",
|
|
28
|
+
"debug": "bun --watch server --config=softpro",
|
|
29
|
+
"ip-test": "node server --config=ip-test",
|
|
30
|
+
"ip": "node --env-file=.env.ip server",
|
|
31
|
+
"demo": "node --env-file=.env.demo --env-file=.env server",
|
|
32
|
+
"i18n:sync": "node i18n-sync.cjs",
|
|
33
|
+
"prepublishOnly": "bun build:lib",
|
|
34
|
+
"softpro": "bun --env-file=.env.softpro server"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@fastify/compress": "^8.1.0",
|
|
38
|
+
"@opengis/core": "^0.0.30",
|
|
39
|
+
"@opengis/fastify-table": "^2.0.118",
|
|
40
|
+
"@opengis/filter": "^0.1.10",
|
|
41
|
+
"@opengis/form": "^0.0.70",
|
|
42
|
+
"@opengis/richtext": "0.0.38",
|
|
43
|
+
"@vueuse/head": "2.0.0",
|
|
44
|
+
"js-yaml": "^4.1.0",
|
|
45
|
+
"lucide-vue-next": "0.344.0",
|
|
46
|
+
"vite": "5.1.4",
|
|
47
|
+
"vue": "^3.5.17",
|
|
48
|
+
"vue-i18n": "11.1.5",
|
|
49
|
+
"vue-router": "4.4.3",
|
|
50
|
+
"vuedraggable": "4.1.0"
|
|
51
|
+
},
|
|
52
|
+
"resolutions": {
|
|
53
|
+
"rollup": "4.30.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@tailwindcss/typography": "0.5.10",
|
|
57
|
+
"@tsconfig/node22": "^22.0.2",
|
|
58
|
+
"@vitejs/plugin-vue": "5.0.4",
|
|
59
|
+
"autoprefixer": "10.4.18",
|
|
60
|
+
"eslint": "8.49.0",
|
|
61
|
+
"postcss": "8.4.35",
|
|
62
|
+
"sass": "^1.92.1",
|
|
63
|
+
"tailwindcss": "3.4.1",
|
|
64
|
+
"typescript": "~5.8.0",
|
|
65
|
+
"vitest": "3.2.4",
|
|
66
|
+
"vue-tsc": "^2.2.10"
|
|
67
|
+
}
|
|
68
|
+
}
|
package/plugin.js
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { fileURLToPath } from 'url';
|
|
3
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
-
|
|
5
|
-
import { config, execMigrations, getPGAsync } from '@opengis/fastify-table/utils.js';
|
|
6
|
-
import { table } from 'node:console';
|
|
7
|
-
|
|
8
|
-
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
-
|
|
10
|
-
// node server --config=softpro
|
|
11
|
-
console.log(process.argv);
|
|
12
|
-
if (process.argv.find(el => el.includes('--config'))) {
|
|
13
|
-
const filename = process.argv.find(el => el.includes('--config')).split('=').pop();
|
|
14
|
-
const cmsConfig = existsSync(`config/${filename}.json`)
|
|
15
|
-
? JSON.parse(readFileSync(`config/${filename}.json`, 'utf8'))
|
|
16
|
-
: {};
|
|
17
|
-
|
|
18
|
-
console.log('cms init', cmsConfig.pg?.database);
|
|
19
|
-
Object.keys(cmsConfig).forEach(key => {
|
|
20
|
-
config[key] = cmsConfig[key];
|
|
21
|
-
});
|
|
22
|
-
config.spacename = 'default' || cmsConfig.name || filename;
|
|
23
|
-
} else {
|
|
24
|
-
config.spacename = 'default' || config.spacename || process.env.NODE_ENV; // --env.file=.env.ip
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const { prefix = '/api' } = config;
|
|
28
|
-
|
|
29
|
-
export default async function (app) {
|
|
30
|
-
app.register(import('./server/routes/menu/index.mjs'), { prefix });
|
|
31
|
-
app.register(import('./server/routes/migration/index.mjs'), { prefix });
|
|
32
|
-
app.register(import('./server/routes/cms/index.mjs'), { prefix });
|
|
33
|
-
app.register(import('./server/routes/cmsSpace/index.mjs'), { prefix });
|
|
34
|
-
app.register(import('./server/routes/contentType/index.mjs'), { prefix });
|
|
35
|
-
app.register(import('./server/routes/category/index.mjs'), { prefix });
|
|
36
|
-
app.register(import('./server/routes/tags/index.mjs'), { prefix });
|
|
37
|
-
app.register(import('./server/routes/logs/index.mjs'), { prefix });
|
|
38
|
-
app.register(import('./server/routes/feedback/index.mjs'), { prefix });
|
|
39
|
-
const pg = await getPGAsync(config.pg);
|
|
40
|
-
execMigrations(path.join(dirname, 'server/migrations'), pg).catch(err => console.log(err));
|
|
41
|
-
if (pg?.pk?.['site.content_types']) {
|
|
42
|
-
const customTables = await pg.query('select array_agg(table_name) from site.content_types where table_name is not null').then(el => el.rows?.[0]?.array_agg || []).catch(err => console.log(err));
|
|
43
|
-
|
|
44
|
-
await Promise.all(customTables.filter(table => pg.pk?.[`data.${table}`])?.map(async (table) => {
|
|
45
|
-
await pg.query(`alter table data.${table} add column if not exists meta json`).catch(err => console.log(err));
|
|
46
|
-
await pg.query(`alter table data.${table} add column if not exists main_image text`).catch(err => console.log(err));
|
|
47
|
-
await pg.query(`update site.content_types
|
|
48
|
-
SET columns = columns::jsonb || jsonb_build_object('name', 'main_image', 'type', 'image', 'label', 'Зображення')
|
|
49
|
-
WHERE not EXISTS (
|
|
50
|
-
SELECT 1
|
|
51
|
-
FROM jsonb_array_elements(columns::jsonb) AS obj(elem)
|
|
52
|
-
JOIN LATERAL jsonb_each_text(elem) AS kv(key, value) ON true
|
|
53
|
-
WHERE key = 'name' and value='main_image'
|
|
54
|
-
)`);
|
|
55
|
-
await pg.query(`alter table data.${table} add column if not exists published_at timestamp without time zone not null default now()`).catch(err => console.log(err));
|
|
56
|
-
await pg.query(`alter table data.${table} add column if not exists is_pin boolean DEFAULT false`).catch(err => console.log(err));
|
|
57
|
-
await pg.query(`alter table data.${table} drop column if exists publish_at`).catch(err => console.log(err));
|
|
58
|
-
}));
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
/*customTables.filter(table => pg.pk?.[`data.${table}`])?.forEach(table => pg.query(`alter table data.${table} add column if not exists meta json`).catch(err => console.log(err)));
|
|
63
|
-
customTables.filter(table => pg.pk?.[`data.${table}`])?.forEach(table => pg.query(`alter table data.${table} add column if not exists published_at timestamp without time zone not null default now()`).catch(err => console.log(err)));
|
|
64
|
-
customTables.filter(table => pg.pk?.[`data.${table}`])?.forEach(table => pg.query(`alter table data.${table} add column if not exists is_pin boolean DEFAULT false`).catch(err => console.log(err)));*/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
/* if (pg?.pk?.['site.content_types'] && pg?.pk?.['site.contents']) {
|
|
69
|
-
await pg.query('insert into site.contents(content_type_id, space_id, locale) select content_type_id, $1, $2 from site.content_types where content_type_id not in (select content_type_id from site.contents)', [config.spacename || 'default', config.locale || 'ua']).catch(err => {
|
|
70
|
-
console.log(err.toString());
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
if (pg?.pk?.['site.spaces']) {
|
|
74
|
-
pg.query('insert into site.spaces(space_id, name) values($1, $1) on conflict(space_id) do nothing', [config.spacename || 'default']).catch(err => console.error('spaces insert error', err.toString())); // for content site.spaces
|
|
75
|
-
} */
|
|
76
|
-
}
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
+
|
|
5
|
+
import { config, execMigrations, getPGAsync } from '@opengis/fastify-table/utils.js';
|
|
6
|
+
import { table } from 'node:console';
|
|
7
|
+
|
|
8
|
+
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
// node server --config=softpro
|
|
11
|
+
console.log(process.argv);
|
|
12
|
+
if (process.argv.find(el => el.includes('--config'))) {
|
|
13
|
+
const filename = process.argv.find(el => el.includes('--config')).split('=').pop();
|
|
14
|
+
const cmsConfig = existsSync(`config/${filename}.json`)
|
|
15
|
+
? JSON.parse(readFileSync(`config/${filename}.json`, 'utf8'))
|
|
16
|
+
: {};
|
|
17
|
+
|
|
18
|
+
console.log('cms init', cmsConfig.pg?.database);
|
|
19
|
+
Object.keys(cmsConfig).forEach(key => {
|
|
20
|
+
config[key] = cmsConfig[key];
|
|
21
|
+
});
|
|
22
|
+
config.spacename = 'default' || cmsConfig.name || filename;
|
|
23
|
+
} else {
|
|
24
|
+
config.spacename = 'default' || config.spacename || process.env.NODE_ENV; // --env.file=.env.ip
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const { prefix = '/api' } = config;
|
|
28
|
+
|
|
29
|
+
export default async function (app) {
|
|
30
|
+
app.register(import('./server/routes/menu/index.mjs'), { prefix });
|
|
31
|
+
app.register(import('./server/routes/migration/index.mjs'), { prefix });
|
|
32
|
+
app.register(import('./server/routes/cms/index.mjs'), { prefix });
|
|
33
|
+
app.register(import('./server/routes/cmsSpace/index.mjs'), { prefix });
|
|
34
|
+
app.register(import('./server/routes/contentType/index.mjs'), { prefix });
|
|
35
|
+
app.register(import('./server/routes/category/index.mjs'), { prefix });
|
|
36
|
+
app.register(import('./server/routes/tags/index.mjs'), { prefix });
|
|
37
|
+
app.register(import('./server/routes/logs/index.mjs'), { prefix });
|
|
38
|
+
app.register(import('./server/routes/feedback/index.mjs'), { prefix });
|
|
39
|
+
const pg = await getPGAsync(config.pg);
|
|
40
|
+
execMigrations(path.join(dirname, 'server/migrations'), pg).catch(err => console.log(err));
|
|
41
|
+
if (pg?.pk?.['site.content_types']) {
|
|
42
|
+
const customTables = await pg.query('select array_agg(table_name) from site.content_types where table_name is not null').then(el => el.rows?.[0]?.array_agg || []).catch(err => console.log(err));
|
|
43
|
+
|
|
44
|
+
await Promise.all(customTables.filter(table => pg.pk?.[`data.${table}`])?.map(async (table) => {
|
|
45
|
+
await pg.query(`alter table data.${table} add column if not exists meta json`).catch(err => console.log(err));
|
|
46
|
+
await pg.query(`alter table data.${table} add column if not exists main_image text`).catch(err => console.log(err));
|
|
47
|
+
await pg.query(`update site.content_types
|
|
48
|
+
SET columns = columns::jsonb || jsonb_build_object('name', 'main_image', 'type', 'image', 'label', 'Зображення')
|
|
49
|
+
WHERE not EXISTS (
|
|
50
|
+
SELECT 1
|
|
51
|
+
FROM jsonb_array_elements(columns::jsonb) AS obj(elem)
|
|
52
|
+
JOIN LATERAL jsonb_each_text(elem) AS kv(key, value) ON true
|
|
53
|
+
WHERE key = 'name' and value='main_image'
|
|
54
|
+
)`);
|
|
55
|
+
await pg.query(`alter table data.${table} add column if not exists published_at timestamp without time zone not null default now()`).catch(err => console.log(err));
|
|
56
|
+
await pg.query(`alter table data.${table} add column if not exists is_pin boolean DEFAULT false`).catch(err => console.log(err));
|
|
57
|
+
await pg.query(`alter table data.${table} drop column if exists publish_at`).catch(err => console.log(err));
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
/*customTables.filter(table => pg.pk?.[`data.${table}`])?.forEach(table => pg.query(`alter table data.${table} add column if not exists meta json`).catch(err => console.log(err)));
|
|
63
|
+
customTables.filter(table => pg.pk?.[`data.${table}`])?.forEach(table => pg.query(`alter table data.${table} add column if not exists published_at timestamp without time zone not null default now()`).catch(err => console.log(err)));
|
|
64
|
+
customTables.filter(table => pg.pk?.[`data.${table}`])?.forEach(table => pg.query(`alter table data.${table} add column if not exists is_pin boolean DEFAULT false`).catch(err => console.log(err)));*/
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
/* if (pg?.pk?.['site.content_types'] && pg?.pk?.['site.contents']) {
|
|
69
|
+
await pg.query('insert into site.contents(content_type_id, space_id, locale) select content_type_id, $1, $2 from site.content_types where content_type_id not in (select content_type_id from site.contents)', [config.spacename || 'default', config.locale || 'ua']).catch(err => {
|
|
70
|
+
console.log(err.toString());
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (pg?.pk?.['site.spaces']) {
|
|
74
|
+
pg.query('insert into site.spaces(space_id, name) values($1, $1) on conflict(space_id) do nothing', [config.spacename || 'default']).catch(err => console.error('spaces insert error', err.toString())); // for content site.spaces
|
|
75
|
+
} */
|
|
76
|
+
}
|
package/server/app.js
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import { config, addHook } from '@opengis/fastify-table/utils.js';
|
|
2
|
-
|
|
3
|
-
config.rateLimit = false;
|
|
4
|
-
config.prefix = config.prefix || '/api';
|
|
5
|
-
config.mode = config.mode || 'cms';
|
|
6
|
-
// config.auth.oneUser = true;
|
|
7
|
-
config.auth = config.auth || {};
|
|
8
|
-
config.auth['2fa'] = config.auth['2fa'] || {};
|
|
9
|
-
config.auth['2fa'].prefix = config.auth['2fa'].prefix || 'cms';
|
|
10
|
-
config.auth['2fa'].sufix = config.auth['2fa'].sufix || 'login';
|
|
11
|
-
|
|
12
|
-
// when frontend is implemented/used
|
|
13
|
-
// config.auth.loginPage = true; // disable core loginPage api, use vue component instead
|
|
14
|
-
// config.auth.link = config.auth.link || { '2fa': { login: '/2fa' } };
|
|
15
|
-
|
|
16
|
-
export default async function (app) {
|
|
17
|
-
// core
|
|
18
|
-
app.register(import('@fastify/compress'), { encodings: ['br', 'gzip'], });
|
|
19
|
-
app.register(import('./plugins/adminHook.js'));
|
|
20
|
-
app.register(import('./plugins/hook.js'));
|
|
21
|
-
|
|
22
|
-
app.register(import('@opengis/fastify-table'), config);
|
|
23
|
-
|
|
24
|
-
app.register(import('./plugins/vite.js'));
|
|
25
|
-
// API
|
|
26
|
-
app.register(import('./routes/root.mjs'));
|
|
27
|
-
app.register(import('../plugin.js'));
|
|
28
|
-
|
|
29
|
-
addHook('errorMessage', (params) => {
|
|
30
|
-
if (params?.constraint && params.constraint === 'content_data_content_id_fkey') {
|
|
31
|
-
return 'Перед видаленням даного типу контенту, необхідно видалити всі дані, що до нього відносяться.';
|
|
32
|
-
}
|
|
33
|
-
return params?.message || 'Помилка API';
|
|
34
|
-
});
|
|
35
|
-
}
|
|
1
|
+
import { config, addHook } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
config.rateLimit = false;
|
|
4
|
+
config.prefix = config.prefix || '/api';
|
|
5
|
+
config.mode = config.mode || 'cms';
|
|
6
|
+
// config.auth.oneUser = true;
|
|
7
|
+
config.auth = config.auth || {};
|
|
8
|
+
config.auth['2fa'] = config.auth['2fa'] || {};
|
|
9
|
+
config.auth['2fa'].prefix = config.auth['2fa'].prefix || 'cms';
|
|
10
|
+
config.auth['2fa'].sufix = config.auth['2fa'].sufix || 'login';
|
|
11
|
+
|
|
12
|
+
// when frontend is implemented/used
|
|
13
|
+
// config.auth.loginPage = true; // disable core loginPage api, use vue component instead
|
|
14
|
+
// config.auth.link = config.auth.link || { '2fa': { login: '/2fa' } };
|
|
15
|
+
|
|
16
|
+
export default async function (app) {
|
|
17
|
+
// core
|
|
18
|
+
app.register(import('@fastify/compress'), { encodings: ['br', 'gzip'], });
|
|
19
|
+
app.register(import('./plugins/adminHook.js'));
|
|
20
|
+
app.register(import('./plugins/hook.js'));
|
|
21
|
+
|
|
22
|
+
app.register(import('@opengis/fastify-table'), config);
|
|
23
|
+
|
|
24
|
+
app.register(import('./plugins/vite.js'));
|
|
25
|
+
// API
|
|
26
|
+
app.register(import('./routes/root.mjs'));
|
|
27
|
+
app.register(import('../plugin.js'));
|
|
28
|
+
|
|
29
|
+
addHook('errorMessage', (params) => {
|
|
30
|
+
if (params?.constraint && params.constraint === 'content_data_content_id_fkey') {
|
|
31
|
+
return 'Перед видаленням даного типу контенту, необхідно видалити всі дані, що до нього відносяться.';
|
|
32
|
+
}
|
|
33
|
+
return params?.message || 'Помилка API';
|
|
34
|
+
});
|
|
35
|
+
}
|
package/server/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { readFile } from 'fs/promises';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
const config = fs.existsSync('config.json') ? JSON.parse(await readFile('config.json')) : {};
|
|
4
|
-
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
const config = fs.existsSync('config.json') ? JSON.parse(await readFile('config.json')) : {};
|
|
4
|
+
|
|
5
5
|
export default config;
|
|
@@ -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
|
+
}
|
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
|
+
});
|