@brightsideoy/kama 0.1.0-alpha.157 → 0.1.0-alpha.159

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.
@@ -1852,24 +1852,6 @@ var u = /* @__PURE__ */ o({
1852
1852
  },
1853
1853
  required: !0
1854
1854
  },
1855
- logoText: {
1856
- label: "Logo Text",
1857
- type: "text",
1858
- required: !1,
1859
- public: !0,
1860
- inherits: "logoText",
1861
- rules: { required: !1 }
1862
- },
1863
- logoImage: {
1864
- label: "Logo Image",
1865
- type: "image",
1866
- maxPreviewWidth: "300px",
1867
- multiple: !1,
1868
- allowedTypes: ["image/svg"],
1869
- public: !0,
1870
- inherits: "logoImage",
1871
- rules: {}
1872
- },
1873
1855
  layoutId: {
1874
1856
  label: "Page Layout",
1875
1857
  type: "layout-select",
@@ -2198,24 +2180,6 @@ var u = /* @__PURE__ */ o({
2198
2180
  },
2199
2181
  required: !0
2200
2182
  },
2201
- logoText: {
2202
- label: "Logo Text",
2203
- type: "text",
2204
- required: !1,
2205
- public: !0,
2206
- inherits: "logoText",
2207
- rules: { required: !1 }
2208
- },
2209
- logoImage: {
2210
- label: "Logo Image",
2211
- type: "image",
2212
- maxPreviewWidth: "300px",
2213
- multiple: !1,
2214
- allowedTypes: ["image/svg"],
2215
- public: !0,
2216
- inherits: "logoImage",
2217
- rules: {}
2218
- },
2219
2183
  layoutId: {
2220
2184
  label: "Page Layout",
2221
2185
  type: "layout-select",
@@ -4075,6 +4039,7 @@ var u = /* @__PURE__ */ o({
4075
4039
  footer: {
4076
4040
  label: "Footer",
4077
4041
  inherit: "parent",
4042
+ purgeTargets: ["/partials/footer"],
4078
4043
  disallowedBlocks: [
4079
4044
  "hero",
4080
4045
  "image_card",
@@ -4128,6 +4093,7 @@ var u = /* @__PURE__ */ o({
4128
4093
  footer: {
4129
4094
  label: "Footer",
4130
4095
  inherit: "parent",
4096
+ purgeTargets: ["/partials/footer"],
4131
4097
  disallowedBlocks: [
4132
4098
  "hero",
4133
4099
  "image_card",
@@ -4190,6 +4156,7 @@ var u = /* @__PURE__ */ o({
4190
4156
  footer: {
4191
4157
  label: "Footer",
4192
4158
  inherit: "parent",
4159
+ purgeTargets: ["/partials/footer"],
4193
4160
  disallowedBlocks: [
4194
4161
  "hero",
4195
4162
  "image_card",
@@ -6077,52 +6044,80 @@ var V = class {
6077
6044
  console.warn("[CacheManager] Failed to purge internal worker cache:", e);
6078
6045
  }
6079
6046
  }
6080
- purgeNode(e, t, n, r = !1) {
6081
- let i = (async () => {
6047
+ purgeNode(e, t, n, r = !1, i = []) {
6048
+ let a = (async () => {
6082
6049
  try {
6083
- let i = t.prepare("SELECT slug, status, language FROM content_nodes WHERE id = ?"), a = (typeof i.get == "function" ? await i.get(n) : (await i.bind(n).all())?.results?.[0]) || {};
6084
- if (!a.slug) return;
6085
- let o = t.prepare("\n SELECT c.id, c.key, c.baseUrl, c.defaultLanguage \n FROM node_channels nc \n JOIN channels c ON nc.channelId = c.id \n WHERE nc.nodeId = ?\n "), s = typeof o.all == "function" ? await o.all(n) : await o.bind(n).all(), c = Array.isArray(s) ? s : s?.results || [], l = c.length > 0 ? c[0]?.defaultLanguage?.trim() : null, u = a.language?.trim() || l || null, d = String(a.slug).replace(/^\/+|\/+$/g, ""), f = this.getEnv(e).frontendUrl, p = /* @__PURE__ */ new Set();
6086
- for (let e of c) if (e.baseUrl && typeof e.baseUrl == "string" && e.baseUrl.trim() !== "") {
6050
+ let a = t.prepare("SELECT slug, status, language FROM content_nodes WHERE id = ?"), o = (typeof a.get == "function" ? await a.get(n) : (await a.bind(n).all())?.results?.[0]) || {};
6051
+ if (!o.slug) return;
6052
+ let s = t.prepare("\n SELECT c.id, c.key, c.baseUrl, c.defaultLanguage \n FROM node_channels nc \n JOIN channels c ON nc.channelId = c.id \n WHERE nc.nodeId = ?\n "), c = typeof s.all == "function" ? await s.all(n) : await s.bind(n).all(), l = Array.isArray(c) ? c : c?.results || [], u = l.length > 0 ? l[0]?.defaultLanguage?.trim() : null, d = o.language?.trim() || u || null, f = String(o.slug).replace(/^\/+|\/+$/g, ""), p = this.getEnv(e).frontendUrl, m = /* @__PURE__ */ new Set();
6053
+ for (let e of l) if (e.baseUrl && typeof e.baseUrl == "string" && e.baseUrl.trim() !== "") {
6087
6054
  let t = e.baseUrl.trim();
6088
- !t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), p.add(t.replace(/\/+$/, ""));
6055
+ !t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), m.add(t.replace(/\/+$/, ""));
6056
+ }
6057
+ m.size === 0 && p && m.add(p);
6058
+ let h = t.prepare("\n SELECT DISTINCT a.cdnUrl, a.storageKeyPrivate\n FROM node_assets na\n JOIN assets a ON na.assetId = a.id\n WHERE na.nodeId = ?\n "), g = typeof h.all == "function" ? await h.all(n) : await h.bind(n).all(), _ = (Array.isArray(g) ? g : g?.results || []).map((t) => t.url || this.getSafeUrl(t.cdnUrl, t.storageKeyPrivate, this.getEnv(e).cdnDomain)).filter(Boolean);
6059
+ await this.purgeInternalWorkerCache(e, t, n, f, d);
6060
+ let v = this.getEnv(e).cdnDomain, { zoneId: y, apiToken: b } = this.getEnv(e), x = e.env?.BUNDLED_DEFINITIONS || {}, S = /* @__PURE__ */ new Set();
6061
+ if (i.length > 0 && x.layouts) for (let e of Object.values(x.layouts)) for (let t of i) {
6062
+ let n = e.regions?.[t];
6063
+ if (n) {
6064
+ let e = n.purgeTargets || n.purgeTarget;
6065
+ if (e) {
6066
+ let t = Array.isArray(e) ? e : [e];
6067
+ for (let e of t) typeof e == "string" && e.trim() && S.add(e.trim());
6068
+ }
6069
+ }
6089
6070
  }
6090
- p.size === 0 && f && p.add(f);
6091
- let m = t.prepare("\n SELECT DISTINCT a.cdnUrl, a.storageKeyPrivate\n FROM node_assets na\n JOIN assets a ON na.assetId = a.id\n WHERE na.nodeId = ?\n "), h = typeof m.all == "function" ? await m.all(n) : await m.bind(n).all(), g = (Array.isArray(h) ? h : h?.results || []).map((t) => t.url || this.getSafeUrl(t.cdnUrl, t.storageKeyPrivate, this.getEnv(e).cdnDomain)).filter(Boolean);
6092
- await this.purgeInternalWorkerCache(e, t, n, d, u);
6093
- let _ = this.getEnv(e).cdnDomain, { zoneId: v, apiToken: y } = this.getEnv(e);
6094
- for (let t of p) {
6095
- let n = d === "home" || !d ? t : `${t}/${d}`, i = [n, `${n}/`], a = u ? `&lang=${u}` : "";
6096
- if (c.length > 0) for (let e of c) e.id && i.push(`https://${_}/api/v1/node/${d}?channelId=${e.id}${a}`), e.key && i.push(`https://${_}/api/v1/node/${d}?channelId=${e.key}${a}`);
6097
- else i.push(`https://${_}/api/v1/node/${d}${u ? `?lang=${u}` : ""}`);
6098
- for (let e of g) e && i.push(`${t}${e.startsWith("/") ? e : `/${e}`}`);
6099
- if (await this.callAstroPurge(e, { urls: i }, t), v && y && !this.isLocalEnv(e, t) && fetch(`https://api.cloudflare.com/client/v4/zones/${v}/purge_cache`, {
6071
+ for (let t of m) {
6072
+ let n = f === "home" || !f ? t : `${t}/${f}`, i = [n, `${n}/`];
6073
+ r && i.push(`${t}/partials/nav`);
6074
+ for (let e of S) {
6075
+ let n = e.startsWith("/") ? e : `/${e}`;
6076
+ i.push(`${t}${n}`);
6077
+ }
6078
+ let a = d ? `&lang=${d}` : "";
6079
+ if (l.length > 0) for (let e of l) e.id && i.push(`https://${v}/api/v1/node/${f}?channelId=${e.id}${a}`), e.key && i.push(`https://${v}/api/v1/node/${f}?channelId=${e.key}${a}`), r && (e.id && i.push(`https://${v}/api/v1/tree/main-nav?channelId=${e.id}`), e.key && i.push(`https://${v}/api/v1/tree/main-nav?channelId=${e.key}`));
6080
+ else i.push(`https://${v}/api/v1/node/${f}${d ? `?lang=${d}` : ""}`), r && i.push(`https://${v}/api/v1/tree/main-nav`);
6081
+ for (let e of _) e && i.push(`${t}${e.startsWith("/") ? e : `/${e}`}`);
6082
+ if (await this.callAstroPurge(e, { urls: i }, t), y && b && !this.isLocalEnv(e, t) && fetch(`https://api.cloudflare.com/client/v4/zones/${y}/purge_cache`, {
6100
6083
  method: "POST",
6101
6084
  headers: {
6102
- Authorization: `Bearer ${y}`,
6085
+ Authorization: `Bearer ${b}`,
6103
6086
  "Content-Type": "application/json"
6104
6087
  },
6105
6088
  body: JSON.stringify({ files: i })
6106
- }).catch(() => {}), !r) {
6089
+ }).catch(() => {}), r) {
6090
+ let e = `${t}/partials/nav?_warmer=${Date.now()}`;
6091
+ console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
6092
+ "X-Cache-Warmer": "true",
6093
+ "User-Agent": "Kama-Cache-Warmer/1.0"
6094
+ } }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
6095
+ } else {
6107
6096
  let e = `${n}${n.includes("?") ? "&" : "?"} _warmer=${Date.now()}`;
6108
6097
  console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
6109
6098
  "X-Cache-Warmer": "true",
6110
6099
  "User-Agent": "Kama-Cache-Warmer/1.0"
6111
6100
  } }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
6112
6101
  }
6102
+ for (let e of S) {
6103
+ let n = `${t}${e.startsWith("/") ? e : `/${e}`}?_warmer=${Date.now()}`;
6104
+ console.log(`[CacheManager] Prewarming custom target: ${n}`), fetch(n, { headers: {
6105
+ "X-Cache-Warmer": "true",
6106
+ "User-Agent": "Kama-Cache-Warmer/1.0"
6107
+ } }).catch(() => {});
6108
+ }
6113
6109
  }
6114
- r && await this.purgeGlobalCacheDirect(e, t);
6115
6110
  } catch (e) {
6116
6111
  console.warn("[CacheManager] Dynamic purgeNode failed:", e);
6117
6112
  }
6118
6113
  })();
6119
- this.dispatch(e, i);
6114
+ this.dispatch(e, a);
6120
6115
  }
6121
6116
  purgeAsset(e, t, n) {
6122
6117
  let r = (async () => {
6123
6118
  try {
6124
6119
  let r = t.prepare("\n SELECT DISTINCT cn.id\n FROM node_assets na\n INNER JOIN content_nodes cn ON na.nodeId = cn.id\n LEFT JOIN assets crop ON na.assetId = crop.id\n WHERE cn.status = 'published' AND (\n na.assetId = ? OR crop.parentAssetId = ? OR crop.id = (SELECT parentAssetId FROM assets WHERE id = ?)\n )\n "), i = typeof r.all == "function" ? await r.all(n, n, n) : await r.bind(n, n, n).all(), a = Array.isArray(i) ? i : i?.results || [];
6125
- for (let n of a) n.id && this.purgeNode(e, t, n.id, !1);
6120
+ for (let n of a) n.id && this.purgeNode(e, t, n.id, !1, []);
6126
6121
  } catch (e) {
6127
6122
  console.warn("[CacheManager] purgeAsset failed:", e);
6128
6123
  }
@@ -6565,7 +6560,7 @@ H.get("/", async (e) => {
6565
6560
  await he(t, n, i);
6566
6561
  }
6567
6562
  }
6568
- return await I(e).clear(), D && new V(e.env).purgeNode(e, t, D, k), e.json({
6563
+ return await I(e).clear(), e.json({
6569
6564
  success: !0,
6570
6565
  id: D,
6571
6566
  status: "draft",
@@ -6782,7 +6777,7 @@ W.get("/tree.json", async (e) => {
6782
6777
  c.push(e.id, e.sortOrder);
6783
6778
  }), c.push(...i), c.push(o), await t.prepare(s).run(...c);
6784
6779
  }
6785
- return await i.clear(), a.purgeGlobalCache(e, t), e.json({
6780
+ return await i.clear(), r.length > 0 && a.purgeNode(e, t, r[0].id, !0), e.json({
6786
6781
  success: !0,
6787
6782
  reorderedCount: r.length
6788
6783
  });
@@ -6791,9 +6786,9 @@ W.get("/tree.json", async (e) => {
6791
6786
  delete m._isTreeDraft, delete m._draftParentId, delete m.isNew, delete m.nodeType, delete m.contentType, delete m.title, delete m.slug, delete m.hidden, delete m.is_hidden, delete m.isHidden, delete m.status;
6792
6787
  let g = G(u), _ = e.get("user")?.id || null;
6793
6788
  if (s === "create") {
6794
- let r = m.slug || n.slug || c, s = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
6795
- if (s) {
6796
- let r = g === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = n.contentId || n.id ? Number(n.contentId || n.id) : null, a = `
6789
+ let r = m.slug || n.slug || c, a = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
6790
+ if (a) {
6791
+ let r = g === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = n.contentId || n.id ? Number(n.contentId || n.id) : null, s = `
6797
6792
  SELECT 1
6798
6793
  FROM tree_nodes tn
6799
6794
  INNER JOIN content_nodes cn ON tn.contentId = cn.id
@@ -6801,51 +6796,51 @@ W.get("/tree.json", async (e) => {
6801
6796
  AND ${r}
6802
6797
  AND cn.slug = ?
6803
6798
  AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
6804
- `, c = g === null ? [o, s] : [
6799
+ `, c = g === null ? [o, a] : [
6805
6800
  o,
6806
6801
  g,
6807
- s
6802
+ a
6808
6803
  ];
6809
- if (i && !isNaN(i) && (a += " AND cn.id != ?", c.push(i)), a += " LIMIT 1", await t.prepare(a).get(...c)) return e.json({
6810
- error: `The slug '${s}' is already in use by another page in this section.`,
6804
+ if (i && !isNaN(i) && (s += " AND cn.id != ?", c.push(i)), s += " LIMIT 1", await t.prepare(s).get(...c)) return e.json({
6805
+ error: `The slug '${a}' is already in use by another page in this section.`,
6811
6806
  field: "slug"
6812
6807
  }, 409);
6813
6808
  }
6814
- let u = m.language?.trim() || n.language?.trim() || null;
6815
- if (!u) {
6809
+ let s = m.language?.trim() || n.language?.trim() || null;
6810
+ if (!s) {
6816
6811
  let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ?").get(o);
6817
6812
  if (e?.dataJson) try {
6818
6813
  let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
6819
- t.defaultLanguage && (u = t.defaultLanguage.trim());
6814
+ t.defaultLanguage && (s = t.defaultLanguage.trim());
6820
6815
  } catch {}
6821
6816
  }
6822
- if (!u) {
6817
+ if (!s) {
6823
6818
  let e = [];
6824
6819
  if (n.channels && Array.isArray(n.channels) ? e = n.channels : n.channelId && n.channelId !== "all" && (e = [n.channelId]), e.length > 0) {
6825
6820
  let n = Number(e[0]);
6826
6821
  if (!isNaN(n)) {
6827
6822
  let e = await t.prepare("SELECT defaultLanguage FROM channels WHERE id = ?").get(n);
6828
- e?.defaultLanguage && (u = e.defaultLanguage.trim());
6823
+ e?.defaultLanguage && (s = e.defaultLanguage.trim());
6829
6824
  }
6830
6825
  }
6831
6826
  }
6832
- let d = JSON.stringify(m), f = await t.prepare("\n INSERT INTO content_nodes (contentType, title, slug, language, isHidden, status, draftDataJson, dataJson, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, 'draft', ?, NULL, ?, ?)\n ").run(l || "page", c || "Untitled", s, u, h, d, _, _), p = Number(f.lastInsertRowid);
6833
- await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, p);
6834
- let v = g === null ? "parentId IS NULL" : "parentId = ?", y = g === null ? [o] : [o, g], b = (await t.prepare(`
6827
+ let u = JSON.stringify(m), d = await t.prepare("\n INSERT INTO content_nodes (contentType, title, slug, language, isHidden, status, draftDataJson, dataJson, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, 'draft', ?, NULL, ?, ?)\n ").run(l || "page", c || "Untitled", a, s, h, u, _, _), f = Number(d.lastInsertRowid);
6828
+ await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, f);
6829
+ let p = g === null ? "parentId IS NULL" : "parentId = ?", v = g === null ? [o] : [o, g], y = (await t.prepare(`
6835
6830
  SELECT COALESCE(MAX(sortOrder), -1) + 1 as nextSort
6836
6831
  FROM tree_nodes
6837
- WHERE treeId = ? AND ${v}
6838
- `).get(...y))?.nextSort ?? 0, x = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, ?)\n ").run(o, p, g, b), S = Number(x.lastInsertRowid), C = [];
6839
- n.channels && Array.isArray(n.channels) ? C = n.channels : n.channelId && n.channelId !== "all" && (C = [n.channelId]);
6840
- let w = [...new Set(C)].filter((e) => e && e !== "all").map((e) => Number(e));
6841
- if (w.length > 0) {
6842
- let e = w.map(() => "(?, ?)").join(", "), n = w.flatMap((e) => [p, e]);
6832
+ WHERE treeId = ? AND ${p}
6833
+ `).get(...v))?.nextSort ?? 0, b = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, ?)\n ").run(o, f, g, y), x = Number(b.lastInsertRowid), S = [];
6834
+ n.channels && Array.isArray(n.channels) ? S = n.channels : n.channelId && n.channelId !== "all" && (S = [n.channelId]);
6835
+ let C = [...new Set(S)].filter((e) => e && e !== "all").map((e) => Number(e));
6836
+ if (C.length > 0) {
6837
+ let e = C.map(() => "(?, ?)").join(", "), n = C.flatMap((e) => [f, e]);
6843
6838
  await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...n);
6844
6839
  }
6845
- return await i.clear(), a.purgeGlobalCache(e, t), e.json({
6840
+ return await i.clear(), e.json({
6846
6841
  success: !0,
6847
- id: p,
6848
- treeNodeId: S,
6842
+ id: f,
6843
+ treeNodeId: x,
6849
6844
  status: "draft"
6850
6845
  }, 201);
6851
6846
  }
@@ -6880,14 +6875,14 @@ W.get("/tree.json", async (e) => {
6880
6875
  }
6881
6876
  await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, d);
6882
6877
  let r = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, 0)\n ").run(o, d, g), s = Number(r.lastInsertRowid);
6883
- return await i.clear(), a.purgeGlobalCache(e, t), e.json({
6878
+ return await i.clear(), a.purgeNode(e, t, d, !0), e.json({
6884
6879
  success: !0,
6885
6880
  treeNodeId: s
6886
6881
  });
6887
6882
  }
6888
6883
  if (s === "detach") {
6889
6884
  let r = n.treeNodeId || n.contentId;
6890
- return r ? (await t.prepare("\n UPDATE tree_nodes \n SET parentId = (SELECT parentId FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?) \n WHERE parentId = ? AND treeId = ?\n ").run(r, r, o, r, o), await t.prepare("DELETE FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?").run(r, r, o), await i.clear(), a.purgeGlobalCache(e, t), e.json({ success: !0 })) : e.json({ error: "treeNodeId or contentId required for detach" }, 400);
6885
+ return r ? (await t.prepare("\n UPDATE tree_nodes \n SET parentId = (SELECT parentId FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?) \n WHERE parentId = ? AND treeId = ?\n ").run(r, r, o, r, o), await t.prepare("DELETE FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?").run(r, r, o), await i.clear(), a.purgeNode(e, t, r, !0), e.json({ success: !0 })) : e.json({ error: "treeNodeId or contentId required for detach" }, 400);
6891
6886
  }
6892
6887
  return e.json({ error: "Invalid payload or action" }, 400);
6893
6888
  } catch (t) {
@@ -6951,7 +6946,7 @@ W.get("/tree.json", async (e) => {
6951
6946
  await t.prepare(`INSERT OR IGNORE INTO channel_trees (channelId, treeId, key) VALUES ${n}`).run(...r);
6952
6947
  }
6953
6948
  }
6954
- return await I(e).clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
6949
+ return await cache.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
6955
6950
  success: !0,
6956
6951
  id: p,
6957
6952
  key: o,
package/dist/index.html CHANGED
@@ -6,8 +6,8 @@
6
6
  <title>KAMA</title>
7
7
  <link rel="icon" href="/favicon.png">
8
8
  <link rel="apple-touch-icon" sizes="180x180" href="/favicon.png">
9
- <script type="module" crossorigin src="/assets/index-BesA3e7A.js"></script>
10
- <link rel="stylesheet" crossorigin href="/assets/index-D6yHZ_u1.css">
9
+ <script type="module" crossorigin src="/assets/index-DIxtk5i5.js"></script>
10
+ <link rel="stylesheet" crossorigin href="/assets/index-C5TmJVER.css">
11
11
  </head>
12
12
  <body>
13
13
  <div id="app"></div>
package/dist/index.js CHANGED
@@ -1854,24 +1854,6 @@ var u = /* @__PURE__ */ o({
1854
1854
  },
1855
1855
  required: !0
1856
1856
  },
1857
- logoText: {
1858
- label: "Logo Text",
1859
- type: "text",
1860
- required: !1,
1861
- public: !0,
1862
- inherits: "logoText",
1863
- rules: { required: !1 }
1864
- },
1865
- logoImage: {
1866
- label: "Logo Image",
1867
- type: "image",
1868
- maxPreviewWidth: "300px",
1869
- multiple: !1,
1870
- allowedTypes: ["image/svg"],
1871
- public: !0,
1872
- inherits: "logoImage",
1873
- rules: {}
1874
- },
1875
1857
  layoutId: {
1876
1858
  label: "Page Layout",
1877
1859
  type: "layout-select",
@@ -2200,24 +2182,6 @@ var u = /* @__PURE__ */ o({
2200
2182
  },
2201
2183
  required: !0
2202
2184
  },
2203
- logoText: {
2204
- label: "Logo Text",
2205
- type: "text",
2206
- required: !1,
2207
- public: !0,
2208
- inherits: "logoText",
2209
- rules: { required: !1 }
2210
- },
2211
- logoImage: {
2212
- label: "Logo Image",
2213
- type: "image",
2214
- maxPreviewWidth: "300px",
2215
- multiple: !1,
2216
- allowedTypes: ["image/svg"],
2217
- public: !0,
2218
- inherits: "logoImage",
2219
- rules: {}
2220
- },
2221
2185
  layoutId: {
2222
2186
  label: "Page Layout",
2223
2187
  type: "layout-select",
@@ -4077,6 +4041,7 @@ var u = /* @__PURE__ */ o({
4077
4041
  footer: {
4078
4042
  label: "Footer",
4079
4043
  inherit: "parent",
4044
+ purgeTargets: ["/partials/footer"],
4080
4045
  disallowedBlocks: [
4081
4046
  "hero",
4082
4047
  "image_card",
@@ -4130,6 +4095,7 @@ var u = /* @__PURE__ */ o({
4130
4095
  footer: {
4131
4096
  label: "Footer",
4132
4097
  inherit: "parent",
4098
+ purgeTargets: ["/partials/footer"],
4133
4099
  disallowedBlocks: [
4134
4100
  "hero",
4135
4101
  "image_card",
@@ -4192,6 +4158,7 @@ var u = /* @__PURE__ */ o({
4192
4158
  footer: {
4193
4159
  label: "Footer",
4194
4160
  inherit: "parent",
4161
+ purgeTargets: ["/partials/footer"],
4195
4162
  disallowedBlocks: [
4196
4163
  "hero",
4197
4164
  "image_card",
@@ -6095,52 +6062,80 @@ var V = class {
6095
6062
  console.warn("[CacheManager] Failed to purge internal worker cache:", e);
6096
6063
  }
6097
6064
  }
6098
- purgeNode(e, t, n, r = !1) {
6099
- let i = (async () => {
6065
+ purgeNode(e, t, n, r = !1, i = []) {
6066
+ let a = (async () => {
6100
6067
  try {
6101
- let i = t.prepare("SELECT slug, status, language FROM content_nodes WHERE id = ?"), a = (typeof i.get == "function" ? await i.get(n) : (await i.bind(n).all())?.results?.[0]) || {};
6102
- if (!a.slug) return;
6103
- let o = t.prepare("\n SELECT c.id, c.key, c.baseUrl, c.defaultLanguage \n FROM node_channels nc \n JOIN channels c ON nc.channelId = c.id \n WHERE nc.nodeId = ?\n "), s = typeof o.all == "function" ? await o.all(n) : await o.bind(n).all(), c = Array.isArray(s) ? s : s?.results || [], l = c.length > 0 ? c[0]?.defaultLanguage?.trim() : null, u = a.language?.trim() || l || null, d = String(a.slug).replace(/^\/+|\/+$/g, ""), f = this.getEnv(e).frontendUrl, p = /* @__PURE__ */ new Set();
6104
- for (let e of c) if (e.baseUrl && typeof e.baseUrl == "string" && e.baseUrl.trim() !== "") {
6068
+ let a = t.prepare("SELECT slug, status, language FROM content_nodes WHERE id = ?"), o = (typeof a.get == "function" ? await a.get(n) : (await a.bind(n).all())?.results?.[0]) || {};
6069
+ if (!o.slug) return;
6070
+ let s = t.prepare("\n SELECT c.id, c.key, c.baseUrl, c.defaultLanguage \n FROM node_channels nc \n JOIN channels c ON nc.channelId = c.id \n WHERE nc.nodeId = ?\n "), c = typeof s.all == "function" ? await s.all(n) : await s.bind(n).all(), l = Array.isArray(c) ? c : c?.results || [], u = l.length > 0 ? l[0]?.defaultLanguage?.trim() : null, d = o.language?.trim() || u || null, f = String(o.slug).replace(/^\/+|\/+$/g, ""), p = this.getEnv(e).frontendUrl, m = /* @__PURE__ */ new Set();
6071
+ for (let e of l) if (e.baseUrl && typeof e.baseUrl == "string" && e.baseUrl.trim() !== "") {
6105
6072
  let t = e.baseUrl.trim();
6106
- !t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), p.add(t.replace(/\/+$/, ""));
6073
+ !t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), m.add(t.replace(/\/+$/, ""));
6074
+ }
6075
+ m.size === 0 && p && m.add(p);
6076
+ let h = t.prepare("\n SELECT DISTINCT a.cdnUrl, a.storageKeyPrivate\n FROM node_assets na\n JOIN assets a ON na.assetId = a.id\n WHERE na.nodeId = ?\n "), g = typeof h.all == "function" ? await h.all(n) : await h.bind(n).all(), _ = (Array.isArray(g) ? g : g?.results || []).map((t) => t.url || this.getSafeUrl(t.cdnUrl, t.storageKeyPrivate, this.getEnv(e).cdnDomain)).filter(Boolean);
6077
+ await this.purgeInternalWorkerCache(e, t, n, f, d);
6078
+ let v = this.getEnv(e).cdnDomain, { zoneId: y, apiToken: b } = this.getEnv(e), x = e.env?.BUNDLED_DEFINITIONS || {}, S = /* @__PURE__ */ new Set();
6079
+ if (i.length > 0 && x.layouts) for (let e of Object.values(x.layouts)) for (let t of i) {
6080
+ let n = e.regions?.[t];
6081
+ if (n) {
6082
+ let e = n.purgeTargets || n.purgeTarget;
6083
+ if (e) {
6084
+ let t = Array.isArray(e) ? e : [e];
6085
+ for (let e of t) typeof e == "string" && e.trim() && S.add(e.trim());
6086
+ }
6087
+ }
6107
6088
  }
6108
- p.size === 0 && f && p.add(f);
6109
- let m = t.prepare("\n SELECT DISTINCT a.cdnUrl, a.storageKeyPrivate\n FROM node_assets na\n JOIN assets a ON na.assetId = a.id\n WHERE na.nodeId = ?\n "), h = typeof m.all == "function" ? await m.all(n) : await m.bind(n).all(), g = (Array.isArray(h) ? h : h?.results || []).map((t) => t.url || this.getSafeUrl(t.cdnUrl, t.storageKeyPrivate, this.getEnv(e).cdnDomain)).filter(Boolean);
6110
- await this.purgeInternalWorkerCache(e, t, n, d, u);
6111
- let _ = this.getEnv(e).cdnDomain, { zoneId: v, apiToken: y } = this.getEnv(e);
6112
- for (let t of p) {
6113
- let n = d === "home" || !d ? t : `${t}/${d}`, i = [n, `${n}/`], a = u ? `&lang=${u}` : "";
6114
- if (c.length > 0) for (let e of c) e.id && i.push(`https://${_}/api/v1/node/${d}?channelId=${e.id}${a}`), e.key && i.push(`https://${_}/api/v1/node/${d}?channelId=${e.key}${a}`);
6115
- else i.push(`https://${_}/api/v1/node/${d}${u ? `?lang=${u}` : ""}`);
6116
- for (let e of g) e && i.push(`${t}${e.startsWith("/") ? e : `/${e}`}`);
6117
- if (await this.callAstroPurge(e, { urls: i }, t), v && y && !this.isLocalEnv(e, t) && fetch(`https://api.cloudflare.com/client/v4/zones/${v}/purge_cache`, {
6089
+ for (let t of m) {
6090
+ let n = f === "home" || !f ? t : `${t}/${f}`, i = [n, `${n}/`];
6091
+ r && i.push(`${t}/partials/nav`);
6092
+ for (let e of S) {
6093
+ let n = e.startsWith("/") ? e : `/${e}`;
6094
+ i.push(`${t}${n}`);
6095
+ }
6096
+ let a = d ? `&lang=${d}` : "";
6097
+ if (l.length > 0) for (let e of l) e.id && i.push(`https://${v}/api/v1/node/${f}?channelId=${e.id}${a}`), e.key && i.push(`https://${v}/api/v1/node/${f}?channelId=${e.key}${a}`), r && (e.id && i.push(`https://${v}/api/v1/tree/main-nav?channelId=${e.id}`), e.key && i.push(`https://${v}/api/v1/tree/main-nav?channelId=${e.key}`));
6098
+ else i.push(`https://${v}/api/v1/node/${f}${d ? `?lang=${d}` : ""}`), r && i.push(`https://${v}/api/v1/tree/main-nav`);
6099
+ for (let e of _) e && i.push(`${t}${e.startsWith("/") ? e : `/${e}`}`);
6100
+ if (await this.callAstroPurge(e, { urls: i }, t), y && b && !this.isLocalEnv(e, t) && fetch(`https://api.cloudflare.com/client/v4/zones/${y}/purge_cache`, {
6118
6101
  method: "POST",
6119
6102
  headers: {
6120
- Authorization: `Bearer ${y}`,
6103
+ Authorization: `Bearer ${b}`,
6121
6104
  "Content-Type": "application/json"
6122
6105
  },
6123
6106
  body: JSON.stringify({ files: i })
6124
- }).catch(() => {}), !r) {
6107
+ }).catch(() => {}), r) {
6108
+ let e = `${t}/partials/nav?_warmer=${Date.now()}`;
6109
+ console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
6110
+ "X-Cache-Warmer": "true",
6111
+ "User-Agent": "Kama-Cache-Warmer/1.0"
6112
+ } }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
6113
+ } else {
6125
6114
  let e = `${n}${n.includes("?") ? "&" : "?"} _warmer=${Date.now()}`;
6126
6115
  console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
6127
6116
  "X-Cache-Warmer": "true",
6128
6117
  "User-Agent": "Kama-Cache-Warmer/1.0"
6129
6118
  } }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
6130
6119
  }
6120
+ for (let e of S) {
6121
+ let n = `${t}${e.startsWith("/") ? e : `/${e}`}?_warmer=${Date.now()}`;
6122
+ console.log(`[CacheManager] Prewarming custom target: ${n}`), fetch(n, { headers: {
6123
+ "X-Cache-Warmer": "true",
6124
+ "User-Agent": "Kama-Cache-Warmer/1.0"
6125
+ } }).catch(() => {});
6126
+ }
6131
6127
  }
6132
- r && await this.purgeGlobalCacheDirect(e, t);
6133
6128
  } catch (e) {
6134
6129
  console.warn("[CacheManager] Dynamic purgeNode failed:", e);
6135
6130
  }
6136
6131
  })();
6137
- this.dispatch(e, i);
6132
+ this.dispatch(e, a);
6138
6133
  }
6139
6134
  purgeAsset(e, t, n) {
6140
6135
  let r = (async () => {
6141
6136
  try {
6142
6137
  let r = t.prepare("\n SELECT DISTINCT cn.id\n FROM node_assets na\n INNER JOIN content_nodes cn ON na.nodeId = cn.id\n LEFT JOIN assets crop ON na.assetId = crop.id\n WHERE cn.status = 'published' AND (\n na.assetId = ? OR crop.parentAssetId = ? OR crop.id = (SELECT parentAssetId FROM assets WHERE id = ?)\n )\n "), i = typeof r.all == "function" ? await r.all(n, n, n) : await r.bind(n, n, n).all(), a = Array.isArray(i) ? i : i?.results || [];
6143
- for (let n of a) n.id && this.purgeNode(e, t, n.id, !1);
6138
+ for (let n of a) n.id && this.purgeNode(e, t, n.id, !1, []);
6144
6139
  } catch (e) {
6145
6140
  console.warn("[CacheManager] purgeAsset failed:", e);
6146
6141
  }
@@ -6583,7 +6578,7 @@ H.get("/", async (e) => {
6583
6578
  await he(t, n, i);
6584
6579
  }
6585
6580
  }
6586
- return await I(e).clear(), D && new V(e.env).purgeNode(e, t, D, k), e.json({
6581
+ return await I(e).clear(), e.json({
6587
6582
  success: !0,
6588
6583
  id: D,
6589
6584
  status: "draft",
@@ -6802,7 +6797,7 @@ W.get("/tree.json", async (e) => {
6802
6797
  c.push(e.id, e.sortOrder);
6803
6798
  }), c.push(...i), c.push(o), await t.prepare(s).run(...c);
6804
6799
  }
6805
- return await i.clear(), a.purgeGlobalCache(e, t), e.json({
6800
+ return await i.clear(), r.length > 0 && a.purgeNode(e, t, r[0].id, !0), e.json({
6806
6801
  success: !0,
6807
6802
  reorderedCount: r.length
6808
6803
  });
@@ -6811,9 +6806,9 @@ W.get("/tree.json", async (e) => {
6811
6806
  delete m._isTreeDraft, delete m._draftParentId, delete m.isNew, delete m.nodeType, delete m.contentType, delete m.title, delete m.slug, delete m.hidden, delete m.is_hidden, delete m.isHidden, delete m.status;
6812
6807
  let g = G(u), _ = e.get("user")?.id || null;
6813
6808
  if (s === "create") {
6814
- let r = m.slug || n.slug || c, s = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
6815
- if (s) {
6816
- let r = g === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = n.contentId || n.id ? Number(n.contentId || n.id) : null, a = `
6809
+ let r = m.slug || n.slug || c, a = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
6810
+ if (a) {
6811
+ let r = g === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = n.contentId || n.id ? Number(n.contentId || n.id) : null, s = `
6817
6812
  SELECT 1
6818
6813
  FROM tree_nodes tn
6819
6814
  INNER JOIN content_nodes cn ON tn.contentId = cn.id
@@ -6821,51 +6816,51 @@ W.get("/tree.json", async (e) => {
6821
6816
  AND ${r}
6822
6817
  AND cn.slug = ?
6823
6818
  AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
6824
- `, c = g === null ? [o, s] : [
6819
+ `, c = g === null ? [o, a] : [
6825
6820
  o,
6826
6821
  g,
6827
- s
6822
+ a
6828
6823
  ];
6829
- if (i && !isNaN(i) && (a += " AND cn.id != ?", c.push(i)), a += " LIMIT 1", await t.prepare(a).get(...c)) return e.json({
6830
- error: `The slug '${s}' is already in use by another page in this section.`,
6824
+ if (i && !isNaN(i) && (s += " AND cn.id != ?", c.push(i)), s += " LIMIT 1", await t.prepare(s).get(...c)) return e.json({
6825
+ error: `The slug '${a}' is already in use by another page in this section.`,
6831
6826
  field: "slug"
6832
6827
  }, 409);
6833
6828
  }
6834
- let u = m.language?.trim() || n.language?.trim() || null;
6835
- if (!u) {
6829
+ let s = m.language?.trim() || n.language?.trim() || null;
6830
+ if (!s) {
6836
6831
  let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ?").get(o);
6837
6832
  if (e?.dataJson) try {
6838
6833
  let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
6839
- t.defaultLanguage && (u = t.defaultLanguage.trim());
6834
+ t.defaultLanguage && (s = t.defaultLanguage.trim());
6840
6835
  } catch {}
6841
6836
  }
6842
- if (!u) {
6837
+ if (!s) {
6843
6838
  let e = [];
6844
6839
  if (n.channels && Array.isArray(n.channels) ? e = n.channels : n.channelId && n.channelId !== "all" && (e = [n.channelId]), e.length > 0) {
6845
6840
  let n = Number(e[0]);
6846
6841
  if (!isNaN(n)) {
6847
6842
  let e = await t.prepare("SELECT defaultLanguage FROM channels WHERE id = ?").get(n);
6848
- e?.defaultLanguage && (u = e.defaultLanguage.trim());
6843
+ e?.defaultLanguage && (s = e.defaultLanguage.trim());
6849
6844
  }
6850
6845
  }
6851
6846
  }
6852
- let d = JSON.stringify(m), f = await t.prepare("\n INSERT INTO content_nodes (contentType, title, slug, language, isHidden, status, draftDataJson, dataJson, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, 'draft', ?, NULL, ?, ?)\n ").run(l || "page", c || "Untitled", s, u, h, d, _, _), p = Number(f.lastInsertRowid);
6853
- await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, p);
6854
- let v = g === null ? "parentId IS NULL" : "parentId = ?", y = g === null ? [o] : [o, g], b = (await t.prepare(`
6847
+ let u = JSON.stringify(m), d = await t.prepare("\n INSERT INTO content_nodes (contentType, title, slug, language, isHidden, status, draftDataJson, dataJson, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, 'draft', ?, NULL, ?, ?)\n ").run(l || "page", c || "Untitled", a, s, h, u, _, _), f = Number(d.lastInsertRowid);
6848
+ await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, f);
6849
+ let p = g === null ? "parentId IS NULL" : "parentId = ?", v = g === null ? [o] : [o, g], y = (await t.prepare(`
6855
6850
  SELECT COALESCE(MAX(sortOrder), -1) + 1 as nextSort
6856
6851
  FROM tree_nodes
6857
- WHERE treeId = ? AND ${v}
6858
- `).get(...y))?.nextSort ?? 0, x = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, ?)\n ").run(o, p, g, b), S = Number(x.lastInsertRowid), C = [];
6859
- n.channels && Array.isArray(n.channels) ? C = n.channels : n.channelId && n.channelId !== "all" && (C = [n.channelId]);
6860
- let w = [...new Set(C)].filter((e) => e && e !== "all").map((e) => Number(e));
6861
- if (w.length > 0) {
6862
- let e = w.map(() => "(?, ?)").join(", "), n = w.flatMap((e) => [p, e]);
6852
+ WHERE treeId = ? AND ${p}
6853
+ `).get(...v))?.nextSort ?? 0, b = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, ?)\n ").run(o, f, g, y), x = Number(b.lastInsertRowid), S = [];
6854
+ n.channels && Array.isArray(n.channels) ? S = n.channels : n.channelId && n.channelId !== "all" && (S = [n.channelId]);
6855
+ let C = [...new Set(S)].filter((e) => e && e !== "all").map((e) => Number(e));
6856
+ if (C.length > 0) {
6857
+ let e = C.map(() => "(?, ?)").join(", "), n = C.flatMap((e) => [f, e]);
6863
6858
  await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...n);
6864
6859
  }
6865
- return await i.clear(), a.purgeGlobalCache(e, t), e.json({
6860
+ return await i.clear(), e.json({
6866
6861
  success: !0,
6867
- id: p,
6868
- treeNodeId: S,
6862
+ id: f,
6863
+ treeNodeId: x,
6869
6864
  status: "draft"
6870
6865
  }, 201);
6871
6866
  }
@@ -6900,14 +6895,14 @@ W.get("/tree.json", async (e) => {
6900
6895
  }
6901
6896
  await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, d);
6902
6897
  let r = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, 0)\n ").run(o, d, g), s = Number(r.lastInsertRowid);
6903
- return await i.clear(), a.purgeGlobalCache(e, t), e.json({
6898
+ return await i.clear(), a.purgeNode(e, t, d, !0), e.json({
6904
6899
  success: !0,
6905
6900
  treeNodeId: s
6906
6901
  });
6907
6902
  }
6908
6903
  if (s === "detach") {
6909
6904
  let r = n.treeNodeId || n.contentId;
6910
- return r ? (await t.prepare("\n UPDATE tree_nodes \n SET parentId = (SELECT parentId FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?) \n WHERE parentId = ? AND treeId = ?\n ").run(r, r, o, r, o), await t.prepare("DELETE FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?").run(r, r, o), await i.clear(), a.purgeGlobalCache(e, t), e.json({ success: !0 })) : e.json({ error: "treeNodeId or contentId required for detach" }, 400);
6905
+ return r ? (await t.prepare("\n UPDATE tree_nodes \n SET parentId = (SELECT parentId FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?) \n WHERE parentId = ? AND treeId = ?\n ").run(r, r, o, r, o), await t.prepare("DELETE FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?").run(r, r, o), await i.clear(), a.purgeNode(e, t, r, !0), e.json({ success: !0 })) : e.json({ error: "treeNodeId or contentId required for detach" }, 400);
6911
6906
  }
6912
6907
  return e.json({ error: "Invalid payload or action" }, 400);
6913
6908
  } catch (t) {
@@ -6971,7 +6966,7 @@ W.get("/tree.json", async (e) => {
6971
6966
  await t.prepare(`INSERT OR IGNORE INTO channel_trees (channelId, treeId, key) VALUES ${n}`).run(...r);
6972
6967
  }
6973
6968
  }
6974
- return await I(e).clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
6969
+ return await cache.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
6975
6970
  success: !0,
6976
6971
  id: p,
6977
6972
  key: o,