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

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 (33) hide show
  1. package/bin/cli.js +229 -231
  2. package/dist/assets/index-BesA3e7A.js +164 -0
  3. package/dist/assets/index-D6yHZ_u1.css +1 -0
  4. package/dist/{dist-C-WAK7EF.js → dist-mic4UZBb.js} +691 -439
  5. package/dist/index.html +2 -2
  6. package/dist/index.js +693 -439
  7. package/dist/schema-compiler.js +1 -1
  8. package/package.json +1 -1
  9. package/schema.sql +2 -2
  10. package/templates/astro-starter/src/components/blocks/BlockRenderer.astro +1 -0
  11. package/templates/astro-starter/src/components/blocks/ColumnLayout.astro +1 -0
  12. package/templates/astro-starter/src/components/blocks/HeaderImage.astro +1 -0
  13. package/templates/astro-starter/src/components/blocks/HtmlBlock.astro +2 -1
  14. package/templates/astro-starter/src/components/blocks/ImageBlock.astro +39 -71
  15. package/templates/astro-starter/src/components/blocks/TextBlock.astro +2 -0
  16. package/templates/astro-starter/src/components/global/Breadcrumb.astro +2 -0
  17. package/templates/astro-starter/src/components/global/Footer.astro +2 -0
  18. package/templates/astro-starter/src/components/global/Header.astro +100 -28
  19. package/templates/astro-starter/src/components/{seo/SeoHead.astro → global/MetaHead.astro} +101 -49
  20. package/templates/astro-starter/src/components/global/NavigationMenu.astro +1 -0
  21. package/templates/astro-starter/src/components/ui/KamaImage.astro +114 -67
  22. package/templates/astro-starter/src/layouts/SkeletonLayout.astro +5 -3
  23. package/templates/astro-starter/src/layouts/StandardLayout.astro +14 -5
  24. package/templates/astro-starter/src/lib/cms.ts +48 -0
  25. package/templates/astro-starter/src/lib/media/kama-image-service.ts +16 -1
  26. package/templates/astro-starter/src/lib/media/media-proxy.ts +8 -6
  27. package/templates/astro-starter/src/lib/media/media-url.ts +65 -1
  28. package/templates/astro-starter/src/middleware.ts +131 -18
  29. package/templates/astro-starter/src/pages/[...slug].astro +10 -9
  30. package/definitions/_page.yaml +0 -52
  31. package/dist/assets/index-DGHRgyms.js +0 -164
  32. package/dist/assets/index-EaDn3OUJ.css +0 -1
  33. /package/templates/astro-starter/{public/css → src/styles}/standard-theme.css +0 -0
