@brightsideoy/kama 0.1.0-alpha.156 → 0.1.0-alpha.158

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 (34) hide show
  1. package/bin/cli.js +222 -253
  2. package/content/definitions/nodes/page.yaml +0 -16
  3. package/dist/assets/index-B-WxBAFU.js +164 -0
  4. package/dist/assets/index-C5TmJVER.css +1 -0
  5. package/dist/{dist-C-WAK7EF.js → dist-CBGESg3a.js} +691 -475
  6. package/dist/index.html +2 -2
  7. package/dist/index.js +693 -475
  8. package/dist/schema-compiler.js +1 -1
  9. package/package.json +1 -1
  10. package/schema.sql +2 -2
  11. package/templates/astro-starter/src/components/blocks/BlockRenderer.astro +1 -0
  12. package/templates/astro-starter/src/components/blocks/ColumnLayout.astro +1 -0
  13. package/templates/astro-starter/src/components/blocks/HeaderImage.astro +1 -0
  14. package/templates/astro-starter/src/components/blocks/HtmlBlock.astro +2 -1
  15. package/templates/astro-starter/src/components/blocks/ImageBlock.astro +39 -71
  16. package/templates/astro-starter/src/components/blocks/TextBlock.astro +2 -0
  17. package/templates/astro-starter/src/components/global/Breadcrumb.astro +2 -0
  18. package/templates/astro-starter/src/components/global/Footer.astro +2 -0
  19. package/templates/astro-starter/src/components/global/Header.astro +99 -33
  20. package/templates/astro-starter/src/components/{seo/SeoHead.astro → global/MetaHead.astro} +101 -49
  21. package/templates/astro-starter/src/components/global/NavigationMenu.astro +1 -0
  22. package/templates/astro-starter/src/components/ui/KamaImage.astro +114 -67
  23. package/templates/astro-starter/src/layouts/SkeletonLayout.astro +5 -3
  24. package/templates/astro-starter/src/layouts/StandardLayout.astro +14 -5
  25. package/templates/astro-starter/src/lib/cms.ts +48 -0
  26. package/templates/astro-starter/src/lib/media/kama-image-service.ts +16 -1
  27. package/templates/astro-starter/src/lib/media/media-proxy.ts +8 -6
  28. package/templates/astro-starter/src/lib/media/media-url.ts +65 -1
  29. package/templates/astro-starter/src/middleware.ts +86 -17
  30. package/templates/astro-starter/src/pages/[...slug].astro +10 -22
  31. package/definitions/_page.yaml +0 -52
  32. package/dist/assets/index-DnRQYNN4.js +0 -164
  33. package/dist/assets/index-EaDn3OUJ.css +0 -1
  34. /package/templates/astro-starter/{public/css → src/styles}/standard-theme.css +0 -0
@@ -1852,24 +1852,6 @@ var u = /* @__PURE__ */ o({
1852
1852
  },
1853
1853
  required: !0
1854
1854
  },
