@opengis/cms 0.0.59 → 0.0.61

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 (48) hide show
  1. package/README.md +4 -4
  2. package/dist/{ArticlesPage-BjYzvTWM.js → ArticlesPage-CFjE_cw_.js} +3 -3
  3. package/dist/{CollectionsBreadcrumb-HePNJb-d.js → CollectionsBreadcrumb-BCxeRikP.js} +1 -1
  4. package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-umRzB5mY.js +53 -0
  5. package/dist/{Dashboard-CXkg_pk8.js → Dashboard-C1eGscNd.js} +132 -132
  6. package/dist/EditCollectionPage-3Q57ptN3.js +188 -0
  7. package/dist/{MenuAddPage-QTnwCoGh.js → MenuAddPage-D-p3gFgm.js} +1 -1
  8. package/dist/{MenuBody-Bi0ONVZf.js → MenuBody-rN5j4YBu.js} +2 -2
  9. package/dist/{MenuItemPage-B7Y9KFyb.js → MenuItemPage-BoJw885D.js} +3 -3
  10. package/dist/{MenuList-BLIpeqSd.js → MenuList-DFEBS0NB.js} +53 -53
  11. package/dist/{MenuPage-3W6jZ15H.js → MenuPage-BCZB_S8j.js} +1 -1
  12. package/dist/{MenuWrapper-OrOv6sOb.js → MenuWrapper-AZ_8s-zd.js} +1 -1
  13. package/dist/{MonacoEditor-ByPT8pnv.js → MonacoEditor-Db-3Jc3E.js} +1 -1
  14. package/dist/MonacoEditor.vue_vue_type_script_setup_true_lang-B1DrxmQX.js +84 -0
  15. package/dist/{UniversalTable-GBd_pStq.js → UniversalTable-CzqPG-tY.js} +80 -80
  16. package/dist/{UniversalTablePagination-Dw2hc0nc.js → UniversalTablePagination-4gL47A7I.js} +46 -46
  17. package/dist/{contentForm-Buku-lel.js → contentForm-CLStrfSg.js} +49 -52
  18. package/dist/index.js +5 -5
  19. package/dist/{vs-builder-monaco-Cw-f19gc.js → vs-builder-monaco-B3Jj0V31.js} +1 -1
  20. package/package.json +69 -69
  21. package/server/migrations/fixes.sql +5 -2
  22. package/server/migrations/site.sql +4 -3
  23. package/server/routes/cms/controllers/deleteContent.js +7 -7
  24. package/server/routes/cms/controllers/getContent.js +6 -6
  25. package/server/routes/cms/controllers/getContentBySlug.js +13 -13
  26. package/server/routes/cms/controllers/getPermissions.js +15 -15
  27. package/server/routes/cms/controllers/insertContent.js +28 -19
  28. package/server/routes/cms/controllers/setPermissions.js +49 -49
  29. package/server/routes/cms/controllers/updateContent.js +12 -47
  30. package/server/routes/cms/utils/getCollection.js +1 -1
  31. package/server/routes/cms/utils/getSingle.js +1 -1
  32. package/server/routes/cms/utils/insertContentLocalization.js +1 -1
  33. package/server/routes/cms/utils/requestTranslation.js +73 -23
  34. package/server/routes/cms/utils/updateLocalization.js +1 -6
  35. package/server/routes/cmsSpace/controllers/deleteSpace.js +1 -0
  36. package/server/routes/cmsSpace/controllers/getSpaces.js +1 -0
  37. package/server/routes/cmsSpace/controllers/insertSpace.js +1 -0
  38. package/server/routes/cmsSpace/controllers/updateSpace.js +1 -0
  39. package/server/routes/contentType/controllers/contentTypeList.js +4 -11
  40. package/server/routes/contentType/controllers/editContentType.js +7 -25
  41. package/server/routes/contentType/controllers/getContentType.js +5 -13
  42. package/server/templates/select/core.user_mentioned.sql +1 -1
  43. package/dist/CollectionsBreadcrumb.vue_vue_type_script_setup_true_lang-BJh-tjam.js +0 -53
  44. package/dist/EditCollectionPage-CqYHpEON.js +0 -187
  45. package/dist/MonacoEditor.vue_vue_type_script_setup_true_lang-C8cip9Ci.js +0 -84
  46. package/dist/images/logo.png +0 -0
  47. package/dist/index.html +0 -29
  48. package/dist/vite.svg +0 -1
