@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
package/dist/index.js CHANGED
@@ -1854,24 +1854,6 @@ var u = /* @__PURE__ */ o({
1854
1854
  },
1855
1855
  required: !0
1856
1856
  },
1857
- logoText: {
1858
- label: "Logo Text",
1859
- type: "text",
1860
- required: !1,
1861
- public: !0,
1862
- inherits: "logoText",
1863
- rules: { required: !1 }
1864
- },
1865
- logoImage: {
1866
- label: "Logo Image",
1867
- type: "image",
1868
- maxPreviewWidth: "300px",
1869
- multiple: !1,
1870
- allowedTypes: ["image/svg"],
1871
- public: !0,
1872
- inherits: "logoImage",
1873
- rules: {}
1874
- },
1875
1857
  layoutId: {
1876
1858
  label: "Page Layout",
1877
1859
  type: "layout-select",
@@ -2200,24 +2182,6 @@ var u = /* @__PURE__ */ o({
2200
2182
  },
2201
2183
  required: !0
2202
2184
  },
2203
- logoText: {
2204
- label: "Logo Text",
2205
- type: "text",
2206
- required: !1,
2207
- public: !0,
2208
- inherits: "logoText",
2209
- rules: { required: !1 }
2210
- },
2211
- logoImage: {
2212
- label: "Logo Image",
2213
- type: "image",
2214
- maxPreviewWidth: "300px",
2215
- multiple: !1,
2216
- allowedTypes: ["image/svg"],
2217
- public: !0,
2218
- inherits: "logoImage",
2219
- rules: {}
2220
- },
2221
2185
  layoutId: {
2222
2186
  label: "Page Layout",
2223
2187
  type: "layout-select",
@@ -4815,10 +4779,10 @@ var u = /* @__PURE__ */ o({
4815
4779
  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 ",
4816
4780
  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 ",
4817
4781
  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 ",
4818
- 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 ",
4782
+ 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 ",
4819
4783
  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 ",
4820
4784
  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 ",
4821
- 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 ",
4785
+ 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 ",
4822
4786
  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 ",
4823
4787
  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 ",
4824
4788
  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 ",
@@ -5583,7 +5547,7 @@ var b = { hasSubscribers: !1 }, x = b, S = b, C = typeof performance == "object"
5583
5547
  async clear() {
5584
5548
  this.cache.clear();
5585
5549
  }
5586
- }, te = class {
5550
+ }, P = class {
5587
5551
  kv;
5588
5552
  constructor(e) {
5589
5553
  this.kv = e;
@@ -5600,7 +5564,7 @@ var b = { hasSubscribers: !1 }, x = b, S = b, C = typeof performance == "object"
5600
5564
  this.kv && await this.kv.delete(e);
5601
5565
  }
5602
5566
  async clear() {}
5603
- }, P = class {
5567
+ }, te = class {
5604
5568
  async get() {
5605
5569
  return null;
5606
5570
  }
@@ -5610,7 +5574,7 @@ var b = { hasSubscribers: !1 }, x = b, S = b, C = typeof performance == "object"
5610
5574
  }, F = null;
5611
5575
  function I(e) {
5612
5576
  let t = process.env.CACHE_DRIVER || "lru";
5613
- 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();
5577
+ 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();
5614
5578
  }
5615
5579
  //#endregion
5616
5580
  //#region server/storage/local.ts
@@ -5683,7 +5647,7 @@ var L = class {
5683
5647
  if (e.code !== "ENOENT") throw e;
5684
5648
  }
5685
5649
  }
5686
- }, R = class {
5650
+ }, ne = class {
5687
5651
  async process(e, t, n) {
5688
5652
  let r = await import(
5689
5653
  /* @vite-ignore */
@@ -5710,7 +5674,7 @@ var L = class {
5710
5674
  return console.warn("⚠️ [SharpImageOptimizer] Processing failed, returning raw buffer."), e;
5711
5675
  }
5712
5676
  }
5713
- }, ne = class {
5677
+ }, re = class {
5714
5678
  bucket;
5715
5679
  publicDomain;
5716
5680
  constructor(e, t) {
@@ -5755,7 +5719,7 @@ var L = class {
5755
5719
  async delete(e) {
5756
5720
  await this.bucket.delete(e);
5757
5721
  }
5758
- }, re = class {
5722
+ }, ie = class {
5759
5723
  async process(e, t, n) {
5760
5724
  let { env: r, key: i, req: a } = n;
5761
5725
  if (r.IMAGES) try {
@@ -5792,18 +5756,18 @@ var L = class {
5792
5756
  };
5793
5757
  //#endregion
5794
5758
  //#region server/storage/factory.ts
5795
- function ie(e) {
5759
+ function ae(e) {
5796
5760
  return e.KAMA_RUNTIME === "cloudflare" || e.MEDIA_BUCKET ? {
5797
- storage: new ne(e.MEDIA_BUCKET, e.CDN_DOMAIN || ""),
5798
- optimizer: new re()
5761
+ storage: new re(e.MEDIA_BUCKET, e.CDN_DOMAIN || ""),
5762
+ optimizer: new ie()
5799
5763
  } : {
5800
5764
  storage: new L(e.LOCAL_MEDIA_PATH),
5801
- optimizer: new R()
5765
+ optimizer: new ne()
5802
5766
  };
5803
5767
  }
5804
5768
  //#endregion
5805
5769
  //#region server/utils/node-assets-interceptor.ts
5806
- function ae(e) {
5770
+ function R(e) {
5807
5771
  if (!e || typeof e != "object") return {
5808
5772
  cleanedData: e,
5809
5773
  assetRefs: []
@@ -5881,7 +5845,7 @@ function z(e) {
5881
5845
  }
5882
5846
  return null;
5883
5847
  }
5884
- async function se(e, t) {
5848
+ async function B(e, t) {
5885
5849
  if (!t || typeof t != "object") return t;
5886
5850
  let n = /* @__PURE__ */ new Set(), r = (e) => {
5887
5851
  if (!e) return;
@@ -5994,7 +5958,7 @@ async function se(e, t) {
5994
5958
  }
5995
5959
  //#endregion
5996
5960
  //#region src/utils/schema-loader.ts
5997
- function ce(e) {
5961
+ function se(e) {
5998
5962
  return e ? {
5999
5963
  nodes: e.nodes || {},
6000
5964
  trees: e.trees || {},
@@ -6013,7 +5977,7 @@ function ce(e) {
6013
5977
  }
6014
5978
  //#endregion
6015
5979
  //#region server/services/cache-manager.ts
6016
- var B = class {
5980
+ var V = class {
6017
5981
  env;
6018
5982
  constructor(e) {
6019
5983
  this.env = e || {};
@@ -6025,7 +5989,8 @@ var B = class {
6025
5989
  apiToken: e.env?.CLOUDFLARE_API_TOKEN || this.env.CLOUDFLARE_API_TOKEN,
6026
5990
  frontendUrl: (e.env?.PUBLIC_FRONTEND_URL || this.env.PUBLIC_FRONTEND_URL || "http://localhost:4321").replace(/\/+$/, ""),
6027
5991
  cdnDomain: t ? t.replace(/^https?:\/\//, "").replace(/\/+$/, "") : "localhost:8787",
6028
- frontendWorker: e.env?.FRONTEND_WORKER || this.env.FRONTEND_WORKER
5992
+ frontendWorker: e.env?.FRONTEND_WORKER || this.env.FRONTEND_WORKER,
5993
+ disableCachePurge: e.env?.DISABLE_CACHE_PURGE || this.env.DISABLE_CACHE_PURGE
6029
5994
  };
6030
5995
  }
6031
5996
  isLocalEnv(e, t) {
@@ -6049,19 +6014,33 @@ var B = class {
6049
6014
  return r && n && r.startsWith(`https://${n}/`) && !r.includes("/media/") && (r = r.replace(`https://${n}/`, `https://${n}/media/`)), r;
6050
6015
  }
6051
6016
  async callAstroPurge(e, t, n) {
6052
- let { apiToken: r, frontendUrl: i } = this.getEnv(e), a = (n || i).replace(/\/+$/, "");
6053
- if (this.isLocalEnv(e, a)) return console.log(`[CacheManager] Skipped external purge for local target: ${a}`), new Response(JSON.stringify({
6054
- success: !0,
6055
- local: !0
6056
- }), { status: 200 });
6057
- let o = `${a}/api/purge`, s = { "Content-Type": "application/json" };
6058
- return r && (s.Authorization = `Bearer ${r}`), console.log(`[CacheManager] Dispatching POST purge request to: ${o}`), fetch(o, {
6059
- method: "POST",
6060
- headers: s,
6061
- body: JSON.stringify(t)
6062
- });
6017
+ let { apiToken: r, frontendUrl: i, frontendWorker: a, disableCachePurge: o } = this.getEnv(e);
6018
+ if (o === "true" || o === !0 || o === "1") return new Response(JSON.stringify({ skipped: !0 }), { status: 200 });
6019
+ let s = (n || i).replace(/\/+$/, ""), c = `${s}/api/purge`, l = { "Content-Type": "application/json" };
6020
+ if (r && (l.Authorization = `Bearer ${r}`), a && typeof a.fetch == "function") try {
6021
+ return await a.fetch(new Request(c, {
6022
+ method: "POST",
6023
+ headers: l,
6024
+ body: JSON.stringify(t)
6025
+ }));
6026
+ } catch (e) {
6027
+ return console.info(`[CacheManager] Worker binding purge call to ${c} failed silently:`, e?.message || e), new Response(JSON.stringify({ error: e?.message }), { status: 502 });
6028
+ }
6029
+ try {
6030
+ let e = new AbortController(), n = setTimeout(() => e.abort(), 1500);
6031
+ console.log(`[CacheManager] Dispatching POST purge request to: ${c}`);
6032
+ let r = await fetch(c, {
6033
+ method: "POST",
6034
+ headers: l,
6035
+ body: JSON.stringify(t),
6036
+ signal: e.signal
6037
+ });
6038
+ return clearTimeout(n), r;
6039
+ } catch (e) {
6040
+ 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 });
6041
+ }
6063
6042
  }
6064
- async purgeInternalWorkerCache(e, t, n, r, i = "en") {
6043
+ async purgeInternalWorkerCache(e, t, n, r, i) {
6065
6044
  try {
6066
6045
  let a = I(e);
6067
6046
  if (n) {
@@ -6074,7 +6053,7 @@ var B = class {
6074
6053
  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 || [];
6075
6054
  i.length > 0 && (o = i.flatMap((e) => [String(e.id), e.key]).filter(Boolean));
6076
6055
  }
6077
- for (let t of o) await a.delete(`node:${t}:${i}:${e}`), await a.delete(`node:${t}:${i}:/${e}`);
6056
+ 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}`);
6078
6057
  }
6079
6058
  } catch (e) {
6080
6059
  console.warn("[CacheManager] Failed to purge internal worker cache:", e);
@@ -6085,30 +6064,30 @@ var B = class {
6085
6064
  try {
6086
6065
  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]) || {};
6087
6066
  if (!a.slug) return;
6088
- 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();
6089
- for (let e of u) if (e.baseUrl && typeof e.baseUrl == "string" && e.baseUrl.trim() !== "") {
6067
+ 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();
6068
+ for (let e of c) if (e.baseUrl && typeof e.baseUrl == "string" && e.baseUrl.trim() !== "") {
6090
6069
  let t = e.baseUrl.trim();
6091
- !t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), f.add(t.replace(/\/+$/, ""));
6070
+ !t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), p.add(t.replace(/\/+$/, ""));
6092
6071
  }
6093
- f.size === 0 && d && f.add(d);
6094
- 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);
6095
- await this.purgeInternalWorkerCache(e, t, n, s, o);
6096
- let g = this.getEnv(e).cdnDomain, { zoneId: _, apiToken: v } = this.getEnv(e);
6097
- for (let t of f) {
6098
- let n = s === "home" || !s ? t : `${t}/${s}`, i = [n, `${n}/`];
6099
- 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}`);
6100
- else i.push(`https://${g}/api/v1/node/${s}?lang=${o}`);
6101
- for (let e of h) e && i.push(`${t}${e.startsWith("/") ? e : `/${e}`}`);
6102
- if (await this.callAstroPurge(e, { urls: i }, t), _ && v && !this.isLocalEnv(e, t) && fetch(`https://api.cloudflare.com/client/v4/zones/${_}/purge_cache`, {
6072
+ p.size === 0 && f && p.add(f);
6073
+ 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);
6074
+ await this.purgeInternalWorkerCache(e, t, n, d, u);
6075
+ let _ = this.getEnv(e).cdnDomain, { zoneId: v, apiToken: y } = this.getEnv(e);
6076
+ for (let t of p) {
6077
+ let n = d === "home" || !d ? t : `${t}/${d}`, i = [n, `${n}/`], a = u ? `&lang=${u}` : "";
6078
+ 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}`);
6079
+ else i.push(`https://${_}/api/v1/node/${d}${u ? `?lang=${u}` : ""}`);
6080
+ for (let e of g) e && i.push(`${t}${e.startsWith("/") ? e : `/${e}`}`);
6081
+ 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`, {
6103
6082
  method: "POST",
6104
6083
  headers: {
6105
- Authorization: `Bearer ${v}`,
6084
+ Authorization: `Bearer ${y}`,
6106
6085
  "Content-Type": "application/json"
6107
6086
  },
6108
6087
  body: JSON.stringify({ files: i })
6109
6088
  }).catch(() => {}), !r) {
6110
6089
  let e = `${n}${n.includes("?") ? "&" : "?"} _warmer=${Date.now()}`;
6111
- console.log(`[CacheManager] Prewarming cache at: ${e}`), await fetch(e, { headers: {
6090
+ console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
6112
6091
  "X-Cache-Warmer": "true",
6113
6092
  "User-Agent": "Kama-Cache-Warmer/1.0"
6114
6093
  } }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
@@ -6137,35 +6116,49 @@ var B = class {
6137
6116
  }
6138
6117
  async purgeGlobalCacheDirect(e, t) {
6139
6118
  try {
6140
- let { zoneId: n, apiToken: r, frontendUrl: i } = this.getEnv(e);
6141
- if (this.isLocalEnv(e) || !(await this.callAstroPurge(e, { purge_everything: !0 })).ok) return;
6142
- n && r && fetch(`https://api.cloudflare.com/client/v4/zones/${n}/purge_cache`, {
6119
+ let { zoneId: n, apiToken: r } = this.getEnv(e);
6120
+ if (!(await this.callAstroPurge(e, { purge_everything: !0 })).ok) return;
6121
+ if (n && r && !this.isLocalEnv(e) && fetch(`https://api.cloudflare.com/client/v4/zones/${n}/purge_cache`, {
6143
6122
  method: "POST",
6144
6123
  headers: {
6145
6124
  Authorization: `Bearer ${r}`,
6146
6125
  "Content-Type": "application/json"
6147
6126
  },
6148
6127
  body: JSON.stringify({ purge_everything: !0 })
6149
- }).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(() => {});
6128
+ }).catch(() => {}), await new Promise((e) => setTimeout(e, 100)), t) await this.warmAllPublishedPages(e, t);
6129
+ else {
6130
+ let { frontendUrl: t } = this.getEnv(e);
6131
+ fetch(`${t.replace(/\/+$/, "")}/?_warmer=${Date.now()}`, { headers: { "X-Cache-Warmer": "true" } }).catch(() => {});
6132
+ }
6150
6133
  } catch (e) {
6151
6134
  console.warn("[CacheManager] Direct Global Purge skipped:", e);
6152
6135
  }
6153
6136
  }
6154
6137
  async warmAllPublishedPages(e, t) {
6155
6138
  try {
6156
- let { frontendUrl: n } = this.getEnv(e);
6157
- if (this.isLocalEnv(e)) return;
6158
- 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) => {
6159
- let t = String(e.slug).replace(/^\/+|\/+$/g, ""), r = t === "home" || !t ? n : `${n}/${t}`;
6160
- return fetch(`${r}?_warmer=${s}`, { headers: o }).catch(() => {});
6161
- });
6162
- c.push(fetch(`${n}/?_warmer=${s}`, { headers: o }).catch(() => {})), await Promise.all(c);
6139
+ 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 = {
6140
+ "X-Cache-Warmer": "true",
6141
+ "User-Agent": "Kama-Cache-Warmer/1.0"
6142
+ }, s = Date.now(), c = /* @__PURE__ */ new Set();
6143
+ for (let e of i) {
6144
+ let t = String(e.slug).replace(/^\/+|\/+$/g, ""), n = a;
6145
+ 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(/\/+$/, ""));
6146
+ let r = t === "home" || !t ? n : `${n}/${t}`;
6147
+ c.add(`${r}?_warmer=${s}`);
6148
+ }
6149
+ c.add(`${a}/?_warmer=${s}`);
6150
+ let l = Array.from(c);
6151
+ for (let e = 0; e < l.length; e += 6) {
6152
+ let t = l.slice(e, e + 6);
6153
+ await Promise.all(t.map((e) => fetch(e, { headers: o }).catch((t) => console.warn(`[CacheWarmer] Skipped prewarm for ${e}:`, t?.message || t))));
6154
+ }
6155
+ console.log(`[CacheWarmer] Prewarmed ${l.length} published pages across ${Math.ceil(l.length / 6)} batches.`);
6163
6156
  } catch (e) {
6164
6157
  console.warn("⚠️ [CacheWarmer] Tree-wide warming failed:", e);
6165
6158
  }
6166
6159
  }
6167
- }, V = new e();
6168
- async function le(e, t, n = []) {
6160
+ }, H = new e();
6161
+ async function ce(e, t, n = []) {
6169
6162
  let r = e.prepare(t);
6170
6163
  if (typeof r.bind == "function") {
6171
6164
  let e = await r.bind(...n).all();
@@ -6177,24 +6170,25 @@ async function le(e, t, n = []) {
6177
6170
  }
6178
6171
  return [];
6179
6172
  }
6180
- async function ue(e, t, n = []) {
6173
+ async function le(e, t, n = []) {
6181
6174
  let r = e.prepare(t);
6182
6175
  if (typeof r.bind == "function") return r.bind(...n).run();
6183
6176
  if (typeof r.run == "function") return r.run(...n);
6184
6177
  }
6185
- function de(e) {
6178
+ function U(e) {
6186
6179
  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;
6187
6180
  }
6188
- function fe(e) {
6181
+ function ue(e) {
6189
6182
  return +(e === !0 || e === 1 || e === "1" || e === "true");
6190
6183
  }
6191
- function pe(e) {
6184
+ function de(e) {
6192
6185
  if (e == null || e === "null" || e === "" || typeof e == "string" && e.startsWith("draft-")) return null;
6193
6186
  let t = Number(e);
6194
6187
  return isNaN(t) ? null : t;
6195
6188
  }
6196
- function H(e) {
6189
+ function fe(e) {
6197
6190
  let t = { ...e };
6191
+ delete t.language, delete t.defaultLanguage;
6198
6192
  for (let e of [
6199
6193
  "id",
6200
6194
  "treeNodeId",
@@ -6205,7 +6199,6 @@ function H(e) {
6205
6199
  "contentType",
6206
6200
  "title",
6207
6201
  "slug",
6208
- "language",
6209
6202
  "hidden",
6210
6203
  "is_hidden",
6211
6204
  "isHidden",
@@ -6222,17 +6215,22 @@ function H(e) {
6222
6215
  ]) delete t[e];
6223
6216
  return t;
6224
6217
  }
6225
- function me(e, t = /* @__PURE__ */ new Set()) {
6226
- 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;
6218
+ function pe(e, t = /* @__PURE__ */ new Set()) {
6219
+ 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;
6220
+ }
6221
+ function me(e, t) {
6222
+ if (!e) return !0;
6223
+ 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;
6224
+ return n || r || i || a || c;
6227
6225
  }
6228
- async function U(e, t, n) {
6226
+ async function he(e, t, n) {
6229
6227
  for (let r of n) {
6230
- let n = (await le(e, "\n SELECT id, storageKeyPrivate, isSystemVariant, parentAssetId, filename\n FROM assets WHERE id = ?\n ", [r]))[0];
6231
- if (!n || (await le(e, "SELECT 1 FROM node_assets WHERE assetId = ? LIMIT 1", [n.id])).length > 0) continue;
6228
+ let n = (await ce(e, "\n SELECT id, storageKeyPrivate, isSystemVariant, parentAssetId, filename\n FROM assets WHERE id = ?\n ", [r]))[0];
6229
+ if (!n || (await ce(e, "SELECT 1 FROM node_assets WHERE assetId = ? LIMIT 1", [n.id])).length > 0) continue;
6232
6230
  let i = [n];
6233
6231
  if (!n.isSystemVariant) {
6234
- 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);
6235
- if (r.length > 0 && (await le(e, `SELECT DISTINCT assetId FROM node_assets WHERE assetId IN (${r.map(() => "?").join(",")})`, r)).length > 0) continue;
6232
+ 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);
6233
+ if (r.length > 0 && (await ce(e, `SELECT DISTINCT assetId FROM node_assets WHERE assetId IN (${r.map(() => "?").join(",")})`, r)).length > 0) continue;
6236
6234
  i = [n, ...t];
6237
6235
  }
6238
6236
  for (let e of i) if (e.storageKeyPrivate) try {
@@ -6241,10 +6239,10 @@ async function U(e, t, n) {
6241
6239
  console.warn(`[Asset Cleanup] Failed to delete ${e.storageKeyPrivate}:`, t);
6242
6240
  }
6243
6241
  let a = i.map((e) => e.id), o = a.map(() => "?").join(",");
6244
- await ue(e, `DELETE FROM node_assets WHERE assetId IN (${o})`, a), await ue(e, `DELETE FROM assets WHERE id IN (${o})`, a);
6242
+ await le(e, `DELETE FROM node_assets WHERE assetId IN (${o})`, a), await le(e, `DELETE FROM assets WHERE id IN (${o})`, a);
6245
6243
  }
6246
6244
  }
6247
- async function W(e, t, n) {
6245
+ async function ge(e, t, n) {
6248
6246
  let r = {}, i = null;
6249
6247
  if (t) {
6250
6248
  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 || [];
@@ -6258,7 +6256,7 @@ async function W(e, t, n) {
6258
6256
  }
6259
6257
  }
6260
6258
  if (!i) {
6261
- let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ?").get(n);
6259
+ let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ? OR key = ? LIMIT 1").get(Number(n) || -1, String(n));
6262
6260
  if (t && t.dataJson) try {
6263
6261
  let e = typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson;
6264
6262
  e.subpageLayoutId && e.subpageLayoutId !== "inherit" && (i = e.subpageLayoutId);
@@ -6269,7 +6267,7 @@ async function W(e, t, n) {
6269
6267
  inheritedFields: r
6270
6268
  };
6271
6269
  }
6272
- V.get("/", async (e) => {
6270
+ H.get("/", async (e) => {
6273
6271
  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));
6274
6272
  if (n) {
6275
6273
  let r = Number(n);
@@ -6280,7 +6278,7 @@ V.get("/", async (e) => {
6280
6278
  id: i.id,
6281
6279
  title: i.title,
6282
6280
  slug: i.slug,
6283
- language: i.language || "en",
6281
+ language: i.language || null,
6284
6282
  nodeType: i.contentType,
6285
6283
  contentType: i.contentType,
6286
6284
  isHidden: !!i.isHidden,
@@ -6294,9 +6292,9 @@ V.get("/", async (e) => {
6294
6292
  updatedAt: i.updatedAt
6295
6293
  }, s = i.draftDataJson || i.dataJson;
6296
6294
  if (s) try {
6297
- 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;
6295
+ 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;
6298
6296
  if (a) {
6299
- let { resolvedLayoutId: e, inheritedFields: r } = await W(t, a.parentId, a.treeId);
6297
+ let { resolvedLayoutId: e, inheritedFields: r } = await ge(t, a.parentId, a.treeId);
6300
6298
  (l === "inherit" || !l) && (l = e);
6301
6299
  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);
6302
6300
  }
@@ -6311,7 +6309,7 @@ V.get("/", async (e) => {
6311
6309
  let r = t.allowedLayouts;
6312
6310
  return r ? typeof r == "string" ? r === e : !Array.isArray(r) || r.length === 0 || r.includes(e) : !0;
6313
6311
  })(l) && (l = null), (l === "inherit" || !l) && (l = c.defaultLayout || null);
6314
- let u = await se(t, H(n));
6312
+ let u = await B(t, fe(n));
6315
6313
  Object.assign(o, u), o.resolvedLayoutId = l;
6316
6314
  } catch {}
6317
6315
  let c = await t.prepare("SELECT channelId FROM node_channels WHERE nodeId = ?").all(r);
@@ -6321,7 +6319,7 @@ V.get("/", async (e) => {
6321
6319
  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) => {
6322
6320
  let n = {};
6323
6321
  try {
6324
- n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson || "{}") : e.dataJson || {}, n && typeof n == "object" && (n = await se(t, n));
6322
+ n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson || "{}") : e.dataJson || {}, n && typeof n == "object" && (n = await B(t, n));
6325
6323
  } catch {
6326
6324
  n = {};
6327
6325
  }
@@ -6392,7 +6390,7 @@ V.get("/", async (e) => {
6392
6390
  id: e.id,
6393
6391
  title: e.title,
6394
6392
  slug: e.slug,
6395
- language: e.language || "en",
6393
+ language: e.language || null,
6396
6394
  contentType: e.contentType,
6397
6395
  nodeType: e.contentType,
6398
6396
  isHidden: !!e.isHidden,
@@ -6409,7 +6407,7 @@ V.get("/", async (e) => {
6409
6407
  assetCount: e.assetCount || 0
6410
6408
  }, i = e.draftDataJson || e.dataJson;
6411
6409
  if (i) try {
6412
- let e = typeof i == "string" ? JSON.parse(i) : i, n = await se(t, H(e));
6410
+ let e = typeof i == "string" ? JSON.parse(i) : i, n = await B(t, fe(e));
6413
6411
  Object.assign(r, n);
6414
6412
  } catch {}
6415
6413
  return r;
@@ -6421,13 +6419,35 @@ V.get("/", async (e) => {
6421
6419
  offset: p,
6422
6420
  limit: f
6423
6421
  });
6424
- }), V.post("/", async (e) => {
6425
- 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);
6426
- if (E) {
6422
+ }), H.post("/", async (e) => {
6423
+ 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;
6424
+ if (T) {
6425
+ let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ? OR key = ? LIMIT 1").get(Number(T) || -1, String(T));
6426
+ if (e?.dataJson) try {
6427
+ let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
6428
+ E = t.defaultLanguage?.trim() || t.language?.trim() || null;
6429
+ } catch {}
6430
+ }
6431
+ if (!E && h && Array.isArray(h) && h.length > 0) {
6432
+ let e = typeof h[0] == "object" ? h[0].id : h[0];
6433
+ if (e && e !== "all") {
6434
+ let n = await t.prepare("SELECT defaultLanguage, dataJson FROM channels WHERE id = ? LIMIT 1").get(Number(e));
6435
+ if (n) {
6436
+ if (n.defaultLanguage) E = n.defaultLanguage.trim();
6437
+ else if (n.dataJson) try {
6438
+ let e = typeof n.dataJson == "string" ? JSON.parse(n.dataJson) : n.dataJson;
6439
+ E = e.defaultLanguage?.trim() || e.language?.trim() || null;
6440
+ } catch {}
6441
+ }
6442
+ }
6443
+ }
6444
+ C && E && C === E && (C = null);
6445
+ let D = a, O = /* @__PURE__ */ new Set(), k = !1, A = s === void 0 ? null : U(s);
6446
+ if (A) {
6427
6447
  let n = [];
6428
6448
  if (g !== void 0 && Array.isArray(g) && g.length > 0) for (let e of g) n.push({
6429
6449
  treeId: Number(e.treeId),
6430
- parentId: pe(e.parentId ?? e._draftParentId ?? null)
6450
+ parentId: de(e.parentId ?? e._draftParentId ?? null)
6431
6451
  });
6432
6452
  else if (a) {
6433
6453
  let e = await t.prepare("SELECT treeId, parentId FROM tree_nodes WHERE contentId = ?").all(a), r = Array.isArray(e) ? e : e?.results || [];
@@ -6437,94 +6457,103 @@ V.get("/", async (e) => {
6437
6457
  });
6438
6458
  }
6439
6459
  for (let r of n) {
6440
- let n = r.parentId === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = r.parentId === null ? [r.treeId, E] : [
6460
+ let n = r.parentId === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = r.parentId === null ? [r.treeId, A] : [
6441
6461
  r.treeId,
6442
6462
  r.parentId,
6443
- E
6463
+ A
6444
6464
  ], o = `
6445
6465
  SELECT cn.id FROM tree_nodes tn
6446
6466
  INNER JOIN content_nodes cn ON tn.contentId = cn.id
6447
6467
  WHERE tn.treeId = ? AND ${n} AND cn.slug = ? AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
6448
6468
  `;
6449
6469
  if (a && (o += " AND cn.id != ?", i.push(a)), o += " LIMIT 1", await t.prepare(o).get(...i)) return e.json({
6450
- error: `The slug '${E}' is already in use by another page in this section.`,
6470
+ error: `The slug '${A}' is already in use by another page in this section.`,
6451
6471
  field: "slug"
6452
6472
  }, 409);
6453
6473
  }
6454
6474
  }
6455
6475
  if (a) {
6456
- 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 || "{}";
6476
+ let e = await t.prepare("SELECT title, slug, language, contentType, isHidden, draftDataJson, dataJson, publishedAt, status FROM content_nodes WHERE id = ?").get(a);
6477
+ k = me(e, {
6478
+ title: o,
6479
+ slug: A,
6480
+ isHidden: b,
6481
+ sanitizedFields: v
6482
+ });
6483
+ let n = e?.draftDataJson || e?.dataJson || "{}";
6457
6484
  try {
6458
- me(typeof n == "string" ? JSON.parse(n) : n, T);
6485
+ pe(typeof n == "string" ? JSON.parse(n) : n, O);
6459
6486
  } catch {}
6460
6487
  if (m !== void 0) {
6461
6488
  let e = await t.prepare("SELECT dataJson FROM content_blocks WHERE contentId = ? AND isDraft = 1").all(a);
6462
6489
  (Array.isArray(e) ? e : e?.results || []).forEach((e) => {
6463
6490
  try {
6464
- me(typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson, T);
6491
+ pe(typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson, O);
6465
6492
  } catch {}
6466
6493
  });
6467
6494
  }
6468
- 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 = {};
6495
+ 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 = {};
6469
6496
  try {
6470
- u = JSON.parse(l);
6497
+ d = JSON.parse(u);
6471
6498
  } catch {}
6472
- let d = JSON.stringify({
6473
- ...u,
6499
+ let f = JSON.stringify({
6500
+ ...d,
6474
6501
  ...v
6475
- }), f = e?.status === "published" || e?.publishedAt ? "published" : "draft", p = +(f === "published");
6476
- 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);
6502
+ }), p = e?.status === "published" || e?.publishedAt ? "published" : "draft", h = +(p === "published");
6503
+ 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);
6477
6504
  } else {
6478
- 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);
6479
- w = Number(e.lastInsertRowid);
6505
+ k = !0;
6506
+ 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);
6507
+ D = Number(e.lastInsertRowid);
6480
6508
  }
6481
- if (h !== void 0 && Array.isArray(h) && w) {
6482
- await t.prepare("DELETE FROM node_channels WHERE nodeId = ?").run(w);
6509
+ if (h !== void 0 && Array.isArray(h) && D) {
6510
+ await t.prepare("DELETE FROM node_channels WHERE nodeId = ?").run(D);
6483
6511
  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);
6484
6512
  if (e.length > 0) {
6485
- let n = e.map(() => "(?, ?)").join(", "), r = e.flatMap((e) => [w, e]);
6513
+ let n = e.map(() => "(?, ?)").join(", "), r = e.flatMap((e) => [D, e]);
6486
6514
  await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${n}`).run(...r);
6487
6515
  }
6488
6516
  }
6489
- if (g !== void 0 && Array.isArray(g) && g.length > 0 && w) for (let e of g) {
6517
+ if (g !== void 0 && Array.isArray(g) && g.length > 0 && D) for (let e of g) {
6490
6518
  if (!e || !e.treeId) continue;
6491
- 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);
6492
- 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);
6519
+ 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);
6520
+ 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));
6493
6521
  }
6494
- let D = [];
6495
- if (m !== void 0 && Array.isArray(m) && w) {
6496
- await t.prepare("DELETE FROM content_blocks WHERE contentId = ? AND isDraft = 1").run(w);
6522
+ let j = [];
6523
+ if (m !== void 0 && Array.isArray(m) && D) {
6524
+ await t.prepare("DELETE FROM content_blocks WHERE contentId = ? AND isDraft = 1").run(D);
6497
6525
  let e = [], n = [];
6498
6526
  for (let t = 0; t < m.length; t++) {
6499
- 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({
6527
+ 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({
6500
6528
  ...a,
6501
6529
  blockId: o,
6502
6530
  _instanceId: o
6503
6531
  });
6504
- c.forEach((e) => D.push({
6532
+ c.forEach((e) => j.push({
6505
6533
  ...e,
6506
6534
  fieldKey: `blocks[${t}].${e.fieldKey}`
6507
6535
  }));
6508
6536
  let l = r.region !== void 0 && r.region !== null && String(r.region).trim() !== "" ? String(r.region) : "content";
6509
- e.push("(?, ?, ?, ?, ?, 1)"), n.push(w, t, i, JSON.stringify(s), l);
6537
+ e.push("(?, ?, ?, ?, ?, 1)"), n.push(D, t, i, JSON.stringify(s), l);
6510
6538
  }
6511
6539
  e.length > 0 && await t.prepare(`INSERT INTO content_blocks (contentId, sortOrder, elementType, dataJson, region, isDraft) VALUES ${e.join(", ")}`).run(...n);
6512
6540
  }
6513
- if (w) {
6514
- let n = [...y, ...D];
6515
- await oe(t, w, n);
6516
- let r = new Set(n.map((e) => e.assetId)), i = new Set([...T].filter((e) => !r.has(e)));
6541
+ if (D) {
6542
+ let n = [...y, ...j];
6543
+ await oe(t, D, n);
6544
+ let r = new Set(n.map((e) => e.assetId)), i = new Set([...O].filter((e) => !r.has(e)));
6517
6545
  if (i.size > 0) {
6518
- let { storage: n } = ie(e.env);
6519
- await U(t, n, i);
6546
+ let { storage: n } = ae(e.env);
6547
+ await he(t, n, i);
6520
6548
  }
6521
6549
  }
6522
- return await I(e).clear(), e.json({
6550
+ return await I(e).clear(), D && new V(e.env).purgeNode(e, t, D, k), e.json({
6523
6551
  success: !0,
6524
- id: w,
6525
- status: "draft"
6552
+ id: D,
6553
+ status: "draft",
6554
+ isStructuralChange: k
6526
6555
  });
6527
- }), V.post("/publish", async (e) => {
6556
+ }), H.post("/publish", async (e) => {
6528
6557
  let t = e.get("db"), n = await e.req.json(), r = n.id || n.nodeId;
6529
6558
  if (!r || isNaN(Number(r))) return e.json({ error: "Node ID required for publishing" }, 400);
6530
6559
  let i = Number(r), a = e.get("user")?.id || null, o = await t.prepare("SELECT * FROM content_nodes WHERE id = ?").get(i);
@@ -6537,57 +6566,58 @@ V.get("/", async (e) => {
6537
6566
  try {
6538
6567
  c = typeof o.draftDataJson == "string" ? JSON.parse(o.draftDataJson) : o.draftDataJson || {};
6539
6568
  } catch {}
6540
- 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 || "{}";
6541
- 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);
6542
- 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 || [];
6543
- if (g.length > 0) {
6569
+ 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 || "{}";
6570
+ 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);
6571
+ let _ = await t.prepare("SELECT * FROM content_blocks WHERE contentId = ? AND isDraft = 1 ORDER BY sortOrder ASC").all(i), v = Array.isArray(_) ? _ : _?.results || [];
6572
+ if (v.length > 0) {
6544
6573
  let e = [], n = [];
6545
- for (let t of g) {
6574
+ for (let t of v) {
6546
6575
  let r = t.region !== void 0 && t.region !== null && String(t.region).trim() !== "" ? String(t.region) : "content";
6547
6576
  e.push("(?, ?, ?, ?, ?, 0)"), n.push(i, t.sortOrder, t.elementType, t.dataJson, r);
6548
6577
  }
6549
6578
  await t.prepare(`INSERT INTO content_blocks (contentId, sortOrder, elementType, dataJson, region, isDraft) VALUES ${e.join(", ")}`).run(...n);
6550
6579
  }
6551
- let _ = ((await t.prepare("SELECT COUNT(*) as count FROM node_revisions WHERE nodeId = ?").get(i))?.count || 0) + 1, v = {
6552
- version: _,
6580
+ let y = ((await t.prepare("SELECT COUNT(*) as count FROM node_revisions WHERE nodeId = ?").get(i))?.count || 0) + 1, b = {
6581
+ version: y,
6553
6582
  publishedAt: (/* @__PURE__ */ new Date()).toISOString(),
6554
6583
  node: {
6555
6584
  ...o,
6556
- dataJson: m
6585
+ dataJson: g
6557
6586
  },
6558
- blocks: g
6587
+ blocks: v
6559
6588
  };
6560
- 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({
6589
+ 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({
6561
6590
  success: !0,
6562
6591
  id: i,
6563
6592
  status: "published",
6564
- version: _,
6565
- publishedAt: v.publishedAt,
6566
- hasUnpublishedChanges: !1
6593
+ version: y,
6594
+ publishedAt: b.publishedAt,
6595
+ hasUnpublishedChanges: !1,
6596
+ isStructuralChange: h
6567
6597
  });
6568
- }), V.delete("/", async (e) => {
6598
+ }), H.delete("/", async (e) => {
6569
6599
  let t = e.get("db"), n = e.req.query("id");
6570
6600
  if (!n) return e.json({ error: "Node ID required" }, 400);
6571
6601
  let r = Number(n);
6572
- 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({
6602
+ 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({
6573
6603
  success: !0,
6574
6604
  deletedNodeId: r
6575
6605
  });
6576
- }), V.post("/restore", async (e) => {
6606
+ }), H.post("/restore", async (e) => {
6577
6607
  let t = e.get("db"), n = await e.req.json(), r = Number(n.id);
6578
- 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({
6608
+ 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({
6579
6609
  success: !0,
6580
6610
  restoredNodeId: r
6581
6611
  })) : e.json({ error: "Node not found" }, 404) : e.json({ error: "Node ID required" }, 400);
6582
- }), V.delete("/purge", async (e) => {
6612
+ }), H.delete("/purge", async (e) => {
6583
6613
  let t = e.get("db"), n = e.req.query("id");
6584
6614
  if (!n) return e.json({ error: "Node ID required" }, 400);
6585
6615
  let r = Number(n);
6586
- 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({
6616
+ 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({
6587
6617
  success: !0,
6588
6618
  purgedNodeId: r
6589
6619
  });
6590
- }), V.get("/:id/revisions", async (e) => {
6620
+ }), H.get("/:id/revisions", async (e) => {
6591
6621
  let t = e.get("db"), n = Number(e.req.param("id"));
6592
6622
  if (isNaN(n)) return e.json({ error: "Invalid Node ID" }, 400);
6593
6623
  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) => {
@@ -6603,7 +6633,7 @@ V.get("/", async (e) => {
6603
6633
  };
6604
6634
  });
6605
6635
  return e.json({ revisions: i });
6606
- }), V.get("/:id/revisions/:version", async (e) => {
6636
+ }), H.get("/:id/revisions/:version", async (e) => {
6607
6637
  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);
6608
6638
  if (!i) return e.json({ error: "Snapshot not found" }, 404);
6609
6639
  let a = {};
@@ -6613,7 +6643,7 @@ V.get("/", async (e) => {
6613
6643
  return e.json({ error: "Corrupt snapshot data" }, 500);
6614
6644
  }
6615
6645
  return e.json({ snapshot: a });
6616
- }), V.post("/:id/revisions/:version/restore", async (e) => {
6646
+ }), H.post("/:id/revisions/:version/restore", async (e) => {
6617
6647
  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);
6618
6648
  if (!a) return e.json({ error: "Snapshot not found" }, 404);
6619
6649
  let o = {};
@@ -6634,8 +6664,8 @@ V.get("/", async (e) => {
6634
6664
  });
6635
6665
  //#endregion
6636
6666
  //#region server/routes/admin/trees.ts
6637
- var G = new e();
6638
- function he(e, t = null) {
6667
+ var W = new e();
6668
+ function _e(e, t = null) {
6639
6669
  let n = [];
6640
6670
  for (let r = 0; r < e.length; r++) {
6641
6671
  let i = e[r];
@@ -6647,19 +6677,19 @@ function he(e, t = null) {
6647
6677
  id: o,
6648
6678
  parentId: t,
6649
6679
  sortOrder: r
6650
- }), i.children && Array.isArray(i.children) && i.children.length > 0 && n.push(...he(i.children, o)));
6680
+ }), i.children && Array.isArray(i.children) && i.children.length > 0 && n.push(..._e(i.children, o)));
6651
6681
  }
6652
6682
  return n;
6653
6683
  }
6654
- function ge(e) {
6684
+ function G(e) {
6655
6685
  if (e == null || e === "null" || e === "" || typeof e == "string" && e.startsWith("draft-")) return null;
6656
6686
  let t = Number(e);
6657
6687
  return isNaN(t) ? null : t;
6658
6688
  }
6659
- function _e(e) {
6689
+ function ve(e) {
6660
6690
  return +(e === !0 || e === 1 || e === "1" || e === "true");
6661
6691
  }
6662
- G.get("/tree.json", async (e) => {
6692
+ W.get("/tree.json", async (e) => {
6663
6693
  try {
6664
6694
  let t = e.get("db"), n = e.req.query("treeId") || "main-nav", r = e.req.query("preview") === "true", i = 1;
6665
6695
  if (isNaN(Number(n))) {
@@ -6694,7 +6724,7 @@ G.get("/tree.json", async (e) => {
6694
6724
  id: e.contentId,
6695
6725
  treeNodeId: e.treeNodeId,
6696
6726
  parentId: e.parentId || null,
6697
- language: e.language || "en",
6727
+ language: e.language?.trim() || null,
6698
6728
  hidden: +!!s,
6699
6729
  isHidden: s,
6700
6730
  status: e.status || "draft",
@@ -6709,9 +6739,9 @@ G.get("/tree.json", async (e) => {
6709
6739
  } catch (t) {
6710
6740
  return console.error("[CMS Tree API] GET Error:", t), e.json({ error: t.message || "Failed to fetch tree" }, 500);
6711
6741
  }
6712
- }), G.post("/tree.json", async (e) => {
6742
+ }), W.post("/tree.json", async (e) => {
6713
6743
  try {
6714
- 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;
6744
+ 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;
6715
6745
  if (isNaN(Number(r))) {
6716
6746
  let e = await t.prepare("SELECT id FROM trees WHERE key = ?").get(r);
6717
6747
  if (e && e.id) o = Number(e.id);
@@ -6721,7 +6751,7 @@ G.get("/tree.json", async (e) => {
6721
6751
  }
6722
6752
  } else o = Number(r);
6723
6753
  if (n.tree && Array.isArray(n.tree)) {
6724
- let r = he(n.tree, null);
6754
+ let r = _e(n.tree, null);
6725
6755
  if (r.length > 0) for (let e = 0; e < r.length; e += 50) {
6726
6756
  let n = r.slice(e, e + 50), i = n.map((e) => e.id), a = i.map(() => "?").join(","), s = "UPDATE tree_nodes SET \n";
6727
6757
  s += "parentId = CASE id \n", n.forEach(() => {
@@ -6741,9 +6771,9 @@ G.get("/tree.json", async (e) => {
6741
6771
  reorderedCount: r.length
6742
6772
  });
6743
6773
  }
6744
- 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);
6774
+ 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);
6745
6775
  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;
6746
- let g = ge(u), _ = e.get("user")?.id || null;
6776
+ let g = G(u), _ = e.get("user")?.id || null;
6747
6777
  if (s === "create") {
6748
6778
  let r = m.slug || n.slug || c, s = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
6749
6779
  if (s) {
@@ -6765,23 +6795,41 @@ G.get("/tree.json", async (e) => {
6765
6795
  field: "slug"
6766
6796
  }, 409);
6767
6797
  }
6768
- 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);
6769
- await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, f);
6770
- let p = g === null ? "parentId IS NULL" : "parentId = ?", v = g === null ? [o] : [o, g], y = (await t.prepare(`
6798
+ let u = m.language?.trim() || n.language?.trim() || null;
6799
+ if (!u) {
6800
+ let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ?").get(o);
6801
+ if (e?.dataJson) try {
6802
+ let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
6803
+ t.defaultLanguage && (u = t.defaultLanguage.trim());
6804
+ } catch {}
6805
+ }
6806
+ if (!u) {
6807
+ let e = [];
6808
+ if (n.channels && Array.isArray(n.channels) ? e = n.channels : n.channelId && n.channelId !== "all" && (e = [n.channelId]), e.length > 0) {
6809
+ let n = Number(e[0]);
6810
+ if (!isNaN(n)) {
6811
+ let e = await t.prepare("SELECT defaultLanguage FROM channels WHERE id = ?").get(n);
6812
+ e?.defaultLanguage && (u = e.defaultLanguage.trim());
6813
+ }
6814
+ }
6815
+ }
6816
+ 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);
6817
+ await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, p);
6818
+ let v = g === null ? "parentId IS NULL" : "parentId = ?", y = g === null ? [o] : [o, g], b = (await t.prepare(`
6771
6819
  SELECT COALESCE(MAX(sortOrder), -1) + 1 as nextSort
6772
6820
  FROM tree_nodes
6773
- WHERE treeId = ? AND ${p}
6774
- `).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 = [];
6775
- n.channels && Array.isArray(n.channels) ? S = n.channels : n.channelId && n.channelId !== "all" && (S = [n.channelId]);
6776
- let C = [...new Set(S)].filter((e) => e && e !== "all").map((e) => Number(e));
6777
- if (C.length > 0) {
6778
- let e = C.map(() => "(?, ?)").join(", "), n = C.flatMap((e) => [f, e]);
6821
+ WHERE treeId = ? AND ${v}
6822
+ `).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 = [];
6823
+ n.channels && Array.isArray(n.channels) ? C = n.channels : n.channelId && n.channelId !== "all" && (C = [n.channelId]);
6824
+ let w = [...new Set(C)].filter((e) => e && e !== "all").map((e) => Number(e));
6825
+ if (w.length > 0) {
6826
+ let e = w.map(() => "(?, ?)").join(", "), n = w.flatMap((e) => [p, e]);
6779
6827
  await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...n);
6780
6828
  }
6781
6829
  return await i.clear(), a.purgeGlobalCache(e, t), e.json({
6782
6830
  success: !0,
6783
- id: f,
6784
- treeNodeId: x,
6831
+ id: p,
6832
+ treeNodeId: S,
6785
6833
  status: "draft"
6786
6834
  }, 201);
6787
6835
  }
@@ -6832,7 +6880,7 @@ G.get("/tree.json", async (e) => {
6832
6880
  details: t.message
6833
6881
  }, 500);
6834
6882
  }
6835
- }), G.get("/trees.json", async (e) => {
6883
+ }), W.get("/trees.json", async (e) => {
6836
6884
  try {
6837
6885
  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) => {
6838
6886
  let n = Number(t.treeId), r = Number(t.channelId);
@@ -6862,7 +6910,7 @@ G.get("/tree.json", async (e) => {
6862
6910
  } catch {
6863
6911
  return e.json([]);
6864
6912
  }
6865
- }), G.post("/trees.json", async (e) => {
6913
+ }), W.post("/trees.json", async (e) => {
6866
6914
  try {
6867
6915
  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 };
6868
6916
  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({
@@ -6887,7 +6935,7 @@ G.get("/tree.json", async (e) => {
6887
6935
  await t.prepare(`INSERT OR IGNORE INTO channel_trees (channelId, treeId, key) VALUES ${n}`).run(...r);
6888
6936
  }
6889
6937
  }
6890
- return await I(e).clear(), new B(e.env).purgeGlobalCache(e, t), e.json({
6938
+ return await I(e).clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
6891
6939
  success: !0,
6892
6940
  id: p,
6893
6941
  key: o,
@@ -6901,12 +6949,12 @@ G.get("/tree.json", async (e) => {
6901
6949
  } catch (t) {
6902
6950
  return console.error("[API Trees] Error saving tree:", t), e.json({ error: t.message || "Failed to save tree" }, 500);
6903
6951
  }
6904
- }), G.delete("/trees.json", async (e) => {
6952
+ }), W.delete("/trees.json", async (e) => {
6905
6953
  let t = e.get("db"), n = e.req.query("id");
6906
6954
  if (!n) return e.json({ error: "Tree ID required" }, 400);
6907
6955
  let r = Number(n);
6908
6956
  try {
6909
- 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({
6957
+ 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({
6910
6958
  success: !0,
6911
6959
  deletedTreeId: r
6912
6960
  });
@@ -6916,8 +6964,8 @@ G.get("/tree.json", async (e) => {
6916
6964
  });
6917
6965
  //#endregion
6918
6966
  //#region server/routes/admin/channels.ts
6919
- var ve = new e();
6920
- ve.get("/", async (e) => {
6967
+ var ye = new e();
6968
+ ye.get("/", async (e) => {
6921
6969
  try {
6922
6970
  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) => {
6923
6971
  e[t.channelId] || (e[t.channelId] = []);
@@ -6941,7 +6989,7 @@ ve.get("/", async (e) => {
6941
6989
  isHidden: !!e.isHidden,
6942
6990
  trees: a[e.id] || []
6943
6991
  };
6944
- }), s = e.env?.BUNDLED_DEFINITIONS, c = ce(s)?.channelTemplate || {
6992
+ }), s = e.env?.BUNDLED_DEFINITIONS, c = se(s), l = c?.channelTemplate || Object.values(c?.channels || {})[0] || {
6945
6993
  label: "Channel Settings",
6946
6994
  fields: {
6947
6995
  key: {
@@ -6973,7 +7021,7 @@ ve.get("/", async (e) => {
6973
7021
  }
6974
7022
  };
6975
7023
  return e.json({
6976
- schema: c,
7024
+ schema: l,
6977
7025
  channels: o
6978
7026
  });
6979
7027
  } catch (t) {
@@ -6983,24 +7031,26 @@ ve.get("/", async (e) => {
6983
7031
  error: t.message
6984
7032
  }, 500);
6985
7033
  }
6986
- }), ve.post("/", async (e) => {
7034
+ }), ye.post("/", async (e) => {
6987
7035
  try {
6988
- 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;
6989
- if (await t.prepare("SELECT id FROM channels WHERE key = ? AND id != ? LIMIT 1").get(y, i ?? -1)) return e.json({
6990
- error: `Channel API key "${y}" is already in use.`,
7036
+ 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 || "";
7037
+ typeof T == "object" && T && (T = T.value || T.id || ""), T = String(T).trim();
7038
+ 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;
7039
+ if (await t.prepare("SELECT id FROM channels WHERE key = ? AND id != ? LIMIT 1").get(C, a ?? -1)) return e.json({
7040
+ error: `Channel API key "${C}" is already in use.`,
6991
7041
  field: "key"
6992
7042
  }, 409);
6993
- let w = i;
6994
- 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);
7043
+ let A = a;
7044
+ 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);
6995
7045
  else {
6996
- 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);
6997
- w = Number(e.lastInsertRowid);
7046
+ 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);
7047
+ A = Number(e.lastInsertRowid);
6998
7048
  }
6999
- await t.prepare("DELETE FROM channel_trees WHERE channelId = ?").run(w);
7000
- let T = x.filter((e) => e && e.treeId && e.key);
7001
- if (T.length > 0) {
7002
- let e = T.map(() => "(?, ?, ?, ?)").join(", "), n = T.flatMap((e) => [
7003
- w,
7049
+ await t.prepare("DELETE FROM channel_trees WHERE channelId = ?").run(A);
7050
+ let j = D.filter((e) => e && e.treeId && e.key);
7051
+ if (j.length > 0) {
7052
+ let e = j.map(() => "(?, ?, ?, ?)").join(", "), n = j.flatMap((e) => [
7053
+ A,
7004
7054
  Number(e.treeId) || e.treeId,
7005
7055
  String(e.key).trim(),
7006
7056
  JSON.stringify(e.meta || {})
@@ -7010,9 +7060,10 @@ ve.get("/", async (e) => {
7010
7060
  VALUES ${e}
7011
7061
  `).run(...n);
7012
7062
  }
7013
- return await I(e).clear(), new B(e.env).purgeGlobalCache(e, t), e.json({
7063
+ let M = I(e);
7064
+ return await M.delete(`channel:${C}`), await M.delete(`channel:${A}`), await M.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
7014
7065
  success: !0,
7015
- id: w
7066
+ id: A
7016
7067
  });
7017
7068
  } catch (t) {
7018
7069
  return console.error("[API Channels] Error saving channel:", t), e.json({
@@ -7020,12 +7071,14 @@ ve.get("/", async (e) => {
7020
7071
  details: t.message
7021
7072
  }, 500);
7022
7073
  }
7023
- }), ve.delete("/", async (e) => {
7074
+ }), ye.delete("/", async (e) => {
7024
7075
  let t = e.get("db"), n = e.req.query("id");
7025
7076
  if (!n) return e.json({ error: "Channel ID required" }, 400);
7026
7077
  let r = Number(n);
7027
7078
  try {
7028
- 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({
7079
+ 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);
7080
+ let n = I(e);
7081
+ return await n.delete(`channel:${r}`), await n.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
7029
7082
  success: !0,
7030
7083
  deletedSiteId: r
7031
7084
  });
@@ -7043,11 +7096,11 @@ if (typeof process < "u" && process?.versions?.node) try {
7043
7096
  let e = i(import.meta.url);
7044
7097
  K = e("node:fs"), q = e("node:path");
7045
7098
  } catch {}
7046
- function ye(e, t = "") {
7099
+ function be(e, t = "") {
7047
7100
  let n = e.split(/[\\/]/).pop() || "";
7048
7101
  return t && n.endsWith(t) ? n.slice(0, -t.length) : n;
7049
7102
  }
7050
- function be(e) {
7103
+ function xe(e) {
7051
7104
  let t = e.match(/\.[^.\\/]+$/);
7052
7105
  return t ? t[0] : "";
7053
7106
  }
@@ -7060,7 +7113,7 @@ var J = {
7060
7113
  nodeLayouts: {},
7061
7114
  blockLayouts: {}
7062
7115
  };
7063
- function xe(e) {
7116
+ function Se(e) {
7064
7117
  return e ? typeof e == "string" ? e.trim() : Array.isArray(e) ? e.includes("*") ? "*" : e : "*" : "*";
7065
7118
  }
7066
7119
  function Y(e = {}, t = {}) {
@@ -7075,47 +7128,47 @@ function Y(e = {}, t = {}) {
7075
7128
  };
7076
7129
  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;
7077
7130
  }
7078
- function Se(e) {
7131
+ function Ce(e) {
7079
7132
  if (!e || typeof e != "object") return e;
7080
- if (Array.isArray(e)) return e.map(Se);
7133
+ if (Array.isArray(e)) return e.map(Ce);
7081
7134
  let t = {};
7082
7135
  for (let [n, r] of Object.entries(e)) if (n === "<<" || n === "<<:") {
7083
- let e = Se(r);
7136
+ let e = Ce(r);
7084
7137
  if (typeof e == "object" && e) {
7085
7138
  if (Array.isArray(e)) for (let n of e) Object.assign(t, n);
7086
7139
  else Object.assign(t, e);
7087
7140
  }
7088
- } else t[n] = Se(r);
7141
+ } else t[n] = Ce(r);
7089
7142
  return t;
7090
7143
  }
7091
- function Ce(e, t) {
7092
- return e ? Se(n.parseDocument(e, { customTags: [{
7144
+ function we(e, t) {
7145
+ return e ? Ce(n.parseDocument(e, { customTags: [{
7093
7146
  tag: "!include",
7094
7147
  resolve(e) {
7095
- let n = (typeof e == "string" ? e : String(e?.strValue || e?.value || "")).trim(), r = ye(n);
7148
+ let n = (typeof e == "string" ? e : String(e?.strValue || e?.value || "")).trim(), r = be(n);
7096
7149
  if (!r) return n;
7097
7150
  if (t && t.fieldSets) {
7098
7151
  let e = Object.keys(t.fieldSets).find((e) => e.endsWith("/" + r) || e === r);
7099
- if (e) return Ce(t.fieldSets[e], t);
7152
+ if (e) return we(t.fieldSets[e], t);
7100
7153
  }
7101
7154
  return n;
7102
7155
  }
7103
7156
  }] }).toJS() || {}) : {};
7104
7157
  }
7105
- function we(e, t = /* @__PURE__ */ new Set()) {
7158
+ function Te(e, t = /* @__PURE__ */ new Set()) {
7106
7159
  if (!K || !q) return {};
7107
7160
  let r = q.resolve(e);
7108
7161
  if (t.has(r) || (t.add(r), !K.existsSync(r))) return {};
7109
7162
  let i = K.readFileSync(r, "utf-8");
7110
- return Se(n.parseDocument(i, { customTags: [{
7163
+ return Ce(n.parseDocument(i, { customTags: [{
7111
7164
  tag: "!include",
7112
7165
  resolve(e) {
7113
7166
  let n = (typeof e == "string" ? e : String(e?.strValue || e?.value || "")).trim();
7114
- return n ? we(q.resolve(q.dirname(r), n), new Set(t)) : {};
7167
+ return n ? Te(q.resolve(q.dirname(r), n), new Set(t)) : {};
7115
7168
  }
7116
7169
  }] }).toJS() || {});
7117
7170
  }
7118
- function Te() {
7171
+ function Ee() {
7119
7172
  if (!K || !q || typeof process > "u" || !process?.versions?.node) return null;
7120
7173
  try {
7121
7174
  let e = process.cwd(), t = "", n = [
@@ -7148,9 +7201,9 @@ function Te() {
7148
7201
  let r = {}, i = K.readdirSync(n);
7149
7202
  for (let e of i) {
7150
7203
  if (!e.endsWith(".yaml") && !e.endsWith(".yml")) continue;
7151
- let t = q.join(n, e), i = ye(e, be(e));
7204
+ let t = q.join(n, e), i = be(e, xe(e));
7152
7205
  try {
7153
- r[i] = we(t);
7206
+ r[i] = Te(t);
7154
7207
  } catch (t) {
7155
7208
  console.error(`❌ Error parsing ${e}:`, t.message);
7156
7209
  }
@@ -7178,14 +7231,14 @@ function Te() {
7178
7231
  return console.error("❌ Exception inside readLocalFsBundle:", e), null;
7179
7232
  }
7180
7233
  }
7181
- var Ee = null, De = null;
7182
- function Oe(e) {
7183
- if (!e) Ee = null, De = null;
7184
- else if (Ee && De === e) return Ee;
7185
- let t = ke(e);
7186
- return Ee = t, De = e, t;
7187
- }
7234
+ var De = null, Oe = null;
7188
7235
  function ke(e) {
7236
+ if (!e) De = null, Oe = null;
7237
+ else if (De && Oe === e) return De;
7238
+ let t = Ae(e);
7239
+ return De = t, Oe = e, t;
7240
+ }
7241
+ function Ae(e) {
7189
7242
  if (e) {
7190
7243
  let t = {
7191
7244
  nodes: {
@@ -7221,12 +7274,12 @@ function ke(e) {
7221
7274
  let e = (e) => {
7222
7275
  let n = {};
7223
7276
  for (let [r, i] of Object.entries(e || {})) {
7224
- let e = ye(r, be(r));
7225
- n[e] = Ce(i, t);
7277
+ let e = be(r, xe(r));
7278
+ n[e] = we(i, t);
7226
7279
  }
7227
7280
  return n;
7228
7281
  };
7229
- return Ae({
7282
+ return je({
7230
7283
  rawNodes: e(t.nodes),
7231
7284
  rawTrees: e(t.trees),
7232
7285
  rawChannels: e(t.channels),
@@ -7236,12 +7289,12 @@ function ke(e) {
7236
7289
  rawFieldSets: e(t.fieldSets)
7237
7290
  });
7238
7291
  }
7239
- return Ae(t);
7292
+ return je(t);
7240
7293
  }
7241
- let t = Te();
7242
- return t && Object.keys(t.rawNodes || {}).length > 0 ? Ae(t) : Ae(null);
7294
+ let t = Ee();
7295
+ return t && Object.keys(t.rawNodes || {}).length > 0 ? je(t) : je(null);
7243
7296
  }
7244
- function Ae(e) {
7297
+ function je(e) {
7245
7298
  if (!e) return {
7246
7299
  nodes: {},
7247
7300
  trees: {},
@@ -7376,8 +7429,8 @@ function Ae(e) {
7376
7429
  inVault: t.inVault !== !1,
7377
7430
  hasCanvas: t.hasCanvas === !0,
7378
7431
  defaultLayout: t.defaultLayout,
7379
- allowedBlocks: xe(t.allowedBlocks),
7380
- disallowedBlocks: t.disallowedBlocks ? xe(t.disallowedBlocks) : void 0,
7432
+ allowedBlocks: Se(t.allowedBlocks),
7433
+ disallowedBlocks: t.disallowedBlocks ? Se(t.disallowedBlocks) : void 0,
7381
7434
  tabs: n,
7382
7435
  fields: r
7383
7436
  };
@@ -7439,17 +7492,17 @@ function Ae(e) {
7439
7492
  fields: n
7440
7493
  };
7441
7494
  });
7442
- let te = {};
7495
+ let P = {};
7443
7496
  Object.entries(T).forEach(([e, t]) => {
7444
7497
  let n = A(t.tabs), r = k(t.fields || [], "settings", n), i = {}, a = t.regions || { content: { label: "Content" } };
7445
7498
  Object.entries(a).forEach(([e, t]) => {
7446
7499
  i[e] = {
7447
7500
  ...t,
7448
7501
  label: t.label || e,
7449
- allowedBlocks: xe(t.allowedBlocks),
7450
- disallowedBlocks: t.disallowedBlocks ? xe(t.disallowedBlocks) : void 0
7502
+ allowedBlocks: Se(t.allowedBlocks),
7503
+ disallowedBlocks: t.disallowedBlocks ? Se(t.disallowedBlocks) : void 0
7451
7504
  };
7452
- }), te[e] = {
7505
+ }), P[e] = {
7453
7506
  ...t,
7454
7507
  id: t.id || e,
7455
7508
  label: t.label || e,
@@ -7462,17 +7515,17 @@ function Ae(e) {
7462
7515
  tabs: n
7463
7516
  };
7464
7517
  });
7465
- let P = {};
7518
+ let te = {};
7466
7519
  Object.entries(E).forEach(([e, t]) => {
7467
7520
  let n = A(t.tabs), r = k(t.fields || [], "settings", n), i = {}, a = t.regions || { main: { label: "Main Content" } };
7468
7521
  Object.entries(a).forEach(([e, t]) => {
7469
7522
  i[e] = {
7470
7523
  ...t,
7471
7524
  label: t.label || e,
7472
- allowedBlocks: xe(t.allowedBlocks),
7473
- disallowedBlocks: t.disallowedBlocks ? xe(t.disallowedBlocks) : void 0
7525
+ allowedBlocks: Se(t.allowedBlocks),
7526
+ disallowedBlocks: t.disallowedBlocks ? Se(t.disallowedBlocks) : void 0
7474
7527
  };
7475
- }), P[e] = {
7528
+ }), te[e] = {
7476
7529
  ...t,
7477
7530
  id: t.id || e,
7478
7531
  label: t.label || e,
@@ -7502,7 +7555,7 @@ function Ae(e) {
7502
7555
  L[e] = Y(L[e] || {}, t);
7503
7556
  });
7504
7557
  });
7505
- let R = h ? {
7558
+ let ne = h ? {
7506
7559
  ...h,
7507
7560
  fields: L
7508
7561
  } : null;
@@ -7511,22 +7564,22 @@ function Ae(e) {
7511
7564
  trees: M,
7512
7565
  channels: N,
7513
7566
  blocks: ee,
7514
- nodeLayouts: te,
7515
- blockLayouts: P,
7567
+ nodeLayouts: P,
7568
+ blockLayouts: te,
7516
7569
  fieldSets: O,
7517
7570
  nodeTemplate: f || null,
7518
7571
  treeTemplate: p || null,
7519
7572
  channelTemplate: I,
7520
- userTemplate: R
7573
+ userTemplate: ne
7521
7574
  };
7522
7575
  }
7523
7576
  //#endregion
7524
7577
  //#region server/routes/admin/schemas.ts
7525
- var je = new e(), Me = (e) => {
7578
+ var Me = new e(), Ne = (e) => {
7526
7579
  try {
7527
7580
  let t = e.env?.BUNDLED_DEFINITIONS;
7528
7581
  (!t || Object.keys(t).length === 0) && (t = f || d || u);
7529
- let n = Oe(t);
7582
+ let n = ke(t);
7530
7583
  return e.json(n, 200, { "Cache-Control": "no-cache, no-store, must-revalidate" });
7531
7584
  } catch (t) {
7532
7585
  return console.error("[CMS API] Error loading schemas:", t), e.json({
@@ -7535,10 +7588,10 @@ var je = new e(), Me = (e) => {
7535
7588
  }, 500);
7536
7589
  }
7537
7590
  };
7538
- je.get("/", Me), je.get("/schemas.json", Me);
7591
+ Me.get("/", Ne), Me.get("/schemas.json", Ne);
7539
7592
  //#endregion
7540
7593
  //#region server/routes/admin/validation.ts
7541
- var Ne = new e(), Pe = {
7594
+ var Pe = new e(), Fe = {
7542
7595
  node: "content_nodes",
7543
7596
  nodes: "content_nodes",
7544
7597
  content_node: "content_nodes",
@@ -7550,7 +7603,7 @@ var Ne = new e(), Pe = {
7550
7603
  user: "users",
7551
7604
  users: "users",
7552
7605
  user_account: "user_accounts"
7553
- }, Fe = {
7606
+ }, Ie = {
7554
7607
  content_nodes: [
7555
7608
  "id",
7556
7609
  "title",
@@ -7607,11 +7660,11 @@ var Ne = new e(), Pe = {
7607
7660
  "createdAt"
7608
7661
  ]
7609
7662
  };
7610
- Ne.post("/validate-unique", async (e) => {
7663
+ Pe.post("/validate-unique", async (e) => {
7611
7664
  try {
7612
7665
  let t = e.get("db"), { entityType: n, field: r, value: i, excludeId: a } = await e.req.json();
7613
7666
  if (!r || i == null || String(i).trim() === "") return e.json({ isUnique: !0 });
7614
- let o = Pe[n] || "content_nodes", s = r.replace(/[^a-zA-Z0-9_]/g, ""), c = (Fe[o] || Fe.content_nodes).includes(s), l = -1;
7667
+ let o = Fe[n] || "content_nodes", s = r.replace(/[^a-zA-Z0-9_]/g, ""), c = (Ie[o] || Ie.content_nodes).includes(s), l = -1;
7615
7668
  if (a != null && String(a).trim() !== "") {
7616
7669
  let e = Number(a);
7617
7670
  l = isNaN(e) ? String(a) : e;
@@ -7623,11 +7676,11 @@ Ne.post("/validate-unique", async (e) => {
7623
7676
  } catch (t) {
7624
7677
  return console.error("[API Validation] Error validating global uniqueness:", t), e.json({ error: "Failed to validate uniqueness" }, 500);
7625
7678
  }
7626
- }), Ne.post("/validate-unique-sibling", async (e) => e.json({ isUnique: !0 }));
7679
+ }), Pe.post("/validate-unique-sibling", async (e) => e.json({ isUnique: !0 }));
7627
7680
  //#endregion
7628
7681
  //#region server/routes/admin/stats.ts
7629
- var Ie = new e();
7630
- Ie.get("/", async (e) => {
7682
+ var Le = new e();
7683
+ Le.get("/", async (e) => {
7631
7684
  try {
7632
7685
  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) => ({
7633
7686
  ...e,
@@ -7644,7 +7697,7 @@ Ie.get("/", async (e) => {
7644
7697
  isHidden: !!e.isHidden,
7645
7698
  channelNames: e.channelLabels ? e.channelLabels.split(",") : [],
7646
7699
  treeNames: e.treeLabels ? e.treeLabels.split(",") : []
7647
- })), p = e.env?.BUNDLED_DEFINITIONS, m = ce(p), h = m.nodes || m.nodeSchemas || {}, g = c.map((e) => {
7700
+ })), p = e.env?.BUNDLED_DEFINITIONS, m = se(p), h = m.nodes || m.nodeSchemas || {}, g = c.map((e) => {
7648
7701
  let t = e.type || "node", n = h[t]?.label || t.charAt(0).toUpperCase() + t.slice(1);
7649
7702
  return {
7650
7703
  type: t,
@@ -7690,7 +7743,7 @@ async function Q(e, t, n = []) {
7690
7743
  if (typeof r.bind == "function") return await r.bind(...n).run();
7691
7744
  if (typeof r.run == "function") return await r.run(...n);
7692
7745
  }
7693
- function Le(e, t, n) {
7746
+ function Re(e, t, n) {
7694
7747
  let r = e || (t ? `/media/${t}` : "");
7695
7748
  return r && n && r.startsWith(`https://${n}/`) && !r.includes("/media/") && (r = r.replace(`https://${n}/`, `https://${n}/media/`)), r;
7696
7749
  }
@@ -7732,7 +7785,7 @@ X.get("/", async (e) => {
7732
7785
  ...JSON.parse(t.dataJson || "{}")
7733
7786
  };
7734
7787
  } catch {}
7735
- let r = Le(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN);
7788
+ let r = Re(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN);
7736
7789
  return {
7737
7790
  id: t.id,
7738
7791
  filename: t.filename || "Untitled Asset",
@@ -7758,7 +7811,7 @@ X.get("/", async (e) => {
7758
7811
  }
7759
7812
  }), X.post("/upload", async (e) => {
7760
7813
  try {
7761
- 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;
7814
+ 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;
7762
7815
  s && (await Z(t, "SELECT id FROM assets WHERE id = ?", [s])).length === 0 && (s = null);
7763
7816
  let c = r.cropCoordinates, u = null, d = null;
7764
7817
  if (c) {
@@ -7790,7 +7843,7 @@ X.get("/", async (e) => {
7790
7843
  let D = x;
7791
7844
  if (s) {
7792
7845
  let n = await Z(t, "SELECT cdnUrl, storageKeyPrivate FROM assets WHERE id = ?", [s]);
7793
- n.length > 0 && (D = Le(n[0].cdnUrl, n[0].storageKeyPrivate, y)), new B(e.env).purgeAsset(e, t, s);
7846
+ n.length > 0 && (D = Re(n[0].cdnUrl, n[0].storageKeyPrivate, y)), new V(e.env).purgeAsset(e, t, s);
7794
7847
  }
7795
7848
  return e.json({
7796
7849
  id: p,
@@ -7832,7 +7885,7 @@ X.get("/", async (e) => {
7832
7885
  ...JSON.parse(i.dataJson || "{}")
7833
7886
  };
7834
7887
  } catch {}
7835
- let u = Le(i.cdnUrl, i.storageKeyPrivate, e.env?.CDN_DOMAIN);
7888
+ let u = Re(i.cdnUrl, i.storageKeyPrivate, e.env?.CDN_DOMAIN);
7836
7889
  return e.json({
7837
7890
  id: i.id,
7838
7891
  filename: i.filename,
@@ -7859,7 +7912,7 @@ X.get("/", async (e) => {
7859
7912
  createdAt: t.createdAt,
7860
7913
  parentAssetId: t.parentAssetId || i.id,
7861
7914
  cropCoordinates: n,
7862
- url: Le(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN),
7915
+ url: Re(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN),
7863
7916
  originalUrl: u
7864
7917
  };
7865
7918
  })
@@ -7879,14 +7932,14 @@ X.get("/", async (e) => {
7879
7932
  r.filename === void 0 ? a.filename : r.filename,
7880
7933
  JSON.stringify(o),
7881
7934
  n
7882
- ]), new B(e.env).purgeAsset(e, t, n), e.json({ success: !0 });
7935
+ ]), new V(e.env).purgeAsset(e, t, n), e.json({ success: !0 });
7883
7936
  } catch {
7884
7937
  return e.json({ error: "Failed to update asset" }, 500);
7885
7938
  }
7886
7939
  }), X.delete("/:id", async (e) => {
7887
7940
  try {
7888
7941
  let t = l(e), n = e.req.param("id"), r = (await Z(t, "SELECT id, filename, isSystemVariant FROM assets WHERE id = ?", [n]))[0];
7889
- 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 ?))", [
7942
+ 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 ?))", [
7890
7943
  n,
7891
7944
  n,
7892
7945
  `crop_%${r.filename ? r.filename.replace(/\.[^/.]+$/, "") : ""}%`,
@@ -7912,7 +7965,7 @@ X.get("/", async (e) => {
7912
7965
  r,
7913
7966
  `crop_%${i.filename ? i.filename.replace(/\.[^/.]+$/, "") : ""}%`,
7914
7967
  `%${r}%`
7915
- ]), new B(e.env).purgeAsset(e, t, r), e.json({
7968
+ ]), new V(e.env).purgeAsset(e, t, r), e.json({
7916
7969
  success: !0,
7917
7970
  id: r,
7918
7971
  restored: !0
@@ -7925,9 +7978,9 @@ X.get("/", async (e) => {
7925
7978
  }
7926
7979
  }), X.delete("/purge/:id", async (e) => {
7927
7980
  try {
7928
- 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];
7981
+ 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];
7929
7982
  if (!i) return e.json({ error: "Asset not found" }, 404);
7930
- new B(e.env).purgeAsset(e, t, r);
7983
+ new V(e.env).purgeAsset(e, t, r);
7931
7984
  let a = [i];
7932
7985
  i.isSystemVariant || (a = [i, ...await Z(t, "SELECT id, storageKeyPrivate FROM assets WHERE parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
7933
7986
  r,
@@ -7959,8 +8012,8 @@ X.get("/", async (e) => {
7959
8012
  });
7960
8013
  //#endregion
7961
8014
  //#region server/routes/public/node.ts
7962
- var Re = new e();
7963
- function ze() {
8015
+ var ze = new e();
8016
+ function Be() {
7964
8017
  return {
7965
8018
  fullPath: /* @__PURE__ */ new Map(),
7966
8019
  treeEdges: /* @__PURE__ */ new Map(),
@@ -7968,10 +8021,10 @@ function ze() {
7968
8021
  assetUrls: /* @__PURE__ */ new Map()
7969
8022
  };
7970
8023
  }
7971
- function Be(...e) {
8024
+ function Ve(...e) {
7972
8025
  return e.map((e) => String(e ?? "")).join(":");
7973
8026
  }
7974
- function Ve(e, t) {
8027
+ function He(e, t) {
7975
8028
  let n = Date.now();
7976
8029
  if (e && String(e).trim() !== "") {
7977
8030
  let t = Date.parse(e);
@@ -7983,27 +8036,27 @@ function Ve(e, t) {
7983
8036
  }
7984
8037
  return !0;
7985
8038
  }
7986
- async function He(e, t, n) {
7987
- let r = t.filter((e) => e.componentId === "content-feed" || e.componentId === "article-list");
7988
- await Promise.all(r.map(async (t) => {
7989
- 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];
7990
- n && n !== "all" && (s += " AND id IN (SELECT nodeId FROM node_channels WHERE channelId = ?)", c.push(Number(n) || n));
7991
- let l = "ORDER BY updatedAt DESC";
7992
- o === "published_desc" || o === "createdAt" ? l = "ORDER BY createdAt DESC" : o === "title_asc" && (l = "ORDER BY LOWER(title) ASC");
7993
- let u = `SELECT id, title, slug, language, dataJson, createdAt, updatedAt ${s} ${l} LIMIT ?`;
7994
- c.push(a);
8039
+ async function Ue(e, t, n, r) {
8040
+ let i = t.filter((e) => e.componentId === "content-feed" || e.componentId === "article-list");
8041
+ await Promise.all(i.map(async (t) => {
8042
+ 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];
8043
+ n && n !== "all" && (c += " AND id IN (SELECT nodeId FROM node_channels WHERE channelId = ?)", l.push(Number(n) || n));
8044
+ let u = "ORDER BY updatedAt DESC";
8045
+ s === "published_desc" || s === "createdAt" ? u = "ORDER BY createdAt DESC" : s === "title_asc" && (u = "ORDER BY LOWER(title) ASC");
8046
+ let d = `SELECT id, title, slug, language, dataJson, createdAt, updatedAt ${c} ${u} LIMIT ?`;
8047
+ l.push(o);
7995
8048
  try {
7996
- let n = await e.prepare(u).all(...c), r = Array.isArray(n) ? n : n?.results || [];
7997
- t.data.initialItems = r.map((e) => {
8049
+ let n = await e.prepare(d).all(...l), i = Array.isArray(n) ? n : n?.results || [];
8050
+ t.data.initialItems = i.map((e) => {
7998
8051
  let t = {};
7999
8052
  if (e.dataJson) try {
8000
8053
  t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
8001
8054
  } catch {}
8002
- return Ve(t.startShowingAt, t.stopShowingAt) ? {
8055
+ return He(t.startShowingAt, t.stopShowingAt) ? {
8003
8056
  id: e.id,
8004
8057
  title: e.title,
8005
8058
  slug: e.slug,
8006
- language: e.language || "en",
8059
+ language: e.language?.trim() || r || null,
8007
8060
  createdAt: e.createdAt,
8008
8061
  updatedAt: e.updatedAt,
8009
8062
  excerpt: t.excerpt || "",
@@ -8016,7 +8069,7 @@ async function He(e, t, n) {
8016
8069
  }
8017
8070
  }));
8018
8071
  }
8019
- async function Ue(e, t, n, r, i = !1, a) {
8072
+ async function We(e, t, n, r, i = !1, a) {
8020
8073
  if (!t) return { blocks: [] };
8021
8074
  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 || [];
8022
8075
  if (!s || s.length === 0) return { blocks: [] };
@@ -8052,10 +8105,10 @@ async function Ue(e, t, n, r, i = !1, a) {
8052
8105
  try {
8053
8106
  a = (typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson) || {};
8054
8107
  } catch {}
8055
- let o = a.hidden === !0 || a.hidden === 1 || a.hidden === "1" || a.hidden === "true", s = Ve(a.startShowingAt, a.stopShowingAt);
8108
+ let o = a.hidden === !0 || a.hidden === 1 || a.hidden === "1" || a.hidden === "true", s = He(a.startShowingAt, a.stopShowingAt);
8056
8109
  if (!i && (o || !s)) return null;
8057
- 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);
8058
- return d = await se(e, d), d = Ge(d), d.blockId = u, {
8110
+ 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);
8111
+ return d = await B(e, d), d = Ke(d), d.blockId = u, {
8059
8112
  region: t.region || n,
8060
8113
  block: {
8061
8114
  instanceId: t.id,
@@ -8075,7 +8128,7 @@ async function Ue(e, t, n, r, i = !1, a) {
8075
8128
  }
8076
8129
  return { blocks: [] };
8077
8130
  }
8078
- function We(e, t = {}) {
8131
+ function Ge(e, t = {}) {
8079
8132
  let n = {};
8080
8133
  for (let [r, i] of Object.entries(e)) r.endsWith("_meta") || [
8081
8134
  "disabledRegions",
@@ -8091,14 +8144,14 @@ function We(e, t = {}) {
8091
8144
  ].includes(r) || r.startsWith("_") || (!t[r] || t[r].public !== !1) && (n[r] = i);
8092
8145
  return n;
8093
8146
  }
8094
- function Ge(e) {
8095
- if (Array.isArray(e)) return e.map(Ge);
8147
+ function Ke(e) {
8148
+ if (Array.isArray(e)) return e.map(Ke);
8096
8149
  if (!e || typeof e != "object") return e;
8097
8150
  if (typeof e.id == "string" && e.id.startsWith("ast_") && typeof e.url == "string") {
8098
8151
  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 ? {
8099
8152
  ...t,
8100
8153
  ...t.crops?.[r] || {}
8101
- } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, Ge({
8154
+ } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, Ke({
8102
8155
  ...n,
8103
8156
  title: n?.title ?? e.title ?? "",
8104
8157
  alt: n?.alt ?? e.alt ?? "",
@@ -8112,9 +8165,9 @@ function Ge(e) {
8112
8165
  ...Object.keys(a).length > 0 ? { variants: a } : {}
8113
8166
  };
8114
8167
  }
8115
- return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, Ge(t)]));
8168
+ return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, Ke(t)]));
8116
8169
  }
8117
- async function Ke(e, t, n) {
8170
+ async function qe(e, t, n) {
8118
8171
  if (typeof t == "string") {
8119
8172
  if (!t.includes("#node:") && !t.includes("data-node-id") && !t.includes("#asset:") && !t.includes("data-asset-id")) return t;
8120
8173
  let r = (e, t) => {
@@ -8132,9 +8185,9 @@ async function Ke(e, t, n) {
8132
8185
  return await Promise.all(Array.from(t.matchAll(p)).map(async (t) => {
8133
8186
  let i = t[1], a = r(i, "data-node-id"), o = r(i, "data-tree-id");
8134
8187
  if (!a || !o) return;
8135
- let s = await Je(e, a, o, n);
8188
+ let s = await Ye(e, a, o, n);
8136
8189
  if (s?.treeNodeId) {
8137
- let t = await Qe(e, String(s.treeNodeId), o, n);
8190
+ let t = await $e(e, String(s.treeNodeId), o, n);
8138
8191
  f.set(`${a}:${o}`, t);
8139
8192
  }
8140
8193
  })), t.replace(p, (e, t) => {
@@ -8154,39 +8207,39 @@ async function Ke(e, t, n) {
8154
8207
  return /href\s*=\s*["'][^"']*["']/i.test(h) ? h = h.replace(/href\s*=\s*["'][^"']*["']/i, `href="${m || "/"}"`) : h += ` href="${m || "/"}"`, `<a ${h}>`;
8155
8208
  });
8156
8209
  }
8157
- if (Array.isArray(t)) return Promise.all(t.map((t) => Ke(e, t, n)));
8210
+ if (Array.isArray(t)) return Promise.all(t.map((t) => qe(e, t, n)));
8158
8211
  if (t && typeof t == "object") {
8159
8212
  if (typeof t.href == "string" && (t.href.startsWith("#node:") || t.href.startsWith("#asset:"))) return {
8160
8213
  ...t,
8161
- href: await qe(e, t, n)
8214
+ href: await Je(e, t, n)
8162
8215
  };
8163
- let r = await Promise.all(Object.entries(t).map(async ([t, r]) => [t, await Ke(e, r, n)]));
8216
+ let r = await Promise.all(Object.entries(t).map(async ([t, r]) => [t, await qe(e, r, n)]));
8164
8217
  return Object.fromEntries(r);
8165
8218
  }
8166
8219
  return t;
8167
8220
  }
8168
- async function qe(e, t, n) {
8221
+ async function Je(e, t, n) {
8169
8222
  let r = t.href.match(/^#node:(.+)$/), i = t.href.match(/^#asset:(.+)$/);
8170
- if (i) return Xe(e, i[1], n);
8223
+ if (i) return Ze(e, i[1], n);
8171
8224
  if (!r) return t.href;
8172
8225
  let a = r[1];
8173
8226
  if (t.treeId) {
8174
- let r = await Je(e, a, String(t.treeId), n);
8227
+ let r = await Ye(e, a, String(t.treeId), n);
8175
8228
  if (r?.treeNodeId) {
8176
- let i = await Qe(e, String(r.treeNodeId), String(t.treeId), n);
8229
+ let i = await $e(e, String(r.treeNodeId), String(t.treeId), n);
8177
8230
  if (i) return i;
8178
8231
  }
8179
8232
  }
8180
- let o = await Ye(e, a, n);
8233
+ let o = await Xe(e, a, n);
8181
8234
  return o === void 0 ? "#" : `/${o}`;
8182
8235
  }
8183
- async function Je(e, t, n, r) {
8184
- let i = Be(t, n), a = r.treeEdges.get(i);
8236
+ async function Ye(e, t, n, r) {
8237
+ let i = Ve(t, n), a = r.treeEdges.get(i);
8185
8238
  if (a) return a;
8186
8239
  let o = e.prepare("SELECT id as treeNodeId FROM tree_nodes WHERE contentId = ? AND treeId = ? LIMIT 1").get(t, n);
8187
8240
  return r.treeEdges.set(i, Promise.resolve(o)), o;
8188
8241
  }
8189
- async function Ye(e, t, n) {
8242
+ async function Xe(e, t, n) {
8190
8243
  let r = String(t), i = n.nodeSlugs.get(r);
8191
8244
  if (i) return i;
8192
8245
  let a = (async () => {
@@ -8195,7 +8248,7 @@ async function Ye(e, t, n) {
8195
8248
  })();
8196
8249
  return n.nodeSlugs.set(r, a), a;
8197
8250
  }
8198
- async function Xe(e, t, n) {
8251
+ async function Ze(e, t, n) {
8199
8252
  let r = String(t), i = n.assetUrls.get(r);
8200
8253
  if (i) return i;
8201
8254
  let a = (async () => {
@@ -8204,7 +8257,7 @@ async function Xe(e, t, n) {
8204
8257
  })();
8205
8258
  return n.assetUrls.set(r, a), a;
8206
8259
  }
8207
- function Ze(e) {
8260
+ function Qe(e) {
8208
8261
  let t = e.socialImage;
8209
8262
  if (!t || typeof t != "object") return null;
8210
8263
  let n = (e, t) => {
@@ -8235,9 +8288,9 @@ function Ze(e) {
8235
8288
  ])
8236
8289
  };
8237
8290
  }
8238
- async function Qe(e, t, n, r) {
8291
+ async function $e(e, t, n, r) {
8239
8292
  if (!t) return "";
8240
- let i = Be(t, n);
8293
+ let i = Ve(t, n);
8241
8294
  if (r) {
8242
8295
  let e = r.fullPath.get(i);
8243
8296
  if (e) return e;
@@ -8252,7 +8305,7 @@ async function Qe(e, t, n, r) {
8252
8305
  })();
8253
8306
  return r && r.fullPath.set(i, a), a;
8254
8307
  }
8255
- async function $e(e, t, n, r, i) {
8308
+ async function et(e, t, n, r, i) {
8256
8309
  let a = {}, o = null;
8257
8310
  if (t) {
8258
8311
  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([
@@ -8279,7 +8332,7 @@ async function $e(e, t, n, r, i) {
8279
8332
  }
8280
8333
  }
8281
8334
  if (!o) {
8282
- let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ?").get(n);
8335
+ let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ? OR key = ? LIMIT 1").get(Number(n) || -1, String(n));
8283
8336
  if (t?.dataJson) try {
8284
8337
  let e = typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson;
8285
8338
  e.subpageLayoutId && e.subpageLayoutId !== "inherit" && (o = e.subpageLayoutId);
@@ -8290,109 +8343,125 @@ async function $e(e, t, n, r, i) {
8290
8343
  inheritedFields: a
8291
8344
  };
8292
8345
  }
8293
- function et(e) {
8346
+ function tt(e) {
8294
8347
  let t = Number(e?.env?.CMS_NODE_CACHE_TTL);
8295
8348
  return Number.isFinite(t) && t >= 60 ? Math.floor(t) : 300;
8296
8349
  }
8297
- async function tt(e, t, n, r) {
8350
+ async function nt(e, t, n, r) {
8298
8351
  try {
8299
8352
  await e.set(t, n, r);
8300
8353
  } catch (e) {
8301
8354
  console.warn("[CMS Cache] Failed to write node response to cache:", e);
8302
8355
  }
8303
8356
  }
8304
- Re.get("/*", async (e) => {
8357
+ ze.get("/*", async (e) => {
8305
8358
  try {
8306
- 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));
8359
+ 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));
8307
8360
  if (!c) return e.json({ error: `Channel '${a}' not found` }, 404);
8308
8361
  let l = c.status === "disabled" || c.status === "inactive" || c.isEnabled === 0 || c.isEnabled === !1;
8309
8362
  if (!s && l) return e.json({ error: `Channel '${c.key || a}' is currently inactive` }, 404);
8310
- 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";
8311
- if (!s && !m) {
8312
- let t = await f.get(p);
8313
- if (t) return e.header("X-Cache", "HIT"), e.json(t);
8314
- }
8315
- 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 = `
8363
+ 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 = `
8316
8364
  SELECT cn.*, tn.id as treeNodeId, tn.parentId, tn.treeId FROM content_nodes cn
8317
8365
  INNER JOIN tree_nodes tn ON cn.id = tn.contentId
8318
8366
  ${u === null ? "" : "INNER JOIN node_channels nc ON cn.id = nc.nodeId"}
8319
8367
  WHERE cn.slug = ? ${u === null ? "" : "AND nc.channelId = ?"}
8320
- `, w = u === null ? [x] : [x, u], T = await t.prepare(C).all(...w), E = Array.isArray(T) ? T : T?.results || [];
8321
- if (E.length > 0) {
8322
- let e = await Promise.all(E.map(async (e) => ({
8368
+ `, S = u === null ? [y] : [y, u], C = await t.prepare(x).all(...S), w = Array.isArray(C) ? C : C?.results || [];
8369
+ if (w.length > 0) {
8370
+ let e = await Promise.all(w.map(async (e) => ({
8323
8371
  candidate: e,
8324
- calculatedPath: await Qe(t, String(e.treeNodeId), String(e.treeId), n)
8325
- }))), r = S.replace(/^\/+|\/+$/g, "");
8372
+ calculatedPath: await $e(t, String(e.treeNodeId), String(e.treeId), n)
8373
+ }))), r = b.replace(/^\/+|\/+$/g, "");
8326
8374
  for (let { candidate: t, calculatedPath: n } of e) {
8327
8375
  let e = n.replace(/^\/+|\/+$/g, "");
8328
8376
  if (e === r || r === "home" && (e === "" || e === "home")) {
8329
- _ = t, v = t;
8377
+ h = t, g = t;
8330
8378
  break;
8331
8379
  }
8332
8380
  }
8333
8381
  }
8334
- 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);
8335
- if (!v) {
8336
- let e = y ? [_.id, y] : [_.id];
8337
- v = await t.prepare(`SELECT id as treeNodeId, treeId, parentId FROM tree_nodes WHERE contentId = ? ${y ? "AND treeId = ?" : ""} LIMIT 1`).get(...e);
8382
+ 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);
8383
+ if (!g) {
8384
+ let e = _ ? [h.id, _] : [h.id];
8385
+ g = await t.prepare(`SELECT id as treeNodeId, treeId, parentId FROM tree_nodes WHERE contentId = ? ${_ ? "AND treeId = ?" : ""} LIMIT 1`).get(...e);
8386
+ }
8387
+ let T = g?.treeId || _ || "main-nav", E = null;
8388
+ if (T) {
8389
+ 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));
8390
+ if (e?.dataJson) try {
8391
+ let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
8392
+ t.defaultLanguage ? E = String(t.defaultLanguage).trim() : t.language && (E = String(t.language).trim());
8393
+ } catch {}
8394
+ }
8395
+ let D = null;
8396
+ if (c) {
8397
+ if (c.defaultLanguage) D = String(c.defaultLanguage).trim();
8398
+ else if (c.dataJson) try {
8399
+ let e = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson;
8400
+ e.defaultLanguage ? D = String(e.defaultLanguage).trim() : e.language && (D = String(e.language).trim());
8401
+ } catch {}
8402
+ }
8403
+ 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";
8404
+ if (!s && !M) {
8405
+ let t = await f.get(j);
8406
+ if (t) return e.header("X-Cache", "HIT"), e.json(t);
8338
8407
  }
8339
- 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 = {
8340
- id: _.id,
8341
- title: _.title,
8342
- slug: _.slug,
8343
- language: _.language || o || "en",
8344
- path: k === "" ? "/" : k,
8345
- nodeType: _.contentType,
8346
- createdAt: _.createdAt,
8347
- updatedAt: _.updatedAt
8348
- }, j = _.contentType || "node", M = h.nodes?.[j] || Object.values(h.nodes || {})[0] || {}, N = { ...M.fields || {} };
8349
- M.tabs && Object.values(M.tabs).forEach((e) => {
8350
- Object.assign(N, e.fields || {});
8408
+ let N = g?.parentId || null, ee = g?.treeNodeId ? await $e(t, String(g.treeNodeId), String(T), n) : `/${(h.slug || "").replace(/^\/+|\/+$/g, "")}`, P = {
8409
+ id: h.id,
8410
+ title: h.title,
8411
+ slug: h.slug,
8412
+ language: A,
8413
+ path: ee === "" ? "/" : ee,
8414
+ nodeType: h.contentType,
8415
+ createdAt: h.createdAt,
8416
+ updatedAt: h.updatedAt
8417
+ }, te = h.contentType || "node", F = p.nodes?.[te] || Object.values(p.nodes || {})[0] || {}, L = { ...F.fields || {} };
8418
+ F.tabs && Object.values(F.tabs).forEach((e) => {
8419
+ Object.assign(L, e.fields || {});
8351
8420
  });
8352
- let ee = {}, te = null, P = null, F = !1, L = {}, R = s && _.draftDataJson || _.dataJson;
8353
- if (R) try {
8354
- L = typeof R == "string" ? JSON.parse(R) : R;
8421
+ let ne = {}, re = null, ie = null, ae = !1, R = {}, oe = s && h.draftDataJson || h.dataJson;
8422
+ if (oe) try {
8423
+ R = typeof oe == "string" ? JSON.parse(oe) : oe;
8355
8424
  } catch {}
8356
- 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;
8357
- 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;
8358
- 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);
8359
- let z = await se(t, We(L, N));
8360
- z = Ge(z), z = await Ke(t, z, n);
8361
- let B = Ze(z);
8362
- 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;
8363
- let V = Number(_.isHidden) === 1 || F, le = !Ve(te, P), ue = _.status === "draft" || _.status === "new", de = _.dataJson && _.dataJson !== "{}" && _.dataJson !== "null";
8364
- if (!s && (V || le || ue && !de)) return e.json({ error: "Node is hidden, offline, or has never been published." }, 404);
8365
- let fe = [];
8366
- if (v?.treeNodeId) {
8367
- 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;
8368
- fe = n.map((e) => {
8425
+ 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;
8426
+ 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;
8427
+ 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);
8428
+ let U = await B(t, Ge(R, L));
8429
+ U = Ke(U), U = await qe(t, U, n), delete U.language;
8430
+ let ue = Qe(U);
8431
+ 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;
8432
+ 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";
8433
+ if (!s && (de || fe || pe && !me)) return e.json({ error: "Node is hidden, offline, or has never been published." }, 404);
8434
+ let he = [];
8435
+ if (g?.treeNodeId) {
8436
+ 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;
8437
+ he = n.map((e) => {
8369
8438
  let t = {}, n = s && e.draftDataJson || e.dataJson;
8370
8439
  if (!n) return null;
8371
8440
  try {
8372
8441
  t = (typeof n == "string" ? JSON.parse(n) : n) || {};
8373
8442
  } catch {}
8374
- 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, "");
8443
+ 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, "");
8375
8444
  return !s && (i || !a) ? null : {
8376
8445
  treeNodeId: e.treeNodeId,
8377
8446
  id: e.id,
8378
8447
  title: e.title,
8379
8448
  slug: o,
8380
- language: e.language || "en",
8449
+ language: e.language?.trim() || A || null,
8381
8450
  path: `${r}/${o}`.replace(/\/+/g, "/"),
8382
8451
  nodeType: e.nodeType
8383
8452
  };
8384
8453
  }).filter(Boolean);
8385
8454
  }
8386
- A.children = fe;
8387
- 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) => {
8455
+ P.children = he;
8456
+ 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) => {
8388
8457
  let r = e.region || "main", i = {};
8389
8458
  try {
8390
8459
  i = (typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson) || {};
8391
8460
  } catch {}
8392
- let a = i.hidden === !0 || i.hidden === 1 || i.hidden === "1" || i.hidden === "true", o = Ve(i.startShowingAt, i.stopShowingAt);
8461
+ let a = i.hidden === !0 || i.hidden === 1 || i.hidden === "1" || i.hidden === "true", o = He(i.startShowingAt, i.stopShowingAt);
8393
8462
  if (!s && (a || !o)) return null;
8394
- 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);
8395
- return d = await se(t, d), d = Ge(d), d = await Ke(t, d, n), d.blockId = u, {
8463
+ 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);
8464
+ return d = await B(t, d), d = Ke(d), d = await qe(t, d, n), d.blockId = u, {
8396
8465
  region: r,
8397
8466
  block: {
8398
8467
  instanceId: e.id,
@@ -8402,8 +8471,8 @@ Re.get("/*", async (e) => {
8402
8471
  }
8403
8472
  };
8404
8473
  }));
8405
- for (let e of G) e && (U[e.region] || (U[e.region] = [], W[e.region] = { isInherited: !1 }), U[e.region].push(e.block));
8406
- let he = {
8474
+ for (let e of ye) e && (G[e.region] || (G[e.region] = [], ve[e.region] = { isInherited: !1 }), G[e.region].push(e.block));
8475
+ let K = {
8407
8476
  header: {
8408
8477
  label: "Header",
8409
8478
  inherit: "parent"
@@ -8412,33 +8481,33 @@ Re.get("/*", async (e) => {
8412
8481
  label: "Footer",
8413
8482
  inherit: "parent"
8414
8483
  },
8415
- ...(oe ? h.nodeLayouts?.[oe] || h.layouts?.[oe] : null)?.regions || { main: { label: "Content" } }
8484
+ ...(le ? p.nodeLayouts?.[le] || p.layouts?.[le] : null)?.regions || { main: { label: "Content" } }
8416
8485
  };
8417
- for (let [e, r] of Object.entries(he)) {
8418
- let i = U[e] && U[e].length > 0, a = !!ee[e];
8419
- 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) {
8420
- let r = await Ue(t, O, e, h, s, n);
8421
- if (r.blocks.length > 0 && (U[e] = r.blocks, W[e] = {
8486
+ for (let [e, r] of Object.entries(K)) {
8487
+ let i = G[e] && G[e].length > 0, a = !!ne[e];
8488
+ 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) {
8489
+ let r = await We(t, N, e, p, s, n);
8490
+ if (r.blocks.length > 0 && (G[e] = r.blocks, ve[e] = {
8422
8491
  isInherited: !0,
8423
8492
  inheritedFromId: r.inheritedFromId,
8424
8493
  inheritedFromTitle: r.inheritedFromTitle
8425
- }, r.subRegions)) for (let [t, n] of Object.entries(r.subRegions)) t !== e && (U[t] = n, W[t] = {
8494
+ }, r.subRegions)) for (let [t, n] of Object.entries(r.subRegions)) t !== e && (G[t] = n, ve[t] = {
8426
8495
  isInherited: !0,
8427
8496
  inheritedFromId: r.inheritedFromId,
8428
8497
  inheritedFromTitle: r.inheritedFromTitle
8429
8498
  });
8430
8499
  }
8431
8500
  }
8432
- await Promise.all(Object.keys(U).map((e) => He(t, U[e], u)));
8433
- let ge = {
8501
+ await Promise.all(Object.keys(G).map((e) => Ue(t, G[e], u, A)));
8502
+ let q = {
8434
8503
  channelId: u || d,
8435
- treeId: D,
8436
- language: A.language,
8437
- node: A,
8438
- content: U,
8439
- regionMeta: W
8504
+ treeId: T,
8505
+ language: A,
8506
+ node: P,
8507
+ content: G,
8508
+ regionMeta: ve
8440
8509
  };
8441
- return !s && !m && (e.header("X-Cache", "MISS"), await tt(f, p, ge, et(e))), e.json(ge);
8510
+ return !s && !M && (e.header("X-Cache", "MISS"), await nt(f, j, q, tt(e))), e.json(q);
8442
8511
  } catch (t) {
8443
8512
  return console.error("[CMS Public API] Error fetching node by path:", t), e.json({
8444
8513
  error: "Failed to fetch JSON payload",
@@ -8448,8 +8517,8 @@ Re.get("/*", async (e) => {
8448
8517
  });
8449
8518
  //#endregion
8450
8519
  //#region server/routes/public/tree.ts
8451
- var nt = new e();
8452
- function rt(e, t) {
8520
+ var rt = new e();
8521
+ function it(e, t) {
8453
8522
  let n = /* @__PURE__ */ new Date();
8454
8523
  if (e && String(e).trim() !== "") {
8455
8524
  let t = new Date(e);
@@ -8461,93 +8530,103 @@ function rt(e, t) {
8461
8530
  }
8462
8531
  return !0;
8463
8532
  }
8464
- async function it(e, t, n, r) {
8533
+ async function at(e, t, n, r) {
8465
8534
  try {
8466
8535
  await e.set(t, n, r);
8467
8536
  } catch (e) {
8468
8537
  console.warn("[CMS Cache] Failed to write tree response to cache:", e);
8469
8538
  }
8470
8539
  }
8471
- nt.get("/:treeParam", async (e) => {
8540
+ rt.get("/:treeParam", async (e) => {
8472
8541
  try {
8473
- let t = e.get("db"), n = e.req.param("treeParam"), r = e.req.query("channelId") || e.req.query("channel") || "default", i = e.req.query("preview") === "true";
8542
+ let t = e.get("db"), n = e.req.param("treeParam"), r = e.req.query("channelId") || e.req.query("channel") || "default", i = e.req.query("lang"), a = e.req.query("preview") === "true", o = null;
8474
8543
  if (r && r !== "default" && r !== "all") {
8475
8544
  let n = isNaN(Number(r)) ? await t.prepare("SELECT * FROM channels WHERE key = ?").get(r) : await t.prepare("SELECT * FROM channels WHERE id = ?").get(Number(r));
8476
8545
  if (n) {
8546
+ n.defaultLanguage && (o = n.defaultLanguage.trim());
8477
8547
  let t = n.status === "disabled" || n.status === "inactive" || n.isEnabled === 0 || n.isEnabled === !1;
8478
- if (!i && t) return e.json({ error: `Channel '${n.key || r}' is currently inactive` }, 404);
8548
+ if (!a && t) return e.json({ error: `Channel '${n.key || r}' is currently inactive` }, 404);
8479
8549
  }
8480
8550
  }
8481
- let a = I(e), o = `tree:${r}:${n}`, s = e.req.header("x-bypass-cache") === "true";
8482
- if (!i && !s) {
8483
- let t = await a.get(o);
8551
+ let s = !isNaN(Number(n)), c = s ? await t.prepare("SELECT * FROM trees WHERE id = ?").get(Number(n)) : await t.prepare("SELECT * FROM trees WHERE key = ?").get(n);
8552
+ if (c && Number(c.isHidden) === 1 && !a) return e.json({ error: `Tree '${n}' is hidden` }, 404);
8553
+ let l = null;
8554
+ if (c) {
8555
+ if (c.defaultLanguage) l = String(c.defaultLanguage).trim();
8556
+ else if (c.dataJson) try {
8557
+ let e = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson;
8558
+ e.defaultLanguage && (l = String(e.defaultLanguage).trim());
8559
+ } catch {}
8560
+ }
8561
+ let u = l || o || i?.trim() || null, d = I(e), f = `tree:${r}:${n}:${u || "default"}`, p = e.req.header("x-bypass-cache") === "true";
8562
+ if (!a && !p) {
8563
+ let t = await d.get(f);
8484
8564
  if (t) return e.header("X-Cache", "HIT"), e.json(t);
8485
8565
  }
8486
- 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);
8487
- if (l && Number(l.isHidden) === 1 && !i) return e.json({ error: `Tree '${n}' is hidden` }, 404);
8488
- let u = l?.id || (c ? Number(n) : null), d = {};
8489
- if (l && l.dataJson) try {
8490
- 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 || {};
8491
- for (let [e, n] of Object.entries(t)) a[e]?.public === !0 && (d[e] = n);
8566
+ let m = c?.id || (s ? Number(n) : null), h = {};
8567
+ if (c && c.dataJson) try {
8568
+ let t = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson, r = e.env?.BUNDLED_DEFINITIONS, i = se(r), a = (i.trees?.[c.treeType || n] || i.trees?.site || {}).fields || {};
8569
+ for (let [e, n] of Object.entries(t)) a[e]?.public === !0 && (h[e] = n);
8492
8570
  } catch (e) {
8493
8571
  console.warn("[CMS Public Tree API] Failed to parse tree dataJson", e);
8494
8572
  }
8495
- let f = [];
8496
- if (u !== null) {
8497
- 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);
8498
- f = Array.isArray(e) ? e : e?.results || [];
8573
+ let g = [];
8574
+ if (m !== null) {
8575
+ let e = await t.prepare("\n SELECT \n t.id as treeNodeId,\n t.treeId,\n t.contentId as id,\n t.parentId,\n t.sortOrder,\n c.title,\n c.slug,\n c.language,\n c.contentType as nodeType,\n c.isHidden,\n c.status,\n c.dataJson,\n c.draftDataJson\n FROM tree_nodes t\n INNER JOIN content_nodes c ON t.contentId = c.id\n WHERE t.treeId = ? AND (c.deletedAt IS NULL OR c.deletedAt = '')\n ORDER BY t.sortOrder ASC\n ").all(m);
8576
+ g = Array.isArray(e) ? e : e?.results || [];
8499
8577
  }
8500
- if ((!f || f.length === 0) && !l) return e.json({ error: `Tree '${n}' not found` }, 404);
8501
- let p = /* @__PURE__ */ new Map();
8502
- for (let e of f) {
8503
- let t = !e.parentId || e.parentId === "null" || e.parentId === "" ? null : e.parentId, n = t === null ? "__ROOT__" : String(t), r = p.get(n);
8504
- r ? r.push(e) : p.set(n, [e]);
8578
+ if ((!g || g.length === 0) && !c) return e.json({ error: `Tree '${n}' not found` }, 404);
8579
+ let _ = /* @__PURE__ */ new Map();
8580
+ for (let e of g) {
8581
+ let t = !e.parentId || e.parentId === "null" || e.parentId === "" ? null : e.parentId, n = t === null ? "__ROOT__" : String(t), r = _.get(n);
8582
+ r ? r.push(e) : _.set(n, [e]);
8505
8583
  }
8506
- let m = /* @__PURE__ */ new Map();
8507
- for (let e of f) {
8508
- let t = String(e.treeNodeId), n = i && e.draftDataJson ? e.draftDataJson : e.dataJson;
8584
+ let v = /* @__PURE__ */ new Map();
8585
+ for (let e of g) {
8586
+ let t = String(e.treeNodeId), n = a && e.draftDataJson ? e.draftDataJson : e.dataJson;
8509
8587
  if (!n) {
8510
- m.set(t, {});
8588
+ v.set(t, {});
8511
8589
  continue;
8512
8590
  }
8513
8591
  try {
8514
8592
  let e = typeof n == "string" ? JSON.parse(n) : n;
8515
- m.set(t, e && typeof e == "object" ? e : {});
8593
+ v.set(t, e && typeof e == "object" ? e : {});
8516
8594
  } catch {
8517
- m.set(t, {});
8595
+ v.set(t, {});
8518
8596
  }
8519
8597
  }
8520
- function h(e = null, t = "") {
8598
+ function y(e = null, t = "") {
8521
8599
  let n = e == null || e === "" || e === "null" ? "__ROOT__" : String(e);
8522
- return (p.get(n) || []).map((e) => {
8523
- let n = m.get(String(e.treeNodeId)) || {}, r = {};
8600
+ return (_.get(n) || []).map((e) => {
8601
+ let n = v.get(String(e.treeNodeId)) || {}, r = {};
8524
8602
  for (let [e, t] of Object.entries(n)) e !== "_isTreeDraft" && e !== "_draftParentId" && e !== "isNew" && e !== "hidden" && e !== "is_hidden" && e !== "isHidden" && e !== "status" && (r[e] = t);
8525
- let a = !i && (e.status === "draft" || e.status === "new"), o = Number(e.isHidden) === 1 || a || n.hidden === !0 || n.hidden === 1 || n.hidden === "1" || n.hidden === "true", s = rt(n.startShowingAt, n.stopShowingAt), c = (e.slug || "").replace(/^\/+|\/+$/g, ""), l = (!e.parentId || e.parentId === "null" || e.parentId === "") && (c === "home" || c === "homee") ? "/" : `${t}/${c}`.replace(/\/+/g, "/"), u = {
8603
+ let i = !a && (e.status === "draft" || e.status === "new"), o = Number(e.isHidden) === 1 || i || n.hidden === !0 || n.hidden === 1 || n.hidden === "1" || n.hidden === "true", s = it(n.startShowingAt, n.stopShowingAt), c = (e.slug || "").replace(/^\/+|\/+$/g, ""), l = (!e.parentId || e.parentId === "null" || e.parentId === "") && (c === "home" || c === "homee") ? "/" : `${t}/${c}`.replace(/\/+/g, "/"), d = e.language && String(e.language).trim() !== "" ? e.language.trim() : u, f = {
8526
8604
  id: e.id,
8527
8605
  treeNodeId: e.treeNodeId,
8528
8606
  parentId: e.parentId || null,
8529
8607
  title: e.title,
8530
8608
  slug: c,
8531
- language: e.language || "en",
8609
+ language: d,
8532
8610
  path: l,
8533
8611
  nodeType: e.nodeType,
8534
8612
  hidden: o || !s ? 1 : 0,
8535
8613
  summary: r.summary || ""
8536
8614
  };
8537
- e.nodeType === "external-link" && (r.url && (u.url = r.url), r.target && (u.target = r.target));
8538
- let d = l === "/" ? "" : l;
8539
- return u.children = h(e.treeNodeId, d), u;
8540
- }).filter((e) => i || !e.hidden);
8615
+ e.nodeType === "external-link" && (r.url && (f.url = r.url), r.target && (f.target = r.target));
8616
+ let p = l === "/" ? "" : l;
8617
+ return f.children = y(e.treeNodeId, p), f;
8618
+ }).filter((e) => a || !e.hidden);
8541
8619
  }
8542
- let g = {
8543
- treeId: l?.id || u,
8544
- key: l?.key || n,
8620
+ let b = {
8621
+ treeId: c?.id || m,
8622
+ key: c?.key || n,
8545
8623
  channelId: r,
8546
- label: l?.label || n,
8547
- ...d,
8548
- items: h(null)
8624
+ language: u,
8625
+ label: c?.label || n,
8626
+ ...h,
8627
+ items: y(null)
8549
8628
  };
8550
- return !i && !s && (e.header("X-Cache", "MISS"), await it(a, o, g, 300)), e.json(g);
8629
+ return !a && !p && (e.header("X-Cache", "MISS"), await at(d, f, b, 300)), e.json(b);
8551
8630
  } catch (t) {
8552
8631
  return console.error("[CMS Public Tree API] Error:", t), e.json({
8553
8632
  error: "Failed to fetch public tree",
@@ -8556,9 +8635,148 @@ nt.get("/:treeParam", async (e) => {
8556
8635
  }
8557
8636
  });
8558
8637
  //#endregion
8638
+ //#region server/routes/public/channel.ts
8639
+ var ot = new e();
8640
+ function st(e) {
8641
+ let t = Number(e?.env?.CMS_CHANNEL_CACHE_TTL);
8642
+ return Number.isFinite(t) && t >= 60 ? Math.floor(t) : 300;
8643
+ }
8644
+ async function ct(e, t, n, r) {
8645
+ try {
8646
+ await e.set(t, n, r);
8647
+ } catch (e) {
8648
+ console.warn("[CMS Cache] Failed to write channel response to cache:", e);
8649
+ }
8650
+ }
8651
+ function lt(e, t) {
8652
+ let n = {}, r = (e) => {
8653
+ if (!e || typeof e != "string") return;
8654
+ let n = t?.fieldSets?.[e] || t?.fieldsets?.[e] || t?.definitions?.[e] || t?.channels?.[e] || t?.[e];
8655
+ n?.fields && i(n.fields);
8656
+ }, i = (e) => {
8657
+ 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);
8658
+ };
8659
+ 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);
8660
+ return n;
8661
+ }
8662
+ function ut(e, t = {}) {
8663
+ let n = {}, r = Object.keys(t).length > 0;
8664
+ for (let [i, a] of Object.entries(e)) {
8665
+ if (i.endsWith("_meta") || [
8666
+ "disabledRegions",
8667
+ "hidden",
8668
+ "is_hidden",
8669
+ "isHidden",
8670
+ "status",
8671
+ "startShowingAt",
8672
+ "stopShowingAt",
8673
+ "dataJson",
8674
+ "draftDataJson"
8675
+ ].includes(i) || i.startsWith("_")) continue;
8676
+ let e = t[i];
8677
+ (!r || !e || e.public !== !1) && a != null && a !== "" && (n[i] = a);
8678
+ }
8679
+ return n;
8680
+ }
8681
+ function dt(e) {
8682
+ if (Array.isArray(e)) return e.map(dt);
8683
+ if (!e || typeof e != "object") return e;
8684
+ if (typeof e.id == "string" && e.id.startsWith("ast_") && typeof e.url == "string") {
8685
+ 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 ? {
8686
+ ...t,
8687
+ ...t.crops?.[r] || {}
8688
+ } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, dt({
8689
+ ...n,
8690
+ title: n?.title ?? e.title ?? "",
8691
+ alt: n?.alt ?? e.alt ?? "",
8692
+ description: n?.description ?? e.description ?? ""
8693
+ })])), { metadataOverrides: o, ...s } = e;
8694
+ return {
8695
+ ...s,
8696
+ title: i.title ?? e.title ?? "",
8697
+ alt: i.alt ?? e.alt ?? "",
8698
+ description: i.description ?? e.description ?? "",
8699
+ ...Object.keys(a).length > 0 ? { variants: a } : {}
8700
+ };
8701
+ }
8702
+ return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, dt(t)]));
8703
+ }
8704
+ async function ft(e, t) {
8705
+ if (typeof t == "string") {
8706
+ if (!t.includes("#node:") && !t.includes("data-node-id") && !t.includes("#asset:") && !t.includes("data-asset-id")) return t;
8707
+ let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set();
8708
+ for (let e of t.matchAll(/(?:#node:|data-node-id\s*=\s*["'])([^"'\s>]+)/gi)) n.add(e[1]);
8709
+ for (let e of t.matchAll(/(?:#asset:|data-asset-id\s*=\s*["'])([^"'\s>]+)/gi)) r.add(e[1]);
8710
+ if (n.size === 0 && r.size === 0) return t;
8711
+ 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();
8712
+ (Array.isArray(a) ? a : a?.results || []).forEach((e) => o.set(String(e.id), String(e.slug || "").replace(/^\/+|\/+$/g, "")));
8713
+ 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();
8714
+ 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) => {
8715
+ let n = (e, t) => {
8716
+ let n = e.match(RegExp(`\\b${t}\\s*=\\s*(["'])(.*?)\\1`, "i"));
8717
+ return n ? n[2] : void 0;
8718
+ }, r = n(t, "data-node-id"), i = n(t, "data-asset-id"), a = n(t, "href") || "";
8719
+ if (a.startsWith("mailto:")) return `<a ${t.replace(/\s+target\s*=\s*["'][^"']*["']/i, "")}>`;
8720
+ let s = i || a.match(/^#asset:(.+)$/i)?.[1], c = r || a.match(/^#node:(.+)$/i)?.[1];
8721
+ if (!c && !s) return e;
8722
+ if (s && !c) {
8723
+ let n = l.get(s);
8724
+ if (n) {
8725
+ let e = t;
8726
+ return /href\s*=\s*["'][^"']*["']/i.test(e) ? e = e.replace(/href\s*=\s*["'][^"']*["']/i, `href="${n}"`) : e += ` href="${n}"`, `<a ${e}>`;
8727
+ }
8728
+ return e;
8729
+ }
8730
+ let u = o.get(c), d = u === void 0 ? "#" : `/${u}`, f = t;
8731
+ return /href\s*=\s*["'][^"']*["']/i.test(f) ? f = f.replace(/href\s*=\s*["'][^"']*["']/i, `href="${d || "/"}"`) : f += ` href="${d || "/"}"`, `<a ${f}>`;
8732
+ });
8733
+ }
8734
+ if (Array.isArray(t)) return Promise.all(t.map((t) => ft(e, t)));
8735
+ if (t && typeof t == "object") {
8736
+ let n = await Promise.all(Object.entries(t).map(async ([t, n]) => [t, await ft(e, n)]));
8737
+ return Object.fromEntries(n);
8738
+ }
8739
+ return t;
8740
+ }
8741
+ ot.get("/:channelParam", async (e) => {
8742
+ try {
8743
+ 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);
8744
+ if (!r && !i) {
8745
+ let t = await o.get(a);
8746
+ if (t) return e.header("X-Cache", "HIT"), e.json(t);
8747
+ }
8748
+ 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));
8749
+ if (!s) return e.json({ error: `Channel '${n}' not found` }, 404);
8750
+ let c = s.status === "disabled" || s.status === "inactive" || s.isEnabled === 0 || s.isEnabled === !1;
8751
+ if (!r && c) return e.json({ error: `Channel '${s.key || n}' is currently inactive` }, 404);
8752
+ 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;
8753
+ if (m) try {
8754
+ p = typeof m == "string" ? JSON.parse(m) : m;
8755
+ } catch (e) {
8756
+ console.warn("[CMS Public Channel API] Failed to parse channel dataJson:", e);
8757
+ }
8758
+ let h = ut({
8759
+ ...p,
8760
+ ...s
8761
+ }, f);
8762
+ h = await B(t, h), h = dt(h), h = await ft(t, h);
8763
+ let g = {
8764
+ id: s.id,
8765
+ key: s.key,
8766
+ ...h
8767
+ };
8768
+ return !r && !i && (e.header("X-Cache", "MISS"), await ct(o, a, g, st(e))), e.json(g);
8769
+ } catch (t) {
8770
+ return console.error("[CMS Public Channel API] Error:", t), e.json({
8771
+ error: "Failed to fetch public channel",
8772
+ ...e.env?.ENVIRONMENT === "development" ? { details: t.message } : {}
8773
+ }, 500);
8774
+ }
8775
+ });
8776
+ //#endregion
8559
8777
  //#region server/routes/public/assets.ts
8560
- var at = new e();
8561
- function ot(e, t) {
8778
+ var pt = new e();
8779
+ function mt(e, t) {
8562
8780
  if (t === "webp") return "image/webp";
8563
8781
  if (t === "avif") return "image/avif";
8564
8782
  if (t === "jpeg" || t === "jpg") return "image/jpeg";
@@ -8566,7 +8784,7 @@ function ot(e, t) {
8566
8784
  let n = e.toLowerCase();
8567
8785
  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";
8568
8786
  }
8569
- at.get("/*", async (e) => {
8787
+ pt.get("/*", async (e) => {
8570
8788
  try {
8571
8789
  let t = e.req.path.replace(/^\/media\//, "").replace(/^\//, "");
8572
8790
  if (!t) return e.text("Asset key missing", 400);
@@ -8582,11 +8800,11 @@ at.get("/*", async (e) => {
8582
8800
  let e = await l.match(d);
8583
8801
  if (e) return e;
8584
8802
  }
8585
- let { storage: f, optimizer: p } = ie(e.env), m = await f.get(t);
8803
+ let { storage: f, optimizer: p } = ae(e.env), m = await f.get(t);
8586
8804
  if (!m) return e.text(`Asset not found: ${t}`, 404);
8587
8805
  if (!o) {
8588
8806
  let n = e.body(m, 200, {
8589
- "Content-Type": ot(t),
8807
+ "Content-Type": mt(t),
8590
8808
  "Cache-Control": "public, max-age=31536000, immutable"
8591
8809
  });
8592
8810
  return l && d && e.executionCtx?.waitUntil && e.executionCtx.waitUntil(l.put(d, n.clone())), n;
@@ -8600,7 +8818,7 @@ at.get("/*", async (e) => {
8600
8818
  key: t,
8601
8819
  env: e.env,
8602
8820
  req: e.req.raw
8603
- }), _ = ot(t, c), v = e.body(g, 200, {
8821
+ }), _ = mt(t, c), v = e.body(g, 200, {
8604
8822
  "Content-Type": _,
8605
8823
  "Cache-Control": "public, max-age=31536000, immutable"
8606
8824
  });
@@ -8611,8 +8829,8 @@ at.get("/*", async (e) => {
8611
8829
  });
8612
8830
  //#endregion
8613
8831
  //#region server/routes/public/paths.ts
8614
- var st = new e();
8615
- function ct(e, t) {
8832
+ var ht = new e();
8833
+ function gt(e, t) {
8616
8834
  let n = /* @__PURE__ */ new Date();
8617
8835
  if (e && String(e).trim() !== "") {
8618
8836
  let t = new Date(e);
@@ -8624,7 +8842,7 @@ function ct(e, t) {
8624
8842
  }
8625
8843
  return !0;
8626
8844
  }
8627
- st.get("/", async (e) => {
8845
+ ht.get("/", async (e) => {
8628
8846
  try {
8629
8847
  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();
8630
8848
  for (let e of n) {
@@ -8648,7 +8866,7 @@ st.get("/", async (e) => {
8648
8866
  function o(e = null, t = "") {
8649
8867
  let n = e == null || e === "" || e === "null" ? "__ROOT__" : String(e), s = i.get(n) || [];
8650
8868
  for (let e of s) {
8651
- let n = a.get(String(e.treeNodeId)) || {}, i = e.status === "published" || e.status === "active", s = ct(n.startShowingAt, n.stopShowingAt);
8869
+ let n = a.get(String(e.treeNodeId)) || {}, i = e.status === "published" || e.status === "active", s = gt(n.startShowingAt, n.stopShowingAt);
8652
8870
  if (!i || !s) continue;
8653
8871
  let c = (e.slug || "").replace(/^\/+|\/+$/g, ""), l = c === "home" || c === "homee" ? "/" : `${t}/${c}`.replace(/\/+/g, "/");
8654
8872
  e.nodeType !== "external-link" && r.push(l);
@@ -8665,7 +8883,7 @@ st.get("/", async (e) => {
8665
8883
  });
8666
8884
  //#endregion
8667
8885
  //#region server/index.ts
8668
- var $ = new e(), lt = !1;
8886
+ var $ = new e(), _t = !1;
8669
8887
  $.use("*", t()), $.use("/media/*", t({
8670
8888
  origin: "*",
8671
8889
  allowMethods: [
@@ -8686,13 +8904,13 @@ $.use("*", t()), $.use("/media/*", t({
8686
8904
  let n = new URL(e.req.url), r = (e.req.header("host") || n.hostname).split(":")[0];
8687
8905
  e.set("currentDomain", r);
8688
8906
  let i = l(e);
8689
- if (e.set("db", i), !lt) try {
8690
- await _(i), lt = !0;
8907
+ if (e.set("db", i), !_t) try {
8908
+ await _(i), _t = !0;
8691
8909
  } catch (e) {
8692
8910
  console.error("❌ [CMS Server] Failed to initialize system tables on cold start:", e);
8693
8911
  }
8694
8912
  await t();
8695
- }), $.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) => {
8913
+ }), $.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) => {
8696
8914
  if (e.env?.ASSETS) {
8697
8915
  let t = await e.env.ASSETS.fetch(e.req.raw);
8698
8916
  if (t.status === 404) {
@@ -8704,4 +8922,4 @@ $.use("*", t()), $.use("/media/*", t({
8704
8922
  return t();
8705
8923
  });
8706
8924
  //#endregion
8707
- export { $ as app, $ as default, Oe as compileDefinitions, ke as getCmsDefinitions };
8925
+ export { $ as app, $ as default, ke as compileDefinitions, Ae as getCmsDefinitions };