1855
- logoText: {
1856
- label: "Logo Text",
1857
- type: "text",
1858
- required: !1,
1859
- public: !0,
1860
- inherits: "logoText",
1861
- rules: { required: !1 }
1862
- },
1863
- logoImage: {
1864
- label: "Logo Image",
1865
- type: "image",
1866
- maxPreviewWidth: "300px",
1867
- multiple: !1,
1868
- allowedTypes: ["image/svg"],
1869
- public: !0,
1870
- inherits: "logoImage",
1871
- rules: {}
1872
- },
1873
1855
  layoutId: {
1874
1856
  label: "Page Layout",
1875
1857
  type: "layout-select",
@@ -2198,24 +2180,6 @@ var u = /* @__PURE__ */ o({
2198
2180
  },
2199
2181
  required: !0
2200
2182
  },
2201
- logoText: {
2202
- label: "Logo Text",
2203
- type: "text",
2204
- required: !1,
2205
- public: !0,
2206
- inherits: "logoText",
2207
- rules: { required: !1 }
2208
- },
2209
- logoImage: {
2210
- label: "Logo Image",
2211
- type: "image",
2212
- maxPreviewWidth: "300px",
2213
- multiple: !1,
2214
- allowedTypes: ["image/svg"],
2215
- public: !0,
2216
- inherits: "logoImage",
2217
- rules: {}
2218
- },
2219
2183
  layoutId: {
2220
2184
  label: "Page Layout",
2221
2185
  type: "layout-select",
@@ -4813,10 +4777,10 @@ var u = /* @__PURE__ */ o({
4813
4777
  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
4778
  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
4779
  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 ",
4780
+ 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
4781
  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
4782
  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 ",
4783
+ 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
4784
  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
4785
  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
4786
  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 +5541,7 @@ var b = { hasSubscribers: !1 }, x = b, S = b, C = typeof performance == "object"
5577
5541
  async clear() {
5578
5542
  this.cache.clear();
5579
5543
  }
5580
- }, te = class {
5544
+ }, P = class {
5581
5545
  kv;
5582
5546
  constructor(e) {
5583
5547
  this.kv = e;
@@ -5594,7 +5558,7 @@ var b = { hasSubscribers: !1 }, x = b, S = b, C = typeof performance == "object"
5594
5558
  this.kv && await this.kv.delete(e);
5595
5559
  }
5596
5560
  async clear() {}
5597
- }, P = class {
5561
+ }, te = class {
5598
5562
  async get() {
5599
5563
  return null;
5600
5564
  }
@@ -5604,7 +5568,7 @@ var b = { hasSubscribers: !1 }, x = b, S = b, C = typeof performance == "object"
5604
5568
  }, F = null;
5605
5569
  function I(e) {
5606
5570
  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();
5571
+ 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
5572
  }
5609
5573
  var L = class {
5610
5574
  customStoragePath;
@@ -5675,7 +5639,7 @@ var L = class {
5675
5639
  if (e.code !== "ENOENT") throw e;
5676
5640
  }
5677
5641
  }
5678
- }, R = class {
5642
+ }, ne = class {
5679
5643
  async process(e, t, n) {
5680
5644
  let r = await import(
5681
5645
  /* @vite-ignore */
@@ -5702,7 +5666,7 @@ var L = class {
5702
5666
  return console.warn("⚠️ [SharpImageOptimizer] Processing failed, returning raw buffer."), e;
5703
5667
  }
5704
5668
  }
5705
- }, ne = class {
5669
+ }, re = class {
5706
5670
  bucket;
5707
5671
  publicDomain;
5708
5672
  constructor(e, t) {
@@ -5747,7 +5711,7 @@ var L = class {
5747
5711
  async delete(e) {
5748
5712
  await this.bucket.delete(e);
5749
5713
  }
5750
- }, re = class {
5714
+ }, ie = class {
5751
5715
  async process(e, t, n) {
5752
5716
  let { env: r, key: i, req: a } = n;
5753
5717
  if (r.IMAGES) try {
@@ -5782,16 +5746,16 @@ var L = class {
5782
5746
  return e;
5783
5747
  }
5784
5748
  };
5785
- function ie(e) {
5749
+ function ae(e) {
5786
5750
  return e.KAMA_RUNTIME === "cloudflare" || e.MEDIA_BUCKET ? {
5787
- storage: new ne(e.MEDIA_BUCKET, e.CDN_DOMAIN || ""),
5788
- optimizer: new re()
5751
+ storage: new re(e.MEDIA_BUCKET, e.CDN_DOMAIN || ""),
5752
+ optimizer: new ie()
5789
5753
  } : {
5790
5754
  storage: new L(e.LOCAL_MEDIA_PATH),
5791
- optimizer: new R()
5755
+ optimizer: new ne()
5792
5756
  };
5793
5757
  }
5794
- function ae(e) {
5758
+ function R(e) {
5795
5759
  if (!e || typeof e != "object") return {
5796
5760
  cleanedData: e,
5797
5761
  assetRefs: []
@@ -5867,7 +5831,7 @@ function z(e) {
5867
5831
  }
5868
5832
  return null;
5869
5833
  }
5870
- async function se(e, t) {
5834
+ async function B(e, t) {
5871
5835
  if (!t || typeof t != "object") return t;
5872
5836
  let n = /* @__PURE__ */ new Set(), r = (e) => {
5873
5837
  if (!e) return;
@@ -5978,7 +5942,7 @@ async function se(e, t) {
5978
5942
  };
5979
5943
  return d(t);
5980
5944
  }
5981
- function ce(e) {
5945
+ function se(e) {
5982
5946
  return e ? {
5983
5947
  nodes: e.nodes || {},
5984
5948
  trees: e.trees || {},
@@ -5995,7 +5959,7 @@ function ce(e) {
5995
5959
  channels: {}
5996
5960
  };
5997
5961
  }
5998
- var B = class {
5962
+ var V = class {
5999
5963
  env;
6000
5964
  constructor(e) {
6001
5965
  this.env = e || {};
@@ -6007,7 +5971,8 @@ var B = class {
6007
5971
  apiToken: e.env?.CLOUDFLARE_API_TOKEN || this.env.CLOUDFLARE_API_TOKEN,
6008
5972
  frontendUrl: (e.env?.PUBLIC_FRONTEND_URL || this.env.PUBLIC_FRONTEND_URL || "http://localhost:4321").replace(/\/+$/, ""),
6009
5973
  cdnDomain: t ? t.replace(/^https?:\/\//, "").replace(/\/+$/, "") : "localhost:8787",
6010
- frontendWorker: e.env?.FRONTEND_WORKER || this.env.FRONTEND_WORKER
5974
+ frontendWorker: e.env?.FRONTEND_WORKER || this.env.FRONTEND_WORKER,
5975
+ disableCachePurge: e.env?.DISABLE_CACHE_PURGE || this.env.DISABLE_CACHE_PURGE
6011
5976
  };
6012
5977
  }
6013
5978
  isLocalEnv(e, t) {
@@ -6031,19 +5996,33 @@ var B = class {
6031
5996
  return r && n && r.startsWith(`https://${n}/`) && !r.includes("/media/") && (r = r.replace(`https://${n}/`, `https://${n}/media/`)), r;
6032
5997
  }
6033
5998
  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
- });
5999
+ let { apiToken: r, frontendUrl: i, frontendWorker: a, disableCachePurge: o } = this.getEnv(e);
6000
+ if (o === "true" || o === !0 || o === "1") return new Response(JSON.stringify({ skipped: !0 }), { status: 200 });
6001
+ let s = (n || i).replace(/\/+$/, ""), c = `${s}/api/purge`, l = { "Content-Type": "application/json" };
6002
+ if (r && (l.Authorization = `Bearer ${r}`), a && typeof a.fetch == "function") try {
6003
+ return await a.fetch(new Request(c, {
6004
+ method: "POST",
6005
+ headers: l,
6006
+ body: JSON.stringify(t)
6007
+ }));
6008
+ } catch (e) {
6009
+ return console.info(`[CacheManager] Worker binding purge call to ${c} failed silently:`, e?.message || e), new Response(JSON.stringify({ error: e?.message }), { status: 502 });
6010
+ }
6011
+ try {
6012
+ let e = new AbortController(), n = setTimeout(() => e.abort(), 1500);
6013
+ console.log(`[CacheManager] Dispatching POST purge request to: ${c}`);
6014
+ let r = await fetch(c, {
6015
+ method: "POST",
6016
+ headers: l,
6017
+ body: JSON.stringify(t),
6018
+ signal: e.signal
6019
+ });
6020
+ return clearTimeout(n), r;
6021
+ } catch (e) {
6022
+ 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 });
6023
+ }
6045
6024
  }
6046
- async purgeInternalWorkerCache(e, t, n, r, i = "en") {
6025
+ async purgeInternalWorkerCache(e, t, n, r, i) {
6047
6026
  try {
6048
6027
  let a = I(e);
6049
6028
  if (n) {
@@ -6056,7 +6035,7 @@ var B = class {
6056
6035
  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
6036
  i.length > 0 && (o = i.flatMap((e) => [String(e.id), e.key]).filter(Boolean));
6058
6037
  }
6059
- for (let t of o) await a.delete(`node:${t}:${i}:${e}`), await a.delete(`node:${t}:${i}:/${e}`);
6038
+ 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
6039
  }
6061
6040
  } catch (e) {
6062
6041
  console.warn("[CacheManager] Failed to purge internal worker cache:", e);
@@ -6067,30 +6046,30 @@ var B = class {
6067
6046
  try {
6068
6047
  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
6048
  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() !== "") {
6049
+ 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();
6050
+ for (let e of c) if (e.baseUrl && typeof e.baseUrl == "string" && e.baseUrl.trim() !== "") {
6072
6051
  let t = e.baseUrl.trim();
6073
- !t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), f.add(t.replace(/\/+$/, ""));
6052
+ !t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), p.add(t.replace(/\/+$/, ""));
6074
6053
  }
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`, {
6054
+ p.size === 0 && f && p.add(f);
6055
+ 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);
6056
+ await this.purgeInternalWorkerCache(e, t, n, d, u);
6057
+ let _ = this.getEnv(e).cdnDomain, { zoneId: v, apiToken: y } = this.getEnv(e);
6058
+ for (let t of p) {
6059
+ let n = d === "home" || !d ? t : `${t}/${d}`, i = [n, `${n}/`], a = u ? `&lang=${u}` : "";
6060
+ 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}`);
6061
+ else i.push(`https://${_}/api/v1/node/${d}${u ? `?lang=${u}` : ""}`);
6062
+ for (let e of g) e && i.push(`${t}${e.startsWith("/") ? e : `/${e}`}`);
6063
+ 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
6064
  method: "POST",
6086
6065
  headers: {
6087
- Authorization: `Bearer ${v}`,
6066
+ Authorization: `Bearer ${y}`,
6088
6067
  "Content-Type": "application/json"
6089
6068
  },
6090
6069
  body: JSON.stringify({ files: i })
6091
6070
  }).catch(() => {}), !r) {
6092
6071
  let e = `${n}${n.includes("?") ? "&" : "?"} _warmer=${Date.now()}`;
6093
- console.log(`[CacheManager] Prewarming cache at: ${e}`), await fetch(e, { headers: {
6072
+ console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
6094
6073
  "X-Cache-Warmer": "true",
6095
6074
  "User-Agent": "Kama-Cache-Warmer/1.0"
6096
6075
  } }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
@@ -6119,35 +6098,49 @@ var B = class {
6119
6098
  }
6120
6099
  async purgeGlobalCacheDirect(e, t) {
6121
6100
  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`, {
6101
+ let { zoneId: n, apiToken: r } = this.getEnv(e);
6102
+ if (!(await this.callAstroPurge(e, { purge_everything: !0 })).ok) return;
6103
+ if (n && r && !this.isLocalEnv(e) && fetch(`https://api.cloudflare.com/client/v4/zones/${n}/purge_cache`, {
6125
6104
  method: "POST",
6126
6105
  headers: {
6127
6106
  Authorization: `Bearer ${r}`,
6128
6107
  "Content-Type": "application/json"
6129
6108
  },
6130
6109
  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(() => {});
6110
+ }).catch(() => {}), await new Promise((e) => setTimeout(e, 100)), t) await this.warmAllPublishedPages(e, t);
6111
+ else {
6112
+ let { frontendUrl: t } = this.getEnv(e);
6113
+ fetch(`${t.replace(/\/+$/, "")}/?_warmer=${Date.now()}`, { headers: { "X-Cache-Warmer": "true" } }).catch(() => {});
6114
+ }
6132
6115
  } catch (e) {
6133
6116
  console.warn("[CacheManager] Direct Global Purge skipped:", e);
6134
6117
  }
6135
6118
  }
6136
6119
  async warmAllPublishedPages(e, t) {
6137
6120
  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);
6121
+ 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 = {
6122
+ "X-Cache-Warmer": "true",
6123
+ "User-Agent": "Kama-Cache-Warmer/1.0"
6124
+ }, s = Date.now(), c = /* @__PURE__ */ new Set();
6125
+ for (let e of i) {
6126
+ let t = String(e.slug).replace(/^\/+|\/+$/g, ""), n = a;
6127
+ 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(/\/+$/, ""));
6128
+ let r = t === "home" || !t ? n : `${n}/${t}`;
6129
+ c.add(`${r}?_warmer=${s}`);
6130
+ }
6131
+ c.add(`${a}/?_warmer=${s}`);
6132
+ let l = Array.from(c);
6133
+ for (let e = 0; e < l.length; e += 6) {
6134
+ let t = l.slice(e, e + 6);
6135
+ await Promise.all(t.map((e) => fetch(e, { headers: o }).catch((t) => console.warn(`[CacheWarmer] Skipped prewarm for ${e}:`, t?.message || t))));
6136
+ }
6137
+ console.log(`[CacheWarmer] Prewarmed ${l.length} published pages across ${Math.ceil(l.length / 6)} batches.`);
6145
6138
  } catch (e) {
6146
6139
  console.warn("⚠️ [CacheWarmer] Tree-wide warming failed:", e);
6147
6140
  }
6148
6141
  }
6149
- }, V = new e();
6150
- async function le(e, t, n = []) {
6142
+ }, H = new e();
6143
+ async function ce(e, t, n = []) {
6151
6144
  let r = e.prepare(t);
6152
6145
  if (typeof r.bind == "function") {
6153
6146
  let e = await r.bind(...n).all();
@@ -6159,24 +6152,25 @@ async function le(e, t, n = []) {
6159
6152
  }
6160
6153
  return [];
6161
6154
  }
6162
- async function ue(e, t, n = []) {
6155
+ async function le(e, t, n = []) {
6163
6156
  let r = e.prepare(t);
6164
6157
  if (typeof r.bind == "function") return r.bind(...n).run();
6165
6158
  if (typeof r.run == "function") return r.run(...n);
6166
6159
  }
6167
- function de(e) {
6160
+ function U(e) {
6168
6161
  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
6162
  }
6170
- function fe(e) {
6163
+ function ue(e) {
6171
6164
  return +(e === !0 || e === 1 || e === "1" || e === "true");
6172
6165
  }
6173
- function pe(e) {
6166
+ function de(e) {
6174
6167
  if (e == null || e === "null" || e === "" || typeof e == "string" && e.startsWith("draft-")) return null;
6175
6168
  let t = Number(e);
6176
6169
  return isNaN(t) ? null : t;
6177
6170
  }
6178
- function H(e) {
6171
+ function fe(e) {
6179
6172
  let t = { ...e };
6173
+ delete t.language, delete t.defaultLanguage;
6180
6174
  for (let e of [
6181
6175
  "id",
6182
6176
  "treeNodeId",
@@ -6187,7 +6181,6 @@ function H(e) {
6187
6181
  "contentType",
6188
6182
  "title",
6189
6183
  "slug",
6190
- "language",
6191
6184
  "hidden",
6192
6185
  "is_hidden",
6193
6186
  "isHidden",
@@ -6204,17 +6197,22 @@ function H(e) {
6204
6197
  ]) delete t[e];
6205
6198
  return t;
6206
6199
  }
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;
6200
+ function pe(e, t = /* @__PURE__ */ new Set()) {
6201
+ 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
6202
  }
6210
- async function U(e, t, n) {
6203
+ function me(e, t) {
6204
+ if (!e) return !0;
6205
+ 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;
6206
+ return n || r || i || a || c;
6207
+ }
6208
+ async function he(e, t, n) {
6211
6209
  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;
6210
+ let n = (await ce(e, "\n SELECT id, storageKeyPrivate, isSystemVariant, parentAssetId, filename\n FROM assets WHERE id = ?\n ", [r]))[0];
6211
+ if (!n || (await ce(e, "SELECT 1 FROM node_assets WHERE assetId = ? LIMIT 1", [n.id])).length > 0) continue;
6214
6212
  let i = [n];
6215
6213
  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;
6214
+ 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);
6215
+ if (r.length > 0 && (await ce(e, `SELECT DISTINCT assetId FROM node_assets WHERE assetId IN (${r.map(() => "?").join(",")})`, r)).length > 0) continue;
6218
6216
  i = [n, ...t];
6219
6217
  }
6220
6218
  for (let e of i) if (e.storageKeyPrivate) try {
@@ -6223,10 +6221,10 @@ async function U(e, t, n) {
6223
6221
  console.warn(`[Asset Cleanup] Failed to delete ${e.storageKeyPrivate}:`, t);
6224
6222
  }
6225
6223
  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);
6224
+ await le(e, `DELETE FROM node_assets WHERE assetId IN (${o})`, a), await le(e, `DELETE FROM assets WHERE id IN (${o})`, a);
6227
6225
  }
6228
6226
  }
6229
- async function W(e, t, n) {
6227
+ async function ge(e, t, n) {
6230
6228
  let r = {}, i = null;
6231
6229
  if (t) {
6232
6230
  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 +6238,7 @@ async function W(e, t, n) {
6240
6238
  }
6241
6239
  }
6242
6240
  if (!i) {
6243
- let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ?").get(n);
6241
+ let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ? OR key = ? LIMIT 1").get(Number(n) || -1, String(n));
6244
6242
  if (t && t.dataJson) try {
6245
6243
  let e = typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson;
6246
6244
  e.subpageLayoutId && e.subpageLayoutId !== "inherit" && (i = e.subpageLayoutId);
@@ -6251,7 +6249,7 @@ async function W(e, t, n) {
6251
6249
  inheritedFields: r
6252
6250
  };
6253
6251
  }
6254
- V.get("/", async (e) => {
6252
+ H.get("/", async (e) => {
6255
6253
  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
6254
  if (n) {
6257
6255
  let r = Number(n);
@@ -6262,7 +6260,7 @@ V.get("/", async (e) => {
6262
6260
  id: i.id,
6263
6261
  title: i.title,
6264
6262
  slug: i.slug,
6265
- language: i.language || "en",
6263
+ language: i.language || null,
6266
6264
  nodeType: i.contentType,
6267
6265
  contentType: i.contentType,
6268
6266
  isHidden: !!i.isHidden,
@@ -6276,9 +6274,9 @@ V.get("/", async (e) => {
6276
6274
  updatedAt: i.updatedAt
6277
6275
  }, s = i.draftDataJson || i.dataJson;
6278
6276
  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;
6277
+ 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
6278
  if (a) {
6281
- let { resolvedLayoutId: e, inheritedFields: r } = await W(t, a.parentId, a.treeId);
6279
+ let { resolvedLayoutId: e, inheritedFields: r } = await ge(t, a.parentId, a.treeId);
6282
6280
  (l === "inherit" || !l) && (l = e);
6283
6281
  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
6282
  }
@@ -6293,7 +6291,7 @@ V.get("/", async (e) => {
6293
6291
  let r = t.allowedLayouts;
6294
6292
  return r ? typeof r == "string" ? r === e : !Array.isArray(r) || r.length === 0 || r.includes(e) : !0;
6295
6293
  })(l) && (l = null), (l === "inherit" || !l) && (l = c.defaultLayout || null);
6296
- let u = await se(t, H(n));
6294
+ let u = await B(t, fe(n));
6297
6295
  Object.assign(o, u), o.resolvedLayoutId = l;
6298
6296
  } catch {}
6299
6297
  let c = await t.prepare("SELECT channelId FROM node_channels WHERE nodeId = ?").all(r);
@@ -6303,7 +6301,7 @@ V.get("/", async (e) => {
6303
6301
  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
6302
  let n = {};
6305
6303
  try {
6306
- n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson || "{}") : e.dataJson || {}, n && typeof n == "object" && (n = await se(t, n));
6304
+ n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson || "{}") : e.dataJson || {}, n && typeof n == "object" && (n = await B(t, n));
6307
6305
  } catch {
6308
6306
  n = {};
6309
6307
  }
@@ -6374,7 +6372,7 @@ V.get("/", async (e) => {
6374
6372
  id: e.id,
6375
6373
  title: e.title,
6376
6374
  slug: e.slug,
6377
- language: e.language || "en",
6375
+ language: e.language || null,
6378
6376
  contentType: e.contentType,
6379
6377
  nodeType: e.contentType,
6380
6378
  isHidden: !!e.isHidden,
@@ -6391,7 +6389,7 @@ V.get("/", async (e) => {
6391
6389
  assetCount: e.assetCount || 0
6392
6390
  }, i = e.draftDataJson || e.dataJson;
6393
6391
  if (i) try {
6394
- let e = typeof i == "string" ? JSON.parse(i) : i, n = await se(t, H(e));
6392
+ let e = typeof i == "string" ? JSON.parse(i) : i, n = await B(t, fe(e));
6395
6393
  Object.assign(r, n);
6396
6394
  } catch {}
6397
6395
  return r;
@@ -6403,13 +6401,35 @@ V.get("/", async (e) => {
6403
6401
  offset: p,
6404
6402
  limit: f
6405
6403
  });
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) {
6404
+ }), H.post("/", async (e) => {
6405
+ 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;
6406
+ if (T) {
6407
+ let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ? OR key = ? LIMIT 1").get(Number(T) || -1, String(T));
6408
+ if (e?.dataJson) try {
6409
+ let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
6410
+ E = t.defaultLanguage?.trim() || t.language?.trim() || null;
6411
+ } catch {}
6412
+ }
6413
+ if (!E && h && Array.isArray(h) && h.length > 0) {
6414
+ let e = typeof h[0] == "object" ? h[0].id : h[0];
6415
+ if (e && e !== "all") {
6416
+ let n = await t.prepare("SELECT defaultLanguage, dataJson FROM channels WHERE id = ? LIMIT 1").get(Number(e));
6417
+ if (n) {
6418
+ if (n.defaultLanguage) E = n.defaultLanguage.trim();
6419
+ else if (n.dataJson) try {
6420
+ let e = typeof n.dataJson == "string" ? JSON.parse(n.dataJson) : n.dataJson;
6421
+ E = e.defaultLanguage?.trim() || e.language?.trim() || null;
6422
+ } catch {}
6423
+ }
6424
+ }
6425
+ }
6426
+ C && E && C === E && (C = null);
6427
+ let D = a, O = /* @__PURE__ */ new Set(), k = !1, A = s === void 0 ? null : U(s);
6428
+ if (A) {
6409
6429
  let n = [];
6410
6430
  if (g !== void 0 && Array.isArray(g) && g.length > 0) for (let e of g) n.push({
6411
6431
  treeId: Number(e.treeId),
6412
- parentId: pe(e.parentId ?? e._draftParentId ?? null)
6432
+ parentId: de(e.parentId ?? e._draftParentId ?? null)
6413
6433
  });
6414
6434
  else if (a) {
6415
6435
  let e = await t.prepare("SELECT treeId, parentId FROM tree_nodes WHERE contentId = ?").all(a), r = Array.isArray(e) ? e : e?.results || [];
@@ -6419,94 +6439,103 @@ V.get("/", async (e) => {
6419
6439
  });
6420
6440
  }
6421
6441
  for (let r of n) {
6422
- let n = r.parentId === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = r.parentId === null ? [r.treeId, E] : [
6442
+ let n = r.parentId === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = r.parentId === null ? [r.treeId, A] : [
6423
6443
  r.treeId,
6424
6444
  r.parentId,
6425
- E
6445
+ A
6426
6446
  ], o = `
6427
6447
  SELECT cn.id FROM tree_nodes tn
6428
6448
  INNER JOIN content_nodes cn ON tn.contentId = cn.id
6429
6449
  WHERE tn.treeId = ? AND ${n} AND cn.slug = ? AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
6430
6450
  `;
6431
6451
  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.`,
6452
+ error: `The slug '${A}' is already in use by another page in this section.`,
6433
6453
  field: "slug"
6434
6454
  }, 409);
6435
6455
  }
6436
6456
  }
6437
6457
  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 || "{}";
6458
+ let e = await t.prepare("SELECT title, slug, language, contentType, isHidden, draftDataJson, dataJson, publishedAt, status FROM content_nodes WHERE id = ?").get(a);
6459
+ k = me(e, {
6460
+ title: o,
6461
+ slug: A,
6462
+ isHidden: b,
6463
+ sanitizedFields: v
6464
+ });
6465
+ let n = e?.draftDataJson || e?.dataJson || "{}";
6439
6466
  try {
6440
- me(typeof n == "string" ? JSON.parse(n) : n, T);
6467
+ pe(typeof n == "string" ? JSON.parse(n) : n, O);
6441
6468
  } catch {}
6442
6469
  if (m !== void 0) {
6443
6470
  let e = await t.prepare("SELECT dataJson FROM content_blocks WHERE contentId = ? AND isDraft = 1").all(a);
6444
6471
  (Array.isArray(e) ? e : e?.results || []).forEach((e) => {
6445
6472
  try {
6446
- me(typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson, T);
6473
+ pe(typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson, O);
6447
6474
  } catch {}
6448
6475
  });
6449
6476
  }
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 = {};
6477
+ 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
6478
  try {
6452
- u = JSON.parse(l);
6479
+ d = JSON.parse(u);
6453
6480
  } catch {}
6454
- let d = JSON.stringify({
6455
- ...u,
6481
+ let f = JSON.stringify({
6482
+ ...d,
6456
6483
  ...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);
6484
+ }), p = e?.status === "published" || e?.publishedAt ? "published" : "draft", h = +(p === "published");
6485
+ 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
6486
  } 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);
6487
+ k = !0;
6488
+ 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);
6489
+ D = Number(e.lastInsertRowid);
6462
6490
  }
6463
- if (h !== void 0 && Array.isArray(h) && w) {
6464
- await t.prepare("DELETE FROM node_channels WHERE nodeId = ?").run(w);
6491
+ if (h !== void 0 && Array.isArray(h) && D) {
6492
+ await t.prepare("DELETE FROM node_channels WHERE nodeId = ?").run(D);
6465
6493
  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
6494
  if (e.length > 0) {
6467
- let n = e.map(() => "(?, ?)").join(", "), r = e.flatMap((e) => [w, e]);
6495
+ let n = e.map(() => "(?, ?)").join(", "), r = e.flatMap((e) => [D, e]);
6468
6496
  await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${n}`).run(...r);
6469
6497
  }
6470
6498
  }
6471
- if (g !== void 0 && Array.isArray(g) && g.length > 0 && w) for (let e of g) {
6499
+ if (g !== void 0 && Array.isArray(g) && g.length > 0 && D) for (let e of g) {
6472
6500
  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);
6501
+ 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);
6502
+ 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
6503
  }
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);
6504
+ let j = [];
6505
+ if (m !== void 0 && Array.isArray(m) && D) {
6506
+ await t.prepare("DELETE FROM content_blocks WHERE contentId = ? AND isDraft = 1").run(D);
6479
6507
  let e = [], n = [];
6480
6508
  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({
6509
+ 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
6510
  ...a,
6483
6511
  blockId: o,
6484
6512
  _instanceId: o
6485
6513
  });
6486
- c.forEach((e) => D.push({
6514
+ c.forEach((e) => j.push({
6487
6515
  ...e,
6488
6516
  fieldKey: `blocks[${t}].${e.fieldKey}`
6489
6517
  }));
6490
6518
  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);
6519
+ e.push("(?, ?, ?, ?, ?, 1)"), n.push(D, t, i, JSON.stringify(s), l);
6492
6520
  }
6493
6521
  e.length > 0 && await t.prepare(`INSERT INTO content_blocks (contentId, sortOrder, elementType, dataJson, region, isDraft) VALUES ${e.join(", ")}`).run(...n);
6494
6522
  }
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)));
6523
+ if (D) {
6524
+ let n = [...y, ...j];
6525
+ await oe(t, D, n);
6526
+ let r = new Set(n.map((e) => e.assetId)), i = new Set([...O].filter((e) => !r.has(e)));
6499
6527
  if (i.size > 0) {
6500
- let { storage: n } = ie(e.env);
6501
- await U(t, n, i);
6528
+ let { storage: n } = ae(e.env);
6529
+ await he(t, n, i);
6502
6530
  }
6503
6531
  }
6504
- return await I(e).clear(), e.json({
6532
+ return await I(e).clear(), D && new V(e.env).purgeNode(e, t, D, k), e.json({
6505
6533
  success: !0,
6506
- id: w,
6507
- status: "draft"
6534
+ id: D,
6535
+ status: "draft",
6536
+ isStructuralChange: k
6508
6537
  });
6509
- }), V.post("/publish", async (e) => {
6538
+ }), H.post("/publish", async (e) => {
6510
6539
  let t = e.get("db"), n = await e.req.json(), r = n.id || n.nodeId;
6511
6540
  if (!r || isNaN(Number(r))) return e.json({ error: "Node ID required for publishing" }, 400);
6512
6541
  let i = Number(r), a = e.get("user")?.id || null, o = await t.prepare("SELECT * FROM content_nodes WHERE id = ?").get(i);
@@ -6519,57 +6548,58 @@ V.get("/", async (e) => {
6519
6548
  try {
6520
6549
  c = typeof o.draftDataJson == "string" ? JSON.parse(o.draftDataJson) : o.draftDataJson || {};
6521
6550
  } 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) {
6551
+ 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 || "{}";
6552
+ 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);
6553
+ let _ = await t.prepare("SELECT * FROM content_blocks WHERE contentId = ? AND isDraft = 1 ORDER BY sortOrder ASC").all(i), v = Array.isArray(_) ? _ : _?.results || [];
6554
+ if (v.length > 0) {
6526
6555
  let e = [], n = [];
6527
- for (let t of g) {
6556
+ for (let t of v) {
6528
6557
  let r = t.region !== void 0 && t.region !== null && String(t.region).trim() !== "" ? String(t.region) : "content";
6529
6558
  e.push("(?, ?, ?, ?, ?, 0)"), n.push(i, t.sortOrder, t.elementType, t.dataJson, r);
6530
6559
  }
6531
6560
  await t.prepare(`INSERT INTO content_blocks (contentId, sortOrder, elementType, dataJson, region, isDraft) VALUES ${e.join(", ")}`).run(...n);
6532
6561
  }
6533
- let _ = ((await t.prepare("SELECT COUNT(*) as count FROM node_revisions WHERE nodeId = ?").get(i))?.count || 0) + 1, v = {
6534
- version: _,
6562
+ let y = ((await t.prepare("SELECT COUNT(*) as count FROM node_revisions WHERE nodeId = ?").get(i))?.count || 0) + 1, b = {
6563
+ version: y,
6535
6564
  publishedAt: (/* @__PURE__ */ new Date()).toISOString(),
6536
6565
  node: {
6537
6566
  ...o,
6538
- dataJson: m
6567
+ dataJson: g
6539
6568
  },
6540
- blocks: g
6569
+ blocks: v
6541
6570
  };
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({
6571
+ 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
6572
  success: !0,
6544
6573
  id: i,
6545
6574
  status: "published",
6546
- version: _,
6547
- publishedAt: v.publishedAt,
6548
- hasUnpublishedChanges: !1
6575
+ version: y,
6576
+ publishedAt: b.publishedAt,
6577
+ hasUnpublishedChanges: !1,
6578
+ isStructuralChange: h
6549
6579
  });
6550
- }), V.delete("/", async (e) => {
6580
+ }), H.delete("/", async (e) => {
6551
6581
  let t = e.get("db"), n = e.req.query("id");
6552
6582
  if (!n) return e.json({ error: "Node ID required" }, 400);
6553
6583
  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({
6584
+ 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
6585
  success: !0,
6556
6586
  deletedNodeId: r
6557
6587
  });
6558
- }), V.post("/restore", async (e) => {
6588
+ }), H.post("/restore", async (e) => {
6559
6589
  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({
6590
+ 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
6591
  success: !0,
6562
6592
  restoredNodeId: r
6563
6593
  })) : e.json({ error: "Node not found" }, 404) : e.json({ error: "Node ID required" }, 400);
6564
- }), V.delete("/purge", async (e) => {
6594
+ }), H.delete("/purge", async (e) => {
6565
6595
  let t = e.get("db"), n = e.req.query("id");
6566
6596
  if (!n) return e.json({ error: "Node ID required" }, 400);
6567
6597
  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({
6598
+ 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
6599
  success: !0,
6570
6600
  purgedNodeId: r
6571
6601
  });
6572
- }), V.get("/:id/revisions", async (e) => {
6602
+ }), H.get("/:id/revisions", async (e) => {
6573
6603
  let t = e.get("db"), n = Number(e.req.param("id"));
6574
6604
  if (isNaN(n)) return e.json({ error: "Invalid Node ID" }, 400);
6575
6605
  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 +6615,7 @@ V.get("/", async (e) => {
6585
6615
  };
6586
6616
  });
6587
6617
  return e.json({ revisions: i });
6588
- }), V.get("/:id/revisions/:version", async (e) => {
6618
+ }), H.get("/:id/revisions/:version", async (e) => {
6589
6619
  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
6620
  if (!i) return e.json({ error: "Snapshot not found" }, 404);
6591
6621
  let a = {};
@@ -6595,7 +6625,7 @@ V.get("/", async (e) => {
6595
6625
  return e.json({ error: "Corrupt snapshot data" }, 500);
6596
6626
  }
6597
6627
  return e.json({ snapshot: a });
6598
- }), V.post("/:id/revisions/:version/restore", async (e) => {
6628
+ }), H.post("/:id/revisions/:version/restore", async (e) => {
6599
6629
  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
6630
  if (!a) return e.json({ error: "Snapshot not found" }, 404);
6601
6631
  let o = {};
@@ -6614,8 +6644,8 @@ V.get("/", async (e) => {
6614
6644
  restoredVersion: r
6615
6645
  });
6616
6646
  });
6617
- var G = new e();
6618
- function he(e, t = null) {
6647
+ var W = new e();
6648
+ function _e(e, t = null) {
6619
6649
  let n = [];
6620
6650
  for (let r = 0; r < e.length; r++) {
6621
6651
  let i = e[r];
@@ -6627,19 +6657,19 @@ function he(e, t = null) {
6627
6657
  id: o,
6628
6658
  parentId: t,
6629
6659
  sortOrder: r
6630
- }), i.children && Array.isArray(i.children) && i.children.length > 0 && n.push(...he(i.children, o)));
6660
+ }), i.children && Array.isArray(i.children) && i.children.length > 0 && n.push(..._e(i.children, o)));
6631
6661
  }
6632
6662
  return n;
6633
6663
  }
6634
- function ge(e) {
6664
+ function G(e) {
6635
6665
  if (e == null || e === "null" || e === "" || typeof e == "string" && e.startsWith("draft-")) return null;
6636
6666
  let t = Number(e);
6637
6667
  return isNaN(t) ? null : t;
6638
6668
  }
6639
- function _e(e) {
6669
+ function ve(e) {
6640
6670
  return +(e === !0 || e === 1 || e === "1" || e === "true");
6641
6671
  }
6642
- G.get("/tree.json", async (e) => {
6672
+ W.get("/tree.json", async (e) => {
6643
6673
  try {
6644
6674
  let t = e.get("db"), n = e.req.query("treeId") || "main-nav", r = e.req.query("preview") === "true", i = 1;
6645
6675
  if (isNaN(Number(n))) {
@@ -6674,7 +6704,7 @@ G.get("/tree.json", async (e) => {
6674
6704
  id: e.contentId,
6675
6705
  treeNodeId: e.treeNodeId,
6676
6706
  parentId: e.parentId || null,
6677
- language: e.language || "en",
6707
+ language: e.language?.trim() || null,
6678
6708
  hidden: +!!s,
6679
6709
  isHidden: s,
6680
6710
  status: e.status || "draft",
@@ -6689,9 +6719,9 @@ G.get("/tree.json", async (e) => {
6689
6719
  } catch (t) {
6690
6720
  return console.error("[CMS Tree API] GET Error:", t), e.json({ error: t.message || "Failed to fetch tree" }, 500);
6691
6721
  }
6692
- }), G.post("/tree.json", async (e) => {
6722
+ }), W.post("/tree.json", async (e) => {
6693
6723
  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;
6724
+ 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
6725
  if (isNaN(Number(r))) {
6696
6726
  let e = await t.prepare("SELECT id FROM trees WHERE key = ?").get(r);
6697
6727
  if (e && e.id) o = Number(e.id);
@@ -6701,7 +6731,7 @@ G.get("/tree.json", async (e) => {
6701
6731
  }
6702
6732
  } else o = Number(r);
6703
6733
  if (n.tree && Array.isArray(n.tree)) {
6704
- let r = he(n.tree, null);
6734
+ let r = _e(n.tree, null);
6705
6735
  if (r.length > 0) for (let e = 0; e < r.length; e += 50) {
6706
6736
  let n = r.slice(e, e + 50), i = n.map((e) => e.id), a = i.map(() => "?").join(","), s = "UPDATE tree_nodes SET \n";
6707
6737
  s += "parentId = CASE id \n", n.forEach(() => {
@@ -6721,9 +6751,9 @@ G.get("/tree.json", async (e) => {
6721
6751
  reorderedCount: r.length
6722
6752
  });
6723
6753
  }
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);
6754
+ 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
6755
  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;
6756
+ let g = G(u), _ = e.get("user")?.id || null;
6727
6757
  if (s === "create") {
6728
6758
  let r = m.slug || n.slug || c, s = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
6729
6759
  if (s) {
@@ -6745,23 +6775,41 @@ G.get("/tree.json", async (e) => {
6745
6775
  field: "slug"
6746
6776
  }, 409);
6747
6777
  }
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(`
6778
+ let u = m.language?.trim() || n.language?.trim() || null;
6779
+ if (!u) {
6780
+ let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ?").get(o);
6781
+ if (e?.dataJson) try {
6782
+ let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
6783
+ t.defaultLanguage && (u = t.defaultLanguage.trim());
6784
+ } catch {}
6785
+ }
6786
+ if (!u) {
6787
+ let e = [];
6788
+ if (n.channels && Array.isArray(n.channels) ? e = n.channels : n.channelId && n.channelId !== "all" && (e = [n.channelId]), e.length > 0) {
6789
+ let n = Number(e[0]);
6790
+ if (!isNaN(n)) {
6791
+ let e = await t.prepare("SELECT defaultLanguage FROM channels WHERE id = ?").get(n);
6792
+ e?.defaultLanguage && (u = e.defaultLanguage.trim());
6793
+ }
6794
+ }
6795
+ }
6796
+ 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);
6797
+ await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, p);
6798
+ let v = g === null ? "parentId IS NULL" : "parentId = ?", y = g === null ? [o] : [o, g], b = (await t.prepare(`
6751
6799
  SELECT COALESCE(MAX(sortOrder), -1) + 1 as nextSort
6752
6800
  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]);
6801
+ WHERE treeId = ? AND ${v}
6802
+ `).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 = [];
6803
+ n.channels && Array.isArray(n.channels) ? C = n.channels : n.channelId && n.channelId !== "all" && (C = [n.channelId]);
6804
+ let w = [...new Set(C)].filter((e) => e && e !== "all").map((e) => Number(e));
6805
+ if (w.length > 0) {
6806
+ let e = w.map(() => "(?, ?)").join(", "), n = w.flatMap((e) => [p, e]);
6759
6807
  await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...n);
6760
6808
  }
6761
6809
  return await i.clear(), a.purgeGlobalCache(e, t), e.json({
6762
6810
  success: !0,
6763
- id: f,
6764
- treeNodeId: x,
6811
+ id: p,
6812
+ treeNodeId: S,
6765
6813
  status: "draft"
6766
6814
  }, 201);
6767
6815
  }
@@ -6812,7 +6860,7 @@ G.get("/tree.json", async (e) => {
6812
6860
  details: t.message
6813
6861
  }, 500);
6814
6862
  }
6815
- }), G.get("/trees.json", async (e) => {
6863
+ }), W.get("/trees.json", async (e) => {
6816
6864
  try {
6817
6865
  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
6866
  let n = Number(t.treeId), r = Number(t.channelId);
@@ -6842,7 +6890,7 @@ G.get("/tree.json", async (e) => {
6842
6890
  } catch {
6843
6891
  return e.json([]);
6844
6892
  }
6845
- }), G.post("/trees.json", async (e) => {
6893
+ }), W.post("/trees.json", async (e) => {
6846
6894
  try {
6847
6895
  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
6896
  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 +6915,7 @@ G.get("/tree.json", async (e) => {
6867
6915
  await t.prepare(`INSERT OR IGNORE INTO channel_trees (channelId, treeId, key) VALUES ${n}`).run(...r);
6868
6916
  }
6869
6917
  }
6870
- return await I(e).clear(), new B(e.env).purgeGlobalCache(e, t), e.json({
6918
+ return await I(e).clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
6871
6919
  success: !0,
6872
6920
  id: p,
6873
6921
  key: o,
@@ -6881,12 +6929,12 @@ G.get("/tree.json", async (e) => {
6881
6929
  } catch (t) {
6882
6930
  return console.error("[API Trees] Error saving tree:", t), e.json({ error: t.message || "Failed to save tree" }, 500);
6883
6931
  }
6884
- }), G.delete("/trees.json", async (e) => {
6932
+ }), W.delete("/trees.json", async (e) => {
6885
6933
  let t = e.get("db"), n = e.req.query("id");
6886
6934
  if (!n) return e.json({ error: "Tree ID required" }, 400);
6887
6935
  let r = Number(n);
6888
6936
  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({
6937
+ 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
6938
  success: !0,
6891
6939
  deletedTreeId: r
6892
6940
  });
@@ -6894,8 +6942,8 @@ G.get("/tree.json", async (e) => {
6894
6942
  return e.json({ error: "Failed to delete tree" }, 500);
6895
6943
  }
6896
6944
  });
6897
- var ve = new e();
6898
- ve.get("/", async (e) => {
6945
+ var ye = new e();
6946
+ ye.get("/", async (e) => {
6899
6947
  try {
6900
6948
  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
6949
  e[t.channelId] || (e[t.channelId] = []);
@@ -6919,7 +6967,7 @@ ve.get("/", async (e) => {
6919
6967
  isHidden: !!e.isHidden,
6920
6968
  trees: a[e.id] || []
6921
6969
  };
6922
- }), s = e.env?.BUNDLED_DEFINITIONS, c = ce(s)?.channelTemplate || {
6970
+ }), s = e.env?.BUNDLED_DEFINITIONS, c = se(s), l = c?.channelTemplate || Object.values(c?.channels || {})[0] || {
6923
6971
  label: "Channel Settings",
6924
6972
  fields: {
6925
6973
  key: {
@@ -6951,7 +6999,7 @@ ve.get("/", async (e) => {
6951
6999
  }
6952
7000
  };
6953
7001
  return e.json({
6954
- schema: c,
7002
+ schema: l,
6955
7003
  channels: o
6956
7004
  });
6957
7005
  } catch (t) {
@@ -6961,24 +7009,26 @@ ve.get("/", async (e) => {
6961
7009
  error: t.message
6962
7010
  }, 500);
6963
7011
  }
6964
- }), ve.post("/", async (e) => {
7012
+ }), ye.post("/", async (e) => {
6965
7013
  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.`,
7014
+ 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 || "";
7015
+ typeof T == "object" && T && (T = T.value || T.id || ""), T = String(T).trim();
7016
+ 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;
7017
+ if (await t.prepare("SELECT id FROM channels WHERE key = ? AND id != ? LIMIT 1").get(C, a ?? -1)) return e.json({
7018
+ error: `Channel API key "${C}" is already in use.`,
6969
7019
  field: "key"
6970
7020
  }, 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);
7021
+ let A = a;
7022
+ 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
7023
  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);
7024
+ 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);
7025
+ A = Number(e.lastInsertRowid);
6976
7026
  }
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,
7027
+ await t.prepare("DELETE FROM channel_trees WHERE channelId = ?").run(A);
7028
+ let j = D.filter((e) => e && e.treeId && e.key);
7029
+ if (j.length > 0) {
7030
+ let e = j.map(() => "(?, ?, ?, ?)").join(", "), n = j.flatMap((e) => [
7031
+ A,
6982
7032
  Number(e.treeId) || e.treeId,
6983
7033
  String(e.key).trim(),
6984
7034
  JSON.stringify(e.meta || {})
@@ -6988,9 +7038,10 @@ ve.get("/", async (e) => {
6988
7038
  VALUES ${e}
6989
7039
  `).run(...n);
6990
7040
  }
6991
- return await I(e).clear(), new B(e.env).purgeGlobalCache(e, t), e.json({
7041
+ let M = I(e);
7042
+ return await M.delete(`channel:${C}`), await M.delete(`channel:${A}`), await M.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
6992
7043
  success: !0,
6993
- id: w
7044
+ id: A
6994
7045
  });
6995
7046
  } catch (t) {
6996
7047
  return console.error("[API Channels] Error saving channel:", t), e.json({
@@ -6998,12 +7049,14 @@ ve.get("/", async (e) => {
6998
7049
  details: t.message
6999
7050
  }, 500);
7000
7051
  }
7001
- }), ve.delete("/", async (e) => {
7052
+ }), ye.delete("/", async (e) => {
7002
7053
  let t = e.get("db"), n = e.req.query("id");
7003
7054
  if (!n) return e.json({ error: "Channel ID required" }, 400);
7004
7055
  let r = Number(n);
7005
7056
  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({
7057
+ 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);
7058
+ let n = I(e);
7059
+ return await n.delete(`channel:${r}`), await n.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
7007
7060
  success: !0,
7008
7061
  deletedSiteId: r
7009
7062
  });
@@ -7019,11 +7072,11 @@ if (typeof process < "u" && process?.versions?.node) try {
7019
7072
  let e = i(import.meta.url);
7020
7073
  K = e("node:fs"), q = e("node:path");
7021
7074
  } catch {}
7022
- function ye(e, t = "") {
7075
+ function be(e, t = "") {
7023
7076
  let n = e.split(/[\\/]/).pop() || "";
7024
7077
  return t && n.endsWith(t) ? n.slice(0, -t.length) : n;
7025
7078
  }
7026
- function be(e) {
7079
+ function xe(e) {
7027
7080
  let t = e.match(/\.[^.\\/]+$/);
7028
7081
  return t ? t[0] : "";
7029
7082
  }
@@ -7036,7 +7089,7 @@ var J = {
7036
7089
  nodeLayouts: {},
7037
7090
  blockLayouts: {}
7038
7091
  };
7039
- function xe(e) {
7092
+ function Se(e) {
7040
7093
  return e ? typeof e == "string" ? e.trim() : Array.isArray(e) ? e.includes("*") ? "*" : e : "*" : "*";
7041
7094
  }
7042
7095
  function Y(e = {}, t = {}) {
@@ -7051,47 +7104,47 @@ function Y(e = {}, t = {}) {
7051
7104
  };
7052
7105
  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
7106
  }
7054
- function Se(e) {
7107
+ function Ce(e) {
7055
7108
  if (!e || typeof e != "object") return e;
7056
- if (Array.isArray(e)) return e.map(Se);
7109
+ if (Array.isArray(e)) return e.map(Ce);
7057
7110
  let t = {};
7058
7111
  for (let [n, r] of Object.entries(e)) if (n === "<<" || n === "<<:") {
7059
- let e = Se(r);
7112
+ let e = Ce(r);
7060
7113
  if (typeof e == "object" && e) {
7061
7114
  if (Array.isArray(e)) for (let n of e) Object.assign(t, n);
7062
7115
  else Object.assign(t, e);
7063
7116
  }
7064
- } else t[n] = Se(r);
7117
+ } else t[n] = Ce(r);
7065
7118
  return t;
7066
7119
  }
7067
- function Ce(e, t) {
7068
- return e ? Se(n.parseDocument(e, { customTags: [{
7120
+ function we(e, t) {
7121
+ return e ? Ce(n.parseDocument(e, { customTags: [{
7069
7122
  tag: "!include",
7070
7123
  resolve(e) {
7071
- let n = (typeof e == "string" ? e : String(e?.strValue || e?.value || "")).trim(), r = ye(n);
7124
+ let n = (typeof e == "string" ? e : String(e?.strValue || e?.value || "")).trim(), r = be(n);
7072
7125
  if (!r) return n;
7073
7126
  if (t && t.fieldSets) {
7074
7127
  let e = Object.keys(t.fieldSets).find((e) => e.endsWith("/" + r) || e === r);
7075
- if (e) return Ce(t.fieldSets[e], t);
7128
+ if (e) return we(t.fieldSets[e], t);
7076
7129
  }
7077
7130
  return n;
7078
7131
  }
7079
7132
  }] }).toJS() || {}) : {};
7080
7133
  }
7081
- function we(e, t = /* @__PURE__ */ new Set()) {
7134
+ function Te(e, t = /* @__PURE__ */ new Set()) {
7082
7135
  if (!K || !q) return {};
7083
7136
  let r = q.resolve(e);
7084
7137
  if (t.has(r) || (t.add(r), !K.existsSync(r))) return {};
7085
7138
  let i = K.readFileSync(r, "utf-8");
7086
- return Se(n.parseDocument(i, { customTags: [{
7139
+ return Ce(n.parseDocument(i, { customTags: [{
7087
7140
  tag: "!include",
7088
7141
  resolve(e) {
7089
7142
  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)) : {};
7143
+ return n ? Te(q.resolve(q.dirname(r), n), new Set(t)) : {};
7091
7144
  }
7092
7145
  }] }).toJS() || {});
7093
7146
  }
7094
- function Te() {
7147
+ function Ee() {
7095
7148
  if (!K || !q || typeof process > "u" || !process?.versions?.node) return null;
7096
7149
  try {
7097
7150
  let e = process.cwd(), t = "", n = [
@@ -7124,9 +7177,9 @@ function Te() {
7124
7177
  let r = {}, i = K.readdirSync(n);
7125
7178
  for (let e of i) {
7126
7179
  if (!e.endsWith(".yaml") && !e.endsWith(".yml")) continue;
7127
- let t = q.join(n, e), i = ye(e, be(e));
7180
+ let t = q.join(n, e), i = be(e, xe(e));
7128
7181
  try {
7129
- r[i] = we(t);
7182
+ r[i] = Te(t);
7130
7183
  } catch (t) {
7131
7184
  console.error(`❌ Error parsing ${e}:`, t.message);
7132
7185
  }
@@ -7154,14 +7207,14 @@ function Te() {
7154
7207
  return console.error("❌ Exception inside readLocalFsBundle:", e), null;
7155
7208
  }
7156
7209
  }
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
- }
7210
+ var De = null, Oe = null;
7164
7211
  function ke(e) {
7212
+ if (!e) De = null, Oe = null;
7213
+ else if (De && Oe === e) return De;
7214
+ let t = Ae(e);
7215
+ return De = t, Oe = e, t;
7216
+ }
7217
+ function Ae(e) {
7165
7218
  if (e) {
7166
7219
  let t = {
7167
7220
  nodes: {
@@ -7197,12 +7250,12 @@ function ke(e) {
7197
7250
  let e = (e) => {
7198
7251
  let n = {};
7199
7252
  for (let [r, i] of Object.entries(e || {})) {
7200
- let e = ye(r, be(r));
7201
- n[e] = Ce(i, t);
7253
+ let e = be(r, xe(r));
7254
+ n[e] = we(i, t);
7202
7255
  }
7203
7256
  return n;
7204
7257
  };
7205
- return Ae({
7258
+ return je({
7206
7259
  rawNodes: e(t.nodes),
7207
7260
  rawTrees: e(t.trees),
7208
7261
  rawChannels: e(t.channels),
@@ -7212,12 +7265,12 @@ function ke(e) {
7212
7265
  rawFieldSets: e(t.fieldSets)
7213
7266
  });
7214
7267
  }
7215
- return Ae(t);
7268
+ return je(t);
7216
7269
  }
7217
- let t = Te();
7218
- return t && Object.keys(t.rawNodes || {}).length > 0 ? Ae(t) : Ae(null);
7270
+ let t = Ee();
7271
+ return t && Object.keys(t.rawNodes || {}).length > 0 ? je(t) : je(null);
7219
7272
  }
7220
- function Ae(e) {
7273
+ function je(e) {
7221
7274
  if (!e) return {
7222
7275
  nodes: {},
7223
7276
  trees: {},
@@ -7352,8 +7405,8 @@ function Ae(e) {
7352
7405
  inVault: t.inVault !== !1,
7353
7406
  hasCanvas: t.hasCanvas === !0,
7354
7407
  defaultLayout: t.defaultLayout,
7355
- allowedBlocks: xe(t.allowedBlocks),
7356
- disallowedBlocks: t.disallowedBlocks ? xe(t.disallowedBlocks) : void 0,
7408
+ allowedBlocks: Se(t.allowedBlocks),
7409
+ disallowedBlocks: t.disallowedBlocks ? Se(t.disallowedBlocks) : void 0,
7357
7410
  tabs: n,
7358
7411
  fields: r
7359
7412
  };
@@ -7415,17 +7468,17 @@ function Ae(e) {
7415
7468
  fields: n
7416
7469
  };
7417
7470
  });
7418
- let te = {};
7471
+ let P = {};
7419
7472
  Object.entries(T).forEach(([e, t]) => {
7420
7473
  let n = A(t.tabs), r = k(t.fields || [], "settings", n), i = {}, a = t.regions || { content: { label: "Content" } };
7421
7474
  Object.entries(a).forEach(([e, t]) => {
7422
7475
  i[e] = {
7423
7476
  ...t,
7424
7477
  label: t.label || e,
7425
- allowedBlocks: xe(t.allowedBlocks),
7426
- disallowedBlocks: t.disallowedBlocks ? xe(t.disallowedBlocks) : void 0
7478
+ allowedBlocks: Se(t.allowedBlocks),
7479
+ disallowedBlocks: t.disallowedBlocks ? Se(t.disallowedBlocks) : void 0
7427
7480
  };
7428
- }), te[e] = {
7481
+ }), P[e] = {
7429
7482
  ...t,
7430
7483
  id: t.id || e,
7431
7484
  label: t.label || e,
@@ -7438,17 +7491,17 @@ function Ae(e) {
7438
7491
  tabs: n
7439
7492
  };
7440
7493
  });
7441
- let P = {};
7494
+ let te = {};
7442
7495
  Object.entries(E).forEach(([e, t]) => {
7443
7496
  let n = A(t.tabs), r = k(t.fields || [], "settings", n), i = {}, a = t.regions || { main: { label: "Main Content" } };
7444
7497
  Object.entries(a).forEach(([e, t]) => {
7445
7498
  i[e] = {
7446
7499
  ...t,
7447
7500
  label: t.label || e,
7448
- allowedBlocks: xe(t.allowedBlocks),
7449
- disallowedBlocks: t.disallowedBlocks ? xe(t.disallowedBlocks) : void 0
7501
+ allowedBlocks: Se(t.allowedBlocks),
7502
+ disallowedBlocks: t.disallowedBlocks ? Se(t.disallowedBlocks) : void 0
7450
7503
  };
7451
- }), P[e] = {
7504
+ }), te[e] = {
7452
7505
  ...t,
7453
7506
  id: t.id || e,
7454
7507
  label: t.label || e,
@@ -7478,7 +7531,7 @@ function Ae(e) {
7478
7531
  L[e] = Y(L[e] || {}, t);
7479
7532
  });
7480
7533
  });
7481
- let R = h ? {
7534
+ let ne = h ? {
7482
7535
  ...h,
7483
7536
  fields: L
7484
7537
  } : null;
@@ -7487,20 +7540,20 @@ function Ae(e) {
7487
7540
  trees: M,
7488
7541
  channels: N,
7489
7542
  blocks: ee,
7490
- nodeLayouts: te,
7491
- blockLayouts: P,
7543
+ nodeLayouts: P,
7544
+ blockLayouts: te,
7492
7545
  fieldSets: O,
7493
7546
  nodeTemplate: f || null,
7494
7547
  treeTemplate: p || null,
7495
7548
  channelTemplate: I,
7496
- userTemplate: R
7549
+ userTemplate: ne
7497
7550
  };
7498
7551
  }
7499
- var je = new e(), Me = (e) => {
7552
+ var Me = new e(), Ne = (e) => {
7500
7553
  try {
7501
7554
  let t = e.env?.BUNDLED_DEFINITIONS;
7502
7555
  (!t || Object.keys(t).length === 0) && (t = f || d || u);
7503
- let n = Oe(t);
7556
+ let n = ke(t);
7504
7557
  return e.json(n, 200, { "Cache-Control": "no-cache, no-store, must-revalidate" });
7505
7558
  } catch (t) {
7506
7559
  return console.error("[CMS API] Error loading schemas:", t), e.json({
@@ -7509,8 +7562,8 @@ var je = new e(), Me = (e) => {
7509
7562
  }, 500);
7510
7563
  }
7511
7564
  };
7512
- je.get("/", Me), je.get("/schemas.json", Me);
7513
- var Ne = new e(), Pe = {
7565
+ Me.get("/", Ne), Me.get("/schemas.json", Ne);
7566
+ var Pe = new e(), Fe = {
7514
7567
  node: "content_nodes",
7515
7568
  nodes: "content_nodes",
7516
7569
  content_node: "content_nodes",
@@ -7522,7 +7575,7 @@ var Ne = new e(), Pe = {
7522
7575
  user: "users",
7523
7576
  users: "users",
7524
7577
  user_account: "user_accounts"
7525
- }, Fe = {
7578
+ }, Ie = {
7526
7579
  content_nodes: [
7527
7580
  "id",
7528
7581
  "title",
@@ -7579,11 +7632,11 @@ var Ne = new e(), Pe = {
7579
7632
  "createdAt"
7580
7633
  ]
7581
7634
  };
7582
- Ne.post("/validate-unique", async (e) => {
7635
+ Pe.post("/validate-unique", async (e) => {
7583
7636
  try {
7584
7637
  let t = e.get("db"), { entityType: n, field: r, value: i, excludeId: a } = await e.req.json();
7585
7638
  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;
7639
+ 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
7640
  if (a != null && String(a).trim() !== "") {
7588
7641
  let e = Number(a);
7589
7642
  l = isNaN(e) ? String(a) : e;
@@ -7595,9 +7648,9 @@ Ne.post("/validate-unique", async (e) => {
7595
7648
  } catch (t) {
7596
7649
  return console.error("[API Validation] Error validating global uniqueness:", t), e.json({ error: "Failed to validate uniqueness" }, 500);
7597
7650
  }
7598
- }), Ne.post("/validate-unique-sibling", async (e) => e.json({ isUnique: !0 }));
7599
- var Ie = new e();
7600
- Ie.get("/", async (e) => {
7651
+ }), Pe.post("/validate-unique-sibling", async (e) => e.json({ isUnique: !0 }));
7652
+ var Le = new e();
7653
+ Le.get("/", async (e) => {
7601
7654
  try {
7602
7655
  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
7656
  ...e,
@@ -7614,7 +7667,7 @@ Ie.get("/", async (e) => {
7614
7667
  isHidden: !!e.isHidden,
7615
7668
  channelNames: e.channelLabels ? e.channelLabels.split(",") : [],
7616
7669
  treeNames: e.treeLabels ? e.treeLabels.split(",") : []
7617
- })), p = e.env?.BUNDLED_DEFINITIONS, m = ce(p), h = m.nodes || m.nodeSchemas || {}, g = c.map((e) => {
7670
+ })), p = e.env?.BUNDLED_DEFINITIONS, m = se(p), h = m.nodes || m.nodeSchemas || {}, g = c.map((e) => {
7618
7671
  let t = e.type || "node", n = h[t]?.label || t.charAt(0).toUpperCase() + t.slice(1);
7619
7672
  return {
7620
7673
  type: t,
@@ -7658,7 +7711,7 @@ async function Q(e, t, n = []) {
7658
7711
  if (typeof r.bind == "function") return await r.bind(...n).run();
7659
7712
  if (typeof r.run == "function") return await r.run(...n);
7660
7713
  }
7661
- function Le(e, t, n) {
7714
+ function Re(e, t, n) {
7662
7715
  let r = e || (t ? `/media/${t}` : "");
7663
7716
  return r && n && r.startsWith(`https://${n}/`) && !r.includes("/media/") && (r = r.replace(`https://${n}/`, `https://${n}/media/`)), r;
7664
7717
  }
@@ -7700,7 +7753,7 @@ X.get("/", async (e) => {
7700
7753
  ...JSON.parse(t.dataJson || "{}")
7701
7754
  };
7702
7755
  } catch {}
7703
- let r = Le(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN);
7756
+ let r = Re(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN);
7704
7757
  return {
7705
7758
  id: t.id,
7706
7759
  filename: t.filename || "Untitled Asset",
@@ -7726,7 +7779,7 @@ X.get("/", async (e) => {
7726
7779
  }
7727
7780
  }), X.post("/upload", async (e) => {
7728
7781
  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;
7782
+ 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
7783
  s && (await Z(t, "SELECT id FROM assets WHERE id = ?", [s])).length === 0 && (s = null);
7731
7784
  let c = r.cropCoordinates, u = null, d = null;
7732
7785
  if (c) {
@@ -7758,7 +7811,7 @@ X.get("/", async (e) => {
7758
7811
  let D = x;
7759
7812
  if (s) {
7760
7813
  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);
7814
+ n.length > 0 && (D = Re(n[0].cdnUrl, n[0].storageKeyPrivate, y)), new V(e.env).purgeAsset(e, t, s);
7762
7815
  }
7763
7816
  return e.json({
7764
7817
  id: p,
@@ -7800,7 +7853,7 @@ X.get("/", async (e) => {
7800
7853
  ...JSON.parse(i.dataJson || "{}")
7801
7854
  };
7802
7855
  } catch {}
7803
- let u = Le(i.cdnUrl, i.storageKeyPrivate, e.env?.CDN_DOMAIN);
7856
+ let u = Re(i.cdnUrl, i.storageKeyPrivate, e.env?.CDN_DOMAIN);
7804
7857
  return e.json({
7805
7858
  id: i.id,
7806
7859
  filename: i.filename,
@@ -7827,7 +7880,7 @@ X.get("/", async (e) => {
7827
7880
  createdAt: t.createdAt,
7828
7881
  parentAssetId: t.parentAssetId || i.id,
7829
7882
  cropCoordinates: n,
7830
- url: Le(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN),
7883
+ url: Re(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN),
7831
7884
  originalUrl: u
7832
7885
  };
7833
7886
  })
@@ -7847,14 +7900,14 @@ X.get("/", async (e) => {
7847
7900
  r.filename === void 0 ? a.filename : r.filename,
7848
7901
  JSON.stringify(o),
7849
7902
  n
7850
- ]), new B(e.env).purgeAsset(e, t, n), e.json({ success: !0 });
7903
+ ]), new V(e.env).purgeAsset(e, t, n), e.json({ success: !0 });
7851
7904
  } catch {
7852
7905
  return e.json({ error: "Failed to update asset" }, 500);
7853
7906
  }
7854
7907
  }), X.delete("/:id", async (e) => {
7855
7908
  try {
7856
7909
  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 ?))", [
7910
+ 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
7911
  n,
7859
7912
  n,
7860
7913
  `crop_%${r.filename ? r.filename.replace(/\.[^/.]+$/, "") : ""}%`,
@@ -7880,7 +7933,7 @@ X.get("/", async (e) => {
7880
7933
  r,
7881
7934
  `crop_%${i.filename ? i.filename.replace(/\.[^/.]+$/, "") : ""}%`,
7882
7935
  `%${r}%`
7883
- ]), new B(e.env).purgeAsset(e, t, r), e.json({
7936
+ ]), new V(e.env).purgeAsset(e, t, r), e.json({
7884
7937
  success: !0,
7885
7938
  id: r,
7886
7939
  restored: !0
@@ -7893,9 +7946,9 @@ X.get("/", async (e) => {
7893
7946
  }
7894
7947
  }), X.delete("/purge/:id", async (e) => {
7895
7948
  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];
7949
+ 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
7950
  if (!i) return e.json({ error: "Asset not found" }, 404);
7898
- new B(e.env).purgeAsset(e, t, r);
7951
+ new V(e.env).purgeAsset(e, t, r);
7899
7952
  let a = [i];
7900
7953
  i.isSystemVariant || (a = [i, ...await Z(t, "SELECT id, storageKeyPrivate FROM assets WHERE parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
7901
7954
  r,
@@ -7925,8 +7978,8 @@ X.get("/", async (e) => {
7925
7978
  }, 500);
7926
7979
  }
7927
7980
  });
7928
- var Re = new e();
7929
- function ze() {
7981
+ var ze = new e();
7982
+ function Be() {
7930
7983
  return {
7931
7984
  fullPath: /* @__PURE__ */ new Map(),
7932
7985
  treeEdges: /* @__PURE__ */ new Map(),
@@ -7934,10 +7987,10 @@ function ze() {
7934
7987
  assetUrls: /* @__PURE__ */ new Map()
7935
7988
  };
7936
7989
  }
7937
- function Be(...e) {
7990
+ function Ve(...e) {
7938
7991
  return e.map((e) => String(e ?? "")).join(":");
7939
7992
  }
7940
- function Ve(e, t) {
7993
+ function He(e, t) {
7941
7994
  let n = Date.now();
7942
7995
  if (e && String(e).trim() !== "") {
7943
7996
  let t = Date.parse(e);
@@ -7949,27 +8002,27 @@ function Ve(e, t) {
7949
8002
  }
7950
8003
  return !0;
7951
8004
  }
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);
8005
+ async function Ue(e, t, n, r) {
8006
+ let i = t.filter((e) => e.componentId === "content-feed" || e.componentId === "article-list");
8007
+ await Promise.all(i.map(async (t) => {
8008
+ 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];
8009
+ n && n !== "all" && (c += " AND id IN (SELECT nodeId FROM node_channels WHERE channelId = ?)", l.push(Number(n) || n));
8010
+ let u = "ORDER BY updatedAt DESC";
8011
+ s === "published_desc" || s === "createdAt" ? u = "ORDER BY createdAt DESC" : s === "title_asc" && (u = "ORDER BY LOWER(title) ASC");
8012
+ let d = `SELECT id, title, slug, language, dataJson, createdAt, updatedAt ${c} ${u} LIMIT ?`;
8013
+ l.push(o);
7961
8014
  try {
7962
- let n = await e.prepare(u).all(...c), r = Array.isArray(n) ? n : n?.results || [];
7963
- t.data.initialItems = r.map((e) => {
8015
+ let n = await e.prepare(d).all(...l), i = Array.isArray(n) ? n : n?.results || [];
8016
+ t.data.initialItems = i.map((e) => {
7964
8017
  let t = {};
7965
8018
  if (e.dataJson) try {
7966
8019
  t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
7967
8020
  } catch {}
7968
- return Ve(t.startShowingAt, t.stopShowingAt) ? {
8021
+ return He(t.startShowingAt, t.stopShowingAt) ? {
7969
8022
  id: e.id,
7970
8023
  title: e.title,
7971
8024
  slug: e.slug,
7972
- language: e.language || "en",
8025
+ language: e.language?.trim() || r || null,
7973
8026
  createdAt: e.createdAt,
7974
8027
  updatedAt: e.updatedAt,
7975
8028
  excerpt: t.excerpt || "",
@@ -7982,7 +8035,7 @@ async function He(e, t, n) {
7982
8035
  }
7983
8036
  }));
7984
8037
  }
7985
- async function Ue(e, t, n, r, i = !1, a) {
8038
+ async function We(e, t, n, r, i = !1, a) {
7986
8039
  if (!t) return { blocks: [] };
7987
8040
  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
8041
  if (!s || s.length === 0) return { blocks: [] };
@@ -8018,10 +8071,10 @@ async function Ue(e, t, n, r, i = !1, a) {
8018
8071
  try {
8019
8072
  a = (typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson) || {};
8020
8073
  } catch {}
8021
- let o = a.hidden === !0 || a.hidden === 1 || a.hidden === "1" || a.hidden === "true", s = Ve(a.startShowingAt, a.stopShowingAt);
8074
+ let o = a.hidden === !0 || a.hidden === 1 || a.hidden === "1" || a.hidden === "true", s = He(a.startShowingAt, a.stopShowingAt);
8022
8075
  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, {
8076
+ 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);
8077
+ return d = await B(e, d), d = Ke(d), d.blockId = u, {
8025
8078
  region: t.region || n,
8026
8079
  block: {
8027
8080
  instanceId: t.id,
@@ -8041,7 +8094,7 @@ async function Ue(e, t, n, r, i = !1, a) {
8041
8094
  }
8042
8095
  return { blocks: [] };
8043
8096
  }
8044
- function We(e, t = {}) {
8097
+ function Ge(e, t = {}) {
8045
8098
  let n = {};
8046
8099
  for (let [r, i] of Object.entries(e)) r.endsWith("_meta") || [
8047
8100
  "disabledRegions",
@@ -8057,14 +8110,14 @@ function We(e, t = {}) {
8057
8110
  ].includes(r) || r.startsWith("_") || (!t[r] || t[r].public !== !1) && (n[r] = i);
8058
8111
  return n;
8059
8112
  }
8060
- function Ge(e) {
8061
- if (Array.isArray(e)) return e.map(Ge);
8113
+ function Ke(e) {
8114
+ if (Array.isArray(e)) return e.map(Ke);
8062
8115
  if (!e || typeof e != "object") return e;
8063
8116
  if (typeof e.id == "string" && e.id.startsWith("ast_") && typeof e.url == "string") {
8064
8117
  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
8118
  ...t,
8066
8119
  ...t.crops?.[r] || {}
8067
- } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, Ge({
8120
+ } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, Ke({
8068
8121
  ...n,
8069
8122
  title: n?.title ?? e.title ?? "",
8070
8123
  alt: n?.alt ?? e.alt ?? "",
@@ -8078,9 +8131,9 @@ function Ge(e) {
8078
8131
  ...Object.keys(a).length > 0 ? { variants: a } : {}
8079
8132
  };
8080
8133
  }
8081
- return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, Ge(t)]));
8134
+ return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, Ke(t)]));
8082
8135
  }
8083
- async function Ke(e, t, n) {
8136
+ async function qe(e, t, n) {
8084
8137
  if (typeof t == "string") {
8085
8138
  if (!t.includes("#node:") && !t.includes("data-node-id") && !t.includes("#asset:") && !t.includes("data-asset-id")) return t;
8086
8139
  let r = (e, t) => {
@@ -8098,9 +8151,9 @@ async function Ke(e, t, n) {
8098
8151
  return await Promise.all(Array.from(t.matchAll(p)).map(async (t) => {
8099
8152
  let i = t[1], a = r(i, "data-node-id"), o = r(i, "data-tree-id");
8100
8153
  if (!a || !o) return;
8101
- let s = await Je(e, a, o, n);
8154
+ let s = await Ye(e, a, o, n);
8102
8155
  if (s?.treeNodeId) {
8103
- let t = await Qe(e, String(s.treeNodeId), o, n);
8156
+ let t = await $e(e, String(s.treeNodeId), o, n);
8104
8157
  f.set(`${a}:${o}`, t);
8105
8158
  }
8106
8159
  })), t.replace(p, (e, t) => {
@@ -8120,39 +8173,39 @@ async function Ke(e, t, n) {
8120
8173
  return /href\s*=\s*["'][^"']*["']/i.test(h) ? h = h.replace(/href\s*=\s*["'][^"']*["']/i, `href="${m || "/"}"`) : h += ` href="${m || "/"}"`, `<a ${h}>`;
8121
8174
  });
8122
8175
  }
8123
- if (Array.isArray(t)) return Promise.all(t.map((t) => Ke(e, t, n)));
8176
+ if (Array.isArray(t)) return Promise.all(t.map((t) => qe(e, t, n)));
8124
8177
  if (t && typeof t == "object") {
8125
8178
  if (typeof t.href == "string" && (t.href.startsWith("#node:") || t.href.startsWith("#asset:"))) return {
8126
8179
  ...t,
8127
- href: await qe(e, t, n)
8180
+ href: await Je(e, t, n)
8128
8181
  };
8129
- let r = await Promise.all(Object.entries(t).map(async ([t, r]) => [t, await Ke(e, r, n)]));
8182
+ let r = await Promise.all(Object.entries(t).map(async ([t, r]) => [t, await qe(e, r, n)]));
8130
8183
  return Object.fromEntries(r);
8131
8184
  }
8132
8185
  return t;
8133
8186
  }
8134
- async function qe(e, t, n) {
8187
+ async function Je(e, t, n) {
8135
8188
  let r = t.href.match(/^#node:(.+)$/), i = t.href.match(/^#asset:(.+)$/);
8136
- if (i) return Xe(e, i[1], n);
8189
+ if (i) return Ze(e, i[1], n);
8137
8190
  if (!r) return t.href;
8138
8191
  let a = r[1];
8139
8192
  if (t.treeId) {
8140
- let r = await Je(e, a, String(t.treeId), n);
8193
+ let r = await Ye(e, a, String(t.treeId), n);
8141
8194
  if (r?.treeNodeId) {
8142
- let i = await Qe(e, String(r.treeNodeId), String(t.treeId), n);
8195
+ let i = await $e(e, String(r.treeNodeId), String(t.treeId), n);
8143
8196
  if (i) return i;
8144
8197
  }
8145
8198
  }
8146
- let o = await Ye(e, a, n);
8199
+ let o = await Xe(e, a, n);
8147
8200
  return o === void 0 ? "#" : `/${o}`;
8148
8201
  }
8149
- async function Je(e, t, n, r) {
8150
- let i = Be(t, n), a = r.treeEdges.get(i);
8202
+ async function Ye(e, t, n, r) {
8203
+ let i = Ve(t, n), a = r.treeEdges.get(i);
8151
8204
  if (a) return a;
8152
8205
  let o = e.prepare("SELECT id as treeNodeId FROM tree_nodes WHERE contentId = ? AND treeId = ? LIMIT 1").get(t, n);
8153
8206
  return r.treeEdges.set(i, Promise.resolve(o)), o;
8154
8207
  }
8155
- async function Ye(e, t, n) {
8208
+ async function Xe(e, t, n) {
8156
8209
  let r = String(t), i = n.nodeSlugs.get(r);
8157
8210
  if (i) return i;
8158
8211
  let a = (async () => {
@@ -8161,7 +8214,7 @@ async function Ye(e, t, n) {
8161
8214
  })();
8162
8215
  return n.nodeSlugs.set(r, a), a;
8163
8216
  }
8164
- async function Xe(e, t, n) {
8217
+ async function Ze(e, t, n) {
8165
8218
  let r = String(t), i = n.assetUrls.get(r);
8166
8219
  if (i) return i;
8167
8220
  let a = (async () => {
@@ -8170,7 +8223,7 @@ async function Xe(e, t, n) {
8170
8223
  })();
8171
8224
  return n.assetUrls.set(r, a), a;
8172
8225
  }
8173
- function Ze(e) {
8226
+ function Qe(e) {
8174
8227
  let t = e.socialImage;
8175
8228
  if (!t || typeof t != "object") return null;
8176
8229
  let n = (e, t) => {
@@ -8201,9 +8254,9 @@ function Ze(e) {
8201
8254
  ])
8202
8255
  };
8203
8256
  }
8204
- async function Qe(e, t, n, r) {
8257
+ async function $e(e, t, n, r) {
8205
8258
  if (!t) return "";
8206
- let i = Be(t, n);
8259
+ let i = Ve(t, n);
8207
8260
  if (r) {
8208
8261
  let e = r.fullPath.get(i);
8209
8262
  if (e) return e;
@@ -8218,7 +8271,7 @@ async function Qe(e, t, n, r) {
8218
8271
  })();
8219
8272
  return r && r.fullPath.set(i, a), a;
8220
8273
  }
8221
- async function $e(e, t, n, r, i) {
8274
+ async function et(e, t, n, r, i) {
8222
8275
  let a = {}, o = null;
8223
8276
  if (t) {
8224
8277
  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 +8298,7 @@ async function $e(e, t, n, r, i) {
8245
8298
  }
8246
8299
  }
8247
8300
  if (!o) {
8248
- let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ?").get(n);
8301
+ let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ? OR key = ? LIMIT 1").get(Number(n) || -1, String(n));
8249
8302
  if (t?.dataJson) try {
8250
8303
  let e = typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson;
8251
8304
  e.subpageLayoutId && e.subpageLayoutId !== "inherit" && (o = e.subpageLayoutId);
@@ -8256,109 +8309,125 @@ async function $e(e, t, n, r, i) {
8256
8309
  inheritedFields: a
8257
8310
  };
8258
8311
  }
8259
- function et(e) {
8312
+ function tt(e) {
8260
8313
  let t = Number(e?.env?.CMS_NODE_CACHE_TTL);
8261
8314
  return Number.isFinite(t) && t >= 60 ? Math.floor(t) : 300;
8262
8315
  }
8263
- async function tt(e, t, n, r) {
8316
+ async function nt(e, t, n, r) {
8264
8317
  try {
8265
8318
  await e.set(t, n, r);
8266
8319
  } catch (e) {
8267
8320
  console.warn("[CMS Cache] Failed to write node response to cache:", e);
8268
8321
  }
8269
8322
  }
8270
- Re.get("/*", async (e) => {
8323
+ ze.get("/*", async (e) => {
8271
8324
  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));
8325
+ 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
8326
  if (!c) return e.json({ error: `Channel '${a}' not found` }, 404);
8274
8327
  let l = c.status === "disabled" || c.status === "inactive" || c.isEnabled === 0 || c.isEnabled === !1;
8275
8328
  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 = `
8329
+ 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
8330
  SELECT cn.*, tn.id as treeNodeId, tn.parentId, tn.treeId FROM content_nodes cn
8283
8331
  INNER JOIN tree_nodes tn ON cn.id = tn.contentId
8284
8332
  ${u === null ? "" : "INNER JOIN node_channels nc ON cn.id = nc.nodeId"}
8285
8333
  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) => ({
8334
+ `, S = u === null ? [y] : [y, u], C = await t.prepare(x).all(...S), w = Array.isArray(C) ? C : C?.results || [];
8335
+ if (w.length > 0) {
8336
+ let e = await Promise.all(w.map(async (e) => ({
8289
8337
  candidate: e,
8290
- calculatedPath: await Qe(t, String(e.treeNodeId), String(e.treeId), n)
8291
- }))), r = S.replace(/^\/+|\/+$/g, "");
8338
+ calculatedPath: await $e(t, String(e.treeNodeId), String(e.treeId), n)
8339
+ }))), r = b.replace(/^\/+|\/+$/g, "");
8292
8340
  for (let { candidate: t, calculatedPath: n } of e) {
8293
8341
  let e = n.replace(/^\/+|\/+$/g, "");
8294
8342
  if (e === r || r === "home" && (e === "" || e === "home")) {
8295
- _ = t, v = t;
8343
+ h = t, g = t;
8296
8344
  break;
8297
8345
  }
8298
8346
  }
8299
8347
  }
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);
8348
+ 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);
8349
+ if (!g) {
8350
+ let e = _ ? [h.id, _] : [h.id];
8351
+ g = await t.prepare(`SELECT id as treeNodeId, treeId, parentId FROM tree_nodes WHERE contentId = ? ${_ ? "AND treeId = ?" : ""} LIMIT 1`).get(...e);
8352
+ }
8353
+ let T = g?.treeId || _ || "main-nav", E = null;
8354
+ if (T) {
8355
+ 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));
8356
+ if (e?.dataJson) try {
8357
+ let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
8358
+ t.defaultLanguage ? E = String(t.defaultLanguage).trim() : t.language && (E = String(t.language).trim());
8359
+ } catch {}
8360
+ }
8361
+ let D = null;
8362
+ if (c) {
8363
+ if (c.defaultLanguage) D = String(c.defaultLanguage).trim();
8364
+ else if (c.dataJson) try {
8365
+ let e = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson;
8366
+ e.defaultLanguage ? D = String(e.defaultLanguage).trim() : e.language && (D = String(e.language).trim());
8367
+ } catch {}
8368
+ }
8369
+ 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";
8370
+ if (!s && !M) {
8371
+ let t = await f.get(j);
8372
+ if (t) return e.header("X-Cache", "HIT"), e.json(t);
8304
8373
  }
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 || {});
8374
+ let N = g?.parentId || null, ee = g?.treeNodeId ? await $e(t, String(g.treeNodeId), String(T), n) : `/${(h.slug || "").replace(/^\/+|\/+$/g, "")}`, P = {
8375
+ id: h.id,
8376
+ title: h.title,
8377
+ slug: h.slug,
8378
+ language: A,
8379
+ path: ee === "" ? "/" : ee,
8380
+ nodeType: h.contentType,
8381
+ createdAt: h.createdAt,
8382
+ updatedAt: h.updatedAt
8383
+ }, te = h.contentType || "node", F = p.nodes?.[te] || Object.values(p.nodes || {})[0] || {}, L = { ...F.fields || {} };
8384
+ F.tabs && Object.values(F.tabs).forEach((e) => {
8385
+ Object.assign(L, e.fields || {});
8317
8386
  });
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;
8387
+ let ne = {}, re = null, ie = null, ae = !1, R = {}, oe = s && h.draftDataJson || h.dataJson;
8388
+ if (oe) try {
8389
+ R = typeof oe == "string" ? JSON.parse(oe) : oe;
8321
8390
  } 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) => {
8391
+ 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;
8392
+ 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;
8393
+ 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);
8394
+ let U = await B(t, Ge(R, L));
8395
+ U = Ke(U), U = await qe(t, U, n), delete U.language;
8396
+ let ue = Qe(U);
8397
+ 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;
8398
+ 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";
8399
+ if (!s && (de || fe || pe && !me)) return e.json({ error: "Node is hidden, offline, or has never been published." }, 404);
8400
+ let he = [];
8401
+ if (g?.treeNodeId) {
8402
+ 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;
8403
+ he = n.map((e) => {
8335
8404
  let t = {}, n = s && e.draftDataJson || e.dataJson;
8336
8405
  if (!n) return null;
8337
8406
  try {
8338
8407
  t = (typeof n == "string" ? JSON.parse(n) : n) || {};
8339
8408
  } 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, "");
8409
+ 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
8410
  return !s && (i || !a) ? null : {
8342
8411
  treeNodeId: e.treeNodeId,
8343
8412
  id: e.id,
8344
8413
  title: e.title,
8345
8414
  slug: o,
8346
- language: e.language || "en",
8415
+ language: e.language?.trim() || A || null,
8347
8416
  path: `${r}/${o}`.replace(/\/+/g, "/"),
8348
8417
  nodeType: e.nodeType
8349
8418
  };
8350
8419
  }).filter(Boolean);
8351
8420
  }
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) => {
8421
+ P.children = he;
8422
+ 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
8423
  let r = e.region || "main", i = {};
8355
8424
  try {
8356
8425
  i = (typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson) || {};
8357
8426
  } catch {}
8358
- let a = i.hidden === !0 || i.hidden === 1 || i.hidden === "1" || i.hidden === "true", o = Ve(i.startShowingAt, i.stopShowingAt);
8427
+ let a = i.hidden === !0 || i.hidden === 1 || i.hidden === "1" || i.hidden === "true", o = He(i.startShowingAt, i.stopShowingAt);
8359
8428
  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, {
8429
+ 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);
8430
+ return d = await B(t, d), d = Ke(d), d = await qe(t, d, n), d.blockId = u, {
8362
8431
  region: r,
8363
8432
  block: {
8364
8433
  instanceId: e.id,
@@ -8368,8 +8437,8 @@ Re.get("/*", async (e) => {
8368
8437
  }
8369
8438
  };
8370
8439
  }));
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 = {
8440
+ for (let e of ye) e && (G[e.region] || (G[e.region] = [], ve[e.region] = { isInherited: !1 }), G[e.region].push(e.block));
8441
+ let K = {
8373
8442
  header: {
8374
8443
  label: "Header",
8375
8444
  inherit: "parent"
@@ -8378,33 +8447,33 @@ Re.get("/*", async (e) => {
8378
8447
  label: "Footer",
8379
8448
  inherit: "parent"
8380
8449
  },
8381
- ...(oe ? h.nodeLayouts?.[oe] || h.layouts?.[oe] : null)?.regions || { main: { label: "Content" } }
8450
+ ...(le ? p.nodeLayouts?.[le] || p.layouts?.[le] : null)?.regions || { main: { label: "Content" } }
8382
8451
  };
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] = {
8452
+ for (let [e, r] of Object.entries(K)) {
8453
+ let i = G[e] && G[e].length > 0, a = !!ne[e];
8454
+ 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) {
8455
+ let r = await We(t, N, e, p, s, n);
8456
+ if (r.blocks.length > 0 && (G[e] = r.blocks, ve[e] = {
8388
8457
  isInherited: !0,
8389
8458
  inheritedFromId: r.inheritedFromId,
8390
8459
  inheritedFromTitle: r.inheritedFromTitle
8391
- }, r.subRegions)) for (let [t, n] of Object.entries(r.subRegions)) t !== e && (U[t] = n, W[t] = {
8460
+ }, r.subRegions)) for (let [t, n] of Object.entries(r.subRegions)) t !== e && (G[t] = n, ve[t] = {
8392
8461
  isInherited: !0,
8393
8462
  inheritedFromId: r.inheritedFromId,
8394
8463
  inheritedFromTitle: r.inheritedFromTitle
8395
8464
  });
8396
8465
  }
8397
8466
  }
8398
- await Promise.all(Object.keys(U).map((e) => He(t, U[e], u)));
8399
- let ge = {
8467
+ await Promise.all(Object.keys(G).map((e) => Ue(t, G[e], u, A)));
8468
+ let q = {
8400
8469
  channelId: u || d,
8401
- treeId: D,
8402
- language: A.language,
8403
- node: A,
8404
- content: U,
8405
- regionMeta: W
8470
+ treeId: T,
8471
+ language: A,
8472
+ node: P,
8473
+ content: G,
8474
+ regionMeta: ve
8406
8475
  };
8407
- return !s && !m && (e.header("X-Cache", "MISS"), await tt(f, p, ge, et(e))), e.json(ge);
8476
+ return !s && !M && (e.header("X-Cache", "MISS"), await nt(f, j, q, tt(e))), e.json(q);
8408
8477
  } catch (t) {
8409
8478
  return console.error("[CMS Public API] Error fetching node by path:", t), e.json({
8410
8479
  error: "Failed to fetch JSON payload",
@@ -8412,8 +8481,8 @@ Re.get("/*", async (e) => {
8412
8481
  }, 500);
8413
8482
  }
8414
8483
  });
8415
- var nt = new e();
8416
- function rt(e, t) {
8484
+ var rt = new e();
8485
+ function it(e, t) {
8417
8486
  let n = /* @__PURE__ */ new Date();
8418
8487
  if (e && String(e).trim() !== "") {
8419
8488
  let t = new Date(e);
@@ -8425,93 +8494,103 @@ function rt(e, t) {
8425
8494
  }
8426
8495
  return !0;
8427
8496
  }
8428
- async function it(e, t, n, r) {
8497
+ async function at(e, t, n, r) {
8429
8498
  try {
8430
8499
  await e.set(t, n, r);
8431
8500
  } catch (e) {
8432
8501
  console.warn("[CMS Cache] Failed to write tree response to cache:", e);
8433
8502
  }
8434
8503
  }
8435
- nt.get("/:treeParam", async (e) => {
8504
+ rt.get("/:treeParam", async (e) => {
8436
8505
  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";
8506
+ 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
8507
  if (r && r !== "default" && r !== "all") {
8439
8508
  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
8509
  if (n) {
8510
+ n.defaultLanguage && (o = n.defaultLanguage.trim());
8441
8511
  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);
8512
+ if (!a && t) return e.json({ error: `Channel '${n.key || r}' is currently inactive` }, 404);
8443
8513
  }
8444
8514
  }
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);
8515
+ 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);
8516
+ if (c && Number(c.isHidden) === 1 && !a) return e.json({ error: `Tree '${n}' is hidden` }, 404);
8517
+ let l = null;
8518
+ if (c) {
8519
+ if (c.defaultLanguage) l = String(c.defaultLanguage).trim();
8520
+ else if (c.dataJson) try {
8521
+ let e = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson;
8522
+ e.defaultLanguage && (l = String(e.defaultLanguage).trim());
8523
+ } catch {}
8524
+ }
8525
+ let u = l || o || i?.trim() || null, d = I(e), f = `tree:${r}:${n}:${u || "default"}`, p = e.req.header("x-bypass-cache") === "true";
8526
+ if (!a && !p) {
8527
+ let t = await d.get(f);
8448
8528
  if (t) return e.header("X-Cache", "HIT"), e.json(t);
8449
8529
  }
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);
8530
+ let m = c?.id || (s ? Number(n) : null), h = {};
8531
+ if (c && c.dataJson) try {
8532
+ 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 || {};
8533
+ for (let [e, n] of Object.entries(t)) a[e]?.public === !0 && (h[e] = n);
8456
8534
  } catch (e) {
8457
8535
  console.warn("[CMS Public Tree API] Failed to parse tree dataJson", e);
8458
8536
  }
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 || [];
8537
+ let g = [];
8538
+ if (m !== null) {
8539
+ 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);
8540
+ g = Array.isArray(e) ? e : e?.results || [];
8463
8541
  }
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]);
8542
+ if ((!g || g.length === 0) && !c) return e.json({ error: `Tree '${n}' not found` }, 404);
8543
+ let _ = /* @__PURE__ */ new Map();
8544
+ for (let e of g) {
8545
+ let t = !e.parentId || e.parentId === "null" || e.parentId === "" ? null : e.parentId, n = t === null ? "__ROOT__" : String(t), r = _.get(n);
8546
+ r ? r.push(e) : _.set(n, [e]);
8469
8547
  }
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;
8548
+ let v = /* @__PURE__ */ new Map();
8549
+ for (let e of g) {
8550
+ let t = String(e.treeNodeId), n = a && e.draftDataJson ? e.draftDataJson : e.dataJson;
8473
8551
  if (!n) {
8474
- m.set(t, {});
8552
+ v.set(t, {});
8475
8553
  continue;
8476
8554
  }
8477
8555
  try {
8478
8556
  let e = typeof n == "string" ? JSON.parse(n) : n;
8479
- m.set(t, e && typeof e == "object" ? e : {});
8557
+ v.set(t, e && typeof e == "object" ? e : {});
8480
8558
  } catch {
8481
- m.set(t, {});
8559
+ v.set(t, {});
8482
8560
  }
8483
8561
  }
8484
- function h(e = null, t = "") {
8562
+ function y(e = null, t = "") {
8485
8563
  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 = {};
8564
+ return (_.get(n) || []).map((e) => {
8565
+ let n = v.get(String(e.treeNodeId)) || {}, r = {};
8488
8566
  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 = {
8567
+ 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
8568
  id: e.id,
8491
8569
  treeNodeId: e.treeNodeId,
8492
8570
  parentId: e.parentId || null,
8493
8571
  title: e.title,
8494
8572
  slug: c,
8495
- language: e.language || "en",
8573
+ language: d,
8496
8574
  path: l,
8497
8575
  nodeType: e.nodeType,
8498
8576
  hidden: o || !s ? 1 : 0,
8499
8577
  summary: r.summary || ""
8500
8578
  };
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);
8579
+ e.nodeType === "external-link" && (r.url && (f.url = r.url), r.target && (f.target = r.target));
8580
+ let p = l === "/" ? "" : l;
8581
+ return f.children = y(e.treeNodeId, p), f;
8582
+ }).filter((e) => a || !e.hidden);
8505
8583
  }
8506
- let g = {
8507
- treeId: l?.id || u,
8508
- key: l?.key || n,
8584
+ let b = {
8585
+ treeId: c?.id || m,
8586
+ key: c?.key || n,
8509
8587
  channelId: r,
8510
- label: l?.label || n,
8511
- ...d,
8512
- items: h(null)
8588
+ language: u,
8589
+ label: c?.label || n,
8590
+ ...h,
8591
+ items: y(null)
8513
8592
  };
8514
- return !i && !s && (e.header("X-Cache", "MISS"), await it(a, o, g, 300)), e.json(g);
8593
+ return !a && !p && (e.header("X-Cache", "MISS"), await at(d, f, b, 300)), e.json(b);
8515
8594
  } catch (t) {
8516
8595
  return console.error("[CMS Public Tree API] Error:", t), e.json({
8517
8596
  error: "Failed to fetch public tree",
@@ -8519,8 +8598,145 @@ nt.get("/:treeParam", async (e) => {
8519
8598
  }, 500);
8520
8599
  }
8521
8600
  });
8522
- var at = new e();
8523
- function ot(e, t) {
8601
+ var ot = new e();
8602
+ function st(e) {
8603
+ let t = Number(e?.env?.CMS_CHANNEL_CACHE_TTL);
8604
+ return Number.isFinite(t) && t >= 60 ? Math.floor(t) : 300;
8605
+ }
8606
+ async function ct(e, t, n, r) {
8607
+ try {
8608
+ await e.set(t, n, r);
8609
+ } catch (e) {
8610
+ console.warn("[CMS Cache] Failed to write channel response to cache:", e);
8611
+ }
8612
+ }
8613
+ function lt(e, t) {
8614
+ let n = {}, r = (e) => {
8615
+ if (!e || typeof e != "string") return;
8616
+ let n = t?.fieldSets?.[e] || t?.fieldsets?.[e] || t?.definitions?.[e] || t?.channels?.[e] || t?.[e];
8617
+ n?.fields && i(n.fields);
8618
+ }, i = (e) => {
8619
+ 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);
8620
+ };
8621
+ 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);
8622
+ return n;
8623
+ }
8624
+ function ut(e, t = {}) {
8625
+ let n = {}, r = Object.keys(t).length > 0;
8626
+ for (let [i, a] of Object.entries(e)) {
8627
+ if (i.endsWith("_meta") || [
8628
+ "disabledRegions",
8629
+ "hidden",
8630
+ "is_hidden",
8631
+ "isHidden",
8632
+ "status",
8633
+ "startShowingAt",
8634
+ "stopShowingAt",
8635
+ "dataJson",
8636
+ "draftDataJson"
8637
+ ].includes(i) || i.startsWith("_")) continue;
8638
+ let e = t[i];
8639
+ (!r || !e || e.public !== !1) && a != null && a !== "" && (n[i] = a);
8640
+ }
8641
+ return n;
8642
+ }
8643
+ function dt(e) {
8644
+ if (Array.isArray(e)) return e.map(dt);
8645
+ if (!e || typeof e != "object") return e;
8646
+ if (typeof e.id == "string" && e.id.startsWith("ast_") && typeof e.url == "string") {
8647
+ 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 ? {
8648
+ ...t,
8649
+ ...t.crops?.[r] || {}
8650
+ } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, dt({
8651
+ ...n,
8652
+ title: n?.title ?? e.title ?? "",
8653
+ alt: n?.alt ?? e.alt ?? "",
8654
+ description: n?.description ?? e.description ?? ""
8655
+ })])), { metadataOverrides: o, ...s } = e;
8656
+ return {
8657
+ ...s,
8658
+ title: i.title ?? e.title ?? "",
8659
+ alt: i.alt ?? e.alt ?? "",
8660
+ description: i.description ?? e.description ?? "",
8661
+ ...Object.keys(a).length > 0 ? { variants: a } : {}
8662
+ };
8663
+ }
8664
+ return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, dt(t)]));
8665
+ }
8666
+ async function ft(e, t) {
8667
+ if (typeof t == "string") {
8668
+ if (!t.includes("#node:") && !t.includes("data-node-id") && !t.includes("#asset:") && !t.includes("data-asset-id")) return t;
8669
+ let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set();
8670
+ for (let e of t.matchAll(/(?:#node:|data-node-id\s*=\s*["'])([^"'\s>]+)/gi)) n.add(e[1]);
8671
+ for (let e of t.matchAll(/(?:#asset:|data-asset-id\s*=\s*["'])([^"'\s>]+)/gi)) r.add(e[1]);
8672
+ if (n.size === 0 && r.size === 0) return t;
8673
+ 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();
8674
+ (Array.isArray(a) ? a : a?.results || []).forEach((e) => o.set(String(e.id), String(e.slug || "").replace(/^\/+|\/+$/g, "")));
8675
+ 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();
8676
+ 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) => {
8677
+ let n = (e, t) => {
8678
+ let n = e.match(RegExp(`\\b${t}\\s*=\\s*(["'])(.*?)\\1`, "i"));
8679
+ return n ? n[2] : void 0;
8680
+ }, r = n(t, "data-node-id"), i = n(t, "data-asset-id"), a = n(t, "href") || "";
8681
+ if (a.startsWith("mailto:")) return `<a ${t.replace(/\s+target\s*=\s*["'][^"']*["']/i, "")}>`;
8682
+ let s = i || a.match(/^#asset:(.+)$/i)?.[1], c = r || a.match(/^#node:(.+)$/i)?.[1];
8683
+ if (!c && !s) return e;
8684
+ if (s && !c) {
8685
+ let n = l.get(s);
8686
+ if (n) {
8687
+ let e = t;
8688
+ return /href\s*=\s*["'][^"']*["']/i.test(e) ? e = e.replace(/href\s*=\s*["'][^"']*["']/i, `href="${n}"`) : e += ` href="${n}"`, `<a ${e}>`;
8689
+ }
8690
+ return e;
8691
+ }
8692
+ let u = o.get(c), d = u === void 0 ? "#" : `/${u}`, f = t;
8693
+ return /href\s*=\s*["'][^"']*["']/i.test(f) ? f = f.replace(/href\s*=\s*["'][^"']*["']/i, `href="${d || "/"}"`) : f += ` href="${d || "/"}"`, `<a ${f}>`;
8694
+ });
8695
+ }
8696
+ if (Array.isArray(t)) return Promise.all(t.map((t) => ft(e, t)));
8697
+ if (t && typeof t == "object") {
8698
+ let n = await Promise.all(Object.entries(t).map(async ([t, n]) => [t, await ft(e, n)]));
8699
+ return Object.fromEntries(n);
8700
+ }
8701
+ return t;
8702
+ }
8703
+ ot.get("/:channelParam", async (e) => {
8704
+ try {
8705
+ 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);
8706
+ if (!r && !i) {
8707
+ let t = await o.get(a);
8708
+ if (t) return e.header("X-Cache", "HIT"), e.json(t);
8709
+ }
8710
+ 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));
8711
+ if (!s) return e.json({ error: `Channel '${n}' not found` }, 404);
8712
+ let c = s.status === "disabled" || s.status === "inactive" || s.isEnabled === 0 || s.isEnabled === !1;
8713
+ if (!r && c) return e.json({ error: `Channel '${s.key || n}' is currently inactive` }, 404);
8714
+ 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;
8715
+ if (m) try {
8716
+ p = typeof m == "string" ? JSON.parse(m) : m;
8717
+ } catch (e) {
8718
+ console.warn("[CMS Public Channel API] Failed to parse channel dataJson:", e);
8719
+ }
8720
+ let h = ut({
8721
+ ...p,
8722
+ ...s
8723
+ }, f);
8724
+ h = await B(t, h), h = dt(h), h = await ft(t, h);
8725
+ let g = {
8726
+ id: s.id,
8727
+ key: s.key,
8728
+ ...h
8729
+ };
8730
+ return !r && !i && (e.header("X-Cache", "MISS"), await ct(o, a, g, st(e))), e.json(g);
8731
+ } catch (t) {
8732
+ return console.error("[CMS Public Channel API] Error:", t), e.json({
8733
+ error: "Failed to fetch public channel",
8734
+ ...e.env?.ENVIRONMENT === "development" ? { details: t.message } : {}
8735
+ }, 500);
8736
+ }
8737
+ });
8738
+ var pt = new e();
8739
+ function mt(e, t) {
8524
8740
  if (t === "webp") return "image/webp";
8525
8741
  if (t === "avif") return "image/avif";
8526
8742
  if (t === "jpeg" || t === "jpg") return "image/jpeg";
@@ -8528,7 +8744,7 @@ function ot(e, t) {
8528
8744
  let n = e.toLowerCase();
8529
8745
  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
8746
  }
8531
- at.get("/*", async (e) => {
8747
+ pt.get("/*", async (e) => {
8532
8748
  try {
8533
8749
  let t = e.req.path.replace(/^\/media\//, "").replace(/^\//, "");
8534
8750
  if (!t) return e.text("Asset key missing", 400);
@@ -8544,11 +8760,11 @@ at.get("/*", async (e) => {
8544
8760
  let e = await l.match(d);
8545
8761
  if (e) return e;
8546
8762
  }
8547
- let { storage: f, optimizer: p } = ie(e.env), m = await f.get(t);
8763
+ let { storage: f, optimizer: p } = ae(e.env), m = await f.get(t);
8548
8764
  if (!m) return e.text(`Asset not found: ${t}`, 404);
8549
8765
  if (!o) {
8550
8766
  let n = e.body(m, 200, {
8551
- "Content-Type": ot(t),
8767
+ "Content-Type": mt(t),
8552
8768
  "Cache-Control": "public, max-age=31536000, immutable"
8553
8769
  });
8554
8770
  return l && d && e.executionCtx?.waitUntil && e.executionCtx.waitUntil(l.put(d, n.clone())), n;
@@ -8562,7 +8778,7 @@ at.get("/*", async (e) => {
8562
8778
  key: t,
8563
8779
  env: e.env,
8564
8780
  req: e.req.raw
8565
- }), _ = ot(t, c), v = e.body(g, 200, {
8781
+ }), _ = mt(t, c), v = e.body(g, 200, {
8566
8782
  "Content-Type": _,
8567
8783
  "Cache-Control": "public, max-age=31536000, immutable"
8568
8784
  });
@@ -8571,8 +8787,8 @@ at.get("/*", async (e) => {
8571
8787
  return console.error("❌ [Public Assets Error]:", t), e.text("Internal Server Error", 500);
8572
8788
  }
8573
8789
  });
8574
- var st = new e();
8575
- function ct(e, t) {
8790
+ var ht = new e();
8791
+ function gt(e, t) {
8576
8792
  let n = /* @__PURE__ */ new Date();
8577
8793
  if (e && String(e).trim() !== "") {
8578
8794
  let t = new Date(e);
@@ -8584,7 +8800,7 @@ function ct(e, t) {
8584
8800
  }
8585
8801
  return !0;
8586
8802
  }
8587
- st.get("/", async (e) => {
8803
+ ht.get("/", async (e) => {
8588
8804
  try {
8589
8805
  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
8806
  for (let e of n) {
@@ -8608,7 +8824,7 @@ st.get("/", async (e) => {
8608
8824
  function o(e = null, t = "") {
8609
8825
  let n = e == null || e === "" || e === "null" ? "__ROOT__" : String(e), s = i.get(n) || [];
8610
8826
  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);
8827
+ let n = a.get(String(e.treeNodeId)) || {}, i = e.status === "published" || e.status === "active", s = gt(n.startShowingAt, n.stopShowingAt);
8612
8828
  if (!i || !s) continue;
8613
8829
  let c = (e.slug || "").replace(/^\/+|\/+$/g, ""), l = c === "home" || c === "homee" ? "/" : `${t}/${c}`.replace(/\/+/g, "/");
8614
8830
  e.nodeType !== "external-link" && r.push(l);
@@ -8623,7 +8839,7 @@ st.get("/", async (e) => {
8623
8839
  return console.error("[CMS Paths API] Error:", t), e.json({ error: "Failed to fetch paths" }, 500);
8624
8840
  }
8625
8841
  });
8626
- var $ = new e(), lt = !1;
8842
+ var $ = new e(), _t = !1;
8627
8843
  $.use("*", t()), $.use("/media/*", t({
8628
8844
  origin: "*",
8629
8845
  allowMethods: [
@@ -8644,13 +8860,13 @@ $.use("*", t()), $.use("/media/*", t({
8644
8860
  let n = new URL(e.req.url), r = (e.req.header("host") || n.hostname).split(":")[0];
8645
8861
  e.set("currentDomain", r);
8646
8862
  let i = l(e);
8647
- if (e.set("db", i), !lt) try {
8648
- await _(i), lt = !0;
8863
+ if (e.set("db", i), !_t) try {
8864
+ await _(i), _t = !0;
8649
8865
  } catch (e) {
8650
8866
  console.error("❌ [CMS Server] Failed to initialize system tables on cold start:", e);
8651
8867
  }
8652
8868
  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) => {
8869
+ }), $.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
8870
  if (e.env?.ASSETS) {
8655
8871
  let t = await e.env.ASSETS.fetch(e.req.raw);
8656
8872
  if (t.status === 404) {
@@ -8662,4 +8878,4 @@ $.use("*", t()), $.use("/media/*", t({
8662
8878
  return t();
8663
8879
  });
8664
8880
  //#endregion
8665
- export { Oe as compileDefinitions };
8881
+ export { ke as compileDefinitions };