@@ -4813,10 +4813,10 @@ var u = /* @__PURE__ */ o({
4813
4813
  users: "\n id TEXT PRIMARY KEY,\n email TEXT UNIQUE NOT NULL,\n name TEXT NOT NULL,\n globalRole TEXT DEFAULT 'editor',\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP\n ",
4814
4814
  user_accounts: "\n id TEXT PRIMARY KEY,\n userId TEXT NOT NULL,\n provider TEXT NOT NULL,\n providerAccountId TEXT NOT NULL,\n passwordHash TEXT NOT NULL,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (userId) REFERENCES users(id) ON DELETE CASCADE,\n UNIQUE(provider, providerAccountId)\n ",
4815
4815
  sessions: "\n id TEXT PRIMARY KEY,\n userId TEXT NOT NULL,\n expiresAt TEXT NOT NULL,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (userId) REFERENCES users(id) ON DELETE CASCADE\n ",
4816
- channels: "\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n key TEXT UNIQUE NOT NULL,\n label TEXT NOT NULL,\n channelType TEXT,\n domain TEXT,\n baseUrl TEXT,\n defaultLanguage TEXT DEFAULT 'en',\n isHidden INTEGER NOT NULL DEFAULT 0,\n dataJson TEXT,\n createdById TEXT,\n updatedById TEXT,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (createdById) REFERENCES users(id) ON DELETE SET NULL,\n FOREIGN KEY (updatedById) REFERENCES users(id) ON DELETE SET NULL\n ",
4816
+ channels: "\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n key TEXT UNIQUE NOT NULL,\n label TEXT NOT NULL,\n channelType TEXT,\n domain TEXT,\n baseUrl TEXT,\n defaultLanguage TEXT,\n isHidden INTEGER NOT NULL DEFAULT 0,\n dataJson TEXT,\n createdById TEXT,\n updatedById TEXT,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (createdById) REFERENCES users(id) ON DELETE SET NULL,\n FOREIGN KEY (updatedById) REFERENCES users(id) ON DELETE SET NULL\n ",
4817
4817
  trees: "\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n key TEXT UNIQUE NOT NULL,\n label TEXT NOT NULL,\n treeType TEXT,\n channelId INTEGER,\n isHidden INTEGER NOT NULL DEFAULT 0,\n dataJson TEXT,\n createdById TEXT,\n updatedById TEXT,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (channelId) REFERENCES channels(id) ON DELETE SET NULL,\n FOREIGN KEY (createdById) REFERENCES users(id) ON DELETE SET NULL,\n FOREIGN KEY (updatedById) REFERENCES users(id) ON DELETE SET NULL\n ",
4818
4818
  channel_trees: "\n channelId INTEGER NOT NULL,\n treeId INTEGER NOT NULL,\n key TEXT NOT NULL DEFAULT 'main',\n metaJson TEXT,\n PRIMARY KEY (channelId, treeId, key),\n FOREIGN KEY (channelId) REFERENCES channels(id) ON DELETE CASCADE,\n FOREIGN KEY (treeId) REFERENCES trees(id) ON DELETE CASCADE\n ",
4819
- content_nodes: "\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n contentType TEXT NOT NULL,\n title TEXT NOT NULL,\n slug TEXT,\n language TEXT DEFAULT 'en',\n isHidden INTEGER NOT NULL DEFAULT 0,\n status TEXT DEFAULT 'draft',\n hasUnpublishedChanges INTEGER DEFAULT 0,\n disabledRegionsJson TEXT DEFAULT '{}',\n dataJson TEXT,\n draftDataJson TEXT,\n publishedDataJson TEXT,\n publishedAt TEXT,\n createdById TEXT,\n updatedById TEXT,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n deletedAt TEXT,\n FOREIGN KEY (createdById) REFERENCES users(id) ON DELETE SET NULL,\n FOREIGN KEY (updatedById) REFERENCES users(id) ON DELETE SET NULL\n ",
4819
+ content_nodes: "\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n contentType TEXT NOT NULL,\n title TEXT NOT NULL,\n slug TEXT,\n language TEXT,\n isHidden INTEGER NOT NULL DEFAULT 0,\n status TEXT DEFAULT 'draft',\n hasUnpublishedChanges INTEGER DEFAULT 0,\n disabledRegionsJson TEXT DEFAULT '{}',\n dataJson TEXT,\n draftDataJson TEXT,\n publishedDataJson TEXT,\n publishedAt TEXT,\n createdById TEXT,\n updatedById TEXT,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n deletedAt TEXT,\n FOREIGN KEY (createdById) REFERENCES users(id) ON DELETE SET NULL,\n FOREIGN KEY (updatedById) REFERENCES users(id) ON DELETE SET NULL\n ",
4820
4820
  node_channels: "\n nodeId INTEGER NOT NULL,\n channelId INTEGER NOT NULL,\n PRIMARY KEY (nodeId, channelId),\n FOREIGN KEY (nodeId) REFERENCES content_nodes(id) ON DELETE CASCADE,\n FOREIGN KEY (channelId) REFERENCES channels(id) ON DELETE CASCADE\n ",
4821
4821
  tree_nodes: "\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n treeId INTEGER NOT NULL,\n contentId INTEGER NOT NULL,\n parentId INTEGER,\n sortOrder INTEGER DEFAULT 0,\n FOREIGN KEY (treeId) REFERENCES trees(id) ON DELETE CASCADE,\n FOREIGN KEY (contentId) REFERENCES content_nodes(id) ON DELETE CASCADE,\n FOREIGN KEY (parentId) REFERENCES tree_nodes(id) ON DELETE CASCADE\n ",
4822
4822
  content_blocks: "\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n contentId INTEGER NOT NULL,\n region TEXT DEFAULT 'main',\n elementType TEXT NOT NULL,\n dataJson TEXT,\n sortOrder INTEGER DEFAULT 0,\n isDraft INTEGER NOT NULL DEFAULT 1,\n FOREIGN KEY (contentId) REFERENCES content_nodes(id) ON DELETE CASCADE\n ",
@@ -5577,7 +5577,7 @@ var b = { hasSubscribers: !1 }, x = b, S = b, C = typeof performance == "object"
5577
5577
  async clear() {
5578
5578
  this.cache.clear();
5579
5579
  }
5580
- }, te = class {
5580
+ }, P = class {
5581
5581
  kv;
5582
5582
  constructor(e) {
5583
5583
  this.kv = e;
@@ -5594,7 +5594,7 @@ var b = { hasSubscribers: !1 }, x = b, S = b, C = typeof performance == "object"
5594
5594
  this.kv && await this.kv.delete(e);
5595
5595
  }
5596
5596
  async clear() {}
5597
- }, P = class {
5597
+ }, te = class {
5598
5598
  async get() {
5599
5599
  return null;
5600
5600
  }
@@ -5604,7 +5604,7 @@ var b = { hasSubscribers: !1 }, x = b, S = b, C = typeof performance == "object"
5604
5604
  }, F = null;
5605
5605
  function I(e) {
5606
5606
  let t = process.env.CACHE_DRIVER || "lru";
5607
- return t === "none" || t === "off" || t === "false" ? new P() : e?.env?.CMS_CACHE_KV ? new te(e.env.CMS_CACHE_KV) : t === "lru" ? (F ||= new ee(), F) : new P();
5607
+ return t === "none" || t === "off" || t === "false" ? new te() : e?.env?.CMS_CACHE_KV ? new P(e.env.CMS_CACHE_KV) : t === "lru" ? (F ||= new ee(), F) : new te();
5608
5608
  }
5609
5609
  var L = class {
5610
5610
  customStoragePath;
@@ -5675,7 +5675,7 @@ var L = class {
5675
5675
  if (e.code !== "ENOENT") throw e;
5676
5676
  }
5677
5677
  }
5678
- }, R = class {
5678
+ }, ne = class {
5679
5679
  async process(e, t, n) {
5680
5680
  let r = await import(
5681
5681
  /* @vite-ignore */
@@ -5702,7 +5702,7 @@ var L = class {
5702
5702
  return console.warn("⚠️ [SharpImageOptimizer] Processing failed, returning raw buffer."), e;
5703
5703
  }
5704
5704
  }
5705
- }, ne = class {
5705
+ }, re = class {
5706
5706
  bucket;
5707
5707
  publicDomain;
5708
5708
  constructor(e, t) {
@@ -5747,7 +5747,7 @@ var L = class {
5747
5747
  async delete(e) {
5748
5748
  await this.bucket.delete(e);
5749
5749
  }
5750
- }, re = class {
5750
+ }, ie = class {
5751
5751
  async process(e, t, n) {
5752
5752
  let { env: r, key: i, req: a } = n;
5753
5753
  if (r.IMAGES) try {
@@ -5782,16 +5782,16 @@ var L = class {
5782
5782
  return e;
5783
5783
  }
5784
5784
  };
5785
- function ie(e) {
5785
+ function ae(e) {
5786
5786
  return e.KAMA_RUNTIME === "cloudflare" || e.MEDIA_BUCKET ? {
5787
- storage: new ne(e.MEDIA_BUCKET, e.CDN_DOMAIN || ""),
5788
- optimizer: new re()
5787
+ storage: new re(e.MEDIA_BUCKET, e.CDN_DOMAIN || ""),
5788
+ optimizer: new ie()
5789
5789
  } : {
5790
5790
  storage: new L(e.LOCAL_MEDIA_PATH),
5791
- optimizer: new R()
5791
+ optimizer: new ne()
5792
5792
  };
5793
5793
  }
5794
- function ae(e) {
5794
+ function R(e) {
5795
5795
  if (!e || typeof e != "object") return {
5796
5796
  cleanedData: e,
5797
5797
  assetRefs: []
@@ -5867,7 +5867,7 @@ function z(e) {
5867
5867
  }
5868
5868
  return null;
5869
5869
  }
5870
- async function se(e, t) {
5870
+ async function B(e, t) {
5871
5871
  if (!t || typeof t != "object") return t;
5872
5872
  let n = /* @__PURE__ */ new Set(), r = (e) => {
5873
5873
  if (!e) return;
@@ -5978,7 +5978,7 @@ async function se(e, t) {
5978
5978
  };
5979
5979
  return d(t);
5980
5980
  }
5981
- function ce(e) {
5981
+ function se(e) {
5982
5982
  return e ? {
5983
5983
  nodes: e.nodes || {},
5984
5984
  trees: e.trees || {},
@@ -5995,7 +5995,7 @@ function ce(e) {
5995
5995
  channels: {}
5996
5996
  };
5997
5997
  }
5998
- var B = class {
5998
+ var V = class {
5999
5999
  env;
6000
6000
  constructor(e) {
6001
6001
  this.env = e || {};
@@ -6007,7 +6007,8 @@ var B = class {
6007
6007
  apiToken: e.env?.CLOUDFLARE_API_TOKEN || this.env.CLOUDFLARE_API_TOKEN,
6008
6008
  frontendUrl: (e.env?.PUBLIC_FRONTEND_URL || this.env.PUBLIC_FRONTEND_URL || "http://localhost:4321").replace(/\/+$/, ""),
6009
6009
  cdnDomain: t ? t.replace(/^https?:\/\//, "").replace(/\/+$/, "") : "localhost:8787",
6010
- frontendWorker: e.env?.FRONTEND_WORKER || this.env.FRONTEND_WORKER
6010
+ frontendWorker: e.env?.FRONTEND_WORKER || this.env.FRONTEND_WORKER,
6011
+ disableCachePurge: e.env?.DISABLE_CACHE_PURGE || this.env.DISABLE_CACHE_PURGE
6011
6012
  };
6012
6013
  }
6013
6014
  isLocalEnv(e, t) {
@@ -6031,19 +6032,33 @@ var B = class {
6031
6032
  return r && n && r.startsWith(`https://${n}/`) && !r.includes("/media/") && (r = r.replace(`https://${n}/`, `https://${n}/media/`)), r;
6032
6033
  }
6033
6034
  async callAstroPurge(e, t, n) {
6034
- let { apiToken: r, frontendUrl: i } = this.getEnv(e), a = (n || i).replace(/\/+$/, "");
6035
- if (this.isLocalEnv(e, a)) return console.log(`[CacheManager] Skipped external purge for local target: ${a}`), new Response(JSON.stringify({
6036
- success: !0,
6037
- local: !0
6038
- }), { status: 200 });
6039
- let o = `${a}/api/purge`, s = { "Content-Type": "application/json" };
6040
- return r && (s.Authorization = `Bearer ${r}`), console.log(`[CacheManager] Dispatching POST purge request to: ${o}`), fetch(o, {
6041
- method: "POST",
6042
- headers: s,
6043
- body: JSON.stringify(t)
6044
- });
6035
+ let { apiToken: r, frontendUrl: i, frontendWorker: a, disableCachePurge: o } = this.getEnv(e);
6036
+ if (o === "true" || o === !0 || o === "1") return new Response(JSON.stringify({ skipped: !0 }), { status: 200 });
6037
+ let s = (n || i).replace(/\/+$/, ""), c = `${s}/api/purge`, l = { "Content-Type": "application/json" };
6038
+ if (r && (l.Authorization = `Bearer ${r}`), a && typeof a.fetch == "function") try {
6039
+ return await a.fetch(new Request(c, {
6040
+ method: "POST",
6041
+ headers: l,
6042
+ body: JSON.stringify(t)
6043
+ }));
6044
+ } catch (e) {
6045
+ return console.info(`[CacheManager] Worker binding purge call to ${c} failed silently:`, e?.message || e), new Response(JSON.stringify({ error: e?.message }), { status: 502 });
6046
+ }
6047
+ try {
6048
+ let e = new AbortController(), n = setTimeout(() => e.abort(), 1500);
6049
+ console.log(`[CacheManager] Dispatching POST purge request to: ${c}`);
6050
+ let r = await fetch(c, {
6051
+ method: "POST",
6052
+ headers: l,
6053
+ body: JSON.stringify(t),
6054
+ signal: e.signal
6055
+ });
6056
+ return clearTimeout(n), r;
6057
+ } catch (e) {
6058
+ return e.name === "AbortError" ? console.info(`[CacheManager] Purge request to ${c} timed out (dev server un-responsive).`) : e?.cause?.code === "ECONNREFUSED" || e?.code === "ECONNREFUSED" ? console.info(`[CacheManager] Frontend purge listener offline at ${s} (port not reachable).`) : console.warn(`[CacheManager] Non-fatal purge warning for ${c}:`, e?.message || e), new Response(JSON.stringify({ error: "Connection refused or timed out" }), { status: 503 });
6059
+ }
6045
6060
  }
6046
- async purgeInternalWorkerCache(e, t, n, r, i = "en") {
6061
+ async purgeInternalWorkerCache(e, t, n, r, i) {
6047
6062
  try {
6048
6063
  let a = I(e);
6049
6064
  if (n) {
@@ -6056,7 +6071,7 @@ var B = class {
6056
6071
  let e = t.prepare("SELECT c.key, c.id FROM node_channels nc JOIN channels c ON nc.channelId = c.id WHERE nc.nodeId = ?"), r = typeof e.all == "function" ? await e.all(n) : await e.bind(n).all(), i = Array.isArray(r) ? r : r?.results || [];
6057
6072
  i.length > 0 && (o = i.flatMap((e) => [String(e.id), e.key]).filter(Boolean));
6058
6073
  }
6059
- for (let t of o) await a.delete(`node:${t}:${i}:${e}`), await a.delete(`node:${t}:${i}:/${e}`);
6074
+ for (let t of o) i && (await a.delete(`node:${t}:${i}:${e}`), await a.delete(`node:${t}:${i}:/${e}`)), await a.delete(`node:${t}:${e}`), await a.delete(`node:${t}:/${e}`);
6060
6075
  }
6061
6076
  } catch (e) {
6062
6077
  console.warn("[CacheManager] Failed to purge internal worker cache:", e);
@@ -6067,30 +6082,30 @@ var B = class {
6067
6082
  try {
6068
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]) || {};
6069
6084
  if (!a.slug) return;
6070
- let o = a.language || "en", s = String(a.slug).replace(/^\/+|\/+$/g, ""), c = t.prepare("\n SELECT c.id, c.key, c.baseUrl \n FROM node_channels nc \n JOIN channels c ON nc.channelId = c.id \n WHERE nc.nodeId = ?\n "), l = typeof c.all == "function" ? await c.all(n) : await c.bind(n).all(), u = Array.isArray(l) ? l : l?.results || [], d = this.getEnv(e).frontendUrl, f = /* @__PURE__ */ new Set();
6071
- for (let e of u) if (e.baseUrl && typeof e.baseUrl == "string" && e.baseUrl.trim() !== "") {
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() !== "") {
6072
6087
  let t = e.baseUrl.trim();
6073
- !t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), f.add(t.replace(/\/+$/, ""));
6088
+ !t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), p.add(t.replace(/\/+$/, ""));
6074
6089
  }
6075
- f.size === 0 && d && f.add(d);
6076
- let p = 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 "), m = typeof p.all == "function" ? await p.all(n) : await p.bind(n).all(), h = (Array.isArray(m) ? m : m?.results || []).map((t) => t.url || this.getSafeUrl(t.cdnUrl, t.storageKeyPrivate, this.getEnv(e).cdnDomain)).filter(Boolean);
6077
- await this.purgeInternalWorkerCache(e, t, n, s, o);
6078
- let g = this.getEnv(e).cdnDomain, { zoneId: _, apiToken: v } = this.getEnv(e);
6079
- for (let t of f) {
6080
- let n = s === "home" || !s ? t : `${t}/${s}`, i = [n, `${n}/`];
6081
- if (u.length > 0) for (let e of u) e.id && i.push(`https://${g}/api/v1/node/${s}?channelId=${e.id}&lang=${o}`), e.key && i.push(`https://${g}/api/v1/node/${s}?channelId=${e.key}&lang=${o}`);
6082
- else i.push(`https://${g}/api/v1/node/${s}?lang=${o}`);
6083
- for (let e of h) e && i.push(`${t}${e.startsWith("/") ? e : `/${e}`}`);
6084
- if (await this.callAstroPurge(e, { urls: i }, t), _ && v && !this.isLocalEnv(e, t) && fetch(`https://api.cloudflare.com/client/v4/zones/${_}/purge_cache`, {
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`, {
6085
6100
  method: "POST",
6086
6101
  headers: {
6087
- Authorization: `Bearer ${v}`,
6102
+ Authorization: `Bearer ${y}`,
6088
6103
  "Content-Type": "application/json"
6089
6104
  },
6090
6105
  body: JSON.stringify({ files: i })
6091
6106
  }).catch(() => {}), !r) {
6092
6107
  let e = `${n}${n.includes("?") ? "&" : "?"} _warmer=${Date.now()}`;
6093
- console.log(`[CacheManager] Prewarming cache at: ${e}`), await fetch(e, { headers: {
6108
+ console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
6094
6109
  "X-Cache-Warmer": "true",
6095
6110
  "User-Agent": "Kama-Cache-Warmer/1.0"
6096
6111
  } }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
@@ -6119,35 +6134,49 @@ var B = class {
6119
6134
  }
6120
6135
  async purgeGlobalCacheDirect(e, t) {
6121
6136
  try {
6122
- let { zoneId: n, apiToken: r, frontendUrl: i } = this.getEnv(e);
6123
- if (this.isLocalEnv(e) || !(await this.callAstroPurge(e, { purge_everything: !0 })).ok) return;
6124
- n && r && fetch(`https://api.cloudflare.com/client/v4/zones/${n}/purge_cache`, {
6137
+ let { zoneId: n, apiToken: r } = this.getEnv(e);
6138
+ if (!(await this.callAstroPurge(e, { purge_everything: !0 })).ok) return;
6139
+ if (n && r && !this.isLocalEnv(e) && fetch(`https://api.cloudflare.com/client/v4/zones/${n}/purge_cache`, {
6125
6140
  method: "POST",
6126
6141
  headers: {
6127
6142
  Authorization: `Bearer ${r}`,
6128
6143
  "Content-Type": "application/json"
6129
6144
  },
6130
6145
  body: JSON.stringify({ purge_everything: !0 })
6131
- }).catch(() => {}), await new Promise((e) => setTimeout(e, 100)), t ? await this.warmAllPublishedPages(e, t) : fetch(`${i.replace(/\/+$/, "")}/?_warmer=${Date.now()}`, { headers: { "X-Cache-Warmer": "true" } }).catch(() => {});
6146
+ }).catch(() => {}), await new Promise((e) => setTimeout(e, 100)), t) await this.warmAllPublishedPages(e, t);
6147
+ else {
6148
+ let { frontendUrl: t } = this.getEnv(e);
6149
+ fetch(`${t.replace(/\/+$/, "")}/?_warmer=${Date.now()}`, { headers: { "X-Cache-Warmer": "true" } }).catch(() => {});
6150
+ }
6132
6151
  } catch (e) {
6133
6152
  console.warn("[CacheManager] Direct Global Purge skipped:", e);
6134
6153
  }
6135
6154
  }
6136
6155
  async warmAllPublishedPages(e, t) {
6137
6156
  try {
6138
- let { frontendUrl: n } = this.getEnv(e);
6139
- if (this.isLocalEnv(e)) return;
6140
- let r = t.prepare("SELECT DISTINCT slug FROM content_nodes WHERE status = 'published' AND slug IS NOT NULL AND (deletedAt IS NULL OR deletedAt = '')"), i = typeof r.all == "function" ? await r.all() : await r.bind().all(), a = Array.isArray(i) ? i : i?.results || [], o = { "X-Cache-Warmer": "true" }, s = Date.now(), c = a.map((e) => {
6141
- let t = String(e.slug).replace(/^\/+|\/+$/g, ""), r = t === "home" || !t ? n : `${n}/${t}`;
6142
- return fetch(`${r}?_warmer=${s}`, { headers: o }).catch(() => {});
6143
- });
6144
- c.push(fetch(`${n}/?_warmer=${s}`, { headers: o }).catch(() => {})), await Promise.all(c);
6157
+ let n = t.prepare("\n SELECT DISTINCT cn.slug, c.baseUrl\n FROM content_nodes cn\n LEFT JOIN node_channels nc ON cn.id = nc.nodeId\n LEFT JOIN channels c ON nc.channelId = c.id\n WHERE cn.status = 'published' AND cn.slug IS NOT NULL AND (cn.deletedAt IS NULL OR cn.deletedAt = '')\n LIMIT 100\n "), r = typeof n.all == "function" ? await n.all() : await n.bind().all(), i = Array.isArray(r) ? r : r?.results || [], a = this.getEnv(e).frontendUrl, o = {
6158
+ "X-Cache-Warmer": "true",
6159
+ "User-Agent": "Kama-Cache-Warmer/1.0"
6160
+ }, s = Date.now(), c = /* @__PURE__ */ new Set();
6161
+ for (let e of i) {
6162
+ let t = String(e.slug).replace(/^\/+|\/+$/g, ""), n = a;
6163
+ e.baseUrl && typeof e.baseUrl == "string" && e.baseUrl.trim() !== "" && (n = e.baseUrl.trim(), !n.startsWith("http://") && !n.startsWith("https://") && (n = `https://${n}`), n = n.replace(/\/+$/, ""));
6164
+ let r = t === "home" || !t ? n : `${n}/${t}`;
6165
+ c.add(`${r}?_warmer=${s}`);
6166
+ }
6167
+ c.add(`${a}/?_warmer=${s}`);
6168
+ let l = Array.from(c);
6169
+ for (let e = 0; e < l.length; e += 6) {
6170
+ let t = l.slice(e, e + 6);
6171
+ await Promise.all(t.map((e) => fetch(e, { headers: o }).catch((t) => console.warn(`[CacheWarmer] Skipped prewarm for ${e}:`, t?.message || t))));
6172
+ }
6173
+ console.log(`[CacheWarmer] Prewarmed ${l.length} published pages across ${Math.ceil(l.length / 6)} batches.`);
6145
6174
  } catch (e) {
6146
6175
  console.warn("⚠️ [CacheWarmer] Tree-wide warming failed:", e);
6147
6176
  }
6148
6177
  }
6149
- }, V = new e();
6150
- async function le(e, t, n = []) {
6178
+ }, H = new e();
6179
+ async function ce(e, t, n = []) {
6151
6180
  let r = e.prepare(t);
6152
6181
  if (typeof r.bind == "function") {
6153
6182
  let e = await r.bind(...n).all();
@@ -6159,24 +6188,25 @@ async function le(e, t, n = []) {
6159
6188
  }
6160
6189
  return [];
6161
6190
  }
6162
- async function ue(e, t, n = []) {
6191
+ async function le(e, t, n = []) {
6163
6192
  let r = e.prepare(t);
6164
6193
  if (typeof r.bind == "function") return r.bind(...n).run();
6165
6194
  if (typeof r.run == "function") return r.run(...n);
6166
6195
  }
6167
- function de(e) {
6196
+ function U(e) {
6168
6197
  return !e || !e.trim() ? null : e.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^a-z0-9\s-]/g, "").replace(/[\s-]+/g, "-").replace(/^-+|-+$/g, "") || null;
6169
6198
  }
6170
- function fe(e) {
6199
+ function ue(e) {
6171
6200
  return +(e === !0 || e === 1 || e === "1" || e === "true");
6172
6201
  }
6173
- function pe(e) {
6202
+ function de(e) {
6174
6203
  if (e == null || e === "null" || e === "" || typeof e == "string" && e.startsWith("draft-")) return null;
6175
6204
  let t = Number(e);
6176
6205
  return isNaN(t) ? null : t;
6177
6206
  }
6178
- function H(e) {
6207
+ function fe(e) {
6179
6208
  let t = { ...e };
6209
+ delete t.language, delete t.defaultLanguage;
6180
6210
  for (let e of [
6181
6211
  "id",
6182
6212
  "treeNodeId",
@@ -6187,7 +6217,6 @@ function H(e) {
6187
6217
  "contentType",
6188
6218
  "title",
6189
6219
  "slug",
6190
- "language",
6191
6220
  "hidden",
6192
6221
  "is_hidden",
6193
6222
  "isHidden",
@@ -6204,17 +6233,22 @@ function H(e) {
6204
6233
  ]) delete t[e];
6205
6234
  return t;
6206
6235
  }
6207
- function me(e, t = /* @__PURE__ */ new Set()) {
6208
- return e ? typeof e == "string" ? (e.startsWith("ast_") && t.add(e), t) : Array.isArray(e) ? (e.forEach((e) => me(e, t)), t) : (typeof e == "object" && Object.values(e).forEach((e) => me(e, t)), t) : t;
6236
+ function pe(e, t = /* @__PURE__ */ new Set()) {
6237
+ return e ? typeof e == "string" ? (e.startsWith("ast_") && t.add(e), t) : Array.isArray(e) ? (e.forEach((e) => pe(e, t)), t) : (typeof e == "object" && Object.values(e).forEach((e) => pe(e, t)), t) : t;
6209
6238
  }
6210
- async function U(e, t, n) {
6239
+ function me(e, t) {
6240
+ if (!e) return !0;
6241
+ let n = t.title !== void 0 && t.title?.trim() !== e.title?.trim(), r = t.slug !== void 0 && t.slug !== e.slug, i = t.isHidden !== void 0 && ue(t.isHidden) !== ue(e.isHidden), a = t.status !== void 0 && t.status !== e.status, o = typeof e.draftDataJson == "string" ? JSON.parse(e.draftDataJson || "{}") : e.draftDataJson || {}, s = t.sanitizedFields || {}, c = s.menuTitle !== void 0 && s.menuTitle !== o.menuTitle;
6242
+ return n || r || i || a || c;
6243
+ }
6244
+ async function he(e, t, n) {
6211
6245
  for (let r of n) {
6212
- let n = (await le(e, "\n SELECT id, storageKeyPrivate, isSystemVariant, parentAssetId, filename\n FROM assets WHERE id = ?\n ", [r]))[0];
6213
- if (!n || (await le(e, "SELECT 1 FROM node_assets WHERE assetId = ? LIMIT 1", [n.id])).length > 0) continue;
6246
+ let n = (await ce(e, "\n SELECT id, storageKeyPrivate, isSystemVariant, parentAssetId, filename\n FROM assets WHERE id = ?\n ", [r]))[0];
6247
+ if (!n || (await ce(e, "SELECT 1 FROM node_assets WHERE assetId = ? LIMIT 1", [n.id])).length > 0) continue;
6214
6248
  let i = [n];
6215
6249
  if (!n.isSystemVariant) {
6216
- let t = await le(e, "\n SELECT id, storageKeyPrivate, isSystemVariant, parentAssetId, filename\n FROM assets\n WHERE parentAssetId = ? OR (isSystemVariant = 1 AND filename LIKE ?)\n ", [n.id, `crop_%${String(n.filename || "").replace(/\.[^/.]+$/, "")}%`]), r = t.map((e) => e.id);
6217
- if (r.length > 0 && (await le(e, `SELECT DISTINCT assetId FROM node_assets WHERE assetId IN (${r.map(() => "?").join(",")})`, r)).length > 0) continue;
6250
+ let t = await ce(e, "\n SELECT id, storageKeyPrivate, isSystemVariant, parentAssetId, filename\n FROM assets\n WHERE parentAssetId = ? OR (isSystemVariant = 1 AND filename LIKE ?)\n ", [n.id, `crop_%${String(n.filename || "").replace(/\.[^/.]+$/, "")}%`]), r = t.map((e) => e.id);
6251
+ if (r.length > 0 && (await ce(e, `SELECT DISTINCT assetId FROM node_assets WHERE assetId IN (${r.map(() => "?").join(",")})`, r)).length > 0) continue;
6218
6252
  i = [n, ...t];
6219
6253
  }
6220
6254
  for (let e of i) if (e.storageKeyPrivate) try {
@@ -6223,10 +6257,10 @@ async function U(e, t, n) {
6223
6257
  console.warn(`[Asset Cleanup] Failed to delete ${e.storageKeyPrivate}:`, t);
6224
6258
  }
6225
6259
  let a = i.map((e) => e.id), o = a.map(() => "?").join(",");
6226
- await ue(e, `DELETE FROM node_assets WHERE assetId IN (${o})`, a), await ue(e, `DELETE FROM assets WHERE id IN (${o})`, a);
6260
+ await le(e, `DELETE FROM node_assets WHERE assetId IN (${o})`, a), await le(e, `DELETE FROM assets WHERE id IN (${o})`, a);
6227
6261
  }
6228
6262
  }
6229
- async function W(e, t, n) {
6263
+ async function ge(e, t, n) {
6230
6264
  let r = {}, i = null;
6231
6265
  if (t) {
6232
6266
  let n = await e.prepare("\n WITH RECURSIVE ancestor_path(id, parentId, draftDataJson, dataJson, level) AS (\n SELECT t.id, t.parentId, c.draftDataJson, c.dataJson, 0\n FROM tree_nodes t\n INNER JOIN content_nodes c ON t.contentId = c.id\n WHERE t.id = ?\n UNION ALL\n SELECT t.id, t.parentId, c.draftDataJson, c.dataJson, ap.level + 1\n FROM tree_nodes t\n INNER JOIN content_nodes c ON t.contentId = c.id\n INNER JOIN ancestor_path ap ON t.id = ap.parentId\n )\n SELECT draftDataJson, dataJson FROM ancestor_path ORDER BY level ASC\n ").all(t), a = Array.isArray(n) ? n : n?.results || [];
@@ -6240,7 +6274,7 @@ async function W(e, t, n) {
6240
6274
  }
6241
6275
  }
6242
6276
  if (!i) {
6243
- let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ?").get(n);
6277
+ let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ? OR key = ? LIMIT 1").get(Number(n) || -1, String(n));
6244
6278
  if (t && t.dataJson) try {
6245
6279
  let e = typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson;
6246
6280
  e.subpageLayoutId && e.subpageLayoutId !== "inherit" && (i = e.subpageLayoutId);
@@ -6251,7 +6285,7 @@ async function W(e, t, n) {
6251
6285
  inheritedFields: r
6252
6286
  };
6253
6287
  }
6254
- V.get("/", async (e) => {
6288
+ H.get("/", async (e) => {
6255
6289
  let t = e.get("db"), n = e.req.query("id"), r = e.req.query("type"), i = e.req.query("q") || e.req.query("search"), a = e.req.query("channelId"), o = e.req.query("trashed") === "true", s = e.req.query("assetId"), c = e.req.query("sort") || "updatedAt", l = (e.req.query("order") || "DESC").toUpperCase() === "ASC" ? "ASC" : "DESC", u = e.req.query("limit"), d = e.req.query("offset"), f = Math.max(1, Math.min(100, parseInt(u || "50", 10))), p = Math.max(0, parseInt(d || "0", 10));
6256
6290
  if (n) {
6257
6291
  let r = Number(n);
@@ -6262,7 +6296,7 @@ V.get("/", async (e) => {
6262
6296
  id: i.id,
6263
6297
  title: i.title,
6264
6298
  slug: i.slug,
6265
- language: i.language || "en",
6299
+ language: i.language || null,
6266
6300
  nodeType: i.contentType,
6267
6301
  contentType: i.contentType,
6268
6302
  isHidden: !!i.isHidden,
@@ -6276,9 +6310,9 @@ V.get("/", async (e) => {
6276
6310
  updatedAt: i.updatedAt
6277
6311
  }, s = i.draftDataJson || i.dataJson;
6278
6312
  if (s) try {
6279
- let n = typeof s == "string" ? JSON.parse(s) : s, a = await t.prepare("SELECT id as treeNodeId, treeId, parentId FROM tree_nodes WHERE contentId = ? LIMIT 1").get(r), c = ce(e.env?.BUNDLED_DEFINITIONS).nodes?.[i.contentType] || {}, l = n.layoutId || null;
6313
+ let n = typeof s == "string" ? JSON.parse(s) : s, a = await t.prepare("SELECT id as treeNodeId, treeId, parentId FROM tree_nodes WHERE contentId = ? LIMIT 1").get(r), c = se(e.env?.BUNDLED_DEFINITIONS).nodes?.[i.contentType] || {}, l = n.layoutId || null;
6280
6314
  if (a) {
6281
- let { resolvedLayoutId: e, inheritedFields: r } = await W(t, a.parentId, a.treeId);
6315
+ let { resolvedLayoutId: e, inheritedFields: r } = await ge(t, a.parentId, a.treeId);
6282
6316
  (l === "inherit" || !l) && (l = e);
6283
6317
  for (let [e, t] of Object.entries(r)) e !== "layoutId" && e !== "subpageLayoutId" && (n[e] === void 0 || n[e] === null || n[e] === "") && t !== void 0 && (n[e] = t);
6284
6318
  }
@@ -6293,7 +6327,7 @@ V.get("/", async (e) => {
6293
6327
  let r = t.allowedLayouts;
6294
6328
  return r ? typeof r == "string" ? r === e : !Array.isArray(r) || r.length === 0 || r.includes(e) : !0;
6295
6329
  })(l) && (l = null), (l === "inherit" || !l) && (l = c.defaultLayout || null);
6296
- let u = await se(t, H(n));
6330
+ let u = await B(t, fe(n));
6297
6331
  Object.assign(o, u), o.resolvedLayoutId = l;
6298
6332
  } catch {}
6299
6333
  let c = await t.prepare("SELECT channelId FROM node_channels WHERE nodeId = ?").all(r);
@@ -6303,7 +6337,7 @@ V.get("/", async (e) => {
6303
6337
  let u = await t.prepare("SELECT * FROM content_blocks WHERE contentId = ? AND isDraft = 1 ORDER BY sortOrder ASC").all(r), d = Array.isArray(u) ? u : u?.results || [], f = await Promise.all(d.map(async (e) => {
6304
6338
  let n = {};
6305
6339
  try {
6306
- n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson || "{}") : e.dataJson || {}, n && typeof n == "object" && (n = await se(t, n));
6340
+ n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson || "{}") : e.dataJson || {}, n && typeof n == "object" && (n = await B(t, n));
6307
6341
  } catch {
6308
6342
  n = {};
6309
6343
  }
@@ -6374,7 +6408,7 @@ V.get("/", async (e) => {
6374
6408
  id: e.id,
6375
6409
  title: e.title,
6376
6410
  slug: e.slug,
6377
- language: e.language || "en",
6411
+ language: e.language || null,
6378
6412
  contentType: e.contentType,
6379
6413
  nodeType: e.contentType,
6380
6414
  isHidden: !!e.isHidden,
@@ -6391,7 +6425,7 @@ V.get("/", async (e) => {
6391
6425
  assetCount: e.assetCount || 0
6392
6426
  }, i = e.draftDataJson || e.dataJson;
6393
6427
  if (i) try {
6394
- let e = typeof i == "string" ? JSON.parse(i) : i, n = await se(t, H(e));
6428
+ let e = typeof i == "string" ? JSON.parse(i) : i, n = await B(t, fe(e));
6395
6429
  Object.assign(r, n);
6396
6430
  } catch {}
6397
6431
  return r;
@@ -6403,13 +6437,35 @@ V.get("/", async (e) => {
6403
6437
  offset: p,
6404
6438
  limit: f
6405
6439
  });
6406
- }), V.post("/", async (e) => {
6407
- let t = e.get("db"), n = await e.req.json(), r = n.node || n.activeNode || n, i = r.id || n.id, a = i != null && i !== "" && !isNaN(Number(i)) ? Number(i) : null, { title: o, slug: s, language: c, nodeType: l, contentType: u, isHidden: d, hidden: f, is_hidden: p, blocks: m, channels: h, trees: g, ..._ } = r, { cleanedData: v, assetRefs: y } = ae(H(_)), b = fe(d === void 0 ? f === void 0 ? p : f : d), x = c || "en", S = l || u || "page", C = e.get("user")?.id || null, w = a, T = /* @__PURE__ */ new Set(), E = s === void 0 ? null : de(s);
6408
- if (E) {
6440
+ }), H.post("/", async (e) => {
6441
+ let t = e.get("db"), n = await e.req.json(), r = n.node || n.activeNode || n, i = r.id || n.id, a = i != null && i !== "" && !isNaN(Number(i)) ? Number(i) : null, { title: o, slug: s, language: c, nodeType: l, contentType: u, isHidden: d, hidden: f, is_hidden: p, blocks: m, channels: h, trees: g, ..._ } = r, { cleanedData: v, assetRefs: y } = R(fe(_)), b = ue(d === void 0 ? f === void 0 ? p : f : d), x = l || u || "page", S = e.get("user")?.id || null, C = typeof c == "string" && c.trim() !== "" ? c.trim() : null, w = g && Array.isArray(g) && g.length > 0 ? g[0] : null, T = w ? w.treeId || w.id : null, E = null;
6442
+ if (T) {
6443
+ let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ? OR key = ? LIMIT 1").get(Number(T) || -1, String(T));
6444
+ if (e?.dataJson) try {
6445
+ let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
6446
+ E = t.defaultLanguage?.trim() || t.language?.trim() || null;
6447
+ } catch {}
6448
+ }
6449
+ if (!E && h && Array.isArray(h) && h.length > 0) {
6450
+ let e = typeof h[0] == "object" ? h[0].id : h[0];
6451
+ if (e && e !== "all") {
6452
+ let n = await t.prepare("SELECT defaultLanguage, dataJson FROM channels WHERE id = ? LIMIT 1").get(Number(e));
6453
+ if (n) {
6454
+ if (n.defaultLanguage) E = n.defaultLanguage.trim();
6455
+ else if (n.dataJson) try {
6456
+ let e = typeof n.dataJson == "string" ? JSON.parse(n.dataJson) : n.dataJson;
6457
+ E = e.defaultLanguage?.trim() || e.language?.trim() || null;
6458
+ } catch {}
6459
+ }
6460
+ }
6461
+ }
6462
+ C && E && C === E && (C = null);
6463
+ let D = a, O = /* @__PURE__ */ new Set(), k = !1, A = s === void 0 ? null : U(s);
6464
+ if (A) {
6409
6465
  let n = [];
6410
6466
  if (g !== void 0 && Array.isArray(g) && g.length > 0) for (let e of g) n.push({
6411
6467
  treeId: Number(e.treeId),
6412
- parentId: pe(e.parentId ?? e._draftParentId ?? null)
6468
+ parentId: de(e.parentId ?? e._draftParentId ?? null)
6413
6469
  });
6414
6470
  else if (a) {
6415
6471
  let e = await t.prepare("SELECT treeId, parentId FROM tree_nodes WHERE contentId = ?").all(a), r = Array.isArray(e) ? e : e?.results || [];
@@ -6419,94 +6475,103 @@ V.get("/", async (e) => {
6419
6475
  });
6420
6476
  }
6421
6477
  for (let r of n) {
6422
- let n = r.parentId === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = r.parentId === null ? [r.treeId, E] : [
6478
+ let n = r.parentId === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = r.parentId === null ? [r.treeId, A] : [
6423
6479
  r.treeId,
6424
6480
  r.parentId,
6425
- E
6481
+ A
6426
6482
  ], o = `
6427
6483
  SELECT cn.id FROM tree_nodes tn
6428
6484
  INNER JOIN content_nodes cn ON tn.contentId = cn.id
6429
6485
  WHERE tn.treeId = ? AND ${n} AND cn.slug = ? AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
6430
6486
  `;
6431
6487
  if (a && (o += " AND cn.id != ?", i.push(a)), o += " LIMIT 1", await t.prepare(o).get(...i)) return e.json({
6432
- error: `The slug '${E}' is already in use by another page in this section.`,
6488
+ error: `The slug '${A}' is already in use by another page in this section.`,
6433
6489
  field: "slug"
6434
6490
  }, 409);
6435
6491
  }
6436
6492
  }
6437
6493
  if (a) {
6438
- let e = await t.prepare("SELECT title, slug, language, contentType, draftDataJson, dataJson, publishedAt, status FROM content_nodes WHERE id = ?").get(a), n = e?.draftDataJson || e?.dataJson || "{}";
6494
+ let e = await t.prepare("SELECT title, slug, language, contentType, isHidden, draftDataJson, dataJson, publishedAt, status FROM content_nodes WHERE id = ?").get(a);
6495
+ k = me(e, {
6496
+ title: o,
6497
+ slug: A,
6498
+ isHidden: b,
6499
+ sanitizedFields: v
6500
+ });
6501
+ let n = e?.draftDataJson || e?.dataJson || "{}";
6439
6502
  try {
6440
- me(typeof n == "string" ? JSON.parse(n) : n, T);
6503
+ pe(typeof n == "string" ? JSON.parse(n) : n, O);
6441
6504
  } catch {}
6442
6505
  if (m !== void 0) {
6443
6506
  let e = await t.prepare("SELECT dataJson FROM content_blocks WHERE contentId = ? AND isDraft = 1").all(a);
6444
6507
  (Array.isArray(e) ? e : e?.results || []).forEach((e) => {
6445
6508
  try {
6446
- me(typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson, T);
6509
+ pe(typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson, O);
6447
6510
  } catch {}
6448
6511
  });
6449
6512
  }
6450
- let r = o === void 0 ? e?.title || "Untitled" : o, i = E ?? e?.slug ?? null, s = S || e?.contentType || "page", c = x || e?.language || "en", l = e?.draftDataJson || e?.dataJson || "{}", u = {};
6513
+ let r = o === void 0 ? e?.title || "Untitled" : o, i = A ?? e?.slug ?? null, s = x || e?.contentType || "page", l = c === void 0 ? e?.language : C, u = e?.draftDataJson || e?.dataJson || "{}", d = {};
6451
6514
  try {
6452
- u = JSON.parse(l);
6515
+ d = JSON.parse(u);
6453
6516
  } catch {}
6454
- let d = JSON.stringify({
6455
- ...u,
6517
+ let f = JSON.stringify({
6518
+ ...d,
6456
6519
  ...v
6457
- }), f = e?.status === "published" || e?.publishedAt ? "published" : "draft", p = +(f === "published");
6458
- await t.prepare("\n UPDATE content_nodes \n SET title = ?, slug = ?, language = ?, contentType = ?, isHidden = ?, status = ?, draftDataJson = ?, hasUnpublishedChanges = ?, updatedById = ?, updatedAt = CURRENT_TIMESTAMP\n WHERE id = ?\n ").run(r, i, c, s, b, f, d, p, C, a);
6520
+ }), p = e?.status === "published" || e?.publishedAt ? "published" : "draft", h = +(p === "published");
6521
+ await t.prepare("\n UPDATE content_nodes \n SET title = ?, slug = ?, language = ?, contentType = ?, isHidden = ?, status = ?, draftDataJson = ?, hasUnpublishedChanges = ?, updatedById = ?, updatedAt = CURRENT_TIMESTAMP\n WHERE id = ?\n ").run(r, i, l, s, b, p, f, h, S, a);
6459
6522
  } else {
6460
- let e = await t.prepare("\n INSERT INTO content_nodes (contentType, title, slug, language, isHidden, status, draftDataJson, dataJson, hasUnpublishedChanges, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, 'draft', ?, NULL, 0, ?, ?)\n ").run(S, o || "Untitled", E, x, b, JSON.stringify(v), C, C);
6461
- w = Number(e.lastInsertRowid);
6523
+ k = !0;
6524
+ let e = await t.prepare("\n INSERT INTO content_nodes (contentType, title, slug, language, isHidden, status, draftDataJson, dataJson, hasUnpublishedChanges, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, 'draft', ?, NULL, 0, ?, ?)\n ").run(x, o || "Untitled", A, C, b, JSON.stringify(v), S, S);
6525
+ D = Number(e.lastInsertRowid);
6462
6526
  }
6463
- if (h !== void 0 && Array.isArray(h) && w) {
6464
- await t.prepare("DELETE FROM node_channels WHERE nodeId = ?").run(w);
6527
+ if (h !== void 0 && Array.isArray(h) && D) {
6528
+ await t.prepare("DELETE FROM node_channels WHERE nodeId = ?").run(D);
6465
6529
  let e = [...new Set(h.map((e) => typeof e == "object" && e ? e.id || e.channelId : e))].filter((e) => e && e !== "all").map((e) => Number(e) || e);
6466
6530
  if (e.length > 0) {
6467
- let n = e.map(() => "(?, ?)").join(", "), r = e.flatMap((e) => [w, e]);
6531
+ let n = e.map(() => "(?, ?)").join(", "), r = e.flatMap((e) => [D, e]);
6468
6532
  await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${n}`).run(...r);
6469
6533
  }
6470
6534
  }
6471
- if (g !== void 0 && Array.isArray(g) && g.length > 0 && w) for (let e of g) {
6535
+ if (g !== void 0 && Array.isArray(g) && g.length > 0 && D) for (let e of g) {
6472
6536
  if (!e || !e.treeId) continue;
6473
- let n = Number(e.treeId) || e.treeId, r = pe(e.parentId ?? e._draftParentId ?? null), i = typeof e.sortOrder == "number" ? e.sortOrder : 0, a = await t.prepare("SELECT id FROM tree_nodes WHERE treeId = ? AND contentId = ?").get(n, w);
6474
- a ? await t.prepare("UPDATE tree_nodes SET parentId = ?, sortOrder = ? WHERE id = ?").run(r, i, a.id) : await t.prepare("INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder) VALUES (?, ?, ?, ?)").run(n, w, r, i);
6537
+ let n = Number(e.treeId) || e.treeId, r = de(e.parentId ?? e._draftParentId ?? null), i = typeof e.sortOrder == "number" ? e.sortOrder : 0, a = await t.prepare("SELECT id, parentId, sortOrder FROM tree_nodes WHERE treeId = ? AND contentId = ?").get(n, D);
6538
+ a ? ((a.parentId !== r || a.sortOrder !== i) && (k = !0), await t.prepare("UPDATE tree_nodes SET parentId = ?, sortOrder = ? WHERE id = ?").run(r, i, a.id)) : (k = !0, await t.prepare("INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder) VALUES (?, ?, ?, ?)").run(n, D, r, i));
6475
6539
  }
6476
- let D = [];
6477
- if (m !== void 0 && Array.isArray(m) && w) {
6478
- await t.prepare("DELETE FROM content_blocks WHERE contentId = ? AND isDraft = 1").run(w);
6540
+ let j = [];
6541
+ if (m !== void 0 && Array.isArray(m) && D) {
6542
+ await t.prepare("DELETE FROM content_blocks WHERE contentId = ? AND isDraft = 1").run(D);
6479
6543
  let e = [], n = [];
6480
6544
  for (let t = 0; t < m.length; t++) {
6481
- let r = m[t], i = r.componentId || r.elementType || "text-block", a = r.data || {}, o = String(r.blockId || a.blockId || r.instanceId || r.id || `block-${Date.now()}`), { cleanedData: s, assetRefs: c } = ae({
6545
+ let r = m[t], i = r.componentId || r.elementType || "text-block", a = r.data || {}, o = String(r.blockId || a.blockId || r.instanceId || r.id || `block-${Date.now()}`), { cleanedData: s, assetRefs: c } = R({
6482
6546
  ...a,
6483
6547
  blockId: o,
6484
6548
  _instanceId: o
6485
6549
  });
6486
- c.forEach((e) => D.push({
6550
+ c.forEach((e) => j.push({
6487
6551
  ...e,
6488
6552
  fieldKey: `blocks[${t}].${e.fieldKey}`
6489
6553
  }));
6490
6554
  let l = r.region !== void 0 && r.region !== null && String(r.region).trim() !== "" ? String(r.region) : "content";
6491
- e.push("(?, ?, ?, ?, ?, 1)"), n.push(w, t, i, JSON.stringify(s), l);
6555
+ e.push("(?, ?, ?, ?, ?, 1)"), n.push(D, t, i, JSON.stringify(s), l);
6492
6556
  }
6493
6557
  e.length > 0 && await t.prepare(`INSERT INTO content_blocks (contentId, sortOrder, elementType, dataJson, region, isDraft) VALUES ${e.join(", ")}`).run(...n);
6494
6558
  }
6495
- if (w) {
6496
- let n = [...y, ...D];
6497
- await oe(t, w, n);
6498
- let r = new Set(n.map((e) => e.assetId)), i = new Set([...T].filter((e) => !r.has(e)));
6559
+ if (D) {
6560
+ let n = [...y, ...j];
6561
+ await oe(t, D, n);
6562
+ let r = new Set(n.map((e) => e.assetId)), i = new Set([...O].filter((e) => !r.has(e)));
6499
6563
  if (i.size > 0) {
6500
- let { storage: n } = ie(e.env);
6501
- await U(t, n, i);
6564
+ let { storage: n } = ae(e.env);
6565
+ await he(t, n, i);
6502
6566
  }
6503
6567
  }
6504
- return await I(e).clear(), e.json({
6568
+ return await I(e).clear(), D && new V(e.env).purgeNode(e, t, D, k), e.json({
6505
6569
  success: !0,
6506
- id: w,
6507
- status: "draft"
6570
+ id: D,
6571
+ status: "draft",
6572
+ isStructuralChange: k
6508
6573
  });
6509
- }), V.post("/publish", async (e) => {
6574
+ }), H.post("/publish", async (e) => {
6510
6575
  let t = e.get("db"), n = await e.req.json(), r = n.id || n.nodeId;
6511
6576
  if (!r || isNaN(Number(r))) return e.json({ error: "Node ID required for publishing" }, 400);
6512
6577
  let i = Number(r), a = e.get("user")?.id || null, o = await t.prepare("SELECT * FROM content_nodes WHERE id = ?").get(i);
@@ -6519,57 +6584,58 @@ V.get("/", async (e) => {
6519
6584
  try {
6520
6585
  c = typeof o.draftDataJson == "string" ? JSON.parse(o.draftDataJson) : o.draftDataJson || {};
6521
6586
  } catch {}
6522
- let l = (s.title ?? o.title ?? "").trim(), u = (c.title ?? n.title ?? o.title ?? "").trim(), d = (s.slug ?? o.slug ?? "").trim(), f = (c.slug ?? n.slug ?? o.slug ?? "").trim(), p = l !== "" && u !== "" && l !== u || d !== "" && f !== "" && d !== f, m = o.draftDataJson || o.dataJson || "{}";
6523
- await t.prepare("\n UPDATE content_nodes\n SET publishedDataJson = ?, dataJson = ?, publishedAt = CURRENT_TIMESTAMP, status = 'published', hasUnpublishedChanges = 0, updatedById = ?, updatedAt = CURRENT_TIMESTAMP\n WHERE id = ?\n ").run(m, m, a, i), await t.prepare("DELETE FROM content_blocks WHERE contentId = ? AND isDraft = 0").run(i);
6524
- let h = await t.prepare("SELECT * FROM content_blocks WHERE contentId = ? AND isDraft = 1 ORDER BY sortOrder ASC").all(i), g = Array.isArray(h) ? h : h?.results || [];
6525
- if (g.length > 0) {
6587
+ let l = (s.title ?? o.title ?? "").trim(), u = (c.title ?? n.title ?? o.title ?? "").trim(), d = (s.slug ?? o.slug ?? "").trim(), f = (c.slug ?? n.slug ?? o.slug ?? "").trim(), p = (s.menuTitle ?? "").trim(), m = (c.menuTitle ?? "").trim(), h = l !== "" && u !== "" && l !== u || d !== "" && f !== "" && d !== f || p !== "" && m !== "" && p !== m, g = o.draftDataJson || o.dataJson || "{}";
6588
+ await t.prepare("\n UPDATE content_nodes\n SET publishedDataJson = ?, dataJson = ?, publishedAt = CURRENT_TIMESTAMP, status = 'published', hasUnpublishedChanges = 0, updatedById = ?, updatedAt = CURRENT_TIMESTAMP\n WHERE id = ?\n ").run(g, g, a, i), await t.prepare("DELETE FROM content_blocks WHERE contentId = ? AND isDraft = 0").run(i);
6589
+ let _ = await t.prepare("SELECT * FROM content_blocks WHERE contentId = ? AND isDraft = 1 ORDER BY sortOrder ASC").all(i), v = Array.isArray(_) ? _ : _?.results || [];
6590
+ if (v.length > 0) {
6526
6591
  let e = [], n = [];
6527
- for (let t of g) {
6592
+ for (let t of v) {
6528
6593
  let r = t.region !== void 0 && t.region !== null && String(t.region).trim() !== "" ? String(t.region) : "content";
6529
6594
  e.push("(?, ?, ?, ?, ?, 0)"), n.push(i, t.sortOrder, t.elementType, t.dataJson, r);
6530
6595
  }
6531
6596
  await t.prepare(`INSERT INTO content_blocks (contentId, sortOrder, elementType, dataJson, region, isDraft) VALUES ${e.join(", ")}`).run(...n);
6532
6597
  }
6533
- let _ = ((await t.prepare("SELECT COUNT(*) as count FROM node_revisions WHERE nodeId = ?").get(i))?.count || 0) + 1, v = {
6534
- version: _,
6598
+ let y = ((await t.prepare("SELECT COUNT(*) as count FROM node_revisions WHERE nodeId = ?").get(i))?.count || 0) + 1, b = {
6599
+ version: y,
6535
6600
  publishedAt: (/* @__PURE__ */ new Date()).toISOString(),
6536
6601
  node: {
6537
6602
  ...o,
6538
- dataJson: m
6603
+ dataJson: g
6539
6604
  },
6540
- blocks: g
6605
+ blocks: v
6541
6606
  };
6542
- return await t.prepare("INSERT INTO node_revisions (nodeId, version, snapshotJson, createdById) VALUES (?, ?, ?, ?)").run(i, _, JSON.stringify(v), a), await I(e).clear(), new B(e.env).purgeNode(e, t, i, p), e.json({
6607
+ return await t.prepare("INSERT INTO node_revisions (nodeId, version, snapshotJson, createdById) VALUES (?, ?, ?, ?)").run(i, y, JSON.stringify(b), a), await I(e).clear(), new V(e.env).purgeNode(e, t, i, h), e.json({
6543
6608
  success: !0,
6544
6609
  id: i,
6545
6610
  status: "published",
6546
- version: _,
6547
- publishedAt: v.publishedAt,
6548
- hasUnpublishedChanges: !1
6611
+ version: y,
6612
+ publishedAt: b.publishedAt,
6613
+ hasUnpublishedChanges: !1,
6614
+ isStructuralChange: h
6549
6615
  });
6550
- }), V.delete("/", async (e) => {
6616
+ }), H.delete("/", async (e) => {
6551
6617
  let t = e.get("db"), n = e.req.query("id");
6552
6618
  if (!n) return e.json({ error: "Node ID required" }, 400);
6553
6619
  let r = Number(n);
6554
- return await t.prepare("UPDATE content_nodes SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?").run(r), await I(e).clear(), new B(e.env).purgeNode(e, t, r, !0), e.json({
6620
+ return await t.prepare("UPDATE content_nodes SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?").run(r), await I(e).clear(), new V(e.env).purgeNode(e, t, r, !0), e.json({
6555
6621
  success: !0,
6556
6622
  deletedNodeId: r
6557
6623
  });
6558
- }), V.post("/restore", async (e) => {
6624
+ }), H.post("/restore", async (e) => {
6559
6625
  let t = e.get("db"), n = await e.req.json(), r = Number(n.id);
6560
- return r ? await t.prepare("SELECT id FROM content_nodes WHERE id = ?").get(r) ? (await t.prepare("UPDATE content_nodes SET deletedAt = NULL WHERE id = ?").run(r), await I(e).clear(), new B(e.env).purgeNode(e, t, r, !0), e.json({
6626
+ return r ? await t.prepare("SELECT id FROM content_nodes WHERE id = ?").get(r) ? (await t.prepare("UPDATE content_nodes SET deletedAt = NULL WHERE id = ?").run(r), await I(e).clear(), new V(e.env).purgeNode(e, t, r, !0), e.json({
6561
6627
  success: !0,
6562
6628
  restoredNodeId: r
6563
6629
  })) : e.json({ error: "Node not found" }, 404) : e.json({ error: "Node ID required" }, 400);
6564
- }), V.delete("/purge", async (e) => {
6630
+ }), H.delete("/purge", async (e) => {
6565
6631
  let t = e.get("db"), n = e.req.query("id");
6566
6632
  if (!n) return e.json({ error: "Node ID required" }, 400);
6567
6633
  let r = Number(n);
6568
- return new B(e.env).purgeNode(e, t, r, !0), await t.prepare("DELETE FROM node_channels WHERE nodeId = ?").run(r), await t.prepare("DELETE FROM tree_nodes WHERE contentId = ?").run(r), await t.prepare("DELETE FROM content_blocks WHERE contentId = ?").run(r), await t.prepare("DELETE FROM node_revisions WHERE nodeId = ?").run(r), await t.prepare("DELETE FROM node_assets WHERE nodeId = ?").run(r), await t.prepare("DELETE FROM content_nodes WHERE id = ?").run(r), await I(e).clear(), e.json({
6634
+ return new V(e.env).purgeNode(e, t, r, !0), await t.prepare("DELETE FROM node_channels WHERE nodeId = ?").run(r), await t.prepare("DELETE FROM tree_nodes WHERE contentId = ?").run(r), await t.prepare("DELETE FROM content_blocks WHERE contentId = ?").run(r), await t.prepare("DELETE FROM node_revisions WHERE nodeId = ?").run(r), await t.prepare("DELETE FROM node_assets WHERE nodeId = ?").run(r), await t.prepare("DELETE FROM content_nodes WHERE id = ?").run(r), await I(e).clear(), e.json({
6569
6635
  success: !0,
6570
6636
  purgedNodeId: r
6571
6637
  });
6572
- }), V.get("/:id/revisions", async (e) => {
6638
+ }), H.get("/:id/revisions", async (e) => {
6573
6639
  let t = e.get("db"), n = Number(e.req.param("id"));
6574
6640
  if (isNaN(n)) return e.json({ error: "Invalid Node ID" }, 400);
6575
6641
  let r = await t.prepare("\n SELECT version, createdById, snapshotJson \n FROM node_revisions \n WHERE nodeId = ? \n ORDER BY version DESC\n ").all(n), i = (Array.isArray(r) ? r : r?.results || []).map((e) => {
@@ -6585,7 +6651,7 @@ V.get("/", async (e) => {
6585
6651
  };
6586
6652
  });
6587
6653
  return e.json({ revisions: i });
6588
- }), V.get("/:id/revisions/:version", async (e) => {
6654
+ }), H.get("/:id/revisions/:version", async (e) => {
6589
6655
  let t = e.get("db"), n = Number(e.req.param("id")), r = Number(e.req.param("version")), i = await t.prepare("SELECT snapshotJson FROM node_revisions WHERE nodeId = ? AND version = ?").get(n, r);
6590
6656
  if (!i) return e.json({ error: "Snapshot not found" }, 404);
6591
6657
  let a = {};
@@ -6595,7 +6661,7 @@ V.get("/", async (e) => {
6595
6661
  return e.json({ error: "Corrupt snapshot data" }, 500);
6596
6662
  }
6597
6663
  return e.json({ snapshot: a });
6598
- }), V.post("/:id/revisions/:version/restore", async (e) => {
6664
+ }), H.post("/:id/revisions/:version/restore", async (e) => {
6599
6665
  let t = e.get("db"), n = Number(e.req.param("id")), r = Number(e.req.param("version")), i = e.get("user")?.id || null, a = await t.prepare("SELECT snapshotJson FROM node_revisions WHERE nodeId = ? AND version = ?").get(n, r);
6600
6666
  if (!a) return e.json({ error: "Snapshot not found" }, 404);
6601
6667
  let o = {};
@@ -6614,8 +6680,8 @@ V.get("/", async (e) => {
6614
6680
  restoredVersion: r
6615
6681
  });
6616
6682
  });
6617
- var G = new e();
6618
- function he(e, t = null) {
6683
+ var W = new e();
6684
+ function _e(e, t = null) {
6619
6685
  let n = [];
6620
6686
  for (let r = 0; r < e.length; r++) {
6621
6687
  let i = e[r];
@@ -6627,19 +6693,19 @@ function he(e, t = null) {
6627
6693
  id: o,
6628
6694
  parentId: t,
6629
6695
  sortOrder: r
6630
- }), i.children && Array.isArray(i.children) && i.children.length > 0 && n.push(...he(i.children, o)));
6696
+ }), i.children && Array.isArray(i.children) && i.children.length > 0 && n.push(..._e(i.children, o)));
6631
6697
  }
6632
6698
  return n;
6633
6699
  }
6634
- function ge(e) {
6700
+ function G(e) {
6635
6701
  if (e == null || e === "null" || e === "" || typeof e == "string" && e.startsWith("draft-")) return null;
6636
6702
  let t = Number(e);
6637
6703
  return isNaN(t) ? null : t;
6638
6704
  }
6639
- function _e(e) {
6705
+ function ve(e) {
6640
6706
  return +(e === !0 || e === 1 || e === "1" || e === "true");
6641
6707
  }
6642
- G.get("/tree.json", async (e) => {
6708
+ W.get("/tree.json", async (e) => {
6643
6709
  try {
6644
6710
  let t = e.get("db"), n = e.req.query("treeId") || "main-nav", r = e.req.query("preview") === "true", i = 1;
6645
6711
  if (isNaN(Number(n))) {
@@ -6674,7 +6740,7 @@ G.get("/tree.json", async (e) => {
6674
6740
  id: e.contentId,
6675
6741
  treeNodeId: e.treeNodeId,
6676
6742
  parentId: e.parentId || null,
6677
- language: e.language || "en",
6743
+ language: e.language?.trim() || null,
6678
6744
  hidden: +!!s,
6679
6745
  isHidden: s,
6680
6746
  status: e.status || "draft",
@@ -6689,9 +6755,9 @@ G.get("/tree.json", async (e) => {
6689
6755
  } catch (t) {
6690
6756
  return console.error("[CMS Tree API] GET Error:", t), e.json({ error: t.message || "Failed to fetch tree" }, 500);
6691
6757
  }
6692
- }), G.post("/tree.json", async (e) => {
6758
+ }), W.post("/tree.json", async (e) => {
6693
6759
  try {
6694
- let t = e.get("db"), n = await e.req.json(), r = n.treeId ? String(n.treeId).trim() : "main-nav", i = I(e), a = new B(e.env), o = 1;
6760
+ let t = e.get("db"), n = await e.req.json(), r = n.treeId ? String(n.treeId).trim() : "main-nav", i = I(e), a = new V(e.env), o = 1;
6695
6761
  if (isNaN(Number(r))) {
6696
6762
  let e = await t.prepare("SELECT id FROM trees WHERE key = ?").get(r);
6697
6763
  if (e && e.id) o = Number(e.id);
@@ -6701,7 +6767,7 @@ G.get("/tree.json", async (e) => {
6701
6767
  }
6702
6768
  } else o = Number(r);
6703
6769
  if (n.tree && Array.isArray(n.tree)) {
6704
- let r = he(n.tree, null);
6770
+ let r = _e(n.tree, null);
6705
6771
  if (r.length > 0) for (let e = 0; e < r.length; e += 50) {
6706
6772
  let n = r.slice(e, e + 50), i = n.map((e) => e.id), a = i.map(() => "?").join(","), s = "UPDATE tree_nodes SET \n";
6707
6773
  s += "parentId = CASE id \n", n.forEach(() => {
@@ -6721,9 +6787,9 @@ G.get("/tree.json", async (e) => {
6721
6787
  reorderedCount: r.length
6722
6788
  });
6723
6789
  }
6724
- let { action: s, title: c, nodeType: l, parentId: u, contentId: d, nodeData: f = {}, pageData: p = {} } = n, m = Object.keys(f).length > 0 ? { ...f } : { ...p }, h = _e(n.isHidden === void 0 ? m.isHidden === void 0 ? m.hidden : m.isHidden : n.isHidden);
6790
+ let { action: s, title: c, nodeType: l, parentId: u, contentId: d, nodeData: f = {}, pageData: p = {} } = n, m = Object.keys(f).length > 0 ? { ...f } : { ...p }, h = ve(n.isHidden === void 0 ? m.isHidden === void 0 ? m.hidden : m.isHidden : n.isHidden);
6725
6791
  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;
6726
- let g = ge(u), _ = e.get("user")?.id || null;
6792
+ let g = G(u), _ = e.get("user")?.id || null;
6727
6793
  if (s === "create") {
6728
6794
  let r = m.slug || n.slug || c, s = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
6729
6795
  if (s) {
@@ -6745,23 +6811,41 @@ G.get("/tree.json", async (e) => {
6745
6811
  field: "slug"
6746
6812
  }, 409);
6747
6813
  }
6748
- 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", s, m.language || n.language || "en", h, u, _, _), f = Number(d.lastInsertRowid);
6749
- await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, f);
6750
- let p = g === null ? "parentId IS NULL" : "parentId = ?", v = g === null ? [o] : [o, g], y = (await t.prepare(`
6814
+ let u = m.language?.trim() || n.language?.trim() || null;
6815
+ if (!u) {
6816
+ let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ?").get(o);
6817
+ if (e?.dataJson) try {
6818
+ let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
6819
+ t.defaultLanguage && (u = t.defaultLanguage.trim());
6820
+ } catch {}
6821
+ }
6822
+ if (!u) {
6823
+ let e = [];
6824
+ if (n.channels && Array.isArray(n.channels) ? e = n.channels : n.channelId && n.channelId !== "all" && (e = [n.channelId]), e.length > 0) {
6825
+ let n = Number(e[0]);
6826
+ if (!isNaN(n)) {
6827
+ let e = await t.prepare("SELECT defaultLanguage FROM channels WHERE id = ?").get(n);
6828
+ e?.defaultLanguage && (u = e.defaultLanguage.trim());
6829
+ }
6830
+ }
6831
+ }
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(`
6751
6835
  SELECT COALESCE(MAX(sortOrder), -1) + 1 as nextSort
6752
6836
  FROM tree_nodes
6753
- WHERE treeId = ? AND ${p}
6754
- `).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 = [];
6755
- n.channels && Array.isArray(n.channels) ? S = n.channels : n.channelId && n.channelId !== "all" && (S = [n.channelId]);
6756
- let C = [...new Set(S)].filter((e) => e && e !== "all").map((e) => Number(e));
6757
- if (C.length > 0) {
6758
- let e = C.map(() => "(?, ?)").join(", "), n = C.flatMap((e) => [f, e]);
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]);
6759
6843
  await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...n);
6760
6844
  }
6761
6845
  return await i.clear(), a.purgeGlobalCache(e, t), e.json({
6762
6846
  success: !0,
6763
- id: f,
6764
- treeNodeId: x,
6847
+ id: p,
6848
+ treeNodeId: S,
6765
6849
  status: "draft"
6766
6850
  }, 201);
6767
6851
  }
@@ -6812,7 +6896,7 @@ G.get("/tree.json", async (e) => {
6812
6896
  details: t.message
6813
6897
  }, 500);
6814
6898
  }
6815
- }), G.get("/trees.json", async (e) => {
6899
+ }), W.get("/trees.json", async (e) => {
6816
6900
  try {
6817
6901
  let t = e.get("db"), n = await t.prepare("SELECT * FROM trees ORDER BY LOWER(label) ASC").all(), r = Array.isArray(n) ? n : n?.results || [], i = await t.prepare("SELECT channelId, treeId FROM channel_trees").all(), a = (Array.isArray(i) ? i : i?.results || []).reduce((e, t) => {
6818
6902
  let n = Number(t.treeId), r = Number(t.channelId);
@@ -6842,7 +6926,7 @@ G.get("/tree.json", async (e) => {
6842
6926
  } catch {
6843
6927
  return e.json([]);
6844
6928
  }
6845
- }), G.post("/trees.json", async (e) => {
6929
+ }), W.post("/trees.json", async (e) => {
6846
6930
  try {
6847
6931
  let t = e.get("db"), n = await e.req.json(), r = n.id, i = r != null && r !== "" && !isNaN(Number(r)) ? Number(r) : null, a = `tree-${Date.now().toString(36)}`, o = (n.key || n.slug || a).toLowerCase().replace(/[^a-z0-9_-]/g, "-"), s = n.label?.trim() || o, c = n.treeType !== void 0 && n.treeType !== null ? n.treeType : n.type ?? "site", l = n.channelId !== void 0 && n.channelId !== null && Number(n.channelId) || null, u = +(n.isHidden === !0 || n.isHidden === 1 || n.isHidden === "true"), d = e.get("user")?.id || null, f = { ...n };
6848
6932
  if (delete f.id, delete f.key, delete f.label, delete f.treeType, delete f.type, delete f.channelId, delete f.channels, delete f.isHidden, delete f.createdById, delete f.updatedById, delete f.createdAt, delete f.updatedAt, await t.prepare("SELECT id FROM trees WHERE key = ? AND id != ? LIMIT 1").get(o, i ?? -1)) return e.json({
@@ -6867,7 +6951,7 @@ G.get("/tree.json", async (e) => {
6867
6951
  await t.prepare(`INSERT OR IGNORE INTO channel_trees (channelId, treeId, key) VALUES ${n}`).run(...r);
6868
6952
  }
6869
6953
  }
6870
- return await I(e).clear(), new B(e.env).purgeGlobalCache(e, t), e.json({
6954
+ return await I(e).clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
6871
6955
  success: !0,
6872
6956
  id: p,
6873
6957
  key: o,
@@ -6881,12 +6965,12 @@ G.get("/tree.json", async (e) => {
6881
6965
  } catch (t) {
6882
6966
  return console.error("[API Trees] Error saving tree:", t), e.json({ error: t.message || "Failed to save tree" }, 500);
6883
6967
  }
6884
- }), G.delete("/trees.json", async (e) => {
6968
+ }), W.delete("/trees.json", async (e) => {
6885
6969
  let t = e.get("db"), n = e.req.query("id");
6886
6970
  if (!n) return e.json({ error: "Tree ID required" }, 400);
6887
6971
  let r = Number(n);
6888
6972
  try {
6889
- return await t.prepare("DELETE FROM trees WHERE id = ?").run(r), await t.prepare("DELETE FROM channel_trees WHERE treeId = ?").run(r), await t.prepare("DELETE FROM tree_nodes WHERE treeId = ?").run(r), await I(e).clear(), new B(e.env).purgeGlobalCache(e, t), e.json({
6973
+ return await t.prepare("DELETE FROM trees WHERE id = ?").run(r), await t.prepare("DELETE FROM channel_trees WHERE treeId = ?").run(r), await t.prepare("DELETE FROM tree_nodes WHERE treeId = ?").run(r), await I(e).clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
6890
6974
  success: !0,
6891
6975
  deletedTreeId: r
6892
6976
  });
@@ -6894,8 +6978,8 @@ G.get("/tree.json", async (e) => {
6894
6978
  return e.json({ error: "Failed to delete tree" }, 500);
6895
6979
  }
6896
6980
  });
6897
- var ve = new e();
6898
- ve.get("/", async (e) => {
6981
+ var ye = new e();
6982
+ ye.get("/", async (e) => {
6899
6983
  try {
6900
6984
  let t = e.get("db"), n = await t.prepare("SELECT * FROM channels ORDER BY id ASC").all(), r = Array.isArray(n) ? n : n?.results || [], i = await t.prepare("SELECT channelId, treeId, key, metaJson FROM channel_trees").all(), a = ((Array.isArray(i) ? i : i?.results || []) || []).reduce((e, t) => {
6901
6985
  e[t.channelId] || (e[t.channelId] = []);
@@ -6919,7 +7003,7 @@ ve.get("/", async (e) => {
6919
7003
  isHidden: !!e.isHidden,
6920
7004
  trees: a[e.id] || []
6921
7005
  };
6922
- }), s = e.env?.BUNDLED_DEFINITIONS, c = ce(s)?.channelTemplate || {
7006
+ }), s = e.env?.BUNDLED_DEFINITIONS, c = se(s), l = c?.channelTemplate || Object.values(c?.channels || {})[0] || {
6923
7007
  label: "Channel Settings",
6924
7008
  fields: {
6925
7009
  key: {
@@ -6951,7 +7035,7 @@ ve.get("/", async (e) => {
6951
7035
  }
6952
7036
  };
6953
7037
  return e.json({
6954
- schema: c,
7038
+ schema: l,
6955
7039
  channels: o
6956
7040
  });
6957
7041
  } catch (t) {
@@ -6961,24 +7045,26 @@ ve.get("/", async (e) => {
6961
7045
  error: t.message
6962
7046
  }, 500);
6963
7047
  }
6964
- }), ve.post("/", async (e) => {
7048
+ }), ye.post("/", async (e) => {
6965
7049
  try {
6966
- let t = e.get("db"), n = await e.req.json(), r = n.id, i = r != null && r !== "" && !isNaN(Number(r)) ? Number(r) : null, { key: a, label: o, channelType: s = "website", domain: c = "localhost", baseUrl: l = "http://localhost:4321", defaultLanguage: u = "en", isHidden: d = !1, trees: f = [], createdById: p = null, updatedById: m = null, id: h, createdAt: g, updatedAt: _, ...v } = n, y = a?.trim() || "main", b = o?.trim() || "Untitled Channel", x = Array.isArray(f) ? f : [], S = JSON.stringify(v || {}), C = e.get("user")?.id || m || p || null;
6967
- if (await t.prepare("SELECT id FROM channels WHERE key = ? AND id != ? LIMIT 1").get(y, i ?? -1)) return e.json({
6968
- error: `Channel API key "${y}" is already in use.`,
7050
+ let t = e.get("db"), n = await e.req.json(), r = n.channel || n.data || n, i = r.id, a = i != null && i !== "" && !isNaN(Number(i)) ? Number(i) : null, { key: o, label: s, channelType: c = "website", domain: l = "localhost", baseUrl: u = "http://localhost:4321", defaultLanguage: d, default_language: f, language: p, isHidden: m, hidden: h, trees: g = [], createdById: _ = null, updatedById: v = null, id: y, createdAt: b, updatedAt: x, ...S } = r, C = o?.trim() || "main", w = s?.trim() || "Untitled Channel", T = d || f || p || "";
7051
+ typeof T == "object" && T && (T = T.value || T.id || ""), T = String(T).trim();
7052
+ let E = m === !0 || m === "true" || m === 1 || h === !0 || h === "true" || h === 1, D = Array.isArray(g) ? g : [], O = JSON.stringify(S || {}), k = e.get("user")?.id || v || _ || null;
7053
+ if (await t.prepare("SELECT id FROM channels WHERE key = ? AND id != ? LIMIT 1").get(C, a ?? -1)) return e.json({
7054
+ error: `Channel API key "${C}" is already in use.`,
6969
7055
  field: "key"
6970
7056
  }, 409);
6971
- let w = i;
6972
- if (i) await t.prepare("\n UPDATE channels \n SET key = ?, label = ?, channelType = ?, domain = ?, baseUrl = ?, defaultLanguage = ?, \n isHidden = ?, dataJson = ?, updatedById = ?, updatedAt = CURRENT_TIMESTAMP\n WHERE id = ?\n ").run(y, b, s, c, l, u, +!!d, S, C, i);
7057
+ let A = a;
7058
+ if (a) await t.prepare("\n UPDATE channels \n SET key = ?, label = ?, channelType = ?, domain = ?, baseUrl = ?, defaultLanguage = ?, \n isHidden = ?, dataJson = ?, updatedById = ?, updatedAt = CURRENT_TIMESTAMP\n WHERE id = ?\n ").run(C, w, c, l, u, T, +!!E, O, k, a);
6973
7059
  else {
6974
- let e = await t.prepare("\n INSERT INTO channels (key, label, channelType, domain, baseUrl, defaultLanguage, isHidden, dataJson, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ").run(y, b, s, c, l, u, +!!d, S, C, C);
6975
- w = Number(e.lastInsertRowid);
7060
+ let e = await t.prepare("\n INSERT INTO channels (key, label, channelType, domain, baseUrl, defaultLanguage, isHidden, dataJson, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ").run(C, w, c, l, u, T, +!!E, O, k, k);
7061
+ A = Number(e.lastInsertRowid);
6976
7062
  }
6977
- await t.prepare("DELETE FROM channel_trees WHERE channelId = ?").run(w);
6978
- let T = x.filter((e) => e && e.treeId && e.key);
6979
- if (T.length > 0) {
6980
- let e = T.map(() => "(?, ?, ?, ?)").join(", "), n = T.flatMap((e) => [
6981
- w,
7063
+ await t.prepare("DELETE FROM channel_trees WHERE channelId = ?").run(A);
7064
+ let j = D.filter((e) => e && e.treeId && e.key);
7065
+ if (j.length > 0) {
7066
+ let e = j.map(() => "(?, ?, ?, ?)").join(", "), n = j.flatMap((e) => [
7067
+ A,
6982
7068
  Number(e.treeId) || e.treeId,
6983
7069
  String(e.key).trim(),
6984
7070
  JSON.stringify(e.meta || {})
@@ -6988,9 +7074,10 @@ ve.get("/", async (e) => {
6988
7074
  VALUES ${e}
6989
7075
  `).run(...n);
6990
7076
  }
6991
- return await I(e).clear(), new B(e.env).purgeGlobalCache(e, t), e.json({
7077
+ let M = I(e);
7078
+ return await M.delete(`channel:${C}`), await M.delete(`channel:${A}`), await M.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
6992
7079
  success: !0,
6993
- id: w
7080
+ id: A
6994
7081
  });
6995
7082
  } catch (t) {
6996
7083
  return console.error("[API Channels] Error saving channel:", t), e.json({
@@ -6998,12 +7085,14 @@ ve.get("/", async (e) => {
6998
7085
  details: t.message
6999
7086
  }, 500);
7000
7087
  }
7001
- }), ve.delete("/", async (e) => {
7088
+ }), ye.delete("/", async (e) => {
7002
7089
  let t = e.get("db"), n = e.req.query("id");
7003
7090
  if (!n) return e.json({ error: "Channel ID required" }, 400);
7004
7091
  let r = Number(n);
7005
7092
  try {
7006
- return await t.prepare("DELETE FROM channel_trees WHERE channelId = ?").run(r), await t.prepare("DELETE FROM node_channels WHERE channelId = ?").run(r), await t.prepare("DELETE FROM channels WHERE id = ?").run(r), await I(e).clear(), new B(e.env).purgeGlobalCache(e, t), e.json({
7093
+ await t.prepare("DELETE FROM channel_trees WHERE channelId = ?").run(r), await t.prepare("DELETE FROM node_channels WHERE channelId = ?").run(r), await t.prepare("DELETE FROM channels WHERE id = ?").run(r);
7094
+ let n = I(e);
7095
+ return await n.delete(`channel:${r}`), await n.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
7007
7096
  success: !0,
7008
7097
  deletedSiteId: r
7009
7098
  });
@@ -7019,11 +7108,11 @@ if (typeof process < "u" && process?.versions?.node) try {
7019
7108
  let e = i(import.meta.url);
7020
7109
  K = e("node:fs"), q = e("node:path");
7021
7110
  } catch {}
7022
- function ye(e, t = "") {
7111
+ function be(e, t = "") {
7023
7112
  let n = e.split(/[\\/]/).pop() || "";
7024
7113
  return t && n.endsWith(t) ? n.slice(0, -t.length) : n;
7025
7114
  }
7026
- function be(e) {
7115
+ function xe(e) {
7027
7116
  let t = e.match(/\.[^.\\/]+$/);
7028
7117
  return t ? t[0] : "";
7029
7118
  }
@@ -7036,7 +7125,7 @@ var J = {
7036
7125
  nodeLayouts: {},
7037
7126
  blockLayouts: {}
7038
7127
  };
7039
- function xe(e) {
7128
+ function Se(e) {
7040
7129
  return e ? typeof e == "string" ? e.trim() : Array.isArray(e) ? e.includes("*") ? "*" : e : "*" : "*";
7041
7130
  }
7042
7131
  function Y(e = {}, t = {}) {
@@ -7051,47 +7140,47 @@ function Y(e = {}, t = {}) {
7051
7140
  };
7052
7141
  return t.required === !0 || String(t.required).toLowerCase() === "true" || t.rules?.required === !0 || String(t.rules?.required).toLowerCase() === "true" || t.required === void 0 && (e.required === !0 || String(e.required).toLowerCase() === "true" || e.rules?.required === !0 || String(e.rules?.required).toLowerCase() === "true") ? (n.required = !0, n.rules.required = !0) : (t.required === !1 || t.rules?.required === !1) && (n.required = !1, n.rules.required = !1), n;
7053
7142
  }
7054
- function Se(e) {
7143
+ function Ce(e) {
7055
7144
  if (!e || typeof e != "object") return e;
7056
- if (Array.isArray(e)) return e.map(Se);
7145
+ if (Array.isArray(e)) return e.map(Ce);
7057
7146
  let t = {};
7058
7147
  for (let [n, r] of Object.entries(e)) if (n === "<<" || n === "<<:") {
7059
- let e = Se(r);
7148
+ let e = Ce(r);
7060
7149
  if (typeof e == "object" && e) {
7061
7150
  if (Array.isArray(e)) for (let n of e) Object.assign(t, n);
7062
7151
  else Object.assign(t, e);
7063
7152
  }
7064
- } else t[n] = Se(r);
7153
+ } else t[n] = Ce(r);
7065
7154
  return t;
7066
7155
  }
7067
- function Ce(e, t) {
7068
- return e ? Se(n.parseDocument(e, { customTags: [{
7156
+ function we(e, t) {
7157
+ return e ? Ce(n.parseDocument(e, { customTags: [{
7069
7158
  tag: "!include",
7070
7159
  resolve(e) {
7071
- let n = (typeof e == "string" ? e : String(e?.strValue || e?.value || "")).trim(), r = ye(n);
7160
+ let n = (typeof e == "string" ? e : String(e?.strValue || e?.value || "")).trim(), r = be(n);
7072
7161
  if (!r) return n;
7073
7162
  if (t && t.fieldSets) {
7074
7163
  let e = Object.keys(t.fieldSets).find((e) => e.endsWith("/" + r) || e === r);
7075
- if (e) return Ce(t.fieldSets[e], t);
7164
+ if (e) return we(t.fieldSets[e], t);
7076
7165
  }
7077
7166
  return n;
7078
7167
  }
7079
7168
  }] }).toJS() || {}) : {};
7080
7169
  }
7081
- function we(e, t = /* @__PURE__ */ new Set()) {
7170
+ function Te(e, t = /* @__PURE__ */ new Set()) {
7082
7171
  if (!K || !q) return {};
7083
7172
  let r = q.resolve(e);
7084
7173
  if (t.has(r) || (t.add(r), !K.existsSync(r))) return {};
7085
7174
  let i = K.readFileSync(r, "utf-8");
7086
- return Se(n.parseDocument(i, { customTags: [{
7175
+ return Ce(n.parseDocument(i, { customTags: [{
7087
7176
  tag: "!include",
7088
7177
  resolve(e) {
7089
7178
  let n = (typeof e == "string" ? e : String(e?.strValue || e?.value || "")).trim();
7090
- return n ? we(q.resolve(q.dirname(r), n), new Set(t)) : {};
7179
+ return n ? Te(q.resolve(q.dirname(r), n), new Set(t)) : {};
7091
7180
  }
7092
7181
  }] }).toJS() || {});
7093
7182
  }
7094
- function Te() {
7183
+ function Ee() {
7095
7184
  if (!K || !q || typeof process > "u" || !process?.versions?.node) return null;
7096
7185
  try {
7097
7186
  let e = process.cwd(), t = "", n = [
@@ -7124,9 +7213,9 @@ function Te() {
7124
7213
  let r = {}, i = K.readdirSync(n);
7125
7214
  for (let e of i) {
7126
7215
  if (!e.endsWith(".yaml") && !e.endsWith(".yml")) continue;
7127
- let t = q.join(n, e), i = ye(e, be(e));
7216
+ let t = q.join(n, e), i = be(e, xe(e));
7128
7217
  try {
7129
- r[i] = we(t);
7218
+ r[i] = Te(t);
7130
7219
  } catch (t) {
7131
7220
  console.error(`❌ Error parsing ${e}:`, t.message);
7132
7221
  }
@@ -7154,14 +7243,14 @@ function Te() {
7154
7243
  return console.error("❌ Exception inside readLocalFsBundle:", e), null;
7155
7244
  }
7156
7245
  }
7157
- var Ee = null, De = null;
7158
- function Oe(e) {
7159
- if (!e) Ee = null, De = null;
7160
- else if (Ee && De === e) return Ee;
7161
- let t = ke(e);
7162
- return Ee = t, De = e, t;
7163
- }
7246
+ var De = null, Oe = null;
7164
7247
  function ke(e) {
7248
+ if (!e) De = null, Oe = null;
7249
+ else if (De && Oe === e) return De;
7250
+ let t = Ae(e);
7251
+ return De = t, Oe = e, t;
7252
+ }
7253
+ function Ae(e) {
7165
7254
  if (e) {
7166
7255
  let t = {
7167
7256
  nodes: {
@@ -7197,12 +7286,12 @@ function ke(e) {
7197
7286
  let e = (e) => {
7198
7287
  let n = {};
7199
7288
  for (let [r, i] of Object.entries(e || {})) {
7200
- let e = ye(r, be(r));
7201
- n[e] = Ce(i, t);
7289
+ let e = be(r, xe(r));
7290
+ n[e] = we(i, t);
7202
7291
  }
7203
7292
  return n;
7204
7293
  };
7205
- return Ae({
7294
+ return je({
7206
7295
  rawNodes: e(t.nodes),
7207
7296
  rawTrees: e(t.trees),
7208
7297
  rawChannels: e(t.channels),
@@ -7212,12 +7301,12 @@ function ke(e) {
7212
7301
  rawFieldSets: e(t.fieldSets)
7213
7302
  });
7214
7303
  }
7215
- return Ae(t);
7304
+ return je(t);
7216
7305
  }
7217
- let t = Te();
7218
- return t && Object.keys(t.rawNodes || {}).length > 0 ? Ae(t) : Ae(null);
7306
+ let t = Ee();
7307
+ return t && Object.keys(t.rawNodes || {}).length > 0 ? je(t) : je(null);
7219
7308
  }
7220
- function Ae(e) {
7309
+ function je(e) {
7221
7310
  if (!e) return {
7222
7311
  nodes: {},
7223
7312
  trees: {},
@@ -7352,8 +7441,8 @@ function Ae(e) {
7352
7441
  inVault: t.inVault !== !1,
7353
7442
  hasCanvas: t.hasCanvas === !0,
7354
7443
  defaultLayout: t.defaultLayout,
7355
- allowedBlocks: xe(t.allowedBlocks),
7356
- disallowedBlocks: t.disallowedBlocks ? xe(t.disallowedBlocks) : void 0,
7444
+ allowedBlocks: Se(t.allowedBlocks),
7445
+ disallowedBlocks: t.disallowedBlocks ? Se(t.disallowedBlocks) : void 0,
7357
7446
  tabs: n,
7358
7447
  fields: r
7359
7448
  };
@@ -7415,17 +7504,17 @@ function Ae(e) {
7415
7504
  fields: n
7416
7505
  };
7417
7506
  });
7418
- let te = {};
7507
+ let P = {};
7419
7508
  Object.entries(T).forEach(([e, t]) => {
7420
7509
  let n = A(t.tabs), r = k(t.fields || [], "settings", n), i = {}, a = t.regions || { content: { label: "Content" } };
7421
7510
  Object.entries(a).forEach(([e, t]) => {
7422
7511
  i[e] = {
7423
7512
  ...t,
7424
7513
  label: t.label || e,
7425
- allowedBlocks: xe(t.allowedBlocks),
7426
- disallowedBlocks: t.disallowedBlocks ? xe(t.disallowedBlocks) : void 0
7514
+ allowedBlocks: Se(t.allowedBlocks),
7515
+ disallowedBlocks: t.disallowedBlocks ? Se(t.disallowedBlocks) : void 0
7427
7516
  };
7428
- }), te[e] = {
7517
+ }), P[e] = {
7429
7518
  ...t,
7430
7519
  id: t.id || e,
7431
7520
  label: t.label || e,
@@ -7438,17 +7527,17 @@ function Ae(e) {
7438
7527
  tabs: n
7439
7528
  };
7440
7529
  });
7441
- let P = {};
7530
+ let te = {};
7442
7531
  Object.entries(E).forEach(([e, t]) => {
7443
7532
  let n = A(t.tabs), r = k(t.fields || [], "settings", n), i = {}, a = t.regions || { main: { label: "Main Content" } };
7444
7533
  Object.entries(a).forEach(([e, t]) => {
7445
7534
  i[e] = {
7446
7535
  ...t,
7447
7536
  label: t.label || e,
7448
- allowedBlocks: xe(t.allowedBlocks),
7449
- disallowedBlocks: t.disallowedBlocks ? xe(t.disallowedBlocks) : void 0
7537
+ allowedBlocks: Se(t.allowedBlocks),
7538
+ disallowedBlocks: t.disallowedBlocks ? Se(t.disallowedBlocks) : void 0
7450
7539
  };
7451
- }), P[e] = {
7540
+ }), te[e] = {
7452
7541
  ...t,
7453
7542
  id: t.id || e,
7454
7543
  label: t.label || e,
@@ -7478,7 +7567,7 @@ function Ae(e) {
7478
7567
  L[e] = Y(L[e] || {}, t);
7479
7568
  });
7480
7569
  });
7481
- let R = h ? {
7570
+ let ne = h ? {
7482
7571
  ...h,
7483
7572
  fields: L
7484
7573
  } : null;
@@ -7487,20 +7576,20 @@ function Ae(e) {
7487
7576
  trees: M,
7488
7577
  channels: N,
7489
7578
  blocks: ee,
7490
- nodeLayouts: te,
7491
- blockLayouts: P,
7579
+ nodeLayouts: P,
7580
+ blockLayouts: te,
7492
7581
  fieldSets: O,
7493
7582
  nodeTemplate: f || null,
7494
7583
  treeTemplate: p || null,
7495
7584
  channelTemplate: I,
7496
- userTemplate: R
7585
+ userTemplate: ne
7497
7586
  };
7498
7587
  }
7499
- var je = new e(), Me = (e) => {
7588
+ var Me = new e(), Ne = (e) => {
7500
7589
  try {
7501
7590
  let t = e.env?.BUNDLED_DEFINITIONS;
7502
7591
  (!t || Object.keys(t).length === 0) && (t = f || d || u);
7503
- let n = Oe(t);
7592
+ let n = ke(t);
7504
7593
  return e.json(n, 200, { "Cache-Control": "no-cache, no-store, must-revalidate" });
7505
7594
  } catch (t) {
7506
7595
  return console.error("[CMS API] Error loading schemas:", t), e.json({
@@ -7509,8 +7598,8 @@ var je = new e(), Me = (e) => {
7509
7598
  }, 500);
7510
7599
  }
7511
7600
  };
7512
- je.get("/", Me), je.get("/schemas.json", Me);
7513
- var Ne = new e(), Pe = {
7601
+ Me.get("/", Ne), Me.get("/schemas.json", Ne);
7602
+ var Pe = new e(), Fe = {
7514
7603
  node: "content_nodes",
7515
7604
  nodes: "content_nodes",
7516
7605
  content_node: "content_nodes",
@@ -7522,7 +7611,7 @@ var Ne = new e(), Pe = {
7522
7611
  user: "users",
7523
7612
  users: "users",
7524
7613
  user_account: "user_accounts"
7525
- }, Fe = {
7614
+ }, Ie = {
7526
7615
  content_nodes: [
7527
7616
  "id",
7528
7617
  "title",
@@ -7579,11 +7668,11 @@ var Ne = new e(), Pe = {
7579
7668
  "createdAt"
7580
7669
  ]
7581
7670
  };
7582
- Ne.post("/validate-unique", async (e) => {
7671
+ Pe.post("/validate-unique", async (e) => {
7583
7672
  try {
7584
7673
  let t = e.get("db"), { entityType: n, field: r, value: i, excludeId: a } = await e.req.json();
7585
7674
  if (!r || i == null || String(i).trim() === "") return e.json({ isUnique: !0 });
7586
- let o = Pe[n] || "content_nodes", s = r.replace(/[^a-zA-Z0-9_]/g, ""), c = (Fe[o] || Fe.content_nodes).includes(s), l = -1;
7675
+ let o = Fe[n] || "content_nodes", s = r.replace(/[^a-zA-Z0-9_]/g, ""), c = (Ie[o] || Ie.content_nodes).includes(s), l = -1;
7587
7676
  if (a != null && String(a).trim() !== "") {
7588
7677
  let e = Number(a);
7589
7678
  l = isNaN(e) ? String(a) : e;
@@ -7595,9 +7684,9 @@ Ne.post("/validate-unique", async (e) => {
7595
7684
  } catch (t) {
7596
7685
  return console.error("[API Validation] Error validating global uniqueness:", t), e.json({ error: "Failed to validate uniqueness" }, 500);
7597
7686
  }
7598
- }), Ne.post("/validate-unique-sibling", async (e) => e.json({ isUnique: !0 }));
7599
- var Ie = new e();
7600
- Ie.get("/", async (e) => {
7687
+ }), Pe.post("/validate-unique-sibling", async (e) => e.json({ isUnique: !0 }));
7688
+ var Le = new e();
7689
+ Le.get("/", async (e) => {
7601
7690
  try {
7602
7691
  let t = e.get("db"), n = await t.prepare("\n SELECT \n COUNT(*) as total,\n SUM(CASE WHEN isHidden = 0 THEN 1 ELSE 0 END) as published,\n SUM(CASE WHEN isHidden = 1 THEN 1 ELSE 0 END) as hidden\n FROM content_nodes\n WHERE deletedAt IS NULL OR deletedAt = ''\n ").get(), r = Number(n?.total) || 0, i = Number(n?.published) || 0, a = Number(n?.hidden) || 0, o = await t.prepare("\n SELECT \n (SELECT COUNT(*) FROM channels) as totalChannels,\n (SELECT COUNT(*) FROM trees) as totalTrees,\n (SELECT COUNT(*) FROM users) as totalUsers\n ").get(), s = await t.prepare("\n SELECT contentType as type, COUNT(*) as count \n FROM content_nodes \n WHERE deletedAt IS NULL OR deletedAt = ''\n GROUP BY contentType \n ORDER BY count DESC\n ").all(), c = Array.isArray(s) ? s : s?.results || [], l = await t.prepare("\n SELECT id, title, slug, contentType, isHidden, status, updatedAt \n FROM content_nodes \n WHERE deletedAt IS NULL OR deletedAt = ''\n ORDER BY updatedAt DESC \n LIMIT 5\n ").all(), u = (Array.isArray(l) ? l : l?.results || []).map((e) => ({
7603
7692
  ...e,
@@ -7614,7 +7703,7 @@ Ie.get("/", async (e) => {
7614
7703
  isHidden: !!e.isHidden,
7615
7704
  channelNames: e.channelLabels ? e.channelLabels.split(",") : [],
7616
7705
  treeNames: e.treeLabels ? e.treeLabels.split(",") : []
7617
- })), p = e.env?.BUNDLED_DEFINITIONS, m = ce(p), h = m.nodes || m.nodeSchemas || {}, g = c.map((e) => {
7706
+ })), p = e.env?.BUNDLED_DEFINITIONS, m = se(p), h = m.nodes || m.nodeSchemas || {}, g = c.map((e) => {
7618
7707
  let t = e.type || "node", n = h[t]?.label || t.charAt(0).toUpperCase() + t.slice(1);
7619
7708
  return {
7620
7709
  type: t,
@@ -7658,7 +7747,7 @@ async function Q(e, t, n = []) {
7658
7747
  if (typeof r.bind == "function") return await r.bind(...n).run();
7659
7748
  if (typeof r.run == "function") return await r.run(...n);
7660
7749
  }
7661
- function Le(e, t, n) {
7750
+ function Re(e, t, n) {
7662
7751
  let r = e || (t ? `/media/${t}` : "");
7663
7752
  return r && n && r.startsWith(`https://${n}/`) && !r.includes("/media/") && (r = r.replace(`https://${n}/`, `https://${n}/media/`)), r;
7664
7753
  }
@@ -7700,7 +7789,7 @@ X.get("/", async (e) => {
7700
7789
  ...JSON.parse(t.dataJson || "{}")
7701
7790
  };
7702
7791
  } catch {}
7703
- let r = Le(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN);
7792
+ let r = Re(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN);
7704
7793
  return {
7705
7794
  id: t.id,
7706
7795
  filename: t.filename || "Untitled Asset",
@@ -7726,7 +7815,7 @@ X.get("/", async (e) => {
7726
7815
  }
7727
7816
  }), X.post("/upload", async (e) => {
7728
7817
  try {
7729
- let t = l(e), { storage: n } = ie(e.env), r = await e.req.parseBody(), i = r.file, a = r.isVariant === "true" || r.isVariant === "1" || r.temporary === "true", o = r.parentAssetId || r.parentAsset, s = typeof o == "string" && o.trim().length > 0 ? o.trim() : null;
7818
+ let t = l(e), { storage: n } = ae(e.env), r = await e.req.parseBody(), i = r.file, a = r.isVariant === "true" || r.isVariant === "1" || r.temporary === "true", o = r.parentAssetId || r.parentAsset, s = typeof o == "string" && o.trim().length > 0 ? o.trim() : null;
7730
7819
  s && (await Z(t, "SELECT id FROM assets WHERE id = ?", [s])).length === 0 && (s = null);
7731
7820
  let c = r.cropCoordinates, u = null, d = null;
7732
7821
  if (c) {
@@ -7758,7 +7847,7 @@ X.get("/", async (e) => {
7758
7847
  let D = x;
7759
7848
  if (s) {
7760
7849
  let n = await Z(t, "SELECT cdnUrl, storageKeyPrivate FROM assets WHERE id = ?", [s]);
7761
- n.length > 0 && (D = Le(n[0].cdnUrl, n[0].storageKeyPrivate, y)), new B(e.env).purgeAsset(e, t, s);
7850
+ n.length > 0 && (D = Re(n[0].cdnUrl, n[0].storageKeyPrivate, y)), new V(e.env).purgeAsset(e, t, s);
7762
7851
  }
7763
7852
  return e.json({
7764
7853
  id: p,
@@ -7800,7 +7889,7 @@ X.get("/", async (e) => {
7800
7889
  ...JSON.parse(i.dataJson || "{}")
7801
7890
  };
7802
7891
  } catch {}
7803
- let u = Le(i.cdnUrl, i.storageKeyPrivate, e.env?.CDN_DOMAIN);
7892
+ let u = Re(i.cdnUrl, i.storageKeyPrivate, e.env?.CDN_DOMAIN);
7804
7893
  return e.json({
7805
7894
  id: i.id,
7806
7895
  filename: i.filename,
@@ -7827,7 +7916,7 @@ X.get("/", async (e) => {
7827
7916
  createdAt: t.createdAt,
7828
7917
  parentAssetId: t.parentAssetId || i.id,
7829
7918
  cropCoordinates: n,
7830
- url: Le(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN),
7919
+ url: Re(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN),
7831
7920
  originalUrl: u
7832
7921
  };
7833
7922
  })
@@ -7847,14 +7936,14 @@ X.get("/", async (e) => {
7847
7936
  r.filename === void 0 ? a.filename : r.filename,
7848
7937
  JSON.stringify(o),
7849
7938
  n
7850
- ]), new B(e.env).purgeAsset(e, t, n), e.json({ success: !0 });
7939
+ ]), new V(e.env).purgeAsset(e, t, n), e.json({ success: !0 });
7851
7940
  } catch {
7852
7941
  return e.json({ error: "Failed to update asset" }, 500);
7853
7942
  }
7854
7943
  }), X.delete("/:id", async (e) => {
7855
7944
  try {
7856
7945
  let t = l(e), n = e.req.param("id"), r = (await Z(t, "SELECT id, filename, isSystemVariant FROM assets WHERE id = ?", [n]))[0];
7857
- return r ? (new B(e.env).purgeAsset(e, t, n), r.isSystemVariant ? await Q(t, "UPDATE assets SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?", [n]) : await Q(t, "UPDATE assets SET deletedAt = CURRENT_TIMESTAMP WHERE id = ? OR parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
7946
+ return r ? (new V(e.env).purgeAsset(e, t, n), r.isSystemVariant ? await Q(t, "UPDATE assets SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?", [n]) : await Q(t, "UPDATE assets SET deletedAt = CURRENT_TIMESTAMP WHERE id = ? OR parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
7858
7947
  n,
7859
7948
  n,
7860
7949
  `crop_%${r.filename ? r.filename.replace(/\.[^/.]+$/, "") : ""}%`,
@@ -7880,7 +7969,7 @@ X.get("/", async (e) => {
7880
7969
  r,
7881
7970
  `crop_%${i.filename ? i.filename.replace(/\.[^/.]+$/, "") : ""}%`,
7882
7971
  `%${r}%`
7883
- ]), new B(e.env).purgeAsset(e, t, r), e.json({
7972
+ ]), new V(e.env).purgeAsset(e, t, r), e.json({
7884
7973
  success: !0,
7885
7974
  id: r,
7886
7975
  restored: !0
@@ -7893,9 +7982,9 @@ X.get("/", async (e) => {
7893
7982
  }
7894
7983
  }), X.delete("/purge/:id", async (e) => {
7895
7984
  try {
7896
- let t = l(e), { storage: n } = ie(e.env), r = e.req.param("id"), i = (await Z(t, "SELECT id, filename, storageKeyPrivate, isSystemVariant FROM assets WHERE id = ?", [r]))[0];
7985
+ let t = l(e), { storage: n } = ae(e.env), r = e.req.param("id"), i = (await Z(t, "SELECT id, filename, storageKeyPrivate, isSystemVariant FROM assets WHERE id = ?", [r]))[0];
7897
7986
  if (!i) return e.json({ error: "Asset not found" }, 404);
7898
- new B(e.env).purgeAsset(e, t, r);
7987
+ new V(e.env).purgeAsset(e, t, r);
7899
7988
  let a = [i];
7900
7989
  i.isSystemVariant || (a = [i, ...await Z(t, "SELECT id, storageKeyPrivate FROM assets WHERE parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
7901
7990
  r,
@@ -7925,8 +8014,8 @@ X.get("/", async (e) => {
7925
8014
  }, 500);
7926
8015
  }
7927
8016
  });
7928
- var Re = new e();
7929
- function ze() {
8017
+ var ze = new e();
8018
+ function Be() {
7930
8019
  return {
7931
8020
  fullPath: /* @__PURE__ */ new Map(),
7932
8021
  treeEdges: /* @__PURE__ */ new Map(),
@@ -7934,10 +8023,10 @@ function ze() {
7934
8023
  assetUrls: /* @__PURE__ */ new Map()
7935
8024
  };
7936
8025
  }
7937
- function Be(...e) {
8026
+ function Ve(...e) {
7938
8027
  return e.map((e) => String(e ?? "")).join(":");
7939
8028
  }
7940
- function Ve(e, t) {
8029
+ function He(e, t) {
7941
8030
  let n = Date.now();
7942
8031
  if (e && String(e).trim() !== "") {
7943
8032
  let t = Date.parse(e);
@@ -7949,27 +8038,27 @@ function Ve(e, t) {
7949
8038
  }
7950
8039
  return !0;
7951
8040
  }
7952
- async function He(e, t, n) {
7953
- let r = t.filter((e) => e.componentId === "content-feed" || e.componentId === "article-list");
7954
- await Promise.all(r.map(async (t) => {
7955
- let r = t.data || {}, i = r.nodeType || "article", a = Number(r.limit) || 12, o = r.sortBy || "updatedAt", s = "FROM content_nodes WHERE contentType = ? AND isHidden = 0 AND (status = 'published' OR status IS NULL)", c = [i];
7956
- n && n !== "all" && (s += " AND id IN (SELECT nodeId FROM node_channels WHERE channelId = ?)", c.push(Number(n) || n));
7957
- let l = "ORDER BY updatedAt DESC";
7958
- o === "published_desc" || o === "createdAt" ? l = "ORDER BY createdAt DESC" : o === "title_asc" && (l = "ORDER BY LOWER(title) ASC");
7959
- let u = `SELECT id, title, slug, language, dataJson, createdAt, updatedAt ${s} ${l} LIMIT ?`;
7960
- c.push(a);
8041
+ async function Ue(e, t, n, r) {
8042
+ let i = t.filter((e) => e.componentId === "content-feed" || e.componentId === "article-list");
8043
+ await Promise.all(i.map(async (t) => {
8044
+ let i = t.data || {}, a = i.nodeType || "article", o = Number(i.limit) || 12, s = i.sortBy || "updatedAt", c = "FROM content_nodes WHERE contentType = ? AND isHidden = 0 AND (status = 'published' OR status IS NULL)", l = [a];
8045
+ n && n !== "all" && (c += " AND id IN (SELECT nodeId FROM node_channels WHERE channelId = ?)", l.push(Number(n) || n));
8046
+ let u = "ORDER BY updatedAt DESC";
8047
+ s === "published_desc" || s === "createdAt" ? u = "ORDER BY createdAt DESC" : s === "title_asc" && (u = "ORDER BY LOWER(title) ASC");
8048
+ let d = `SELECT id, title, slug, language, dataJson, createdAt, updatedAt ${c} ${u} LIMIT ?`;
8049
+ l.push(o);
7961
8050
  try {
7962
- let n = await e.prepare(u).all(...c), r = Array.isArray(n) ? n : n?.results || [];
7963
- t.data.initialItems = r.map((e) => {
8051
+ let n = await e.prepare(d).all(...l), i = Array.isArray(n) ? n : n?.results || [];
8052
+ t.data.initialItems = i.map((e) => {
7964
8053
  let t = {};
7965
8054
  if (e.dataJson) try {
7966
8055
  t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
7967
8056
  } catch {}
7968
- return Ve(t.startShowingAt, t.stopShowingAt) ? {
8057
+ return He(t.startShowingAt, t.stopShowingAt) ? {
7969
8058
  id: e.id,
7970
8059
  title: e.title,
7971
8060
  slug: e.slug,
7972
- language: e.language || "en",
8061
+ language: e.language?.trim() || r || null,
7973
8062
  createdAt: e.createdAt,
7974
8063
  updatedAt: e.updatedAt,
7975
8064
  excerpt: t.excerpt || "",
@@ -7982,7 +8071,7 @@ async function He(e, t, n) {
7982
8071
  }
7983
8072
  }));
7984
8073
  }
7985
- async function Ue(e, t, n, r, i = !1, a) {
8074
+ async function We(e, t, n, r, i = !1, a) {
7986
8075
  if (!t) return { blocks: [] };
7987
8076
  let o = await e.prepare("\n WITH RECURSIVE ancestor_path(id, contentId, title, slug, parentId, level) AS (\n SELECT t.id, t.contentId, c.title, c.slug, t.parentId, 0 FROM tree_nodes t INNER JOIN content_nodes c ON t.contentId = c.id WHERE t.id = ? OR c.id = ?\n UNION ALL\n SELECT t.id, t.contentId, c.title, c.slug, t.parentId, ap.level + 1 FROM tree_nodes t INNER JOIN content_nodes c ON t.contentId = c.id INNER JOIN ancestor_path ap ON t.id = ap.parentId\n )\n SELECT * FROM ancestor_path ORDER BY level ASC\n ").all(t, t), s = Array.isArray(o) ? o : o?.results || [];
7988
8077
  if (!s || s.length === 0) return { blocks: [] };
@@ -8018,10 +8107,10 @@ async function Ue(e, t, n, r, i = !1, a) {
8018
8107
  try {
8019
8108
  a = (typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson) || {};
8020
8109
  } catch {}
8021
- let o = a.hidden === !0 || a.hidden === 1 || a.hidden === "1" || a.hidden === "true", s = Ve(a.startShowingAt, a.stopShowingAt);
8110
+ let o = a.hidden === !0 || a.hidden === 1 || a.hidden === "1" || a.hidden === "true", s = He(a.startShowingAt, a.stopShowingAt);
8022
8111
  if (!i && (o || !s)) return null;
8023
- let c = t.elementType || t.componentId || "text-block", l = r.blocks?.[c]?.fields || r.elements?.[c]?.fields || r.components?.[c]?.fields || {}, u = String(a.blockId || a._instanceId || a.id || t.blockId || t.id), d = We(a, l);
8024
- return d = await se(e, d), d = Ge(d), d.blockId = u, {
8112
+ let c = t.elementType || t.componentId || "text-block", l = r.blocks?.[c]?.fields || r.elements?.[c]?.fields || r.components?.[c]?.fields || {}, u = String(a.blockId || a._instanceId || a.id || t.blockId || t.id), d = Ge(a, l);
8113
+ return d = await B(e, d), d = Ke(d), d.blockId = u, {
8025
8114
  region: t.region || n,
8026
8115
  block: {
8027
8116
  instanceId: t.id,
@@ -8041,7 +8130,7 @@ async function Ue(e, t, n, r, i = !1, a) {
8041
8130
  }
8042
8131
  return { blocks: [] };
8043
8132
  }
8044
- function We(e, t = {}) {
8133
+ function Ge(e, t = {}) {
8045
8134
  let n = {};
8046
8135
  for (let [r, i] of Object.entries(e)) r.endsWith("_meta") || [
8047
8136
  "disabledRegions",
@@ -8057,14 +8146,14 @@ function We(e, t = {}) {
8057
8146
  ].includes(r) || r.startsWith("_") || (!t[r] || t[r].public !== !1) && (n[r] = i);
8058
8147
  return n;
8059
8148
  }
8060
- function Ge(e) {
8061
- if (Array.isArray(e)) return e.map(Ge);
8149
+ function Ke(e) {
8150
+ if (Array.isArray(e)) return e.map(Ke);
8062
8151
  if (!e || typeof e != "object") return e;
8063
8152
  if (typeof e.id == "string" && e.id.startsWith("ast_") && typeof e.url == "string") {
8064
8153
  let t = e.metadataOverrides || {}, n = e.variants && typeof e.variants == "object" ? e.variants : {}, r = Object.entries(n).find(([, t]) => t?.id === e.id)?.[0], i = r ? {
8065
8154
  ...t,
8066
8155
  ...t.crops?.[r] || {}
8067
- } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, Ge({
8156
+ } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, Ke({
8068
8157
  ...n,
8069
8158
  title: n?.title ?? e.title ?? "",
8070
8159
  alt: n?.alt ?? e.alt ?? "",
@@ -8078,9 +8167,9 @@ function Ge(e) {
8078
8167
  ...Object.keys(a).length > 0 ? { variants: a } : {}
8079
8168
  };
8080
8169
  }
8081
- return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, Ge(t)]));
8170
+ return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, Ke(t)]));
8082
8171
  }
8083
- async function Ke(e, t, n) {
8172
+ async function qe(e, t, n) {
8084
8173
  if (typeof t == "string") {
8085
8174
  if (!t.includes("#node:") && !t.includes("data-node-id") && !t.includes("#asset:") && !t.includes("data-asset-id")) return t;
8086
8175
  let r = (e, t) => {
@@ -8098,9 +8187,9 @@ async function Ke(e, t, n) {
8098
8187
  return await Promise.all(Array.from(t.matchAll(p)).map(async (t) => {
8099
8188
  let i = t[1], a = r(i, "data-node-id"), o = r(i, "data-tree-id");
8100
8189
  if (!a || !o) return;
8101
- let s = await Je(e, a, o, n);
8190
+ let s = await Ye(e, a, o, n);
8102
8191
  if (s?.treeNodeId) {
8103
- let t = await Qe(e, String(s.treeNodeId), o, n);
8192
+ let t = await $e(e, String(s.treeNodeId), o, n);
8104
8193
  f.set(`${a}:${o}`, t);
8105
8194
  }
8106
8195
  })), t.replace(p, (e, t) => {
@@ -8120,39 +8209,39 @@ async function Ke(e, t, n) {
8120
8209
  return /href\s*=\s*["'][^"']*["']/i.test(h) ? h = h.replace(/href\s*=\s*["'][^"']*["']/i, `href="${m || "/"}"`) : h += ` href="${m || "/"}"`, `<a ${h}>`;
8121
8210
  });
8122
8211
  }
8123
- if (Array.isArray(t)) return Promise.all(t.map((t) => Ke(e, t, n)));
8212
+ if (Array.isArray(t)) return Promise.all(t.map((t) => qe(e, t, n)));
8124
8213
  if (t && typeof t == "object") {
8125
8214
  if (typeof t.href == "string" && (t.href.startsWith("#node:") || t.href.startsWith("#asset:"))) return {
8126
8215
  ...t,
8127
- href: await qe(e, t, n)
8216
+ href: await Je(e, t, n)
8128
8217
  };
8129
- let r = await Promise.all(Object.entries(t).map(async ([t, r]) => [t, await Ke(e, r, n)]));
8218
+ let r = await Promise.all(Object.entries(t).map(async ([t, r]) => [t, await qe(e, r, n)]));
8130
8219
  return Object.fromEntries(r);
8131
8220
  }
8132
8221
  return t;
8133
8222
  }
8134
- async function qe(e, t, n) {
8223
+ async function Je(e, t, n) {
8135
8224
  let r = t.href.match(/^#node:(.+)$/), i = t.href.match(/^#asset:(.+)$/);
8136
- if (i) return Xe(e, i[1], n);
8225
+ if (i) return Ze(e, i[1], n);
8137
8226
  if (!r) return t.href;
8138
8227
  let a = r[1];
8139
8228
  if (t.treeId) {
8140
- let r = await Je(e, a, String(t.treeId), n);
8229
+ let r = await Ye(e, a, String(t.treeId), n);
8141
8230
  if (r?.treeNodeId) {
8142
- let i = await Qe(e, String(r.treeNodeId), String(t.treeId), n);
8231
+ let i = await $e(e, String(r.treeNodeId), String(t.treeId), n);
8143
8232
  if (i) return i;
8144
8233
  }
8145
8234
  }
8146
- let o = await Ye(e, a, n);
8235
+ let o = await Xe(e, a, n);
8147
8236
  return o === void 0 ? "#" : `/${o}`;
8148
8237
  }
8149
- async function Je(e, t, n, r) {
8150
- let i = Be(t, n), a = r.treeEdges.get(i);
8238
+ async function Ye(e, t, n, r) {
8239
+ let i = Ve(t, n), a = r.treeEdges.get(i);
8151
8240
  if (a) return a;
8152
8241
  let o = e.prepare("SELECT id as treeNodeId FROM tree_nodes WHERE contentId = ? AND treeId = ? LIMIT 1").get(t, n);
8153
8242
  return r.treeEdges.set(i, Promise.resolve(o)), o;
8154
8243
  }
8155
- async function Ye(e, t, n) {
8244
+ async function Xe(e, t, n) {
8156
8245
  let r = String(t), i = n.nodeSlugs.get(r);
8157
8246
  if (i) return i;
8158
8247
  let a = (async () => {
@@ -8161,7 +8250,7 @@ async function Ye(e, t, n) {
8161
8250
  })();
8162
8251
  return n.nodeSlugs.set(r, a), a;
8163
8252
  }
8164
- async function Xe(e, t, n) {
8253
+ async function Ze(e, t, n) {
8165
8254
  let r = String(t), i = n.assetUrls.get(r);
8166
8255
  if (i) return i;
8167
8256
  let a = (async () => {
@@ -8170,7 +8259,7 @@ async function Xe(e, t, n) {
8170
8259
  })();
8171
8260
  return n.assetUrls.set(r, a), a;
8172
8261
  }
8173
- function Ze(e) {
8262
+ function Qe(e) {
8174
8263
  let t = e.socialImage;
8175
8264
  if (!t || typeof t != "object") return null;
8176
8265
  let n = (e, t) => {
@@ -8201,9 +8290,9 @@ function Ze(e) {
8201
8290
  ])
8202
8291
  };
8203
8292
  }
8204
- async function Qe(e, t, n, r) {
8293
+ async function $e(e, t, n, r) {
8205
8294
  if (!t) return "";
8206
- let i = Be(t, n);
8295
+ let i = Ve(t, n);
8207
8296
  if (r) {
8208
8297
  let e = r.fullPath.get(i);
8209
8298
  if (e) return e;
@@ -8218,7 +8307,7 @@ async function Qe(e, t, n, r) {
8218
8307
  })();
8219
8308
  return r && r.fullPath.set(i, a), a;
8220
8309
  }
8221
- async function $e(e, t, n, r, i) {
8310
+ async function et(e, t, n, r, i) {
8222
8311
  let a = {}, o = null;
8223
8312
  if (t) {
8224
8313
  let n = await e.prepare("\n WITH RECURSIVE ancestor_path(id, contentId, title, slug, parentId, level) AS (\n SELECT t.id, t.contentId, c.title, c.slug, t.parentId, 0 FROM tree_nodes t INNER JOIN content_nodes c ON t.contentId = c.id WHERE t.id = ? OR c.id = ?\n UNION ALL\n SELECT t.id, t.contentId, c.title, c.slug, t.parentId, ap.level + 1 FROM tree_nodes t INNER JOIN content_nodes c ON t.contentId = c.id INNER JOIN ancestor_path ap ON t.id = ap.parentId\n )\n SELECT c.dataJson, c.draftDataJson FROM ancestor_path ap INNER JOIN content_nodes c ON ap.contentId = c.id ORDER BY ap.level ASC\n ").all(t, t), i = Array.isArray(n) ? n : n?.results || [], s = /* @__PURE__ */ new Set([
@@ -8245,7 +8334,7 @@ async function $e(e, t, n, r, i) {
8245
8334
  }
8246
8335
  }
8247
8336
  if (!o) {
8248
- let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ?").get(n);
8337
+ let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ? OR key = ? LIMIT 1").get(Number(n) || -1, String(n));
8249
8338
  if (t?.dataJson) try {
8250
8339
  let e = typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson;
8251
8340
  e.subpageLayoutId && e.subpageLayoutId !== "inherit" && (o = e.subpageLayoutId);
@@ -8256,109 +8345,125 @@ async function $e(e, t, n, r, i) {
8256
8345
  inheritedFields: a
8257
8346
  };
8258
8347
  }
8259
- function et(e) {
8348
+ function tt(e) {
8260
8349
  let t = Number(e?.env?.CMS_NODE_CACHE_TTL);
8261
8350
  return Number.isFinite(t) && t >= 60 ? Math.floor(t) : 300;
8262
8351
  }
8263
- async function tt(e, t, n, r) {
8352
+ async function nt(e, t, n, r) {
8264
8353
  try {
8265
8354
  await e.set(t, n, r);
8266
8355
  } catch (e) {
8267
8356
  console.warn("[CMS Cache] Failed to write node response to cache:", e);
8268
8357
  }
8269
8358
  }
8270
- Re.get("/*", async (e) => {
8359
+ ze.get("/*", async (e) => {
8271
8360
  try {
8272
- let t = e.get("db"), n = ze(), r = new URL(e.req.url).pathname.match(/\/node\/(.+)$/), i = (r ? r[1] : "home").replace(/^\/+|\/+$/g, ""), a = e.req.query("channelId") || e.req.query("channel") || "1", o = e.req.query("lang") || "en", s = e.req.query("preview") === "true", c = isNaN(Number(a)) ? await t.prepare("SELECT * FROM channels WHERE key = ?").get(a) : await t.prepare("SELECT * FROM channels WHERE id = ?").get(Number(a));
8361
+ let t = e.get("db"), n = Be(), r = new URL(e.req.url).pathname.match(/\/node\/(.+)$/), i = (r ? r[1] : "home").replace(/^\/+|\/+$/g, ""), a = e.req.query("channelId") || e.req.query("channel") || "1", o = e.req.query("lang"), s = e.req.query("preview") === "true", c = isNaN(Number(a)) ? await t.prepare("SELECT * FROM channels WHERE key = ?").get(a) : await t.prepare("SELECT * FROM channels WHERE id = ?").get(Number(a));
8273
8362
  if (!c) return e.json({ error: `Channel '${a}' not found` }, 404);
8274
8363
  let l = c.status === "disabled" || c.status === "inactive" || c.isEnabled === 0 || c.isEnabled === !1;
8275
8364
  if (!s && l) return e.json({ error: `Channel '${c.key || a}' is currently inactive` }, 404);
8276
- let u = c.id, d = c.key || a, f = I(e), p = `node:${u || d}:${o}:${i}`, m = e.req.header("x-bypass-cache") === "true";
8277
- if (!s && !m) {
8278
- let t = await f.get(p);
8279
- if (t) return e.header("X-Cache", "HIT"), e.json(t);
8280
- }
8281
- let h = ce(e.env?.BUNDLED_DEFINITIONS), g = /^\d+$/.test(i), _ = null, v = null, y = e.req.query("treeId"), b = i.split("/"), x = b[b.length - 1], S = "/" + i.replace(/^\/+|\/+$/g, ""), C = `
8365
+ let u = c.id, d = c.key || a, f = I(e), p = se(e.env?.BUNDLED_DEFINITIONS), m = /^\d+$/.test(i), h = null, g = null, _ = e.req.query("treeId"), v = i.split("/"), y = v[v.length - 1], b = "/" + i.replace(/^\/+|\/+$/g, ""), x = `
8282
8366
  SELECT cn.*, tn.id as treeNodeId, tn.parentId, tn.treeId FROM content_nodes cn
8283
8367
  INNER JOIN tree_nodes tn ON cn.id = tn.contentId
8284
8368
  ${u === null ? "" : "INNER JOIN node_channels nc ON cn.id = nc.nodeId"}
8285
8369
  WHERE cn.slug = ? ${u === null ? "" : "AND nc.channelId = ?"}
8286
- `, w = u === null ? [x] : [x, u], T = await t.prepare(C).all(...w), E = Array.isArray(T) ? T : T?.results || [];
8287
- if (E.length > 0) {
8288
- let e = await Promise.all(E.map(async (e) => ({
8370
+ `, S = u === null ? [y] : [y, u], C = await t.prepare(x).all(...S), w = Array.isArray(C) ? C : C?.results || [];
8371
+ if (w.length > 0) {
8372
+ let e = await Promise.all(w.map(async (e) => ({
8289
8373
  candidate: e,
8290
- calculatedPath: await Qe(t, String(e.treeNodeId), String(e.treeId), n)
8291
- }))), r = S.replace(/^\/+|\/+$/g, "");
8374
+ calculatedPath: await $e(t, String(e.treeNodeId), String(e.treeId), n)
8375
+ }))), r = b.replace(/^\/+|\/+$/g, "");
8292
8376
  for (let { candidate: t, calculatedPath: n } of e) {
8293
8377
  let e = n.replace(/^\/+|\/+$/g, "");
8294
8378
  if (e === r || r === "home" && (e === "" || e === "home")) {
8295
- _ = t, v = t;
8379
+ h = t, g = t;
8296
8380
  break;
8297
8381
  }
8298
8382
  }
8299
8383
  }
8300
- if (!_ && b.length === 1 && (_ = u === null ? await t.prepare("SELECT * FROM content_nodes WHERE slug = ?").get(x) : await t.prepare("SELECT cn.* FROM content_nodes cn INNER JOIN node_channels nc ON cn.id = nc.nodeId WHERE cn.slug = ? AND nc.channelId = ?").get(x, u)), !_ && g && (_ = u === null ? await t.prepare("SELECT * FROM content_nodes WHERE id = ?").get(Number(i)) : await t.prepare("SELECT cn.* FROM content_nodes cn INNER JOIN node_channels nc ON cn.id = nc.nodeId WHERE cn.id = ? AND nc.channelId = ?").get(Number(i), u)), !_) return e.json({ error: `Node '${i}' not found for Channel '${a}'` }, 404);
8301
- if (!v) {
8302
- let e = y ? [_.id, y] : [_.id];
8303
- v = await t.prepare(`SELECT id as treeNodeId, treeId, parentId FROM tree_nodes WHERE contentId = ? ${y ? "AND treeId = ?" : ""} LIMIT 1`).get(...e);
8384
+ if (!h && v.length === 1 && (h = u === null ? await t.prepare("SELECT * FROM content_nodes WHERE slug = ?").get(y) : await t.prepare("SELECT cn.* FROM content_nodes cn INNER JOIN node_channels nc ON cn.id = nc.nodeId WHERE cn.slug = ? AND nc.channelId = ?").get(y, u)), !h && m && (h = u === null ? await t.prepare("SELECT * FROM content_nodes WHERE id = ?").get(Number(i)) : await t.prepare("SELECT cn.* FROM content_nodes cn INNER JOIN node_channels nc ON cn.id = nc.nodeId WHERE cn.id = ? AND nc.channelId = ?").get(Number(i), u)), !h) return e.json({ error: `Node '${i}' not found for Channel '${a}'` }, 404);
8385
+ if (!g) {
8386
+ let e = _ ? [h.id, _] : [h.id];
8387
+ g = await t.prepare(`SELECT id as treeNodeId, treeId, parentId FROM tree_nodes WHERE contentId = ? ${_ ? "AND treeId = ?" : ""} LIMIT 1`).get(...e);
8304
8388
  }
8305
- let D = v?.treeId || y || "main-nav", O = v?.parentId || null, k = v?.treeNodeId ? await Qe(t, String(v.treeNodeId), String(D), n) : `/${(_.slug || "").replace(/^\/+|\/+$/g, "")}`, A = {
8306
- id: _.id,
8307
- title: _.title,
8308
- slug: _.slug,
8309
- language: _.language || o || "en",
8310
- path: k === "" ? "/" : k,
8311
- nodeType: _.contentType,
8312
- createdAt: _.createdAt,
8313
- updatedAt: _.updatedAt
8314
- }, j = _.contentType || "node", M = h.nodes?.[j] || Object.values(h.nodes || {})[0] || {}, N = { ...M.fields || {} };
8315
- M.tabs && Object.values(M.tabs).forEach((e) => {
8316
- Object.assign(N, e.fields || {});
8389
+ let T = g?.treeId || _ || "main-nav", E = null;
8390
+ if (T) {
8391
+ let e = await t.prepare("\n SELECT dataJson \n FROM trees \n WHERE id = ? OR key = ? \n LIMIT 1\n ").get(Number(T) || -1, String(T));
8392
+ if (e?.dataJson) try {
8393
+ let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
8394
+ t.defaultLanguage ? E = String(t.defaultLanguage).trim() : t.language && (E = String(t.language).trim());
8395
+ } catch {}
8396
+ }
8397
+ let D = null;
8398
+ if (c) {
8399
+ if (c.defaultLanguage) D = String(c.defaultLanguage).trim();
8400
+ else if (c.dataJson) try {
8401
+ let e = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson;
8402
+ e.defaultLanguage ? D = String(e.defaultLanguage).trim() : e.language && (D = String(e.language).trim());
8403
+ } catch {}
8404
+ }
8405
+ let O = h.language?.trim() || null, k = E || D || o?.trim() || null, A = O || k || null, j = `node:${u || d}:${A || "default"}:${i}`, M = e.req.header("x-bypass-cache") === "true";
8406
+ if (!s && !M) {
8407
+ let t = await f.get(j);
8408
+ if (t) return e.header("X-Cache", "HIT"), e.json(t);
8409
+ }
8410
+ let N = g?.parentId || null, ee = g?.treeNodeId ? await $e(t, String(g.treeNodeId), String(T), n) : `/${(h.slug || "").replace(/^\/+|\/+$/g, "")}`, P = {
8411
+ id: h.id,
8412
+ title: h.title,
8413
+ slug: h.slug,
8414
+ language: A,
8415
+ path: ee === "" ? "/" : ee,
8416
+ nodeType: h.contentType,
8417
+ createdAt: h.createdAt,
8418
+ updatedAt: h.updatedAt
8419
+ }, te = h.contentType || "node", F = p.nodes?.[te] || Object.values(p.nodes || {})[0] || {}, L = { ...F.fields || {} };
8420
+ F.tabs && Object.values(F.tabs).forEach((e) => {
8421
+ Object.assign(L, e.fields || {});
8317
8422
  });
8318
- let ee = {}, te = null, P = null, F = !1, L = {}, R = s && _.draftDataJson || _.dataJson;
8319
- if (R) try {
8320
- L = typeof R == "string" ? JSON.parse(R) : R;
8423
+ let ne = {}, re = null, ie = null, ae = !1, R = {}, oe = s && h.draftDataJson || h.dataJson;
8424
+ if (oe) try {
8425
+ R = typeof oe == "string" ? JSON.parse(oe) : oe;
8321
8426
  } catch {}
8322
- L.disabledRegions && (ee = L.disabledRegions), F = L.hidden === !0 || L.hidden === 1 || L.hidden === "1" || L.hidden === "true", te = L.startShowingAt || null, P = L.stopShowingAt || null;
8323
- let ne = L.layoutId, re = ne && ne !== "inherit", { resolvedLayoutId: ie, inheritedFields: ae } = await $e(t, O, D, s, N), oe = re ? ne : ie || M.defaultLayout || null;
8324
- for (let [e, t] of Object.entries(ae)) (L[e] === void 0 || L[e] === null || L[e] === "" || L[e] === "inherit") && t !== void 0 && (L[e] = t);
8325
- let z = await se(t, We(L, N));
8326
- z = Ge(z), z = await Ke(t, z, n);
8327
- let B = Ze(z);
8328
- delete z.socialImage, delete z.fbImage, delete z.xImage, delete z.whatsappImage, B && (z.socialImages = B), A.slug = _.slug, A.title = _.title, Object.assign(A, z), A.layoutId = oe;
8329
- let V = Number(_.isHidden) === 1 || F, le = !Ve(te, P), ue = _.status === "draft" || _.status === "new", de = _.dataJson && _.dataJson !== "{}" && _.dataJson !== "null";
8330
- if (!s && (V || le || ue && !de)) return e.json({ error: "Node is hidden, offline, or has never been published." }, 404);
8331
- let fe = [];
8332
- if (v?.treeNodeId) {
8333
- let e = await t.prepare("\n SELECT t.id as treeNodeId, t.contentId as id, c.title, c.slug, c.language, c.contentType as nodeType, c.isHidden, c.dataJson, c.draftDataJson\n FROM tree_nodes t INNER JOIN content_nodes c ON t.contentId = c.id WHERE t.parentId = ? AND t.treeId = ? ORDER BY t.sortOrder ASC\n ").all(v.treeNodeId, D), n = Array.isArray(e) ? e : e?.results || [], r = A.path === "/" ? "" : A.path;
8334
- fe = n.map((e) => {
8427
+ R.disabledRegions && (ne = R.disabledRegions), ae = R.hidden === !0 || R.hidden === 1 || R.hidden === "1" || R.hidden === "true", re = R.startShowingAt || null, ie = R.stopShowingAt || null;
8428
+ let z = R.layoutId, V = z && z !== "inherit", { resolvedLayoutId: H, inheritedFields: ce } = await et(t, N, T, s, L), le = V ? z : H || F.defaultLayout || null;
8429
+ for (let [e, t] of Object.entries(ce)) (R[e] === void 0 || R[e] === null || R[e] === "" || R[e] === "inherit") && t !== void 0 && (R[e] = t);
8430
+ let U = await B(t, Ge(R, L));
8431
+ U = Ke(U), U = await qe(t, U, n), delete U.language;
8432
+ let ue = Qe(U);
8433
+ delete U.socialImage, delete U.fbImage, delete U.xImage, delete U.whatsappImage, ue && (U.socialImages = ue), P.slug = h.slug, P.title = h.title, Object.assign(P, U), P.layoutId = le;
8434
+ let de = Number(h.isHidden) === 1 || ae, fe = !He(re, ie), pe = h.status === "draft" || h.status === "new", me = h.dataJson && h.dataJson !== "{}" && h.dataJson !== "null";
8435
+ if (!s && (de || fe || pe && !me)) return e.json({ error: "Node is hidden, offline, or has never been published." }, 404);
8436
+ let he = [];
8437
+ if (g?.treeNodeId) {
8438
+ let e = await t.prepare("\n SELECT t.id as treeNodeId, t.contentId as id, c.title, c.slug, c.language, c.contentType as nodeType, c.isHidden, c.dataJson, c.draftDataJson\n FROM tree_nodes t INNER JOIN content_nodes c ON t.contentId = c.id WHERE t.parentId = ? AND t.treeId = ? ORDER BY t.sortOrder ASC\n ").all(g.treeNodeId, T), n = Array.isArray(e) ? e : e?.results || [], r = P.path === "/" ? "" : P.path;
8439
+ he = n.map((e) => {
8335
8440
  let t = {}, n = s && e.draftDataJson || e.dataJson;
8336
8441
  if (!n) return null;
8337
8442
  try {
8338
8443
  t = (typeof n == "string" ? JSON.parse(n) : n) || {};
8339
8444
  } catch {}
8340
- let i = Number(e.isHidden) === 1 || t.hidden === !0 || t.hidden === 1 || t.hidden === "1", a = Ve(t.startShowingAt, t.stopShowingAt), o = (e.slug || "").replace(/^\/+|\/+$/g, "");
8445
+ let i = Number(e.isHidden) === 1 || t.hidden === !0 || t.hidden === 1 || t.hidden === "1", a = He(t.startShowingAt, t.stopShowingAt), o = (e.slug || "").replace(/^\/+|\/+$/g, "");
8341
8446
  return !s && (i || !a) ? null : {
8342
8447
  treeNodeId: e.treeNodeId,
8343
8448
  id: e.id,
8344
8449
  title: e.title,
8345
8450
  slug: o,
8346
- language: e.language || "en",
8451
+ language: e.language?.trim() || A || null,
8347
8452
  path: `${r}/${o}`.replace(/\/+/g, "/"),
8348
8453
  nodeType: e.nodeType
8349
8454
  };
8350
8455
  }).filter(Boolean);
8351
8456
  }
8352
- A.children = fe;
8353
- let pe = +!!s, H = await t.prepare("SELECT * FROM content_blocks WHERE contentId = ? AND isDraft = ? ORDER BY sortOrder ASC").all(_.id, pe), me = Array.isArray(H) ? H : H?.results || [], U = {}, W = {}, G = await Promise.all(me.map(async (e) => {
8457
+ P.children = he;
8458
+ let ge = +!!s, W = await t.prepare("SELECT * FROM content_blocks WHERE contentId = ? AND isDraft = ? ORDER BY sortOrder ASC").all(h.id, ge), _e = Array.isArray(W) ? W : W?.results || [], G = {}, ve = {}, ye = await Promise.all(_e.map(async (e) => {
8354
8459
  let r = e.region || "main", i = {};
8355
8460
  try {
8356
8461
  i = (typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson) || {};
8357
8462
  } catch {}
8358
- let a = i.hidden === !0 || i.hidden === 1 || i.hidden === "1" || i.hidden === "true", o = Ve(i.startShowingAt, i.stopShowingAt);
8463
+ let a = i.hidden === !0 || i.hidden === 1 || i.hidden === "1" || i.hidden === "true", o = He(i.startShowingAt, i.stopShowingAt);
8359
8464
  if (!s && (a || !o)) return null;
8360
- let c = e.elementType || e.componentId || "text-block", l = h.blocks?.[c]?.fields || h.elements?.[c]?.fields || h.components?.[c]?.fields || {}, u = String(i.blockId || i._instanceId || i.id || e.blockId || e.id), d = We(i, l);
8361
- return d = await se(t, d), d = Ge(d), d = await Ke(t, d, n), d.blockId = u, {
8465
+ let c = e.elementType || e.componentId || "text-block", l = p.blocks?.[c]?.fields || p.elements?.[c]?.fields || p.components?.[c]?.fields || {}, u = String(i.blockId || i._instanceId || i.id || e.blockId || e.id), d = Ge(i, l);
8466
+ return d = await B(t, d), d = Ke(d), d = await qe(t, d, n), d.blockId = u, {
8362
8467
  region: r,
8363
8468
  block: {
8364
8469
  instanceId: e.id,
@@ -8368,8 +8473,8 @@ Re.get("/*", async (e) => {
8368
8473
  }
8369
8474
  };
8370
8475
  }));
8371
- for (let e of G) e && (U[e.region] || (U[e.region] = [], W[e.region] = { isInherited: !1 }), U[e.region].push(e.block));
8372
- let he = {
8476
+ for (let e of ye) e && (G[e.region] || (G[e.region] = [], ve[e.region] = { isInherited: !1 }), G[e.region].push(e.block));
8477
+ let K = {
8373
8478
  header: {
8374
8479
  label: "Header",
8375
8480
  inherit: "parent"
@@ -8378,33 +8483,33 @@ Re.get("/*", async (e) => {
8378
8483
  label: "Footer",
8379
8484
  inherit: "parent"
8380
8485
  },
8381
- ...(oe ? h.nodeLayouts?.[oe] || h.layouts?.[oe] : null)?.regions || { main: { label: "Content" } }
8486
+ ...(le ? p.nodeLayouts?.[le] || p.layouts?.[le] : null)?.regions || { main: { label: "Content" } }
8382
8487
  };
8383
- for (let [e, r] of Object.entries(he)) {
8384
- let i = U[e] && U[e].length > 0, a = !!ee[e];
8385
- if (U[e] || (U[e] = [], W[e] = { isInherited: !1 }), (r?.inherit === "parent" || r?.inherit === !0 || r?.inherit === "true" || e === "header" || e === "footer") && !i && !a && O) {
8386
- let r = await Ue(t, O, e, h, s, n);
8387
- if (r.blocks.length > 0 && (U[e] = r.blocks, W[e] = {
8488
+ for (let [e, r] of Object.entries(K)) {
8489
+ let i = G[e] && G[e].length > 0, a = !!ne[e];
8490
+ if (G[e] || (G[e] = [], ve[e] = { isInherited: !1 }), (r?.inherit === "parent" || r?.inherit === !0 || r?.inherit === "true" || e === "header" || e === "footer") && !i && !a && N) {
8491
+ let r = await We(t, N, e, p, s, n);
8492
+ if (r.blocks.length > 0 && (G[e] = r.blocks, ve[e] = {
8388
8493
  isInherited: !0,
8389
8494
  inheritedFromId: r.inheritedFromId,
8390
8495
  inheritedFromTitle: r.inheritedFromTitle
8391
- }, r.subRegions)) for (let [t, n] of Object.entries(r.subRegions)) t !== e && (U[t] = n, W[t] = {
8496
+ }, r.subRegions)) for (let [t, n] of Object.entries(r.subRegions)) t !== e && (G[t] = n, ve[t] = {
8392
8497
  isInherited: !0,
8393
8498
  inheritedFromId: r.inheritedFromId,
8394
8499
  inheritedFromTitle: r.inheritedFromTitle
8395
8500
  });
8396
8501
  }
8397
8502
  }
8398
- await Promise.all(Object.keys(U).map((e) => He(t, U[e], u)));
8399
- let ge = {
8503
+ await Promise.all(Object.keys(G).map((e) => Ue(t, G[e], u, A)));
8504
+ let q = {
8400
8505
  channelId: u || d,
8401
- treeId: D,
8402
- language: A.language,
8403
- node: A,
8404
- content: U,
8405
- regionMeta: W
8506
+ treeId: T,
8507
+ language: A,
8508
+ node: P,
8509
+ content: G,
8510
+ regionMeta: ve
8406
8511
  };
8407
- return !s && !m && (e.header("X-Cache", "MISS"), await tt(f, p, ge, et(e))), e.json(ge);
8512
+ return !s && !M && (e.header("X-Cache", "MISS"), await nt(f, j, q, tt(e))), e.json(q);
8408
8513
  } catch (t) {
8409
8514
  return console.error("[CMS Public API] Error fetching node by path:", t), e.json({
8410
8515
  error: "Failed to fetch JSON payload",
@@ -8412,8 +8517,8 @@ Re.get("/*", async (e) => {
8412
8517
  }, 500);
8413
8518
  }
8414
8519
  });
8415
- var nt = new e();
8416
- function rt(e, t) {
8520
+ var rt = new e();
8521
+ function it(e, t) {
8417
8522
  let n = /* @__PURE__ */ new Date();
8418
8523
  if (e && String(e).trim() !== "") {
8419
8524
  let t = new Date(e);
@@ -8425,93 +8530,103 @@ function rt(e, t) {
8425
8530
  }
8426
8531
  return !0;
8427
8532
  }
8428
- async function it(e, t, n, r) {
8533
+ async function at(e, t, n, r) {
8429
8534
  try {
8430
8535
  await e.set(t, n, r);
8431
8536
  } catch (e) {
8432
8537
  console.warn("[CMS Cache] Failed to write tree response to cache:", e);
8433
8538
  }
8434
8539
  }
8435
- nt.get("/:treeParam", async (e) => {
8540
+ rt.get("/:treeParam", async (e) => {
8436
8541
  try {
8437
- let t = e.get("db"), n = e.req.param("treeParam"), r = e.req.query("channelId") || e.req.query("channel") || "default", i = e.req.query("preview") === "true";
8542
+ let t = e.get("db"), n = e.req.param("treeParam"), r = e.req.query("channelId") || e.req.query("channel") || "default", i = e.req.query("lang"), a = e.req.query("preview") === "true", o = null;
8438
8543
  if (r && r !== "default" && r !== "all") {
8439
8544
  let n = isNaN(Number(r)) ? await t.prepare("SELECT * FROM channels WHERE key = ?").get(r) : await t.prepare("SELECT * FROM channels WHERE id = ?").get(Number(r));
8440
8545
  if (n) {
8546
+ n.defaultLanguage && (o = n.defaultLanguage.trim());
8441
8547
  let t = n.status === "disabled" || n.status === "inactive" || n.isEnabled === 0 || n.isEnabled === !1;
8442
- if (!i && t) return e.json({ error: `Channel '${n.key || r}' is currently inactive` }, 404);
8548
+ if (!a && t) return e.json({ error: `Channel '${n.key || r}' is currently inactive` }, 404);
8443
8549
  }
8444
8550
  }
8445
- let a = I(e), o = `tree:${r}:${n}`, s = e.req.header("x-bypass-cache") === "true";
8446
- if (!i && !s) {
8447
- let t = await a.get(o);
8551
+ let s = !isNaN(Number(n)), c = s ? await t.prepare("SELECT * FROM trees WHERE id = ?").get(Number(n)) : await t.prepare("SELECT * FROM trees WHERE key = ?").get(n);
8552
+ if (c && Number(c.isHidden) === 1 && !a) return e.json({ error: `Tree '${n}' is hidden` }, 404);
8553
+ let l = null;
8554
+ if (c) {
8555
+ if (c.defaultLanguage) l = String(c.defaultLanguage).trim();
8556
+ else if (c.dataJson) try {
8557
+ let e = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson;
8558
+ e.defaultLanguage && (l = String(e.defaultLanguage).trim());
8559
+ } catch {}
8560
+ }
8561
+ let u = l || o || i?.trim() || null, d = I(e), f = `tree:${r}:${n}:${u || "default"}`, p = e.req.header("x-bypass-cache") === "true";
8562
+ if (!a && !p) {
8563
+ let t = await d.get(f);
8448
8564
  if (t) return e.header("X-Cache", "HIT"), e.json(t);
8449
8565
  }
8450
- let c = !isNaN(Number(n)), l = c ? await t.prepare("SELECT * FROM trees WHERE id = ?").get(Number(n)) : await t.prepare("SELECT * FROM trees WHERE key = ?").get(n);
8451
- if (l && Number(l.isHidden) === 1 && !i) return e.json({ error: `Tree '${n}' is hidden` }, 404);
8452
- let u = l?.id || (c ? Number(n) : null), d = {};
8453
- if (l && l.dataJson) try {
8454
- let t = typeof l.dataJson == "string" ? JSON.parse(l.dataJson) : l.dataJson, r = e.env?.BUNDLED_DEFINITIONS, i = ce(r), a = (i.trees?.[l.treeType || n] || i.trees?.site || {}).fields || {};
8455
- for (let [e, n] of Object.entries(t)) a[e]?.public === !0 && (d[e] = n);
8566
+ let m = c?.id || (s ? Number(n) : null), h = {};
8567
+ if (c && c.dataJson) try {
8568
+ let t = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson, r = e.env?.BUNDLED_DEFINITIONS, i = se(r), a = (i.trees?.[c.treeType || n] || i.trees?.site || {}).fields || {};
8569
+ for (let [e, n] of Object.entries(t)) a[e]?.public === !0 && (h[e] = n);
8456
8570
  } catch (e) {
8457
8571
  console.warn("[CMS Public Tree API] Failed to parse tree dataJson", e);
8458
8572
  }
8459
- let f = [];
8460
- if (u !== null) {
8461
- let e = await t.prepare("\n SELECT \n t.id as treeNodeId,\n t.treeId,\n t.contentId as id,\n t.parentId,\n t.sortOrder,\n c.title,\n c.slug,\n c.language,\n c.contentType as nodeType,\n c.isHidden,\n c.status,\n c.dataJson,\n c.draftDataJson\n FROM tree_nodes t\n INNER JOIN content_nodes c ON t.contentId = c.id\n WHERE t.treeId = ? AND (c.deletedAt IS NULL OR c.deletedAt = '')\n ORDER BY t.sortOrder ASC\n ").all(u);
8462
- f = Array.isArray(e) ? e : e?.results || [];
8573
+ let g = [];
8574
+ if (m !== null) {
8575
+ let e = await t.prepare("\n SELECT \n t.id as treeNodeId,\n t.treeId,\n t.contentId as id,\n t.parentId,\n t.sortOrder,\n c.title,\n c.slug,\n c.language,\n c.contentType as nodeType,\n c.isHidden,\n c.status,\n c.dataJson,\n c.draftDataJson\n FROM tree_nodes t\n INNER JOIN content_nodes c ON t.contentId = c.id\n WHERE t.treeId = ? AND (c.deletedAt IS NULL OR c.deletedAt = '')\n ORDER BY t.sortOrder ASC\n ").all(m);
8576
+ g = Array.isArray(e) ? e : e?.results || [];
8463
8577
  }
8464
- if ((!f || f.length === 0) && !l) return e.json({ error: `Tree '${n}' not found` }, 404);
8465
- let p = /* @__PURE__ */ new Map();
8466
- for (let e of f) {
8467
- let t = !e.parentId || e.parentId === "null" || e.parentId === "" ? null : e.parentId, n = t === null ? "__ROOT__" : String(t), r = p.get(n);
8468
- r ? r.push(e) : p.set(n, [e]);
8578
+ if ((!g || g.length === 0) && !c) return e.json({ error: `Tree '${n}' not found` }, 404);
8579
+ let _ = /* @__PURE__ */ new Map();
8580
+ for (let e of g) {
8581
+ let t = !e.parentId || e.parentId === "null" || e.parentId === "" ? null : e.parentId, n = t === null ? "__ROOT__" : String(t), r = _.get(n);
8582
+ r ? r.push(e) : _.set(n, [e]);
8469
8583
  }
8470
- let m = /* @__PURE__ */ new Map();
8471
- for (let e of f) {
8472
- let t = String(e.treeNodeId), n = i && e.draftDataJson ? e.draftDataJson : e.dataJson;
8584
+ let v = /* @__PURE__ */ new Map();
8585
+ for (let e of g) {
8586
+ let t = String(e.treeNodeId), n = a && e.draftDataJson ? e.draftDataJson : e.dataJson;
8473
8587
  if (!n) {
8474
- m.set(t, {});
8588
+ v.set(t, {});
8475
8589
  continue;
8476
8590
  }
8477
8591
  try {
8478
8592
  let e = typeof n == "string" ? JSON.parse(n) : n;
8479
- m.set(t, e && typeof e == "object" ? e : {});
8593
+ v.set(t, e && typeof e == "object" ? e : {});
8480
8594
  } catch {
8481
- m.set(t, {});
8595
+ v.set(t, {});
8482
8596
  }
8483
8597
  }
8484
- function h(e = null, t = "") {
8598
+ function y(e = null, t = "") {
8485
8599
  let n = e == null || e === "" || e === "null" ? "__ROOT__" : String(e);
8486
- return (p.get(n) || []).map((e) => {
8487
- let n = m.get(String(e.treeNodeId)) || {}, r = {};
8600
+ return (_.get(n) || []).map((e) => {
8601
+ let n = v.get(String(e.treeNodeId)) || {}, r = {};
8488
8602
  for (let [e, t] of Object.entries(n)) e !== "_isTreeDraft" && e !== "_draftParentId" && e !== "isNew" && e !== "hidden" && e !== "is_hidden" && e !== "isHidden" && e !== "status" && (r[e] = t);
8489
- let a = !i && (e.status === "draft" || e.status === "new"), o = Number(e.isHidden) === 1 || a || n.hidden === !0 || n.hidden === 1 || n.hidden === "1" || n.hidden === "true", s = rt(n.startShowingAt, n.stopShowingAt), c = (e.slug || "").replace(/^\/+|\/+$/g, ""), l = (!e.parentId || e.parentId === "null" || e.parentId === "") && (c === "home" || c === "homee") ? "/" : `${t}/${c}`.replace(/\/+/g, "/"), u = {
8603
+ let i = !a && (e.status === "draft" || e.status === "new"), o = Number(e.isHidden) === 1 || i || n.hidden === !0 || n.hidden === 1 || n.hidden === "1" || n.hidden === "true", s = it(n.startShowingAt, n.stopShowingAt), c = (e.slug || "").replace(/^\/+|\/+$/g, ""), l = (!e.parentId || e.parentId === "null" || e.parentId === "") && (c === "home" || c === "homee") ? "/" : `${t}/${c}`.replace(/\/+/g, "/"), d = e.language && String(e.language).trim() !== "" ? e.language.trim() : u, f = {
8490
8604
  id: e.id,
8491
8605
  treeNodeId: e.treeNodeId,
8492
8606
  parentId: e.parentId || null,
8493
8607
  title: e.title,
8494
8608
  slug: c,
8495
- language: e.language || "en",
8609
+ language: d,
8496
8610
  path: l,
8497
8611
  nodeType: e.nodeType,
8498
8612
  hidden: o || !s ? 1 : 0,
8499
8613
  summary: r.summary || ""
8500
8614
  };
8501
- e.nodeType === "external-link" && (r.url && (u.url = r.url), r.target && (u.target = r.target));
8502
- let d = l === "/" ? "" : l;
8503
- return u.children = h(e.treeNodeId, d), u;
8504
- }).filter((e) => i || !e.hidden);
8615
+ e.nodeType === "external-link" && (r.url && (f.url = r.url), r.target && (f.target = r.target));
8616
+ let p = l === "/" ? "" : l;
8617
+ return f.children = y(e.treeNodeId, p), f;
8618
+ }).filter((e) => a || !e.hidden);
8505
8619
  }
8506
- let g = {
8507
- treeId: l?.id || u,
8508
- key: l?.key || n,
8620
+ let b = {
8621
+ treeId: c?.id || m,
8622
+ key: c?.key || n,
8509
8623
  channelId: r,
8510
- label: l?.label || n,
8511
- ...d,
8512
- items: h(null)
8624
+ language: u,
8625
+ label: c?.label || n,
8626
+ ...h,
8627
+ items: y(null)
8513
8628
  };
8514
- return !i && !s && (e.header("X-Cache", "MISS"), await it(a, o, g, 300)), e.json(g);
8629
+ return !a && !p && (e.header("X-Cache", "MISS"), await at(d, f, b, 300)), e.json(b);
8515
8630
  } catch (t) {
8516
8631
  return console.error("[CMS Public Tree API] Error:", t), e.json({
8517
8632
  error: "Failed to fetch public tree",
@@ -8519,8 +8634,145 @@ nt.get("/:treeParam", async (e) => {
8519
8634
  }, 500);
8520
8635
  }
8521
8636
  });
8522
- var at = new e();
8523
- function ot(e, t) {
8637
+ var ot = new e();
8638
+ function st(e) {
8639
+ let t = Number(e?.env?.CMS_CHANNEL_CACHE_TTL);
8640
+ return Number.isFinite(t) && t >= 60 ? Math.floor(t) : 300;
8641
+ }
8642
+ async function ct(e, t, n, r) {
8643
+ try {
8644
+ await e.set(t, n, r);
8645
+ } catch (e) {
8646
+ console.warn("[CMS Cache] Failed to write channel response to cache:", e);
8647
+ }
8648
+ }
8649
+ function lt(e, t) {
8650
+ let n = {}, r = (e) => {
8651
+ if (!e || typeof e != "string") return;
8652
+ let n = t?.fieldSets?.[e] || t?.fieldsets?.[e] || t?.definitions?.[e] || t?.channels?.[e] || t?.[e];
8653
+ n?.fields && i(n.fields);
8654
+ }, i = (e) => {
8655
+ if (!(!e || typeof e != "object")) for (let [t, i] of Object.entries(e)) t === "fieldSet" && typeof i == "string" ? r(i) : i && typeof i == "object" && i.fieldSet ? r(i.fieldSet) : t !== "fieldSet" && (n[t] = i);
8656
+ };
8657
+ if (e?.fieldSets && Array.isArray(e.fieldSets) && e.fieldSets.forEach((e) => r(e)), e?.fields && i(e.fields), e?.tabs && typeof e.tabs == "object") for (let t of Object.values(e.tabs)) t?.fields && i(t.fields);
8658
+ return n;
8659
+ }
8660
+ function ut(e, t = {}) {
8661
+ let n = {}, r = Object.keys(t).length > 0;
8662
+ for (let [i, a] of Object.entries(e)) {
8663
+ if (i.endsWith("_meta") || [
8664
+ "disabledRegions",
8665
+ "hidden",
8666
+ "is_hidden",
8667
+ "isHidden",
8668
+ "status",
8669
+ "startShowingAt",
8670
+ "stopShowingAt",
8671
+ "dataJson",
8672
+ "draftDataJson"
8673
+ ].includes(i) || i.startsWith("_")) continue;
8674
+ let e = t[i];
8675
+ (!r || !e || e.public !== !1) && a != null && a !== "" && (n[i] = a);
8676
+ }
8677
+ return n;
8678
+ }
8679
+ function dt(e) {
8680
+ if (Array.isArray(e)) return e.map(dt);
8681
+ if (!e || typeof e != "object") return e;
8682
+ if (typeof e.id == "string" && e.id.startsWith("ast_") && typeof e.url == "string") {
8683
+ let t = e.metadataOverrides || {}, n = e.variants && typeof e.variants == "object" ? e.variants : {}, r = Object.entries(n).find(([, t]) => t?.id === e.id)?.[0], i = r ? {
8684
+ ...t,
8685
+ ...t.crops?.[r] || {}
8686
+ } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, dt({
8687
+ ...n,
8688
+ title: n?.title ?? e.title ?? "",
8689
+ alt: n?.alt ?? e.alt ?? "",
8690
+ description: n?.description ?? e.description ?? ""
8691
+ })])), { metadataOverrides: o, ...s } = e;
8692
+ return {
8693
+ ...s,
8694
+ title: i.title ?? e.title ?? "",
8695
+ alt: i.alt ?? e.alt ?? "",
8696
+ description: i.description ?? e.description ?? "",
8697
+ ...Object.keys(a).length > 0 ? { variants: a } : {}
8698
+ };
8699
+ }
8700
+ return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, dt(t)]));
8701
+ }
8702
+ async function ft(e, t) {
8703
+ if (typeof t == "string") {
8704
+ if (!t.includes("#node:") && !t.includes("data-node-id") && !t.includes("#asset:") && !t.includes("data-asset-id")) return t;
8705
+ let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set();
8706
+ for (let e of t.matchAll(/(?:#node:|data-node-id\s*=\s*["'])([^"'\s>]+)/gi)) n.add(e[1]);
8707
+ for (let e of t.matchAll(/(?:#asset:|data-asset-id\s*=\s*["'])([^"'\s>]+)/gi)) r.add(e[1]);
8708
+ if (n.size === 0 && r.size === 0) return t;
8709
+ let i = Array.from(n).map(() => "?").join(","), a = n.size > 0 ? await e.prepare(`SELECT id, slug FROM content_nodes WHERE id IN (${i})`).all(...n) : [], o = /* @__PURE__ */ new Map();
8710
+ (Array.isArray(a) ? a : a?.results || []).forEach((e) => o.set(String(e.id), String(e.slug || "").replace(/^\/+|\/+$/g, "")));
8711
+ let s = Array.from(r).map(() => "?").join(","), c = r.size > 0 ? await e.prepare(`SELECT id, cdnUrl, storageKeyPrivate FROM assets WHERE id IN (${s})`).all(...r) : [], l = /* @__PURE__ */ new Map();
8712
+ return (Array.isArray(c) ? c : c?.results || []).forEach((e) => l.set(String(e.id), e.cdnUrl || (e.storageKeyPrivate ? `/media/${e.storageKeyPrivate}` : ""))), t.replace(/<a\s+([^>]+)>/gi, (e, t) => {
8713
+ let n = (e, t) => {
8714
+ let n = e.match(RegExp(`\\b${t}\\s*=\\s*(["'])(.*?)\\1`, "i"));
8715
+ return n ? n[2] : void 0;
8716
+ }, r = n(t, "data-node-id"), i = n(t, "data-asset-id"), a = n(t, "href") || "";
8717
+ if (a.startsWith("mailto:")) return `<a ${t.replace(/\s+target\s*=\s*["'][^"']*["']/i, "")}>`;
8718
+ let s = i || a.match(/^#asset:(.+)$/i)?.[1], c = r || a.match(/^#node:(.+)$/i)?.[1];
8719
+ if (!c && !s) return e;
8720
+ if (s && !c) {
8721
+ let n = l.get(s);
8722
+ if (n) {
8723
+ let e = t;
8724
+ return /href\s*=\s*["'][^"']*["']/i.test(e) ? e = e.replace(/href\s*=\s*["'][^"']*["']/i, `href="${n}"`) : e += ` href="${n}"`, `<a ${e}>`;
8725
+ }
8726
+ return e;
8727
+ }
8728
+ let u = o.get(c), d = u === void 0 ? "#" : `/${u}`, f = t;
8729
+ return /href\s*=\s*["'][^"']*["']/i.test(f) ? f = f.replace(/href\s*=\s*["'][^"']*["']/i, `href="${d || "/"}"`) : f += ` href="${d || "/"}"`, `<a ${f}>`;
8730
+ });
8731
+ }
8732
+ if (Array.isArray(t)) return Promise.all(t.map((t) => ft(e, t)));
8733
+ if (t && typeof t == "object") {
8734
+ let n = await Promise.all(Object.entries(t).map(async ([t, n]) => [t, await ft(e, n)]));
8735
+ return Object.fromEntries(n);
8736
+ }
8737
+ return t;
8738
+ }
8739
+ ot.get("/:channelParam", async (e) => {
8740
+ try {
8741
+ let t = e.get("db"), n = e.req.param("channelParam"), r = e.req.query("preview") === "true", i = e.req.header("x-bypass-cache") === "true", a = `channel:${n}:${r ? "preview" : "live"}`, o = I(e);
8742
+ if (!r && !i) {
8743
+ let t = await o.get(a);
8744
+ if (t) return e.header("X-Cache", "HIT"), e.json(t);
8745
+ }
8746
+ let s = isNaN(Number(n)) ? await t.prepare("SELECT * FROM channels WHERE key = ?").get(n) : await t.prepare("SELECT * FROM channels WHERE id = ?").get(Number(n));
8747
+ if (!s) return e.json({ error: `Channel '${n}' not found` }, 404);
8748
+ let c = s.status === "disabled" || s.status === "inactive" || s.isEnabled === 0 || s.isEnabled === !1;
8749
+ if (!r && c) return e.json({ error: `Channel '${s.key || n}' is currently inactive` }, 404);
8750
+ let l = e.env?.BUNDLED_DEFINITIONS, u = se(l), d = s.channelType || s.key || "website", f = lt(u.channels?.[d] || u.channels?.[s.key] || u.channels?.website || u.definitions?.["channel-base"] || {}, u), p = {}, m = r && s.draftDataJson || s.dataJson;
8751
+ if (m) try {
8752
+ p = typeof m == "string" ? JSON.parse(m) : m;
8753
+ } catch (e) {
8754
+ console.warn("[CMS Public Channel API] Failed to parse channel dataJson:", e);
8755
+ }
8756
+ let h = ut({
8757
+ ...p,
8758
+ ...s
8759
+ }, f);
8760
+ h = await B(t, h), h = dt(h), h = await ft(t, h);
8761
+ let g = {
8762
+ id: s.id,
8763
+ key: s.key,
8764
+ ...h
8765
+ };
8766
+ return !r && !i && (e.header("X-Cache", "MISS"), await ct(o, a, g, st(e))), e.json(g);
8767
+ } catch (t) {
8768
+ return console.error("[CMS Public Channel API] Error:", t), e.json({
8769
+ error: "Failed to fetch public channel",
8770
+ ...e.env?.ENVIRONMENT === "development" ? { details: t.message } : {}
8771
+ }, 500);
8772
+ }
8773
+ });
8774
+ var pt = new e();
8775
+ function mt(e, t) {
8524
8776
  if (t === "webp") return "image/webp";
8525
8777
  if (t === "avif") return "image/avif";
8526
8778
  if (t === "jpeg" || t === "jpg") return "image/jpeg";
@@ -8528,7 +8780,7 @@ function ot(e, t) {
8528
8780
  let n = e.toLowerCase();
8529
8781
  return n.endsWith(".jpg") || n.endsWith(".jpeg") ? "image/jpeg" : n.endsWith(".png") ? "image/png" : n.endsWith(".webp") ? "image/webp" : n.endsWith(".svg") ? "image/svg+xml" : n.endsWith(".pdf") ? "application/pdf" : n.endsWith(".mp4") ? "video/mp4" : "application/octet-stream";
8530
8782
  }
8531
- at.get("/*", async (e) => {
8783
+ pt.get("/*", async (e) => {
8532
8784
  try {
8533
8785
  let t = e.req.path.replace(/^\/media\//, "").replace(/^\//, "");
8534
8786
  if (!t) return e.text("Asset key missing", 400);
@@ -8544,11 +8796,11 @@ at.get("/*", async (e) => {
8544
8796
  let e = await l.match(d);
8545
8797
  if (e) return e;
8546
8798
  }
8547
- let { storage: f, optimizer: p } = ie(e.env), m = await f.get(t);
8799
+ let { storage: f, optimizer: p } = ae(e.env), m = await f.get(t);
8548
8800
  if (!m) return e.text(`Asset not found: ${t}`, 404);
8549
8801
  if (!o) {
8550
8802
  let n = e.body(m, 200, {
8551
- "Content-Type": ot(t),
8803
+ "Content-Type": mt(t),
8552
8804
  "Cache-Control": "public, max-age=31536000, immutable"
8553
8805
  });
8554
8806
  return l && d && e.executionCtx?.waitUntil && e.executionCtx.waitUntil(l.put(d, n.clone())), n;
@@ -8562,7 +8814,7 @@ at.get("/*", async (e) => {
8562
8814
  key: t,
8563
8815
  env: e.env,
8564
8816
  req: e.req.raw
8565
- }), _ = ot(t, c), v = e.body(g, 200, {
8817
+ }), _ = mt(t, c), v = e.body(g, 200, {
8566
8818
  "Content-Type": _,
8567
8819
  "Cache-Control": "public, max-age=31536000, immutable"
8568
8820
  });
@@ -8571,8 +8823,8 @@ at.get("/*", async (e) => {
8571
8823
  return console.error("❌ [Public Assets Error]:", t), e.text("Internal Server Error", 500);
8572
8824
  }
8573
8825
  });
8574
- var st = new e();
8575
- function ct(e, t) {
8826
+ var ht = new e();
8827
+ function gt(e, t) {
8576
8828
  let n = /* @__PURE__ */ new Date();
8577
8829
  if (e && String(e).trim() !== "") {
8578
8830
  let t = new Date(e);
@@ -8584,7 +8836,7 @@ function ct(e, t) {
8584
8836
  }
8585
8837
  return !0;
8586
8838
  }
8587
- st.get("/", async (e) => {
8839
+ ht.get("/", async (e) => {
8588
8840
  try {
8589
8841
  let t = await e.get("db").prepare("\n SELECT\n t.id as treeNodeId,\n t.parentId,\n c.slug,\n c.contentType as nodeType,\n c.status,\n c.dataJson\n FROM tree_nodes t\n INNER JOIN content_nodes c ON t.contentId = c.id\n WHERE (c.deletedAt IS NULL OR c.deletedAt = '')\n ORDER BY t.sortOrder ASC\n ").all(), n = Array.isArray(t) ? t : t?.results || [], r = [], i = /* @__PURE__ */ new Map();
8590
8842
  for (let e of n) {
@@ -8608,7 +8860,7 @@ st.get("/", async (e) => {
8608
8860
  function o(e = null, t = "") {
8609
8861
  let n = e == null || e === "" || e === "null" ? "__ROOT__" : String(e), s = i.get(n) || [];
8610
8862
  for (let e of s) {
8611
- let n = a.get(String(e.treeNodeId)) || {}, i = e.status === "published" || e.status === "active", s = ct(n.startShowingAt, n.stopShowingAt);
8863
+ let n = a.get(String(e.treeNodeId)) || {}, i = e.status === "published" || e.status === "active", s = gt(n.startShowingAt, n.stopShowingAt);
8612
8864
  if (!i || !s) continue;
8613
8865
  let c = (e.slug || "").replace(/^\/+|\/+$/g, ""), l = c === "home" || c === "homee" ? "/" : `${t}/${c}`.replace(/\/+/g, "/");
8614
8866
  e.nodeType !== "external-link" && r.push(l);
@@ -8623,7 +8875,7 @@ st.get("/", async (e) => {
8623
8875
  return console.error("[CMS Paths API] Error:", t), e.json({ error: "Failed to fetch paths" }, 500);
8624
8876
  }
8625
8877
  });
8626
- var $ = new e(), lt = !1;
8878
+ var $ = new e(), _t = !1;
8627
8879
  $.use("*", t()), $.use("/media/*", t({
8628
8880
  origin: "*",
8629
8881
  allowMethods: [
@@ -8644,13 +8896,13 @@ $.use("*", t()), $.use("/media/*", t({
8644
8896
  let n = new URL(e.req.url), r = (e.req.header("host") || n.hostname).split(":")[0];
8645
8897
  e.set("currentDomain", r);
8646
8898
  let i = l(e);
8647
- if (e.set("db", i), !lt) try {
8648
- await _(i), lt = !0;
8899
+ if (e.set("db", i), !_t) try {
8900
+ await _(i), _t = !0;
8649
8901
  } catch (e) {
8650
8902
  console.error("❌ [CMS Server] Failed to initialize system tables on cold start:", e);
8651
8903
  }
8652
8904
  await t();
8653
- }), $.route("/media", at), $.use("/media/*", y()), $.route("/api/cms/nodes", V), $.route("/api/cms/nodes.json", V), $.route("/api/cms/formcsv", V), $.route("/api/cms/formcsv.json", V), $.route("/api/cms/stats", Ie), $.route("/api/cms/stats.json", Ie), $.route("/api/cms", G), $.route("/api/cms/channels", ve), $.route("/api/cms/channels.json", ve), $.route("/api/cms/schemas", je), $.route("/api/cms/schemas.json", je), $.route("/api/cms", Ne), $.route("/api/admin/assets", X), $.route("/api/v1/node", Re), $.route("/api/v1/page", Re), $.route("/api/v1/tree", nt), $.route("/api/v1/all-paths", st), $.get("*", async (e, t) => {
8905
+ }), $.route("/media", pt), $.use("/media/*", y()), $.route("/api/cms/nodes", H), $.route("/api/cms/nodes.json", H), $.route("/api/cms/formcsv", H), $.route("/api/cms/formcsv.json", H), $.route("/api/cms/stats", Le), $.route("/api/cms/stats.json", Le), $.route("/api/cms", W), $.route("/api/cms/channels", ye), $.route("/api/cms/channels.json", ye), $.route("/api/cms/schemas", Me), $.route("/api/cms/schemas.json", Me), $.route("/api/cms", Pe), $.route("/api/admin/assets", X), $.route("/api/v1/node", ze), $.route("/api/v1/page", ze), $.route("/api/v1/tree", rt), $.route("/api/v1/channel", ot), $.route("/api/v1/all-paths", ht), $.get("*", async (e, t) => {
8654
8906
  if (e.env?.ASSETS) {
8655
8907
  let t = await e.env.ASSETS.fetch(e.req.raw);
8656
8908
  if (t.status === 404) {
@@ -8662,4 +8914,4 @@ $.use("*", t()), $.use("/media/*", t({
8662
8914
  return t();
8663
8915
  });
8664
8916
  //#endregion
8665
- export { Oe as compileDefinitions };
8917
+ export { ke as compileDefinitions };