@@ -4,7 +4,7 @@ import { ArrowLeft as Je, HelpCircle as He, Settings as Ke, Save as qe, Loader2
4
4
  import { useI18n as Qe } from "vue-i18n";
5
5
  import { g as We } from "./getField-CpwVE28P.js";
6
6
  import { inputs as x, VForm as ue } from "@opengis/form";
7
- import { notify as F } from "@opengis/core";
7
+ import { notify as P } from "@opengis/core";
8
8
  const Xe = [
9
9
  {
10
10
  key: "title",
@@ -66,16 +66,16 @@ const Xe = [
66
66
  ), be = h(
67
67
  () => import("./VsPreview-DwETkOpb.js")
68
68
  ), he = h(
69
- () => import("./CollectionsBreadcrumb-HePNJb-d.js")
69
+ () => import("./CollectionsBreadcrumb-BCxeRikP.js")
70
70
  );
71
71
  x["vs-input-custom-datatable"] = fe, x["vs-input-reference"] = de, x["vs-input-texteditor"] = me, x["vs-input-mediaselect"] = E, x["vs-input-file"] = E, x["vs-input-image"] = E, x["vs-input-richtext-md"] = pe, x["vs-input-integer"] = ve, x["vs-input-relation-link"] = ye;
72
- const { t: c, locale: G } = Qe(), V = Ue(), d = Oe(), Q = le("cms.menu", null) || le("menu", p([])), _ = p([]), D = p({}), W = p({}), I = p({}), N = p(""), M = p(!0), R = Be(), U = R == null ? void 0 : R.appContext, we = (U == null ? void 0 : U.config.globalProperties) || {}, X = Ee(we, "$settings"), P = m(() => {
72
+ const { t: r, locale: G } = Qe(), V = Ue(), d = Oe(), Q = le("cms.menu", null) || le("menu", p([])), _ = p([]), D = p({}), W = p({}), I = p({}), N = p(""), M = p(!0), R = Be(), U = R == null ? void 0 : R.appContext, we = (U == null ? void 0 : U.config.globalProperties) || {}, X = Ee(we, "$settings"), B = m(() => {
73
73
  var e;
74
74
  return ((e = X.value) == null ? void 0 : e.cms) || {};
75
- }), ke = m(() => Array.isArray(P.value.locales) ? P.value.locales : []), O = m(
75
+ }), ke = m(() => Array.isArray(B.value.locales) ? B.value.locales : []), O = m(
76
76
  () => ke.value.filter(Boolean)
77
77
  ), Y = m(
78
- () => P.value.locale || O.value[0] || "uk"
78
+ () => B.value.locale || O.value[0] || "uk"
79
79
  );
80
80
  De(
81
81
  X,
@@ -114,14 +114,14 @@ const Xe = [
114
114
  return Xe.flatMap((t) => {
115
115
  const o = {
116
116
  ...t,
117
- label: c(t.label)
117
+ label: r(t.label)
118
118
  };
119
119
  if (!t.localization || e.length === 0)
120
120
  return [o];
121
121
  const a = e.map((n) => ({
122
122
  ...t,
123
123
  key: `${t.key}:${n}`,
124
- label: `${c(t.label)} (${n})`,
124
+ label: `${r(t.label)} (${n})`,
125
125
  localization: !1
126
126
  }));
127
127
  return [o, ...a];
@@ -129,21 +129,18 @@ const Xe = [
129
129
  }), g = p({}), i = p({
130
130
  title: "",
131
131
  status: "draft"
132
- }), J = p(null), L = p(""), B = m(
133
- () => {
134
- var e;
135
- return (((e = i.value) == null ? void 0 : e.type) || J.value) === "single";
136
- }
132
+ }), J = p(null), L = p(""), F = m(
133
+ () => J.value === "single"
137
134
  ), Te = m(() => {
138
135
  const e = [
139
- { id: "content", name: c("cms.builder.content") },
140
- { id: "seo", name: c("cms.builder.seo") },
141
- { id: "tags", name: c("cms.builder.tags") }
136
+ { id: "content", name: r("cms.builder.content") },
137
+ { id: "seo", name: r("cms.builder.seo") },
138
+ { id: "tags", name: r("cms.builder.tags") }
142
139
  ];
143
- return N.value && e.push({ id: "preview", name: c("cms.builder.preview") }), e;
140
+ return N.value && e.push({ id: "preview", name: r("cms.builder.preview") }), e;
144
141
  }), A = p("content"), ee = m(() => {
145
- var s, r, l, k, f, b, y, T, oe;
146
- const e = ((s = d.params) == null ? void 0 : s.collection) || ((r = d.params) == null ? void 0 : r.id), t = (l = i.value) == null ? void 0 : l.content_type_id, o = t ? (f = (k = Q.value) == null ? void 0 : k.find((K) => K.id === t)) == null ? void 0 : f.title : null;
142
+ var s, c, l, k, f, b, y, T, oe;
143
+ const e = ((s = d.params) == null ? void 0 : s.collection) || ((c = d.params) == null ? void 0 : c.id), t = (l = i.value) == null ? void 0 : l.content_type_id, o = t ? (f = (k = Q.value) == null ? void 0 : k.find((K) => K.id === t)) == null ? void 0 : f.title : null;
147
144
  if (o)
148
145
  return o;
149
146
  if (L.value)
@@ -154,24 +151,24 @@ const Xe = [
154
151
  if (a)
155
152
  return a;
156
153
  const n = (T = d.params) == null ? void 0 : T.id;
157
- return B.value && n && e === n && ((oe = i.value) != null && oe.title) ? i.value.title : e === "pages" ? c("cms.articles.title") : e;
154
+ return F.value && n && e === n && ((oe = i.value) != null && oe.title) ? i.value.title : e === "pages" ? r("cms.articles.title") : e;
158
155
  }), Se = m(() => {
159
156
  var t, o;
160
- const e = B.value ? "cms.builder.editPage" : "cms.builder.editCollection";
161
- return ((t = i.value) == null ? void 0 : t.title) || ((o = d.params) != null && o.id ? c(e) : c("cms.articles.createArticle"));
157
+ const e = F.value ? "cms.builder.editPage" : "cms.builder.editCollection";
158
+ return ((t = i.value) == null ? void 0 : t.title) || ((o = d.params) != null && o.id ? r(e) : r("cms.articles.createArticle"));
162
159
  }), Ve = m(() => {
163
- var s, r, l;
164
- const e = ((s = d.params) == null ? void 0 : s.collection) || ((r = d.params) == null ? void 0 : r.id), t = (l = d.params) == null ? void 0 : l.id, o = Se.value, a = o === ee.value, n = [
160
+ var s, c, l;
161
+ const e = ((s = d.params) == null ? void 0 : s.collection) || ((c = d.params) == null ? void 0 : c.id), t = (l = d.params) == null ? void 0 : l.id, o = Se.value, a = o === ee.value, n = [
165
162
  {
166
- label: ee.value,
163
+ label: F.value ? r("cms.navigation.singletons") : ee.value,
167
164
  route: `collections/${e}`
168
165
  }
169
166
  ];
170
167
  return t ? n.push({
171
- label: a ? c("cms.collections.edit") : o,
168
+ label: a ? r("cms.collections.edit") : o,
172
169
  route: `collections/${e}/${t}`
173
170
  }) : n.push({
174
- label: c("cms.articles.createArticle"),
171
+ label: r("cms.articles.createArticle"),
175
172
  route: `collections/${e}/create`
176
173
  }), n;
177
174
  }), Ae = (e) => {
@@ -186,9 +183,9 @@ const Xe = [
186
183
  throw new Error("Failed to fetch article");
187
184
  const s = await n.json();
188
185
  if (_.value = (s == null ? void 0 : s.columns) || [], s != null && s.preview_path && (N.value = s == null ? void 0 : s.preview_path), J.value = (s == null ? void 0 : s.type) || null, s.rows) {
189
- let r = s.rows;
190
- Array.isArray(r) || (r = [r]), i.value = r[0];
191
- const l = ((o = r[0]) == null ? void 0 : o.content_type_id) || e;
186
+ let c = s.rows;
187
+ Array.isArray(c) || (c = [c]), i.value = c[0];
188
+ const l = ((o = c[0]) == null ? void 0 : o.content_type_id) || e;
192
189
  if (l) {
193
190
  const k = await fetch(`/api/cms-type/${l}`);
194
191
  if (k.ok) {
@@ -196,7 +193,7 @@ const Xe = [
196
193
  L.value = (f == null ? void 0 : f.title) || (f == null ? void 0 : f.name) || L.value;
197
194
  }
198
195
  }
199
- await ce(), (a = r[0]) != null && a.meta ? g.value = { ...r[0].meta } : g.value = {
196
+ await ce(), (a = c[0]) != null && a.meta ? g.value = { ...c[0].meta } : g.value = {
200
197
  title: "",
201
198
  description: "",
202
199
  keywords: "",
@@ -249,12 +246,12 @@ const Xe = [
249
246
  const e = (t = i.value) == null ? void 0 : t.content_type_id;
250
247
  return e ? `/collections/${e}/edit` : null;
251
248
  }), ze = () => {
252
- var o, a, n;
249
+ var o, a, n, s;
253
250
  if (!H.value)
254
251
  return;
255
252
  const e = ((o = d.params) == null ? void 0 : o.collection) || ((a = d.params) == null ? void 0 : a.id), t = (n = d.params) == null ? void 0 : n.id;
256
253
  if (e && t) {
257
- V.push(`/collections/${e}/${t}/edit`);
254
+ V.push(`/collections/${(s = i.value) == null ? void 0 : s.content_type_id}/edit`);
258
255
  return;
259
256
  }
260
257
  V.push(H.value);
@@ -265,24 +262,24 @@ const Xe = [
265
262
  try {
266
263
  (await fetch(
267
264
  `/api/cms-translate?id=${t}&collection=${e}&to=en&nocache=1`
268
- )).ok ? (F({
269
- title: c("cms.collections.translateContentSuccess"),
270
- message: c("cms.collections.translateContentSuccess"),
265
+ )).ok ? (P({
266
+ title: r("cms.collections.translateContentSuccess"),
267
+ message: r("cms.collections.translateContentSuccess"),
271
268
  type: "success"
272
- }), await te(e, t)) : F({
273
- title: c("cms.collections.translateContentError"),
274
- message: c("cms.collections.translateContentError"),
269
+ }), await te(e, t)) : P({
270
+ title: r("cms.collections.translateContentError"),
271
+ message: r("cms.collections.translateContentError"),
275
272
  type: "error"
276
273
  });
277
274
  } finally {
278
275
  z.value = !1;
279
276
  }
280
277
  }, Fe = async (e) => {
281
- var r, l, k, f;
282
- const t = (r = d.params) == null ? void 0 : r.collection, o = (l = d.params) == null ? void 0 : l.id, a = await D.value.validate();
278
+ var c, l, k, f;
279
+ const t = (c = d.params) == null ? void 0 : c.collection, o = (l = d.params) == null ? void 0 : l.id, a = await D.value.validate();
283
280
  if (a) {
284
- F({
285
- title: c("cms.validation"),
281
+ P({
282
+ title: r("cms.validation"),
286
283
  message: JSON.stringify(a),
287
284
  type: "warning"
288
285
  });
@@ -322,21 +319,21 @@ const Xe = [
322
319
  } catch (y) {
323
320
  console.warn("Could not parse response to get ID:", y);
324
321
  }
325
- F({
326
- title: c("cms.common.success"),
327
- message: c("cms.common.successMessage"),
322
+ P({
323
+ title: r("cms.common.success"),
324
+ message: r("cms.common.successMessage"),
328
325
  type: "success"
329
326
  });
330
327
  } catch (b) {
331
- console.error("Submit error:", b), F({
332
- title: c("cms.common.error"),
328
+ console.error("Submit error:", b), P({
329
+ title: r("cms.common.error"),
333
330
  message: "Помилка збереження",
334
331
  type: "error"
335
332
  });
336
333
  }
337
334
  };
338
335
  return (e, t) => {
339
- var o, a, n, s, r;
336
+ var o, a, n, s, c;
340
337
  return w(), $("div", Ye, [
341
338
  u("div", Ze, [
342
339
  C(v(he), {
@@ -353,7 +350,7 @@ const Xe = [
353
350
  C(v(Je), { class: "w-5 h-5" })
354
351
  ]),
355
352
  u("h1", st, j(e.$t(
356
- B.value ? "cms.builder.editPage" : "cms.builder.editCollection"
353
+ F.value ? "cms.builder.editPage" : "cms.builder.editCollection"
357
354
  )) + ' "' + j(i.value.title) + '" ', 1),
358
355
  u("a", {
359
356
  href: `https://cms.opengis.info/${v(G)}/guides/content/`,
@@ -364,7 +361,7 @@ const Xe = [
364
361
  ], 8, ot)
365
362
  ]),
366
363
  u("div", lt, [
367
- H.value && B.value ? (w(), $("button", {
364
+ H.value && F.value ? (w(), $("button", {
368
365
  key: 0,
369
366
  onClick: ze,
370
367
  type: "button",
@@ -389,7 +386,7 @@ const Xe = [
389
386
  (w(!0), $(Ne, null, Me(Te.value, (l) => (w(), $("button", {
390
387
  key: l.id,
391
388
  onClick: (k) => {
392
- A.value = l.id, console.log("cmsSettings:", P.value.value);
389
+ A.value = l.id, console.log("cmsSettings:", B.value.value);
393
390
  },
394
391
  class: ne([
395
392
  "inline-flex flex-1 items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm data-[state=active]:bg-blue-50 data-[state=active]:text-blue-700 data-[state=active]:border-blue-200",
@@ -476,7 +473,7 @@ const Xe = [
476
473
  ])) : S("", !0),
477
474
  A.value === "preview" ? (w(), $("div", bt, [
478
475
  C(v(be), {
479
- slug: (r = i.value) == null ? void 0 : r.slug,
476
+ slug: (c = i.value) == null ? void 0 : c.slug,
480
477
  preview_path: N.value
481
478
  }, null, 8, ["slug", "preview_path"])
482
479
  ])) : S("", !0)
package/dist/index.js CHANGED
@@ -3,12 +3,12 @@ import { useRoute as $, routeLocationKey as K } from "vue-router";
3
3
  const O = "menu", B = (s, c, a) => {
4
4
  const o = s == null ? void 0 : s.trim(), l = a == null ? void 0 : a.trim();
5
5
  return o ? o === O ? c ? c === "create" ? { type: "createMenu", collection: o } : { type: "editMenu", collection: o, id: c } : { type: "menu", collection: o } : l === "edit" && c ? { type: "editCollection", collection: o, id: c } : c === "edit" ? { type: "editCollection", collection: o } : c ? c === "create" ? { type: "createArticle", collection: o } : { type: "editArticle", collection: o, id: c } : { type: "articles", collection: o } : { type: "collections" };
6
- }, R = u(() => import("./CollectionsPage-DHfPNql6.js")), L = u(() => import("./ArticlesPage-BjYzvTWM.js")), C = u(() => import("./contentForm-Buku-lel.js")), N = u(() => import("./EditCollectionPage-CqYHpEON.js")), W = u(
7
- () => import("./MenuPage-3W6jZ15H.js")
6
+ }, R = u(() => import("./CollectionsPage-DHfPNql6.js")), L = u(() => import("./ArticlesPage-CFjE_cw_.js")), C = u(() => import("./contentForm-CLStrfSg.js")), N = u(() => import("./EditCollectionPage-3Q57ptN3.js")), W = u(
7
+ () => import("./MenuPage-BCZB_S8j.js")
8
8
  ), j = u(
9
- () => import("./MenuItemPage-B7Y9KFyb.js")
9
+ () => import("./MenuItemPage-BoJw885D.js")
10
10
  ), F = u(
11
- () => import("./MenuAddPage-QTnwCoGh.js")
11
+ () => import("./MenuAddPage-D-p3gFgm.js")
12
12
  ), S = {
13
13
  collections: R,
14
14
  articles: L,
@@ -96,7 +96,7 @@ const O = "menu", B = (s, c, a) => {
96
96
  });
97
97
  return M(K, b), (e, n) => v.value ? (g(), k(x(v.value), { key: w.value })) : (g(), E("div", V, D(e.$t("cms.navigation.collections")), 1));
98
98
  }
99
- }), H = u(() => import("./Dashboard-CXkg_pk8.js")), J = u(() => import("./MenuWrapper-OrOv6sOb.js")), Q = q;
99
+ }), H = u(() => import("./Dashboard-C1eGscNd.js")), J = u(() => import("./MenuWrapper-AZ_8s-zd.js")), Q = q;
100
100
  export {
101
101
  Q as Content,
102
102
  H as Dashboard,
@@ -1,5 +1,5 @@
1
1
  import { ref as l, useModel as m, onMounted as u, openBlock as r, createElementBlock as d, createVNode as i, createCommentVNode as s } from "vue";
2
- import { _ as c } from "./MonacoEditor.vue_vue_type_script_setup_true_lang-C8cip9Ci.js";
2
+ import { _ as c } from "./MonacoEditor.vue_vue_type_script_setup_true_lang-B1DrxmQX.js";
3
3
  const g = {
4
4
  __name: "vs-builder-monaco",
5
5
  props: {
package/package.json CHANGED
@@ -1,69 +1,69 @@
1
- {
2
- "name": "@opengis/cms",
3
- "version": "0.0.59",
4
- "description": "cms",
5
- "type": "module",
6
- "author": "Softpro",
7
- "main": "./dist/index.js",
8
- "types": "./dist/index.d.ts",
9
- "license": "EULA",
10
- "files": [
11
- "module",
12
- "locales",
13
- "dist",
14
- "server",
15
- "plugin.js",
16
- "utils.js",
17
- "utils.d.ts",
18
- "input-types.json"
19
- ],
20
- "scripts": {
21
- "patch": "npm version patch && git push && npm publish",
22
- "test": "node --test test/**/*.test.js",
23
- "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
24
- "dev": "NODE_ENV=dev bun --env-file=.env.ip server ",
25
- "admin": "vite admin",
26
- "build": "vite build admin",
27
- "build:lib": "vue-tsc -p tsconfig.build.json --noEmit && vite build && npm run build:types",
28
- "build:types": "vue-tsc -p tsconfig.types.json",
29
- "proxy": "vite dev admin",
30
- "start": "bun --env-file=.env.ip server",
31
- "prod": "NODE_ENV=production bun --env-file=.env.ip server ",
32
- "ip": "bun --env-file=.env.ip server",
33
- "lemken": "bun --env-file=.env.local-lemken server",
34
- "demo": "node --env-file=.env.demo --env-file=.env server",
35
- "i18n:sync": "node i18n-sync.cjs",
36
- "prepublishOnly": "bun build:lib",
37
- "softpro": "bun --env-file=.env.softpro server",
38
- "softpro1": "NODE_ENV=production bun --env-file=.env.prod-softpro.local server"
39
- },
40
- "resolutions": {
41
- "rollup": "4.30.0"
42
- },
43
- "devDependencies": {
44
- "@fastify/compress": "^8.1.0",
45
- "@opengis/core": "^0.0.30",
46
- "@opengis/fastify-table": "^2.0.147",
47
- "@opengis/filter": "^0.1.31",
48
- "@opengis/form": "^0.0.121",
49
- "@tailwindcss/typography": "0.5.10",
50
- "@tsconfig/node22": "^22.0.2",
51
- "@vitejs/plugin-vue": "5.0.4",
52
- "@vueuse/head": "2.0.0",
53
- "autoprefixer": "10.4.18",
54
- "eslint": "8.49.0",
55
- "js-yaml": "^4.1.0",
56
- "lucide-vue-next": "^0.564.0",
57
- "postcss": "8.4.35",
58
- "sass": "^1.92.1",
59
- "tailwindcss": "3.4.1",
60
- "typescript": "~5.8.0",
61
- "vite": "5.1.4",
62
- "vitest": "3.2.4",
63
- "vue": "^3.5.17",
64
- "vue-i18n": "11.1.5",
65
- "vue-router": "4.4.3",
66
- "vue-tsc": "^2.2.10",
67
- "vuedraggable": "4.1.0"
68
- }
69
- }
1
+ {
2
+ "name": "@opengis/cms",
3
+ "version": "0.0.61",
4
+ "description": "cms",
5
+ "type": "module",
6
+ "author": "Softpro",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "license": "EULA",
10
+ "files": [
11
+ "module",
12
+ "locales",
13
+ "dist",
14
+ "server",
15
+ "plugin.js",
16
+ "utils.js",
17
+ "utils.d.ts",
18
+ "input-types.json"
19
+ ],
20
+ "scripts": {
21
+ "patch": "npm version patch && git push && npm publish",
22
+ "test": "node --test test/**/*.test.js",
23
+ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
24
+ "dev": "NODE_ENV=dev bun --env-file=.env.ip server ",
25
+ "admin": "vite admin",
26
+ "build": "vite build admin",
27
+ "build:lib": "vue-tsc -p tsconfig.build.json --noEmit && vite build && npm run build:types",
28
+ "build:types": "vue-tsc -p tsconfig.types.json",
29
+ "proxy": "vite dev admin",
30
+ "start": "bun --env-file=.env.ip server",
31
+ "prod": "NODE_ENV=production bun --env-file=.env.ip server ",
32
+ "ip": "bun --env-file=.env.ip server",
33
+ "lemken": "bun --env-file=.env.local-lemken server",
34
+ "demo": "node --env-file=.env.demo --env-file=.env server",
35
+ "i18n:sync": "node i18n-sync.cjs",
36
+ "prepublishOnly": "bun build:lib",
37
+ "softpro": "bun --env-file=.env.softpro server",
38
+ "softpro1": "NODE_ENV=production bun --env-file=.env.prod-softpro.local server"
39
+ },
40
+ "resolutions": {
41
+ "rollup": "4.30.0"
42
+ },
43
+ "devDependencies": {
44
+ "@fastify/compress": "^8.1.0",
45
+ "@opengis/core": "^0.0.30",
46
+ "@opengis/fastify-table": "^2.0.147",
47
+ "@opengis/filter": "^0.1.31",
48
+ "@opengis/form": "^0.0.121",
49
+ "@tailwindcss/typography": "0.5.10",
50
+ "@tsconfig/node22": "^22.0.2",
51
+ "@vitejs/plugin-vue": "5.0.4",
52
+ "@vueuse/head": "2.0.0",
53
+ "autoprefixer": "10.4.18",
54
+ "eslint": "8.49.0",
55
+ "js-yaml": "^4.1.0",
56
+ "lucide-vue-next": "^0.564.0",
57
+ "postcss": "8.4.35",
58
+ "sass": "^1.92.1",
59
+ "tailwindcss": "3.4.1",
60
+ "typescript": "~5.8.0",
61
+ "vite": "5.1.4",
62
+ "vitest": "3.2.4",
63
+ "vue": "^3.5.17",
64
+ "vue-i18n": "11.1.5",
65
+ "vue-router": "4.4.3",
66
+ "vue-tsc": "^2.2.10",
67
+ "vuedraggable": "4.1.0"
68
+ }
69
+ }
@@ -1,10 +1,13 @@
1
1
  create schema if not exists site;
2
2
 
3
- ALTER TABLE if exists site.spaces add column if not exists locales text[];
3
+ /*ALTER TABLE if exists site.spaces add column if not exists locales text[];
4
4
  ALTER TABLE IF exists site.spaces add column if not exists default_locale text;
5
5
  ALTER TABLE if exists site.spaces alter column default_locale set default 'ua';
6
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;
7
+ ALTER TABLE if exists site.spaces alter column default_locale set not null;*/
8
+ -- uncomment after a while or leave old data as is
9
+ /* --- alter table site.contents drop column if exists space_id;
10
+ drop table if exists site.spaces cascade; */
8
11
 
9
12
  ALTER TABLE if exists site.media ADD COLUMN IF NOT EXISTS subdir TEXT;
10
13
  COMMENT ON COLUMN site.media.subdir is 'Піддиректорія';
@@ -271,7 +271,7 @@ COMMENT ON COLUMN site.tokens.token_type IS 'Type of token, such as CMA or PAT.'
271
271
  COMMENT ON COLUMN site.tokens.token_status IS 'Current status of the token (e.g., Active).';
272
272
  COMMENT ON COLUMN site.tokens.space_id IS 'Identifier for the associated space.';
273
273
 
274
- CREATE TABLE if not exists site.spaces (
274
+ /*CREATE TABLE if not exists site.spaces (
275
275
  space_id text PRIMARY KEY default next_id(), -- Unique identifier for the space
276
276
  name TEXT NOT NULL, -- Human-readable name of the space
277
277
  created_at TIMESTAMP NOT NULL default now(), -- When the space was created
@@ -296,6 +296,7 @@ COMMENT ON COLUMN site.spaces.default_locale IS 'Default language/locale of the
296
296
  COMMENT ON COLUMN site.spaces.plan IS 'Plan type (e.g., "Free", "Premium")';
297
297
 
298
298
  alter table site.spaces alter column default_locale set default 'uk';
299
+ */
299
300
 
300
301
  CREATE TABLE if not exists site.organizations (
301
302
  organization_id TEXT PRIMARY KEY DEFAULT next_id(), -- Unique identifier for the organization
@@ -348,7 +349,7 @@ COMMENT ON COLUMN site.comments.thread_id IS 'ID of the top-level thread this co
348
349
 
349
350
  CREATE TABLE if not exists site.contents (
350
351
  content_id text PRIMARY KEY default next_id(),
351
- space_id text,
352
+ -- space_id text,
352
353
  content_type_id text NOT NULL,
353
354
  created_at TIMESTAMP NOT NULL DEFAULT now(),
354
355
  updated_at TIMESTAMP NOT NULL DEFAULT now(),
@@ -363,7 +364,7 @@ CREATE TABLE if not exists site.contents (
363
364
  updated_by text,
364
365
  meta json,
365
366
  main_image text,
366
- FOREIGN KEY (space_id) REFERENCES site.spaces(space_id),
367
+ -- FOREIGN KEY (space_id) REFERENCES site.spaces(space_id),
367
368
  FOREIGN KEY (content_type_id) REFERENCES site.content_types(content_type_id),
368
369
  FOREIGN KEY (created_by) REFERENCES admin.users(uid),
369
370
  FOREIGN KEY (published_by) REFERENCES admin.users(uid),
@@ -11,15 +11,15 @@ export default async function deleteContent(req, reply) {
11
11
  const { type, id } = params;
12
12
 
13
13
  if (!type) {
14
- return reply.status(400).send('not enough params: type');
14
+ return reply.status(400).send({ error: 'not enough params: type', code: 400 });
15
15
  }
16
16
 
17
17
  if (!id) {
18
- return reply.status(400).send('not enough params: id');
18
+ return reply.status(400).send({ error: 'not enough params: id', code: 400 });
19
19
  }
20
20
 
21
21
  if (id === 'pages') {
22
- return reply.status(403).send('access restricted: pages contents cannot be deleted');
22
+ return reply.status(403).send({ error: 'access restricted: pages contents cannot be deleted', code: 403 });
23
23
  }
24
24
 
25
25
  const { ctid, dbtable } = await pg.query('select content_type_id as ctid, table_name as dbtable from site.content_types where $1 in (content_type_id, name)', [params.type])
@@ -30,7 +30,7 @@ export default async function deleteContent(req, reply) {
30
30
  where a.relam=2 and b.nspname='data'`).then(el => el.rows?.[0]?.array_agg || []) : [];
31
31
 
32
32
  if (!arr.length && type !== 'pages') {
33
- return reply.status(400).send('empty schema: data');
33
+ return reply.status(400).send({ error: 'empty schema: data', code: 400 });
34
34
  }
35
35
 
36
36
  const table = arr.find(el => el === params.type);
@@ -47,11 +47,11 @@ export default async function deleteContent(req, reply) {
47
47
  ).then(el => el.rows?.[0] || {});
48
48
 
49
49
  if (!cid) {
50
- return reply.status(404).send('contents not found');
50
+ return reply.status(404).send({ error: 'contents not found', code: 404 });
51
51
  }
52
52
 
53
53
  if (cid === 'pages') {
54
- return reply.status(403).send('access restricted: pages contents cannot be deleted');
54
+ return reply.status(403).send({ error: 'access restricted: pages contents cannot be deleted', code: 403 });
55
55
  }
56
56
 
57
57
  if (status === 'archived') {
@@ -81,7 +81,7 @@ export default async function deleteContent(req, reply) {
81
81
 
82
82
  // custom table
83
83
  if (!table && !dbtable) {
84
- return reply.status(400).send('invalid params: type');
84
+ return reply.status(400).send({ error: 'invalid params: type', code: 400 });
85
85
  }
86
86
 
87
87
  const status = await pg.query(`select status from data."${(table || dbtable)}" where id =$1`, [id]).then(el => el.rows?.[0]?.status);
@@ -57,11 +57,11 @@ export default async function getContent(req, reply, opt) {
57
57
  ).then(el => el.rows?.[0]?.isvalid);
58
58
 
59
59
  if (!config.local && !isValidToken && config.mode !== 'cms' && !called) {
60
- return reply.status(403).send('access restricted: token');
60
+ return reply.status(403).send({ error: 'access restricted: token', code: 403 });
61
61
  }
62
62
 
63
63
  if (!type) {
64
- return reply.status(400).send('not enough params: type');
64
+ return reply.status(400).send({ error: 'not enough params: type', code: 400 });
65
65
  }
66
66
 
67
67
  const { contentId, contentTypeId, meta } = params.type === 'pages'
@@ -69,7 +69,7 @@ export default async function getContent(req, reply, opt) {
69
69
  : await pg.query(`select content_id as "contentId", content_type_id as "contentTypeId", meta from site.contents where $1 in (slug, content_id, content_type_id)`, [params.type]).then(el => el.rows?.[0] || {});
70
70
 
71
71
  if (!contentId) {
72
- return reply.status(404).send('content not found');
72
+ return reply.status(404).send({ error: 'content not found', code: 404 });
73
73
  }
74
74
 
75
75
  const { table, contentType, preview, columns: columns1 } = await pg.query(
@@ -78,7 +78,7 @@ export default async function getContent(req, reply, opt) {
78
78
  ).then(el => el.rows?.[0] || {});
79
79
 
80
80
  if (!contentType && params.type !== 'pages') {
81
- return reply.status(404).send('content type not found');
81
+ return reply.status(404).send({ error: 'content type not found', code: 404 });
82
82
  }
83
83
 
84
84
  const loadTable = contentType === 'collection' && table
@@ -86,7 +86,7 @@ export default async function getContent(req, reply, opt) {
86
86
  : await getTemplate('table', 'single.default.table');
87
87
  const { columns: defaultColumns = [], filters: defaultFilters = [] } = loadTable || {};
88
88
 
89
- defaultColumns.forEach(col => Object.assign(col, { default: true }));
89
+ defaultColumns.forEach(col => Object.assign(col, { defaultColumn: true }));
90
90
 
91
91
  const columns = (columns1 || []).filter(col => !defaultColumns.map(el => el.name).includes(col.name));
92
92
 
@@ -105,7 +105,7 @@ export default async function getContent(req, reply, opt) {
105
105
  }
106
106
 
107
107
  if (result?.message) {
108
- return reply.status(result.status || 500).send(result.message);
108
+ return reply.status(result.status || 500).send({ error: result.message, code: result.status || 500 });
109
109
  }
110
110
 
111
111
  Object.assign(result, { meta });
@@ -4,11 +4,11 @@ import inputTypes from '../utils/inputTypes.js';
4
4
 
5
5
  export default async function getContentBySlug({ pg = pgClients.client, params = {}, headers = {} }, reply) {
6
6
  if (!params.slug) {
7
- return reply.status(400).send('not enough params: slug');
7
+ return reply.status(400).send({ error: 'not enough params: slug', code: 400 });
8
8
  }
9
9
 
10
10
  if (!pg?.pk?.['site.content_types']) {
11
- return reply.status(404).send('table not found');
11
+ return reply.status(404).send({ error: 'table not found', code: 404 });
12
12
  }
13
13
 
14
14
  // headers.authorization = 'Bearer tokenExample'
@@ -18,18 +18,18 @@ export default async function getContentBySlug({ pg = pgClients.client, params =
18
18
  ).then(el => el.rows?.[0]?.isvalid);
19
19
 
20
20
  if (!config.local && !isValidToken && config.mode !== 'cms') {
21
- return reply.status(403).send('access restricted: token');
21
+ return reply.status(403).send({ error: 'access restricted: token', code: 403 });
22
22
  }
23
23
 
24
- const { cid } = await pg.query(
25
- `select content_id as cid from site.contents where $1 in (content_id,slug) limit 1`,
24
+ const cid = await pg.query(
25
+ `select content_id from site.contents where $1 in (content_id,slug) limit 1`,
26
26
  [params.slug],
27
- ).then(el => el.rows?.[0] || {});
27
+ ).then(el => el.rows?.[0]?.content_id);
28
28
 
29
29
  if (cid) {
30
- const { rows: data = [] } = await pg.query(
30
+ const data = await pg.query(
31
31
  `select field_key, field_type, field_value, field_value_object, content_id from site.content_data where content_id=$1`, [cid]
32
- );
32
+ ).then(el => el.rows || []);
33
33
 
34
34
  const meta = await pg.query(
35
35
  'select title, status, revision, locale, slug, content_type_id, (select columns from site.content_types where content_type_id=a.content_type_id limit 1) as columns from site.contents a where content_id=$1 limit 1',
@@ -63,7 +63,7 @@ export default async function getContentBySlug({ pg = pgClients.client, params =
63
63
  const { rows: contentTypes = [] } = await pg.query(`select content_type_id as ctid, table_name as table, type from site.content_types where table_name is not null and type='collection' `);
64
64
 
65
65
  if (!contentTypes.length || contentTypes.find(row => row.table && pg.pk[row.table])) {
66
- return reply.status(404).send('content not found');
66
+ return reply.status(404).send({ error: 'content not found', code: 404 });
67
67
  }
68
68
 
69
69
  const tlist = await pg.query(`select array_agg((select nspname from pg_namespace where oid=relnamespace)||'.'||relname) tlist
@@ -74,20 +74,20 @@ export default async function getContentBySlug({ pg = pgClients.client, params =
74
74
  const { dataid, ctid } = await pg.query(q).then(el => el.rows?.[0] || {});
75
75
 
76
76
  if (!dataid) {
77
- return reply.status(404).send('content not found: 2');
77
+ return reply.status(404).send({ error: 'content not found: 2', code: 404 });
78
78
  }
79
79
 
80
80
  if (!ctid) {
81
- return reply.status(404).send('content not found: 3');
81
+ return reply.status(404).send({ error: 'content not found: 3', code: 404 });
82
82
  }
83
83
 
84
84
  const meta = await pg.query('select content_type_id, type, table_name as table, title, status, name as slug, columns from site.content_types where content_type_id=$1', [ctid]).then(el => el.rows?.[0] || {});
85
85
 
86
86
  if (!meta?.table) {
87
- return reply.status(404).send('content not found: 4');
87
+ return reply.status(404).send({ error: 'content not found: 4', code: 404 });
88
88
  }
89
89
 
90
- const { rows = [] } = await pg.query(`select * from data.${meta.table} where id=$1`, [dataid]);
90
+ const rows = await pg.query(`select * from data.${meta.table} where id=$1`, [dataid]).then(el => el.rows || []);
91
91
 
92
92
  return reply.status(200).send({ ...meta, custom: true, rows });
93
93
  }