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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/bin/cli.js +229 -231
  2. package/dist/assets/index-BesA3e7A.js +164 -0
  3. package/dist/assets/index-D6yHZ_u1.css +1 -0
  4. package/dist/{dist-C-WAK7EF.js → dist-mic4UZBb.js} +691 -439
  5. package/dist/index.html +2 -2
  6. package/dist/index.js +693 -439
  7. package/dist/schema-compiler.js +1 -1
  8. package/package.json +1 -1
  9. package/schema.sql +2 -2
  10. package/templates/astro-starter/src/components/blocks/BlockRenderer.astro +1 -0
  11. package/templates/astro-starter/src/components/blocks/ColumnLayout.astro +1 -0
  12. package/templates/astro-starter/src/components/blocks/HeaderImage.astro +1 -0
  13. package/templates/astro-starter/src/components/blocks/HtmlBlock.astro +2 -1
  14. package/templates/astro-starter/src/components/blocks/ImageBlock.astro +39 -71
  15. package/templates/astro-starter/src/components/blocks/TextBlock.astro +2 -0
  16. package/templates/astro-starter/src/components/global/Breadcrumb.astro +2 -0
  17. package/templates/astro-starter/src/components/global/Footer.astro +2 -0
  18. package/templates/astro-starter/src/components/global/Header.astro +100 -28
  19. package/templates/astro-starter/src/components/{seo/SeoHead.astro → global/MetaHead.astro} +101 -49
  20. package/templates/astro-starter/src/components/global/NavigationMenu.astro +1 -0
  21. package/templates/astro-starter/src/components/ui/KamaImage.astro +114 -67
  22. package/templates/astro-starter/src/layouts/SkeletonLayout.astro +5 -3
  23. package/templates/astro-starter/src/layouts/StandardLayout.astro +14 -5
  24. package/templates/astro-starter/src/lib/cms.ts +48 -0
  25. package/templates/astro-starter/src/lib/media/kama-image-service.ts +16 -1
  26. package/templates/astro-starter/src/lib/media/media-proxy.ts +8 -6
  27. package/templates/astro-starter/src/lib/media/media-url.ts +65 -1
  28. package/templates/astro-starter/src/middleware.ts +131 -18
  29. package/templates/astro-starter/src/pages/[...slug].astro +10 -9
  30. package/definitions/_page.yaml +0 -52
  31. package/dist/assets/index-DGHRgyms.js +0 -164
  32. package/dist/assets/index-EaDn3OUJ.css +0 -1
  33. /package/templates/astro-starter/{public/css → src/styles}/standard-theme.css +0 -0
package/dist/index.js CHANGED
@@ -4815,10 +4815,10 @@ var u = /* @__PURE__ */ o({
4815
4815
  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
4816
  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
4817
  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 ",
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,\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
4819
  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
4820
  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 ",
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,\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
4822
  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
4823
  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
4824
  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 +5583,7 @@ var b = { hasSubscribers: !1 }, x = b, S = b, C = typeof performance == "object"
5583
5583
  async clear() {
5584
5584
  this.cache.clear();
5585
5585
  }
5586
- }, te = class {
5586
+ }, P = class {
5587
5587
  kv;
5588
5588
  constructor(e) {
5589
5589
  this.kv = e;
@@ -5600,7 +5600,7 @@ var b = { hasSubscribers: !1 }, x = b, S = b, C = typeof performance == "object"
5600
5600
  this.kv && await this.kv.delete(e);
5601
5601
  }
5602
5602
  async clear() {}
5603
- }, P = class {
5603
+ }, te = class {
5604
5604
  async get() {
5605
5605
  return null;
5606
5606
  }
@@ -5610,7 +5610,7 @@ var b = { hasSubscribers: !1 }, x = b, S = b, C = typeof performance == "object"
5610
5610
  }, F = null;
5611
5611
  function I(e) {
5612
5612
  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();
5613
+ 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
5614
  }
5615
5615
  //#endregion
5616
5616
  //#region server/storage/local.ts
@@ -5683,7 +5683,7 @@ var L = class {
5683
5683
  if (e.code !== "ENOENT") throw e;
5684
5684
  }
5685
5685
  }
5686
- }, R = class {
5686
+ }, ne = class {
5687
5687
  async process(e, t, n) {
5688
5688
  let r = await import(
5689
5689
  /* @vite-ignore */
@@ -5710,7 +5710,7 @@ var L = class {
5710
5710
  return console.warn("⚠️ [SharpImageOptimizer] Processing failed, returning raw buffer."), e;
5711
5711
  }
5712
5712
  }
5713
- }, ne = class {
5713
+ }, re = class {
5714
5714
  bucket;
5715
5715
  publicDomain;
5716
5716
  constructor(e, t) {
@@ -5755,7 +5755,7 @@ var L = class {
5755
5755
  async delete(e) {
5756
5756
  await this.bucket.delete(e);
5757
5757
  }
5758
- }, re = class {
5758
+ }, ie = class {
5759
5759
  async process(e, t, n) {
5760
5760
  let { env: r, key: i, req: a } = n;
5761
5761
  if (r.IMAGES) try {
@@ -5792,18 +5792,18 @@ var L = class {
5792
5792
  };
5793
5793
  //#endregion
5794
5794
  //#region server/storage/factory.ts
5795
- function ie(e) {
5795
+ function ae(e) {
5796
5796
  return e.KAMA_RUNTIME === "cloudflare" || e.MEDIA_BUCKET ? {
5797
- storage: new ne(e.MEDIA_BUCKET, e.CDN_DOMAIN || ""),
5798
- optimizer: new re()
5797
+ storage: new re(e.MEDIA_BUCKET, e.CDN_DOMAIN || ""),
5798
+ optimizer: new ie()
5799
5799
  } : {
5800
5800
  storage: new L(e.LOCAL_MEDIA_PATH),
5801
- optimizer: new R()
5801
+ optimizer: new ne()
5802
5802
  };
5803
5803
  }
5804
5804
  //#endregion
5805
5805
  //#region server/utils/node-assets-interceptor.ts
5806
- function ae(e) {
5806
+ function R(e) {
5807
5807
  if (!e || typeof e != "object") return {
5808
5808
  cleanedData: e,
5809
5809
  assetRefs: []
@@ -5881,7 +5881,7 @@ function z(e) {
5881
5881
  }
5882
5882
  return null;
5883
5883
  }
5884
- async function se(e, t) {
5884
+ async function B(e, t) {
5885
5885
  if (!t || typeof t != "object") return t;
5886
5886
  let n = /* @__PURE__ */ new Set(), r = (e) => {
5887
5887
  if (!e) return;
@@ -5994,7 +5994,7 @@ async function se(e, t) {
5994
5994
  }
5995
5995
  //#endregion
5996
5996
  //#region src/utils/schema-loader.ts
5997
- function ce(e) {
5997
+ function se(e) {
5998
5998
  return e ? {
5999
5999
  nodes: e.nodes || {},
6000
6000
  trees: e.trees || {},
@@ -6013,7 +6013,7 @@ function ce(e) {
6013
6013
  }
6014
6014
  //#endregion
6015
6015
  //#region server/services/cache-manager.ts
6016
- var B = class {
6016
+ var V = class {
6017
6017
  env;
6018
6018
  constructor(e) {
6019
6019
  this.env = e || {};
@@ -6025,7 +6025,8 @@ var B = class {
6025
6025
  apiToken: e.env?.CLOUDFLARE_API_TOKEN || this.env.CLOUDFLARE_API_TOKEN,
6026
6026
  frontendUrl: (e.env?.PUBLIC_FRONTEND_URL || this.env.PUBLIC_FRONTEND_URL || "http://localhost:4321").replace(/\/+$/, ""),
6027
6027
  cdnDomain: t ? t.replace(/^https?:\/\//, "").replace(/\/+$/, "") : "localhost:8787",
6028
- frontendWorker: e.env?.FRONTEND_WORKER || this.env.FRONTEND_WORKER
6028
+ frontendWorker: e.env?.FRONTEND_WORKER || this.env.FRONTEND_WORKER,
6029
+ disableCachePurge: e.env?.DISABLE_CACHE_PURGE || this.env.DISABLE_CACHE_PURGE
6029
6030
  };
6030
6031
  }
6031
6032
  isLocalEnv(e, t) {
@@ -6049,19 +6050,33 @@ var B = class {
6049
6050
  return r && n && r.startsWith(`https://${n}/`) && !r.includes("/media/") && (r = r.replace(`https://${n}/`, `https://${n}/media/`)), r;
6050
6051
  }
6051
6052
  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
- });
6053
+ let { apiToken: r, frontendUrl: i, frontendWorker: a, disableCachePurge: o } = this.getEnv(e);
6054
+ if (o === "true" || o === !0 || o === "1") return new Response(JSON.stringify({ skipped: !0 }), { status: 200 });
6055
+ let s = (n || i).replace(/\/+$/, ""), c = `${s}/api/purge`, l = { "Content-Type": "application/json" };
6056
+ if (r && (l.Authorization = `Bearer ${r}`), a && typeof a.fetch == "function") try {
6057
+ return await a.fetch(new Request(c, {
6058
+ method: "POST",
6059
+ headers: l,
6060
+ body: JSON.stringify(t)
6061
+ }));
6062
+ } catch (e) {
6063
+ return console.info(`[CacheManager] Worker binding purge call to ${c} failed silently:`, e?.message || e), new Response(JSON.stringify({ error: e?.message }), { status: 502 });
6064
+ }
6065
+ try {
6066
+ let e = new AbortController(), n = setTimeout(() => e.abort(), 1500);
6067
+ console.log(`[CacheManager] Dispatching POST purge request to: ${c}`);
6068
+ let r = await fetch(c, {
6069
+ method: "POST",
6070
+ headers: l,
6071
+ body: JSON.stringify(t),
6072
+ signal: e.signal
6073
+ });
6074
+ return clearTimeout(n), r;
6075
+ } catch (e) {
6076
+ 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 });
6077
+ }
6063
6078
  }
6064
- async purgeInternalWorkerCache(e, t, n, r, i = "en") {
6079
+ async purgeInternalWorkerCache(e, t, n, r, i) {
6065
6080
  try {
6066
6081
  let a = I(e);
6067
6082
  if (n) {
@@ -6074,7 +6089,7 @@ var B = class {
6074
6089
  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
6090
  i.length > 0 && (o = i.flatMap((e) => [String(e.id), e.key]).filter(Boolean));
6076
6091
  }
6077
- for (let t of o) await a.delete(`node:${t}:${i}:${e}`), await a.delete(`node:${t}:${i}:/${e}`);
6092
+ 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
6093
  }
6079
6094
  } catch (e) {
6080
6095
  console.warn("[CacheManager] Failed to purge internal worker cache:", e);
@@ -6085,30 +6100,30 @@ var B = class {
6085
6100
  try {
6086
6101
  let i = t.prepare("SELECT slug, status, language FROM content_nodes WHERE id = ?"), a = (typeof i.get == "function" ? await i.get(n) : (await i.bind(n).all())?.results?.[0]) || {};
6087
6102
  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() !== "") {
6103
+ let o = t.prepare("\n SELECT c.id, c.key, c.baseUrl, c.defaultLanguage \n FROM node_channels nc \n JOIN channels c ON nc.channelId = c.id \n WHERE nc.nodeId = ?\n "), s = typeof o.all == "function" ? await o.all(n) : await o.bind(n).all(), c = Array.isArray(s) ? s : s?.results || [], l = c.length > 0 ? c[0]?.defaultLanguage?.trim() : null, u = a.language?.trim() || l || null, d = String(a.slug).replace(/^\/+|\/+$/g, ""), f = this.getEnv(e).frontendUrl, p = /* @__PURE__ */ new Set();
6104
+ for (let e of c) if (e.baseUrl && typeof e.baseUrl == "string" && e.baseUrl.trim() !== "") {
6090
6105
  let t = e.baseUrl.trim();
6091
- !t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), f.add(t.replace(/\/+$/, ""));
6106
+ !t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), p.add(t.replace(/\/+$/, ""));
6092
6107
  }
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`, {
6108
+ p.size === 0 && f && p.add(f);
6109
+ let m = t.prepare("\n SELECT DISTINCT a.cdnUrl, a.storageKeyPrivate\n FROM node_assets na\n JOIN assets a ON na.assetId = a.id\n WHERE na.nodeId = ?\n "), h = typeof m.all == "function" ? await m.all(n) : await m.bind(n).all(), g = (Array.isArray(h) ? h : h?.results || []).map((t) => t.url || this.getSafeUrl(t.cdnUrl, t.storageKeyPrivate, this.getEnv(e).cdnDomain)).filter(Boolean);
6110
+ await this.purgeInternalWorkerCache(e, t, n, d, u);
6111
+ let _ = this.getEnv(e).cdnDomain, { zoneId: v, apiToken: y } = this.getEnv(e);
6112
+ for (let t of p) {
6113
+ let n = d === "home" || !d ? t : `${t}/${d}`, i = [n, `${n}/`], a = u ? `&lang=${u}` : "";
6114
+ if (c.length > 0) for (let e of c) e.id && i.push(`https://${_}/api/v1/node/${d}?channelId=${e.id}${a}`), e.key && i.push(`https://${_}/api/v1/node/${d}?channelId=${e.key}${a}`);
6115
+ else i.push(`https://${_}/api/v1/node/${d}${u ? `?lang=${u}` : ""}`);
6116
+ for (let e of g) e && i.push(`${t}${e.startsWith("/") ? e : `/${e}`}`);
6117
+ if (await this.callAstroPurge(e, { urls: i }, t), v && y && !this.isLocalEnv(e, t) && fetch(`https://api.cloudflare.com/client/v4/zones/${v}/purge_cache`, {
6103
6118
  method: "POST",
6104
6119
  headers: {
6105
- Authorization: `Bearer ${v}`,
6120
+ Authorization: `Bearer ${y}`,
6106
6121
  "Content-Type": "application/json"
6107
6122
  },
6108
6123
  body: JSON.stringify({ files: i })
6109
6124
  }).catch(() => {}), !r) {
6110
6125
  let e = `${n}${n.includes("?") ? "&" : "?"} _warmer=${Date.now()}`;
6111
- console.log(`[CacheManager] Prewarming cache at: ${e}`), await fetch(e, { headers: {
6126
+ console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
6112
6127
  "X-Cache-Warmer": "true",
6113
6128
  "User-Agent": "Kama-Cache-Warmer/1.0"
6114
6129
  } }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
@@ -6137,35 +6152,49 @@ var B = class {
6137
6152
  }
6138
6153
  async purgeGlobalCacheDirect(e, t) {
6139
6154
  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`, {
6155
+ let { zoneId: n, apiToken: r } = this.getEnv(e);
6156
+ if (!(await this.callAstroPurge(e, { purge_everything: !0 })).ok) return;
6157
+ if (n && r && !this.isLocalEnv(e) && fetch(`https://api.cloudflare.com/client/v4/zones/${n}/purge_cache`, {
6143
6158
  method: "POST",
6144
6159
  headers: {
6145
6160
  Authorization: `Bearer ${r}`,
6146
6161
  "Content-Type": "application/json"
6147
6162
  },
6148
6163
  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(() => {});
6164
+ }).catch(() => {}), await new Promise((e) => setTimeout(e, 100)), t) await this.warmAllPublishedPages(e, t);
6165
+ else {
6166
+ let { frontendUrl: t } = this.getEnv(e);
6167
+ fetch(`${t.replace(/\/+$/, "")}/?_warmer=${Date.now()}`, { headers: { "X-Cache-Warmer": "true" } }).catch(() => {});
6168
+ }
6150
6169
  } catch (e) {
6151
6170
  console.warn("[CacheManager] Direct Global Purge skipped:", e);
6152
6171
  }
6153
6172
  }
6154
6173
  async warmAllPublishedPages(e, t) {
6155
6174
  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);
6175
+ 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 = {
6176
+ "X-Cache-Warmer": "true",
6177
+ "User-Agent": "Kama-Cache-Warmer/1.0"
6178
+ }, s = Date.now(), c = /* @__PURE__ */ new Set();
6179
+ for (let e of i) {
6180
+ let t = String(e.slug).replace(/^\/+|\/+$/g, ""), n = a;
6181
+ 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(/\/+$/, ""));
6182
+ let r = t === "home" || !t ? n : `${n}/${t}`;
6183
+ c.add(`${r}?_warmer=${s}`);
6184
+ }
6185
+ c.add(`${a}/?_warmer=${s}`);
6186
+ let l = Array.from(c);
6187
+ for (let e = 0; e < l.length; e += 6) {
6188
+ let t = l.slice(e, e + 6);
6189
+ await Promise.all(t.map((e) => fetch(e, { headers: o }).catch((t) => console.warn(`[CacheWarmer] Skipped prewarm for ${e}:`, t?.message || t))));
6190
+ }
6191
+ console.log(`[CacheWarmer] Prewarmed ${l.length} published pages across ${Math.ceil(l.length / 6)} batches.`);
6163
6192
  } catch (e) {
6164
6193
  console.warn("⚠️ [CacheWarmer] Tree-wide warming failed:", e);
6165
6194
  }
6166
6195
  }
6167
- }, V = new e();
6168
- async function le(e, t, n = []) {
6196
+ }, H = new e();
6197
+ async function ce(e, t, n = []) {
6169
6198
  let r = e.prepare(t);
6170
6199
  if (typeof r.bind == "function") {
6171
6200
  let e = await r.bind(...n).all();
@@ -6177,24 +6206,25 @@ async function le(e, t, n = []) {
6177
6206
  }
6178
6207
  return [];
6179
6208
  }
6180
- async function ue(e, t, n = []) {
6209
+ async function le(e, t, n = []) {
6181
6210
  let r = e.prepare(t);
6182
6211
  if (typeof r.bind == "function") return r.bind(...n).run();
6183
6212
  if (typeof r.run == "function") return r.run(...n);
6184
6213
  }
6185
- function de(e) {
6214
+ function U(e) {
6186
6215
  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
6216
  }
6188
- function fe(e) {
6217
+ function ue(e) {
6189
6218
  return +(e === !0 || e === 1 || e === "1" || e === "true");
6190
6219
  }
6191
- function pe(e) {
6220
+ function de(e) {
6192
6221
  if (e == null || e === "null" || e === "" || typeof e == "string" && e.startsWith("draft-")) return null;
6193
6222
  let t = Number(e);
6194
6223
  return isNaN(t) ? null : t;
6195
6224
  }
6196
- function H(e) {
6225
+ function fe(e) {
6197
6226
  let t = { ...e };
6227
+ delete t.language, delete t.defaultLanguage;
6198
6228
  for (let e of [
6199
6229
  "id",
6200
6230
  "treeNodeId",
@@ -6205,7 +6235,6 @@ function H(e) {
6205
6235
  "contentType",
6206
6236
  "title",
6207
6237
  "slug",
6208
- "language",
6209
6238
  "hidden",
6210
6239
  "is_hidden",
6211
6240
  "isHidden",
@@ -6222,17 +6251,22 @@ function H(e) {
6222
6251
  ]) delete t[e];
6223
6252
  return t;
6224
6253
  }
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;
6254
+ function pe(e, t = /* @__PURE__ */ new Set()) {
6255
+ 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;
6256
+ }
6257
+ function me(e, t) {
6258
+ if (!e) return !0;
6259
+ 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;
6260
+ return n || r || i || a || c;
6227
6261
  }
6228
- async function U(e, t, n) {
6262
+ async function he(e, t, n) {
6229
6263
  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;
6264
+ let n = (await ce(e, "\n SELECT id, storageKeyPrivate, isSystemVariant, parentAssetId, filename\n FROM assets WHERE id = ?\n ", [r]))[0];
6265
+ if (!n || (await ce(e, "SELECT 1 FROM node_assets WHERE assetId = ? LIMIT 1", [n.id])).length > 0) continue;
6232
6266
  let i = [n];
6233
6267
  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;
6268
+ 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);
6269
+ if (r.length > 0 && (await ce(e, `SELECT DISTINCT assetId FROM node_assets WHERE assetId IN (${r.map(() => "?").join(",")})`, r)).length > 0) continue;
6236
6270
  i = [n, ...t];
6237
6271
  }
6238
6272
  for (let e of i) if (e.storageKeyPrivate) try {
@@ -6241,10 +6275,10 @@ async function U(e, t, n) {
6241
6275
  console.warn(`[Asset Cleanup] Failed to delete ${e.storageKeyPrivate}:`, t);
6242
6276
  }
6243
6277
  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);
6278
+ await le(e, `DELETE FROM node_assets WHERE assetId IN (${o})`, a), await le(e, `DELETE FROM assets WHERE id IN (${o})`, a);
6245
6279
  }
6246
6280
  }
6247
- async function W(e, t, n) {
6281
+ async function ge(e, t, n) {
6248
6282
  let r = {}, i = null;
6249
6283
  if (t) {
6250
6284
  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 +6292,7 @@ async function W(e, t, n) {
6258
6292
  }
6259
6293
  }
6260
6294
  if (!i) {
6261
- let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ?").get(n);
6295
+ let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ? OR key = ? LIMIT 1").get(Number(n) || -1, String(n));
6262
6296
  if (t && t.dataJson) try {
6263
6297
  let e = typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson;
6264
6298
  e.subpageLayoutId && e.subpageLayoutId !== "inherit" && (i = e.subpageLayoutId);
@@ -6269,7 +6303,7 @@ async function W(e, t, n) {
6269
6303
  inheritedFields: r
6270
6304
  };
6271
6305
  }
6272
- V.get("/", async (e) => {
6306
+ H.get("/", async (e) => {
6273
6307
  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
6308
  if (n) {
6275
6309
  let r = Number(n);
@@ -6280,7 +6314,7 @@ V.get("/", async (e) => {
6280
6314
  id: i.id,
6281
6315
  title: i.title,
6282
6316
  slug: i.slug,
6283
- language: i.language || "en",
6317
+ language: i.language || null,
6284
6318
  nodeType: i.contentType,
6285
6319
  contentType: i.contentType,
6286
6320
  isHidden: !!i.isHidden,
@@ -6294,9 +6328,9 @@ V.get("/", async (e) => {
6294
6328
  updatedAt: i.updatedAt
6295
6329
  }, s = i.draftDataJson || i.dataJson;
6296
6330
  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;
6331
+ 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
6332
  if (a) {
6299
- let { resolvedLayoutId: e, inheritedFields: r } = await W(t, a.parentId, a.treeId);
6333
+ let { resolvedLayoutId: e, inheritedFields: r } = await ge(t, a.parentId, a.treeId);
6300
6334
  (l === "inherit" || !l) && (l = e);
6301
6335
  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
6336
  }
@@ -6311,7 +6345,7 @@ V.get("/", async (e) => {
6311
6345
  let r = t.allowedLayouts;
6312
6346
  return r ? typeof r == "string" ? r === e : !Array.isArray(r) || r.length === 0 || r.includes(e) : !0;
6313
6347
  })(l) && (l = null), (l === "inherit" || !l) && (l = c.defaultLayout || null);
6314
- let u = await se(t, H(n));
6348
+ let u = await B(t, fe(n));
6315
6349
  Object.assign(o, u), o.resolvedLayoutId = l;
6316
6350
  } catch {}
6317
6351
  let c = await t.prepare("SELECT channelId FROM node_channels WHERE nodeId = ?").all(r);
@@ -6321,7 +6355,7 @@ V.get("/", async (e) => {
6321
6355
  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
6356
  let n = {};
6323
6357
  try {
6324
- n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson || "{}") : e.dataJson || {}, n && typeof n == "object" && (n = await se(t, n));
6358
+ n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson || "{}") : e.dataJson || {}, n && typeof n == "object" && (n = await B(t, n));
6325
6359
  } catch {
6326
6360
  n = {};
6327
6361
  }
@@ -6392,7 +6426,7 @@ V.get("/", async (e) => {
6392
6426
  id: e.id,
6393
6427
  title: e.title,
6394
6428
  slug: e.slug,
6395
- language: e.language || "en",
6429
+ language: e.language || null,
6396
6430
  contentType: e.contentType,
6397
6431
  nodeType: e.contentType,
6398
6432
  isHidden: !!e.isHidden,
@@ -6409,7 +6443,7 @@ V.get("/", async (e) => {
6409
6443
  assetCount: e.assetCount || 0
6410
6444
  }, i = e.draftDataJson || e.dataJson;
6411
6445
  if (i) try {
6412
- let e = typeof i == "string" ? JSON.parse(i) : i, n = await se(t, H(e));
6446
+ let e = typeof i == "string" ? JSON.parse(i) : i, n = await B(t, fe(e));
6413
6447
  Object.assign(r, n);
6414
6448
  } catch {}
6415
6449
  return r;
@@ -6421,13 +6455,35 @@ V.get("/", async (e) => {
6421
6455
  offset: p,
6422
6456
  limit: f
6423
6457
  });
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) {
6458
+ }), H.post("/", async (e) => {
6459
+ 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;
6460
+ if (T) {
6461
+ let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ? OR key = ? LIMIT 1").get(Number(T) || -1, String(T));
6462
+ if (e?.dataJson) try {
6463
+ let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
6464
+ E = t.defaultLanguage?.trim() || t.language?.trim() || null;
6465
+ } catch {}
6466
+ }
6467
+ if (!E && h && Array.isArray(h) && h.length > 0) {
6468
+ let e = typeof h[0] == "object" ? h[0].id : h[0];
6469
+ if (e && e !== "all") {
6470
+ let n = await t.prepare("SELECT defaultLanguage, dataJson FROM channels WHERE id = ? LIMIT 1").get(Number(e));
6471
+ if (n) {
6472
+ if (n.defaultLanguage) E = n.defaultLanguage.trim();
6473
+ else if (n.dataJson) try {
6474
+ let e = typeof n.dataJson == "string" ? JSON.parse(n.dataJson) : n.dataJson;
6475
+ E = e.defaultLanguage?.trim() || e.language?.trim() || null;
6476
+ } catch {}
6477
+ }
6478
+ }
6479
+ }
6480
+ C && E && C === E && (C = null);
6481
+ let D = a, O = /* @__PURE__ */ new Set(), k = !1, A = s === void 0 ? null : U(s);
6482
+ if (A) {
6427
6483
  let n = [];
6428
6484
  if (g !== void 0 && Array.isArray(g) && g.length > 0) for (let e of g) n.push({
6429
6485
  treeId: Number(e.treeId),
6430
- parentId: pe(e.parentId ?? e._draftParentId ?? null)
6486
+ parentId: de(e.parentId ?? e._draftParentId ?? null)
6431
6487
  });
6432
6488
  else if (a) {
6433
6489
  let e = await t.prepare("SELECT treeId, parentId FROM tree_nodes WHERE contentId = ?").all(a), r = Array.isArray(e) ? e : e?.results || [];
@@ -6437,94 +6493,103 @@ V.get("/", async (e) => {
6437
6493
  });
6438
6494
  }
6439
6495
  for (let r of n) {
6440
- let n = r.parentId === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = r.parentId === null ? [r.treeId, E] : [
6496
+ let n = r.parentId === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = r.parentId === null ? [r.treeId, A] : [
6441
6497
  r.treeId,
6442
6498
  r.parentId,
6443
- E
6499
+ A
6444
6500
  ], o = `
6445
6501
  SELECT cn.id FROM tree_nodes tn
6446
6502
  INNER JOIN content_nodes cn ON tn.contentId = cn.id
6447
6503
  WHERE tn.treeId = ? AND ${n} AND cn.slug = ? AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
6448
6504
  `;
6449
6505
  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.`,
6506
+ error: `The slug '${A}' is already in use by another page in this section.`,
6451
6507
  field: "slug"
6452
6508
  }, 409);
6453
6509
  }
6454
6510
  }
6455
6511
  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 || "{}";
6512
+ let e = await t.prepare("SELECT title, slug, language, contentType, isHidden, draftDataJson, dataJson, publishedAt, status FROM content_nodes WHERE id = ?").get(a);
6513
+ k = me(e, {
6514
+ title: o,
6515
+ slug: A,
6516
+ isHidden: b,
6517
+ sanitizedFields: v
6518
+ });
6519
+ let n = e?.draftDataJson || e?.dataJson || "{}";
6457
6520
  try {
6458
- me(typeof n == "string" ? JSON.parse(n) : n, T);
6521
+ pe(typeof n == "string" ? JSON.parse(n) : n, O);
6459
6522
  } catch {}
6460
6523
  if (m !== void 0) {
6461
6524
  let e = await t.prepare("SELECT dataJson FROM content_blocks WHERE contentId = ? AND isDraft = 1").all(a);
6462
6525
  (Array.isArray(e) ? e : e?.results || []).forEach((e) => {
6463
6526
  try {
6464
- me(typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson, T);
6527
+ pe(typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson, O);
6465
6528
  } catch {}
6466
6529
  });
6467
6530
  }
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 = {};
6531
+ 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
6532
  try {
6470
- u = JSON.parse(l);
6533
+ d = JSON.parse(u);
6471
6534
  } catch {}
6472
- let d = JSON.stringify({
6473
- ...u,
6535
+ let f = JSON.stringify({
6536
+ ...d,
6474
6537
  ...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);
6538
+ }), p = e?.status === "published" || e?.publishedAt ? "published" : "draft", h = +(p === "published");
6539
+ 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
6540
  } 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);
6541
+ k = !0;
6542
+ 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);
6543
+ D = Number(e.lastInsertRowid);
6480
6544
  }
6481
- if (h !== void 0 && Array.isArray(h) && w) {
6482
- await t.prepare("DELETE FROM node_channels WHERE nodeId = ?").run(w);
6545
+ if (h !== void 0 && Array.isArray(h) && D) {
6546
+ await t.prepare("DELETE FROM node_channels WHERE nodeId = ?").run(D);
6483
6547
  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
6548
  if (e.length > 0) {
6485
- let n = e.map(() => "(?, ?)").join(", "), r = e.flatMap((e) => [w, e]);
6549
+ let n = e.map(() => "(?, ?)").join(", "), r = e.flatMap((e) => [D, e]);
6486
6550
  await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${n}`).run(...r);
6487
6551
  }
6488
6552
  }
6489
- if (g !== void 0 && Array.isArray(g) && g.length > 0 && w) for (let e of g) {
6553
+ if (g !== void 0 && Array.isArray(g) && g.length > 0 && D) for (let e of g) {
6490
6554
  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);
6555
+ 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);
6556
+ 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
6557
  }
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);
6558
+ let j = [];
6559
+ if (m !== void 0 && Array.isArray(m) && D) {
6560
+ await t.prepare("DELETE FROM content_blocks WHERE contentId = ? AND isDraft = 1").run(D);
6497
6561
  let e = [], n = [];
6498
6562
  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({
6563
+ 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
6564
  ...a,
6501
6565
  blockId: o,
6502
6566
  _instanceId: o
6503
6567
  });
6504
- c.forEach((e) => D.push({
6568
+ c.forEach((e) => j.push({
6505
6569
  ...e,
6506
6570
  fieldKey: `blocks[${t}].${e.fieldKey}`
6507
6571
  }));
6508
6572
  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);
6573
+ e.push("(?, ?, ?, ?, ?, 1)"), n.push(D, t, i, JSON.stringify(s), l);
6510
6574
  }
6511
6575
  e.length > 0 && await t.prepare(`INSERT INTO content_blocks (contentId, sortOrder, elementType, dataJson, region, isDraft) VALUES ${e.join(", ")}`).run(...n);
6512
6576
  }
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)));
6577
+ if (D) {
6578
+ let n = [...y, ...j];
6579
+ await oe(t, D, n);
6580
+ let r = new Set(n.map((e) => e.assetId)), i = new Set([...O].filter((e) => !r.has(e)));
6517
6581
  if (i.size > 0) {
6518
- let { storage: n } = ie(e.env);
6519
- await U(t, n, i);
6582
+ let { storage: n } = ae(e.env);
6583
+ await he(t, n, i);
6520
6584
  }
6521
6585
  }
6522
- return await I(e).clear(), e.json({
6586
+ return await I(e).clear(), D && new V(e.env).purgeNode(e, t, D, k), e.json({
6523
6587
  success: !0,
6524
- id: w,
6525
- status: "draft"
6588
+ id: D,
6589
+ status: "draft",
6590
+ isStructuralChange: k
6526
6591
  });
6527
- }), V.post("/publish", async (e) => {
6592
+ }), H.post("/publish", async (e) => {
6528
6593
  let t = e.get("db"), n = await e.req.json(), r = n.id || n.nodeId;
6529
6594
  if (!r || isNaN(Number(r))) return e.json({ error: "Node ID required for publishing" }, 400);
6530
6595
  let i = Number(r), a = e.get("user")?.id || null, o = await t.prepare("SELECT * FROM content_nodes WHERE id = ?").get(i);
@@ -6537,57 +6602,58 @@ V.get("/", async (e) => {
6537
6602
  try {
6538
6603
  c = typeof o.draftDataJson == "string" ? JSON.parse(o.draftDataJson) : o.draftDataJson || {};
6539
6604
  } 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) {
6605
+ 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 || "{}";
6606
+ 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);
6607
+ let _ = await t.prepare("SELECT * FROM content_blocks WHERE contentId = ? AND isDraft = 1 ORDER BY sortOrder ASC").all(i), v = Array.isArray(_) ? _ : _?.results || [];
6608
+ if (v.length > 0) {
6544
6609
  let e = [], n = [];
6545
- for (let t of g) {
6610
+ for (let t of v) {
6546
6611
  let r = t.region !== void 0 && t.region !== null && String(t.region).trim() !== "" ? String(t.region) : "content";
6547
6612
  e.push("(?, ?, ?, ?, ?, 0)"), n.push(i, t.sortOrder, t.elementType, t.dataJson, r);
6548
6613
  }
6549
6614
  await t.prepare(`INSERT INTO content_blocks (contentId, sortOrder, elementType, dataJson, region, isDraft) VALUES ${e.join(", ")}`).run(...n);
6550
6615
  }
6551
- let _ = ((await t.prepare("SELECT COUNT(*) as count FROM node_revisions WHERE nodeId = ?").get(i))?.count || 0) + 1, v = {
6552
- version: _,
6616
+ let y = ((await t.prepare("SELECT COUNT(*) as count FROM node_revisions WHERE nodeId = ?").get(i))?.count || 0) + 1, b = {
6617
+ version: y,
6553
6618
  publishedAt: (/* @__PURE__ */ new Date()).toISOString(),
6554
6619
  node: {
6555
6620
  ...o,
6556
- dataJson: m
6621
+ dataJson: g
6557
6622
  },
6558
- blocks: g
6623
+ blocks: v
6559
6624
  };
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({
6625
+ 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
6626
  success: !0,
6562
6627
  id: i,
6563
6628
  status: "published",
6564
- version: _,
6565
- publishedAt: v.publishedAt,
6566
- hasUnpublishedChanges: !1
6629
+ version: y,
6630
+ publishedAt: b.publishedAt,
6631
+ hasUnpublishedChanges: !1,
6632
+ isStructuralChange: h
6567
6633
  });
6568
- }), V.delete("/", async (e) => {
6634
+ }), H.delete("/", async (e) => {
6569
6635
  let t = e.get("db"), n = e.req.query("id");
6570
6636
  if (!n) return e.json({ error: "Node ID required" }, 400);
6571
6637
  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({
6638
+ 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
6639
  success: !0,
6574
6640
  deletedNodeId: r
6575
6641
  });
6576
- }), V.post("/restore", async (e) => {
6642
+ }), H.post("/restore", async (e) => {
6577
6643
  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({
6644
+ 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
6645
  success: !0,
6580
6646
  restoredNodeId: r
6581
6647
  })) : e.json({ error: "Node not found" }, 404) : e.json({ error: "Node ID required" }, 400);
6582
- }), V.delete("/purge", async (e) => {
6648
+ }), H.delete("/purge", async (e) => {
6583
6649
  let t = e.get("db"), n = e.req.query("id");
6584
6650
  if (!n) return e.json({ error: "Node ID required" }, 400);
6585
6651
  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({
6652
+ 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
6653
  success: !0,
6588
6654
  purgedNodeId: r
6589
6655
  });
6590
- }), V.get("/:id/revisions", async (e) => {
6656
+ }), H.get("/:id/revisions", async (e) => {
6591
6657
  let t = e.get("db"), n = Number(e.req.param("id"));
6592
6658
  if (isNaN(n)) return e.json({ error: "Invalid Node ID" }, 400);
6593
6659
  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 +6669,7 @@ V.get("/", async (e) => {
6603
6669
  };
6604
6670
  });
6605
6671
  return e.json({ revisions: i });
6606
- }), V.get("/:id/revisions/:version", async (e) => {
6672
+ }), H.get("/:id/revisions/:version", async (e) => {
6607
6673
  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
6674
  if (!i) return e.json({ error: "Snapshot not found" }, 404);
6609
6675
  let a = {};
@@ -6613,7 +6679,7 @@ V.get("/", async (e) => {
6613
6679
  return e.json({ error: "Corrupt snapshot data" }, 500);
6614
6680
  }
6615
6681
  return e.json({ snapshot: a });
6616
- }), V.post("/:id/revisions/:version/restore", async (e) => {
6682
+ }), H.post("/:id/revisions/:version/restore", async (e) => {
6617
6683
  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
6684
  if (!a) return e.json({ error: "Snapshot not found" }, 404);
6619
6685
  let o = {};
@@ -6634,8 +6700,8 @@ V.get("/", async (e) => {
6634
6700
  });
6635
6701
  //#endregion
6636
6702
  //#region server/routes/admin/trees.ts
6637
- var G = new e();
6638
- function he(e, t = null) {
6703
+ var W = new e();
6704
+ function _e(e, t = null) {
6639
6705
  let n = [];
6640
6706
  for (let r = 0; r < e.length; r++) {
6641
6707
  let i = e[r];
@@ -6647,19 +6713,19 @@ function he(e, t = null) {
6647
6713
  id: o,
6648
6714
  parentId: t,
6649
6715
  sortOrder: r
6650
- }), i.children && Array.isArray(i.children) && i.children.length > 0 && n.push(...he(i.children, o)));
6716
+ }), i.children && Array.isArray(i.children) && i.children.length > 0 && n.push(..._e(i.children, o)));
6651
6717
  }
6652
6718
  return n;
6653
6719
  }
6654
- function ge(e) {
6720
+ function G(e) {
6655
6721
  if (e == null || e === "null" || e === "" || typeof e == "string" && e.startsWith("draft-")) return null;
6656
6722
  let t = Number(e);
6657
6723
  return isNaN(t) ? null : t;
6658
6724
  }
6659
- function _e(e) {
6725
+ function ve(e) {
6660
6726
  return +(e === !0 || e === 1 || e === "1" || e === "true");
6661
6727
  }
6662
- G.get("/tree.json", async (e) => {
6728
+ W.get("/tree.json", async (e) => {
6663
6729
  try {
6664
6730
  let t = e.get("db"), n = e.req.query("treeId") || "main-nav", r = e.req.query("preview") === "true", i = 1;
6665
6731
  if (isNaN(Number(n))) {
@@ -6694,7 +6760,7 @@ G.get("/tree.json", async (e) => {
6694
6760
  id: e.contentId,
6695
6761
  treeNodeId: e.treeNodeId,
6696
6762
  parentId: e.parentId || null,
6697
- language: e.language || "en",
6763
+ language: e.language?.trim() || null,
6698
6764
  hidden: +!!s,
6699
6765
  isHidden: s,
6700
6766
  status: e.status || "draft",
@@ -6709,9 +6775,9 @@ G.get("/tree.json", async (e) => {
6709
6775
  } catch (t) {
6710
6776
  return console.error("[CMS Tree API] GET Error:", t), e.json({ error: t.message || "Failed to fetch tree" }, 500);
6711
6777
  }
6712
- }), G.post("/tree.json", async (e) => {
6778
+ }), W.post("/tree.json", async (e) => {
6713
6779
  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;
6780
+ 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
6781
  if (isNaN(Number(r))) {
6716
6782
  let e = await t.prepare("SELECT id FROM trees WHERE key = ?").get(r);
6717
6783
  if (e && e.id) o = Number(e.id);
@@ -6721,7 +6787,7 @@ G.get("/tree.json", async (e) => {
6721
6787
  }
6722
6788
  } else o = Number(r);
6723
6789
  if (n.tree && Array.isArray(n.tree)) {
6724
- let r = he(n.tree, null);
6790
+ let r = _e(n.tree, null);
6725
6791
  if (r.length > 0) for (let e = 0; e < r.length; e += 50) {
6726
6792
  let n = r.slice(e, e + 50), i = n.map((e) => e.id), a = i.map(() => "?").join(","), s = "UPDATE tree_nodes SET \n";
6727
6793
  s += "parentId = CASE id \n", n.forEach(() => {
@@ -6741,9 +6807,9 @@ G.get("/tree.json", async (e) => {
6741
6807
  reorderedCount: r.length
6742
6808
  });
6743
6809
  }
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);
6810
+ 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
6811
  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;
6812
+ let g = G(u), _ = e.get("user")?.id || null;
6747
6813
  if (s === "create") {
6748
6814
  let r = m.slug || n.slug || c, s = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
6749
6815
  if (s) {
@@ -6765,23 +6831,41 @@ G.get("/tree.json", async (e) => {
6765
6831
  field: "slug"
6766
6832
  }, 409);
6767
6833
  }
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(`
6834
+ let u = m.language?.trim() || n.language?.trim() || null;
6835
+ if (!u) {
6836
+ let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ?").get(o);
6837
+ if (e?.dataJson) try {
6838
+ let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
6839
+ t.defaultLanguage && (u = t.defaultLanguage.trim());
6840
+ } catch {}
6841
+ }
6842
+ if (!u) {
6843
+ let e = [];
6844
+ if (n.channels && Array.isArray(n.channels) ? e = n.channels : n.channelId && n.channelId !== "all" && (e = [n.channelId]), e.length > 0) {
6845
+ let n = Number(e[0]);
6846
+ if (!isNaN(n)) {
6847
+ let e = await t.prepare("SELECT defaultLanguage FROM channels WHERE id = ?").get(n);
6848
+ e?.defaultLanguage && (u = e.defaultLanguage.trim());
6849
+ }
6850
+ }
6851
+ }
6852
+ let d = JSON.stringify(m), f = await t.prepare("\n INSERT INTO content_nodes (contentType, title, slug, language, isHidden, status, draftDataJson, dataJson, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, 'draft', ?, NULL, ?, ?)\n ").run(l || "page", c || "Untitled", s, u, h, d, _, _), p = Number(f.lastInsertRowid);
6853
+ await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, p);
6854
+ let v = g === null ? "parentId IS NULL" : "parentId = ?", y = g === null ? [o] : [o, g], b = (await t.prepare(`
6771
6855
  SELECT COALESCE(MAX(sortOrder), -1) + 1 as nextSort
6772
6856
  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]);
6857
+ WHERE treeId = ? AND ${v}
6858
+ `).get(...y))?.nextSort ?? 0, x = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, ?)\n ").run(o, p, g, b), S = Number(x.lastInsertRowid), C = [];
6859
+ n.channels && Array.isArray(n.channels) ? C = n.channels : n.channelId && n.channelId !== "all" && (C = [n.channelId]);
6860
+ let w = [...new Set(C)].filter((e) => e && e !== "all").map((e) => Number(e));
6861
+ if (w.length > 0) {
6862
+ let e = w.map(() => "(?, ?)").join(", "), n = w.flatMap((e) => [p, e]);
6779
6863
  await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...n);
6780
6864
  }
6781
6865
  return await i.clear(), a.purgeGlobalCache(e, t), e.json({
6782
6866
  success: !0,
6783
- id: f,
6784
- treeNodeId: x,
6867
+ id: p,
6868
+ treeNodeId: S,
6785
6869
  status: "draft"
6786
6870
  }, 201);
6787
6871
  }
@@ -6832,7 +6916,7 @@ G.get("/tree.json", async (e) => {
6832
6916
  details: t.message
6833
6917
  }, 500);
6834
6918
  }
6835
- }), G.get("/trees.json", async (e) => {
6919
+ }), W.get("/trees.json", async (e) => {
6836
6920
  try {
6837
6921
  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
6922
  let n = Number(t.treeId), r = Number(t.channelId);
@@ -6862,7 +6946,7 @@ G.get("/tree.json", async (e) => {
6862
6946
  } catch {
6863
6947
  return e.json([]);
6864
6948
  }
6865
- }), G.post("/trees.json", async (e) => {
6949
+ }), W.post("/trees.json", async (e) => {
6866
6950
  try {
6867
6951
  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
6952
  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 +6971,7 @@ G.get("/tree.json", async (e) => {
6887
6971
  await t.prepare(`INSERT OR IGNORE INTO channel_trees (channelId, treeId, key) VALUES ${n}`).run(...r);
6888
6972
  }
6889
6973
  }
6890
- return await I(e).clear(), new B(e.env).purgeGlobalCache(e, t), e.json({
6974
+ return await I(e).clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
6891
6975
  success: !0,
6892
6976
  id: p,
6893
6977
  key: o,
@@ -6901,12 +6985,12 @@ G.get("/tree.json", async (e) => {
6901
6985
  } catch (t) {
6902
6986
  return console.error("[API Trees] Error saving tree:", t), e.json({ error: t.message || "Failed to save tree" }, 500);
6903
6987
  }
6904
- }), G.delete("/trees.json", async (e) => {
6988
+ }), W.delete("/trees.json", async (e) => {
6905
6989
  let t = e.get("db"), n = e.req.query("id");
6906
6990
  if (!n) return e.json({ error: "Tree ID required" }, 400);
6907
6991
  let r = Number(n);
6908
6992
  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({
6993
+ 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
6994
  success: !0,
6911
6995
  deletedTreeId: r
6912
6996
  });
@@ -6916,8 +7000,8 @@ G.get("/tree.json", async (e) => {
6916
7000
  });
6917
7001
  //#endregion
6918
7002
  //#region server/routes/admin/channels.ts
6919
- var ve = new e();
6920
- ve.get("/", async (e) => {
7003
+ var ye = new e();
7004
+ ye.get("/", async (e) => {
6921
7005
  try {
6922
7006
  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
7007
  e[t.channelId] || (e[t.channelId] = []);
@@ -6941,7 +7025,7 @@ ve.get("/", async (e) => {
6941
7025
  isHidden: !!e.isHidden,
6942
7026
  trees: a[e.id] || []
6943
7027
  };
6944
- }), s = e.env?.BUNDLED_DEFINITIONS, c = ce(s)?.channelTemplate || {
7028
+ }), s = e.env?.BUNDLED_DEFINITIONS, c = se(s), l = c?.channelTemplate || Object.values(c?.channels || {})[0] || {
6945
7029
  label: "Channel Settings",
6946
7030
  fields: {
6947
7031
  key: {
@@ -6973,7 +7057,7 @@ ve.get("/", async (e) => {
6973
7057
  }
6974
7058
  };
6975
7059
  return e.json({
6976
- schema: c,
7060
+ schema: l,
6977
7061
  channels: o
6978
7062
  });
6979
7063
  } catch (t) {
@@ -6983,24 +7067,26 @@ ve.get("/", async (e) => {
6983
7067
  error: t.message
6984
7068
  }, 500);
6985
7069
  }
6986
- }), ve.post("/", async (e) => {
7070
+ }), ye.post("/", async (e) => {
6987
7071
  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.`,
7072
+ 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 || "";
7073
+ typeof T == "object" && T && (T = T.value || T.id || ""), T = String(T).trim();
7074
+ 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;
7075
+ if (await t.prepare("SELECT id FROM channels WHERE key = ? AND id != ? LIMIT 1").get(C, a ?? -1)) return e.json({
7076
+ error: `Channel API key "${C}" is already in use.`,
6991
7077
  field: "key"
6992
7078
  }, 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);
7079
+ let A = a;
7080
+ 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
7081
  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);
7082
+ 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);
7083
+ A = Number(e.lastInsertRowid);
6998
7084
  }
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,
7085
+ await t.prepare("DELETE FROM channel_trees WHERE channelId = ?").run(A);
7086
+ let j = D.filter((e) => e && e.treeId && e.key);
7087
+ if (j.length > 0) {
7088
+ let e = j.map(() => "(?, ?, ?, ?)").join(", "), n = j.flatMap((e) => [
7089
+ A,
7004
7090
  Number(e.treeId) || e.treeId,
7005
7091
  String(e.key).trim(),
7006
7092
  JSON.stringify(e.meta || {})
@@ -7010,9 +7096,10 @@ ve.get("/", async (e) => {
7010
7096
  VALUES ${e}
7011
7097
  `).run(...n);
7012
7098
  }
7013
- return await I(e).clear(), new B(e.env).purgeGlobalCache(e, t), e.json({
7099
+ let M = I(e);
7100
+ return await M.delete(`channel:${C}`), await M.delete(`channel:${A}`), await M.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
7014
7101
  success: !0,
7015
- id: w
7102
+ id: A
7016
7103
  });
7017
7104
  } catch (t) {
7018
7105
  return console.error("[API Channels] Error saving channel:", t), e.json({
@@ -7020,12 +7107,14 @@ ve.get("/", async (e) => {
7020
7107
  details: t.message
7021
7108
  }, 500);
7022
7109
  }
7023
- }), ve.delete("/", async (e) => {
7110
+ }), ye.delete("/", async (e) => {
7024
7111
  let t = e.get("db"), n = e.req.query("id");
7025
7112
  if (!n) return e.json({ error: "Channel ID required" }, 400);
7026
7113
  let r = Number(n);
7027
7114
  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({
7115
+ 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);
7116
+ let n = I(e);
7117
+ return await n.delete(`channel:${r}`), await n.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
7029
7118
  success: !0,
7030
7119
  deletedSiteId: r
7031
7120
  });
@@ -7043,11 +7132,11 @@ if (typeof process < "u" && process?.versions?.node) try {
7043
7132
  let e = i(import.meta.url);
7044
7133
  K = e("node:fs"), q = e("node:path");
7045
7134
  } catch {}
7046
- function ye(e, t = "") {
7135
+ function be(e, t = "") {
7047
7136
  let n = e.split(/[\\/]/).pop() || "";
7048
7137
  return t && n.endsWith(t) ? n.slice(0, -t.length) : n;
7049
7138
  }
7050
- function be(e) {
7139
+ function xe(e) {
7051
7140
  let t = e.match(/\.[^.\\/]+$/);
7052
7141
  return t ? t[0] : "";
7053
7142
  }
@@ -7060,7 +7149,7 @@ var J = {
7060
7149
  nodeLayouts: {},
7061
7150
  blockLayouts: {}
7062
7151
  };
7063
- function xe(e) {
7152
+ function Se(e) {
7064
7153
  return e ? typeof e == "string" ? e.trim() : Array.isArray(e) ? e.includes("*") ? "*" : e : "*" : "*";
7065
7154
  }
7066
7155
  function Y(e = {}, t = {}) {
@@ -7075,47 +7164,47 @@ function Y(e = {}, t = {}) {
7075
7164
  };
7076
7165
  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
7166
  }
7078
- function Se(e) {
7167
+ function Ce(e) {
7079
7168
  if (!e || typeof e != "object") return e;
7080
- if (Array.isArray(e)) return e.map(Se);
7169
+ if (Array.isArray(e)) return e.map(Ce);
7081
7170
  let t = {};
7082
7171
  for (let [n, r] of Object.entries(e)) if (n === "<<" || n === "<<:") {
7083
- let e = Se(r);
7172
+ let e = Ce(r);
7084
7173
  if (typeof e == "object" && e) {
7085
7174
  if (Array.isArray(e)) for (let n of e) Object.assign(t, n);
7086
7175
  else Object.assign(t, e);
7087
7176
  }
7088
- } else t[n] = Se(r);
7177
+ } else t[n] = Ce(r);
7089
7178
  return t;
7090
7179
  }
7091
- function Ce(e, t) {
7092
- return e ? Se(n.parseDocument(e, { customTags: [{
7180
+ function we(e, t) {
7181
+ return e ? Ce(n.parseDocument(e, { customTags: [{
7093
7182
  tag: "!include",
7094
7183
  resolve(e) {
7095
- let n = (typeof e == "string" ? e : String(e?.strValue || e?.value || "")).trim(), r = ye(n);
7184
+ let n = (typeof e == "string" ? e : String(e?.strValue || e?.value || "")).trim(), r = be(n);
7096
7185
  if (!r) return n;
7097
7186
  if (t && t.fieldSets) {
7098
7187
  let e = Object.keys(t.fieldSets).find((e) => e.endsWith("/" + r) || e === r);
7099
- if (e) return Ce(t.fieldSets[e], t);
7188
+ if (e) return we(t.fieldSets[e], t);
7100
7189
  }
7101
7190
  return n;
7102
7191
  }
7103
7192
  }] }).toJS() || {}) : {};
7104
7193
  }
7105
- function we(e, t = /* @__PURE__ */ new Set()) {
7194
+ function Te(e, t = /* @__PURE__ */ new Set()) {
7106
7195
  if (!K || !q) return {};
7107
7196
  let r = q.resolve(e);
7108
7197
  if (t.has(r) || (t.add(r), !K.existsSync(r))) return {};
7109
7198
  let i = K.readFileSync(r, "utf-8");
7110
- return Se(n.parseDocument(i, { customTags: [{
7199
+ return Ce(n.parseDocument(i, { customTags: [{
7111
7200
  tag: "!include",
7112
7201
  resolve(e) {
7113
7202
  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)) : {};
7203
+ return n ? Te(q.resolve(q.dirname(r), n), new Set(t)) : {};
7115
7204
  }
7116
7205
  }] }).toJS() || {});
7117
7206
  }
7118
- function Te() {
7207
+ function Ee() {
7119
7208
  if (!K || !q || typeof process > "u" || !process?.versions?.node) return null;
7120
7209
  try {
7121
7210
  let e = process.cwd(), t = "", n = [
@@ -7148,9 +7237,9 @@ function Te() {
7148
7237
  let r = {}, i = K.readdirSync(n);
7149
7238
  for (let e of i) {
7150
7239
  if (!e.endsWith(".yaml") && !e.endsWith(".yml")) continue;
7151
- let t = q.join(n, e), i = ye(e, be(e));
7240
+ let t = q.join(n, e), i = be(e, xe(e));
7152
7241
  try {
7153
- r[i] = we(t);
7242
+ r[i] = Te(t);
7154
7243
  } catch (t) {
7155
7244
  console.error(`❌ Error parsing ${e}:`, t.message);
7156
7245
  }
@@ -7178,14 +7267,14 @@ function Te() {
7178
7267
  return console.error("❌ Exception inside readLocalFsBundle:", e), null;
7179
7268
  }
7180
7269
  }
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
- }
7270
+ var De = null, Oe = null;
7188
7271
  function ke(e) {
7272
+ if (!e) De = null, Oe = null;
7273
+ else if (De && Oe === e) return De;
7274
+ let t = Ae(e);
7275
+ return De = t, Oe = e, t;
7276
+ }
7277
+ function Ae(e) {
7189
7278
  if (e) {
7190
7279
  let t = {
7191
7280
  nodes: {
@@ -7221,12 +7310,12 @@ function ke(e) {
7221
7310
  let e = (e) => {
7222
7311
  let n = {};
7223
7312
  for (let [r, i] of Object.entries(e || {})) {
7224
- let e = ye(r, be(r));
7225
- n[e] = Ce(i, t);
7313
+ let e = be(r, xe(r));
7314
+ n[e] = we(i, t);
7226
7315
  }
7227
7316
  return n;
7228
7317
  };
7229
- return Ae({
7318
+ return je({
7230
7319
  rawNodes: e(t.nodes),
7231
7320
  rawTrees: e(t.trees),
7232
7321
  rawChannels: e(t.channels),
@@ -7236,12 +7325,12 @@ function ke(e) {
7236
7325
  rawFieldSets: e(t.fieldSets)
7237
7326
  });
7238
7327
  }
7239
- return Ae(t);
7328
+ return je(t);
7240
7329
  }
7241
- let t = Te();
7242
- return t && Object.keys(t.rawNodes || {}).length > 0 ? Ae(t) : Ae(null);
7330
+ let t = Ee();
7331
+ return t && Object.keys(t.rawNodes || {}).length > 0 ? je(t) : je(null);
7243
7332
  }
7244
- function Ae(e) {
7333
+ function je(e) {
7245
7334
  if (!e) return {
7246
7335
  nodes: {},
7247
7336
  trees: {},
@@ -7376,8 +7465,8 @@ function Ae(e) {
7376
7465
  inVault: t.inVault !== !1,
7377
7466
  hasCanvas: t.hasCanvas === !0,
7378
7467
  defaultLayout: t.defaultLayout,
7379
- allowedBlocks: xe(t.allowedBlocks),
7380
- disallowedBlocks: t.disallowedBlocks ? xe(t.disallowedBlocks) : void 0,
7468
+ allowedBlocks: Se(t.allowedBlocks),
7469
+ disallowedBlocks: t.disallowedBlocks ? Se(t.disallowedBlocks) : void 0,
7381
7470
  tabs: n,
7382
7471
  fields: r
7383
7472
  };
@@ -7439,17 +7528,17 @@ function Ae(e) {
7439
7528
  fields: n
7440
7529
  };
7441
7530
  });
7442
- let te = {};
7531
+ let P = {};
7443
7532
  Object.entries(T).forEach(([e, t]) => {
7444
7533
  let n = A(t.tabs), r = k(t.fields || [], "settings", n), i = {}, a = t.regions || { content: { label: "Content" } };
7445
7534
  Object.entries(a).forEach(([e, t]) => {
7446
7535
  i[e] = {
7447
7536
  ...t,
7448
7537
  label: t.label || e,
7449
- allowedBlocks: xe(t.allowedBlocks),
7450
- disallowedBlocks: t.disallowedBlocks ? xe(t.disallowedBlocks) : void 0
7538
+ allowedBlocks: Se(t.allowedBlocks),
7539
+ disallowedBlocks: t.disallowedBlocks ? Se(t.disallowedBlocks) : void 0
7451
7540
  };
7452
- }), te[e] = {
7541
+ }), P[e] = {
7453
7542
  ...t,
7454
7543
  id: t.id || e,
7455
7544
  label: t.label || e,
@@ -7462,17 +7551,17 @@ function Ae(e) {
7462
7551
  tabs: n
7463
7552
  };
7464
7553
  });
7465
- let P = {};
7554
+ let te = {};
7466
7555
  Object.entries(E).forEach(([e, t]) => {
7467
7556
  let n = A(t.tabs), r = k(t.fields || [], "settings", n), i = {}, a = t.regions || { main: { label: "Main Content" } };
7468
7557
  Object.entries(a).forEach(([e, t]) => {
7469
7558
  i[e] = {
7470
7559
  ...t,
7471
7560
  label: t.label || e,
7472
- allowedBlocks: xe(t.allowedBlocks),
7473
- disallowedBlocks: t.disallowedBlocks ? xe(t.disallowedBlocks) : void 0
7561
+ allowedBlocks: Se(t.allowedBlocks),
7562
+ disallowedBlocks: t.disallowedBlocks ? Se(t.disallowedBlocks) : void 0
7474
7563
  };
7475
- }), P[e] = {
7564
+ }), te[e] = {
7476
7565
  ...t,
7477
7566
  id: t.id || e,
7478
7567
  label: t.label || e,
@@ -7502,7 +7591,7 @@ function Ae(e) {
7502
7591
  L[e] = Y(L[e] || {}, t);
7503
7592
  });
7504
7593
  });
7505
- let R = h ? {
7594
+ let ne = h ? {
7506
7595
  ...h,
7507
7596
  fields: L
7508
7597
  } : null;
@@ -7511,22 +7600,22 @@ function Ae(e) {
7511
7600
  trees: M,
7512
7601
  channels: N,
7513
7602
  blocks: ee,
7514
- nodeLayouts: te,
7515
- blockLayouts: P,
7603
+ nodeLayouts: P,
7604
+ blockLayouts: te,
7516
7605
  fieldSets: O,
7517
7606
  nodeTemplate: f || null,
7518
7607
  treeTemplate: p || null,
7519
7608
  channelTemplate: I,
7520
- userTemplate: R
7609
+ userTemplate: ne
7521
7610
  };
7522
7611
  }
7523
7612
  //#endregion
7524
7613
  //#region server/routes/admin/schemas.ts
7525
- var je = new e(), Me = (e) => {
7614
+ var Me = new e(), Ne = (e) => {
7526
7615
  try {
7527
7616
  let t = e.env?.BUNDLED_DEFINITIONS;
7528
7617
  (!t || Object.keys(t).length === 0) && (t = f || d || u);
7529
- let n = Oe(t);
7618
+ let n = ke(t);
7530
7619
  return e.json(n, 200, { "Cache-Control": "no-cache, no-store, must-revalidate" });
7531
7620
  } catch (t) {
7532
7621
  return console.error("[CMS API] Error loading schemas:", t), e.json({
@@ -7535,10 +7624,10 @@ var je = new e(), Me = (e) => {
7535
7624
  }, 500);
7536
7625
  }
7537
7626
  };
7538
- je.get("/", Me), je.get("/schemas.json", Me);
7627
+ Me.get("/", Ne), Me.get("/schemas.json", Ne);
7539
7628
  //#endregion
7540
7629
  //#region server/routes/admin/validation.ts
7541
- var Ne = new e(), Pe = {
7630
+ var Pe = new e(), Fe = {
7542
7631
  node: "content_nodes",
7543
7632
  nodes: "content_nodes",
7544
7633
  content_node: "content_nodes",
@@ -7550,7 +7639,7 @@ var Ne = new e(), Pe = {
7550
7639
  user: "users",
7551
7640
  users: "users",
7552
7641
  user_account: "user_accounts"
7553
- }, Fe = {
7642
+ }, Ie = {
7554
7643
  content_nodes: [
7555
7644
  "id",
7556
7645
  "title",
@@ -7607,11 +7696,11 @@ var Ne = new e(), Pe = {
7607
7696
  "createdAt"
7608
7697
  ]
7609
7698
  };
7610
- Ne.post("/validate-unique", async (e) => {
7699
+ Pe.post("/validate-unique", async (e) => {
7611
7700
  try {
7612
7701
  let t = e.get("db"), { entityType: n, field: r, value: i, excludeId: a } = await e.req.json();
7613
7702
  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;
7703
+ 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
7704
  if (a != null && String(a).trim() !== "") {
7616
7705
  let e = Number(a);
7617
7706
  l = isNaN(e) ? String(a) : e;
@@ -7623,11 +7712,11 @@ Ne.post("/validate-unique", async (e) => {
7623
7712
  } catch (t) {
7624
7713
  return console.error("[API Validation] Error validating global uniqueness:", t), e.json({ error: "Failed to validate uniqueness" }, 500);
7625
7714
  }
7626
- }), Ne.post("/validate-unique-sibling", async (e) => e.json({ isUnique: !0 }));
7715
+ }), Pe.post("/validate-unique-sibling", async (e) => e.json({ isUnique: !0 }));
7627
7716
  //#endregion
7628
7717
  //#region server/routes/admin/stats.ts
7629
- var Ie = new e();
7630
- Ie.get("/", async (e) => {
7718
+ var Le = new e();
7719
+ Le.get("/", async (e) => {
7631
7720
  try {
7632
7721
  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
7722
  ...e,
@@ -7644,7 +7733,7 @@ Ie.get("/", async (e) => {
7644
7733
  isHidden: !!e.isHidden,
7645
7734
  channelNames: e.channelLabels ? e.channelLabels.split(",") : [],
7646
7735
  treeNames: e.treeLabels ? e.treeLabels.split(",") : []
7647
- })), p = e.env?.BUNDLED_DEFINITIONS, m = ce(p), h = m.nodes || m.nodeSchemas || {}, g = c.map((e) => {
7736
+ })), p = e.env?.BUNDLED_DEFINITIONS, m = se(p), h = m.nodes || m.nodeSchemas || {}, g = c.map((e) => {
7648
7737
  let t = e.type || "node", n = h[t]?.label || t.charAt(0).toUpperCase() + t.slice(1);
7649
7738
  return {
7650
7739
  type: t,
@@ -7690,7 +7779,7 @@ async function Q(e, t, n = []) {
7690
7779
  if (typeof r.bind == "function") return await r.bind(...n).run();
7691
7780
  if (typeof r.run == "function") return await r.run(...n);
7692
7781
  }
7693
- function Le(e, t, n) {
7782
+ function Re(e, t, n) {
7694
7783
  let r = e || (t ? `/media/${t}` : "");
7695
7784
  return r && n && r.startsWith(`https://${n}/`) && !r.includes("/media/") && (r = r.replace(`https://${n}/`, `https://${n}/media/`)), r;
7696
7785
  }
@@ -7732,7 +7821,7 @@ X.get("/", async (e) => {
7732
7821
  ...JSON.parse(t.dataJson || "{}")
7733
7822
  };
7734
7823
  } catch {}
7735
- let r = Le(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN);
7824
+ let r = Re(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN);
7736
7825
  return {
7737
7826
  id: t.id,
7738
7827
  filename: t.filename || "Untitled Asset",
@@ -7758,7 +7847,7 @@ X.get("/", async (e) => {
7758
7847
  }
7759
7848
  }), X.post("/upload", async (e) => {
7760
7849
  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;
7850
+ 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
7851
  s && (await Z(t, "SELECT id FROM assets WHERE id = ?", [s])).length === 0 && (s = null);
7763
7852
  let c = r.cropCoordinates, u = null, d = null;
7764
7853
  if (c) {
@@ -7790,7 +7879,7 @@ X.get("/", async (e) => {
7790
7879
  let D = x;
7791
7880
  if (s) {
7792
7881
  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);
7882
+ n.length > 0 && (D = Re(n[0].cdnUrl, n[0].storageKeyPrivate, y)), new V(e.env).purgeAsset(e, t, s);
7794
7883
  }
7795
7884
  return e.json({
7796
7885
  id: p,
@@ -7832,7 +7921,7 @@ X.get("/", async (e) => {
7832
7921
  ...JSON.parse(i.dataJson || "{}")
7833
7922
  };
7834
7923
  } catch {}
7835
- let u = Le(i.cdnUrl, i.storageKeyPrivate, e.env?.CDN_DOMAIN);
7924
+ let u = Re(i.cdnUrl, i.storageKeyPrivate, e.env?.CDN_DOMAIN);
7836
7925
  return e.json({
7837
7926
  id: i.id,
7838
7927
  filename: i.filename,
@@ -7859,7 +7948,7 @@ X.get("/", async (e) => {
7859
7948
  createdAt: t.createdAt,
7860
7949
  parentAssetId: t.parentAssetId || i.id,
7861
7950
  cropCoordinates: n,
7862
- url: Le(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN),
7951
+ url: Re(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN),
7863
7952
  originalUrl: u
7864
7953
  };
7865
7954
  })
@@ -7879,14 +7968,14 @@ X.get("/", async (e) => {
7879
7968
  r.filename === void 0 ? a.filename : r.filename,
7880
7969
  JSON.stringify(o),
7881
7970
  n
7882
- ]), new B(e.env).purgeAsset(e, t, n), e.json({ success: !0 });
7971
+ ]), new V(e.env).purgeAsset(e, t, n), e.json({ success: !0 });
7883
7972
  } catch {
7884
7973
  return e.json({ error: "Failed to update asset" }, 500);
7885
7974
  }
7886
7975
  }), X.delete("/:id", async (e) => {
7887
7976
  try {
7888
7977
  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 ?))", [
7978
+ 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
7979
  n,
7891
7980
  n,
7892
7981
  `crop_%${r.filename ? r.filename.replace(/\.[^/.]+$/, "") : ""}%`,
@@ -7912,7 +8001,7 @@ X.get("/", async (e) => {
7912
8001
  r,
7913
8002
  `crop_%${i.filename ? i.filename.replace(/\.[^/.]+$/, "") : ""}%`,
7914
8003
  `%${r}%`
7915
- ]), new B(e.env).purgeAsset(e, t, r), e.json({
8004
+ ]), new V(e.env).purgeAsset(e, t, r), e.json({
7916
8005
  success: !0,
7917
8006
  id: r,
7918
8007
  restored: !0
@@ -7925,9 +8014,9 @@ X.get("/", async (e) => {
7925
8014
  }
7926
8015
  }), X.delete("/purge/:id", async (e) => {
7927
8016
  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];
8017
+ 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
8018
  if (!i) return e.json({ error: "Asset not found" }, 404);
7930
- new B(e.env).purgeAsset(e, t, r);
8019
+ new V(e.env).purgeAsset(e, t, r);
7931
8020
  let a = [i];
7932
8021
  i.isSystemVariant || (a = [i, ...await Z(t, "SELECT id, storageKeyPrivate FROM assets WHERE parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
7933
8022
  r,
@@ -7959,8 +8048,8 @@ X.get("/", async (e) => {
7959
8048
  });
7960
8049
  //#endregion
7961
8050
  //#region server/routes/public/node.ts
7962
- var Re = new e();
7963
- function ze() {
8051
+ var ze = new e();
8052
+ function Be() {
7964
8053
  return {
7965
8054
  fullPath: /* @__PURE__ */ new Map(),
7966
8055
  treeEdges: /* @__PURE__ */ new Map(),
@@ -7968,10 +8057,10 @@ function ze() {
7968
8057
  assetUrls: /* @__PURE__ */ new Map()
7969
8058
  };
7970
8059
  }
7971
- function Be(...e) {
8060
+ function Ve(...e) {
7972
8061
  return e.map((e) => String(e ?? "")).join(":");
7973
8062
  }
7974
- function Ve(e, t) {
8063
+ function He(e, t) {
7975
8064
  let n = Date.now();
7976
8065
  if (e && String(e).trim() !== "") {
7977
8066
  let t = Date.parse(e);
@@ -7983,27 +8072,27 @@ function Ve(e, t) {
7983
8072
  }
7984
8073
  return !0;
7985
8074
  }
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);
8075
+ async function Ue(e, t, n, r) {
8076
+ let i = t.filter((e) => e.componentId === "content-feed" || e.componentId === "article-list");
8077
+ await Promise.all(i.map(async (t) => {
8078
+ 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];
8079
+ n && n !== "all" && (c += " AND id IN (SELECT nodeId FROM node_channels WHERE channelId = ?)", l.push(Number(n) || n));
8080
+ let u = "ORDER BY updatedAt DESC";
8081
+ s === "published_desc" || s === "createdAt" ? u = "ORDER BY createdAt DESC" : s === "title_asc" && (u = "ORDER BY LOWER(title) ASC");
8082
+ let d = `SELECT id, title, slug, language, dataJson, createdAt, updatedAt ${c} ${u} LIMIT ?`;
8083
+ l.push(o);
7995
8084
  try {
7996
- let n = await e.prepare(u).all(...c), r = Array.isArray(n) ? n : n?.results || [];
7997
- t.data.initialItems = r.map((e) => {
8085
+ let n = await e.prepare(d).all(...l), i = Array.isArray(n) ? n : n?.results || [];
8086
+ t.data.initialItems = i.map((e) => {
7998
8087
  let t = {};
7999
8088
  if (e.dataJson) try {
8000
8089
  t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
8001
8090
  } catch {}
8002
- return Ve(t.startShowingAt, t.stopShowingAt) ? {
8091
+ return He(t.startShowingAt, t.stopShowingAt) ? {
8003
8092
  id: e.id,
8004
8093
  title: e.title,
8005
8094
  slug: e.slug,
8006
- language: e.language || "en",
8095
+ language: e.language?.trim() || r || null,
8007
8096
  createdAt: e.createdAt,
8008
8097
  updatedAt: e.updatedAt,
8009
8098
  excerpt: t.excerpt || "",
@@ -8016,7 +8105,7 @@ async function He(e, t, n) {
8016
8105
  }
8017
8106
  }));
8018
8107
  }
8019
- async function Ue(e, t, n, r, i = !1, a) {
8108
+ async function We(e, t, n, r, i = !1, a) {
8020
8109
  if (!t) return { blocks: [] };
8021
8110
  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
8111
  if (!s || s.length === 0) return { blocks: [] };
@@ -8052,10 +8141,10 @@ async function Ue(e, t, n, r, i = !1, a) {
8052
8141
  try {
8053
8142
  a = (typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson) || {};
8054
8143
  } catch {}
8055
- let o = a.hidden === !0 || a.hidden === 1 || a.hidden === "1" || a.hidden === "true", s = Ve(a.startShowingAt, a.stopShowingAt);
8144
+ let o = a.hidden === !0 || a.hidden === 1 || a.hidden === "1" || a.hidden === "true", s = He(a.startShowingAt, a.stopShowingAt);
8056
8145
  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, {
8146
+ 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);
8147
+ return d = await B(e, d), d = Ke(d), d.blockId = u, {
8059
8148
  region: t.region || n,
8060
8149
  block: {
8061
8150
  instanceId: t.id,
@@ -8075,7 +8164,7 @@ async function Ue(e, t, n, r, i = !1, a) {
8075
8164
  }
8076
8165
  return { blocks: [] };
8077
8166
  }
8078
- function We(e, t = {}) {
8167
+ function Ge(e, t = {}) {
8079
8168
  let n = {};
8080
8169
  for (let [r, i] of Object.entries(e)) r.endsWith("_meta") || [
8081
8170
  "disabledRegions",
@@ -8091,14 +8180,14 @@ function We(e, t = {}) {
8091
8180
  ].includes(r) || r.startsWith("_") || (!t[r] || t[r].public !== !1) && (n[r] = i);
8092
8181
  return n;
8093
8182
  }
8094
- function Ge(e) {
8095
- if (Array.isArray(e)) return e.map(Ge);
8183
+ function Ke(e) {
8184
+ if (Array.isArray(e)) return e.map(Ke);
8096
8185
  if (!e || typeof e != "object") return e;
8097
8186
  if (typeof e.id == "string" && e.id.startsWith("ast_") && typeof e.url == "string") {
8098
8187
  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
8188
  ...t,
8100
8189
  ...t.crops?.[r] || {}
8101
- } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, Ge({
8190
+ } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, Ke({
8102
8191
  ...n,
8103
8192
  title: n?.title ?? e.title ?? "",
8104
8193
  alt: n?.alt ?? e.alt ?? "",
@@ -8112,9 +8201,9 @@ function Ge(e) {
8112
8201
  ...Object.keys(a).length > 0 ? { variants: a } : {}
8113
8202
  };
8114
8203
  }
8115
- return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, Ge(t)]));
8204
+ return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, Ke(t)]));
8116
8205
  }
8117
- async function Ke(e, t, n) {
8206
+ async function qe(e, t, n) {
8118
8207
  if (typeof t == "string") {
8119
8208
  if (!t.includes("#node:") && !t.includes("data-node-id") && !t.includes("#asset:") && !t.includes("data-asset-id")) return t;
8120
8209
  let r = (e, t) => {
@@ -8132,9 +8221,9 @@ async function Ke(e, t, n) {
8132
8221
  return await Promise.all(Array.from(t.matchAll(p)).map(async (t) => {
8133
8222
  let i = t[1], a = r(i, "data-node-id"), o = r(i, "data-tree-id");
8134
8223
  if (!a || !o) return;
8135
- let s = await Je(e, a, o, n);
8224
+ let s = await Ye(e, a, o, n);
8136
8225
  if (s?.treeNodeId) {
8137
- let t = await Qe(e, String(s.treeNodeId), o, n);
8226
+ let t = await $e(e, String(s.treeNodeId), o, n);
8138
8227
  f.set(`${a}:${o}`, t);
8139
8228
  }
8140
8229
  })), t.replace(p, (e, t) => {
@@ -8154,39 +8243,39 @@ async function Ke(e, t, n) {
8154
8243
  return /href\s*=\s*["'][^"']*["']/i.test(h) ? h = h.replace(/href\s*=\s*["'][^"']*["']/i, `href="${m || "/"}"`) : h += ` href="${m || "/"}"`, `<a ${h}>`;
8155
8244
  });
8156
8245
  }
8157
- if (Array.isArray(t)) return Promise.all(t.map((t) => Ke(e, t, n)));
8246
+ if (Array.isArray(t)) return Promise.all(t.map((t) => qe(e, t, n)));
8158
8247
  if (t && typeof t == "object") {
8159
8248
  if (typeof t.href == "string" && (t.href.startsWith("#node:") || t.href.startsWith("#asset:"))) return {
8160
8249
  ...t,
8161
- href: await qe(e, t, n)
8250
+ href: await Je(e, t, n)
8162
8251
  };
8163
- let r = await Promise.all(Object.entries(t).map(async ([t, r]) => [t, await Ke(e, r, n)]));
8252
+ let r = await Promise.all(Object.entries(t).map(async ([t, r]) => [t, await qe(e, r, n)]));
8164
8253
  return Object.fromEntries(r);
8165
8254
  }
8166
8255
  return t;
8167
8256
  }
8168
- async function qe(e, t, n) {
8257
+ async function Je(e, t, n) {
8169
8258
  let r = t.href.match(/^#node:(.+)$/), i = t.href.match(/^#asset:(.+)$/);
8170
- if (i) return Xe(e, i[1], n);
8259
+ if (i) return Ze(e, i[1], n);
8171
8260
  if (!r) return t.href;
8172
8261
  let a = r[1];
8173
8262
  if (t.treeId) {
8174
- let r = await Je(e, a, String(t.treeId), n);
8263
+ let r = await Ye(e, a, String(t.treeId), n);
8175
8264
  if (r?.treeNodeId) {
8176
- let i = await Qe(e, String(r.treeNodeId), String(t.treeId), n);
8265
+ let i = await $e(e, String(r.treeNodeId), String(t.treeId), n);
8177
8266
  if (i) return i;
8178
8267
  }
8179
8268
  }
8180
- let o = await Ye(e, a, n);
8269
+ let o = await Xe(e, a, n);
8181
8270
  return o === void 0 ? "#" : `/${o}`;
8182
8271
  }
8183
- async function Je(e, t, n, r) {
8184
- let i = Be(t, n), a = r.treeEdges.get(i);
8272
+ async function Ye(e, t, n, r) {
8273
+ let i = Ve(t, n), a = r.treeEdges.get(i);
8185
8274
  if (a) return a;
8186
8275
  let o = e.prepare("SELECT id as treeNodeId FROM tree_nodes WHERE contentId = ? AND treeId = ? LIMIT 1").get(t, n);
8187
8276
  return r.treeEdges.set(i, Promise.resolve(o)), o;
8188
8277
  }
8189
- async function Ye(e, t, n) {
8278
+ async function Xe(e, t, n) {
8190
8279
  let r = String(t), i = n.nodeSlugs.get(r);
8191
8280
  if (i) return i;
8192
8281
  let a = (async () => {
@@ -8195,7 +8284,7 @@ async function Ye(e, t, n) {
8195
8284
  })();
8196
8285
  return n.nodeSlugs.set(r, a), a;
8197
8286
  }
8198
- async function Xe(e, t, n) {
8287
+ async function Ze(e, t, n) {
8199
8288
  let r = String(t), i = n.assetUrls.get(r);
8200
8289
  if (i) return i;
8201
8290
  let a = (async () => {
@@ -8204,7 +8293,7 @@ async function Xe(e, t, n) {
8204
8293
  })();
8205
8294
  return n.assetUrls.set(r, a), a;
8206
8295
  }
8207
- function Ze(e) {
8296
+ function Qe(e) {
8208
8297
  let t = e.socialImage;
8209
8298
  if (!t || typeof t != "object") return null;
8210
8299
  let n = (e, t) => {
@@ -8235,9 +8324,9 @@ function Ze(e) {
8235
8324
  ])
8236
8325
  };
8237
8326
  }
8238
- async function Qe(e, t, n, r) {
8327
+ async function $e(e, t, n, r) {
8239
8328
  if (!t) return "";
8240
- let i = Be(t, n);
8329
+ let i = Ve(t, n);
8241
8330
  if (r) {
8242
8331
  let e = r.fullPath.get(i);
8243
8332
  if (e) return e;
@@ -8252,7 +8341,7 @@ async function Qe(e, t, n, r) {
8252
8341
  })();
8253
8342
  return r && r.fullPath.set(i, a), a;
8254
8343
  }
8255
- async function $e(e, t, n, r, i) {
8344
+ async function et(e, t, n, r, i) {
8256
8345
  let a = {}, o = null;
8257
8346
  if (t) {
8258
8347
  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 +8368,7 @@ async function $e(e, t, n, r, i) {
8279
8368
  }
8280
8369
  }
8281
8370
  if (!o) {
8282
- let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ?").get(n);
8371
+ let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ? OR key = ? LIMIT 1").get(Number(n) || -1, String(n));
8283
8372
  if (t?.dataJson) try {
8284
8373
  let e = typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson;
8285
8374
  e.subpageLayoutId && e.subpageLayoutId !== "inherit" && (o = e.subpageLayoutId);
@@ -8290,109 +8379,125 @@ async function $e(e, t, n, r, i) {
8290
8379
  inheritedFields: a
8291
8380
  };
8292
8381
  }
8293
- function et(e) {
8382
+ function tt(e) {
8294
8383
  let t = Number(e?.env?.CMS_NODE_CACHE_TTL);
8295
8384
  return Number.isFinite(t) && t >= 60 ? Math.floor(t) : 300;
8296
8385
  }
8297
- async function tt(e, t, n, r) {
8386
+ async function nt(e, t, n, r) {
8298
8387
  try {
8299
8388
  await e.set(t, n, r);
8300
8389
  } catch (e) {
8301
8390
  console.warn("[CMS Cache] Failed to write node response to cache:", e);
8302
8391
  }
8303
8392
  }
8304
- Re.get("/*", async (e) => {
8393
+ ze.get("/*", async (e) => {
8305
8394
  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));
8395
+ 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
8396
  if (!c) return e.json({ error: `Channel '${a}' not found` }, 404);
8308
8397
  let l = c.status === "disabled" || c.status === "inactive" || c.isEnabled === 0 || c.isEnabled === !1;
8309
8398
  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 = `
8399
+ 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
8400
  SELECT cn.*, tn.id as treeNodeId, tn.parentId, tn.treeId FROM content_nodes cn
8317
8401
  INNER JOIN tree_nodes tn ON cn.id = tn.contentId
8318
8402
  ${u === null ? "" : "INNER JOIN node_channels nc ON cn.id = nc.nodeId"}
8319
8403
  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) => ({
8404
+ `, S = u === null ? [y] : [y, u], C = await t.prepare(x).all(...S), w = Array.isArray(C) ? C : C?.results || [];
8405
+ if (w.length > 0) {
8406
+ let e = await Promise.all(w.map(async (e) => ({
8323
8407
  candidate: e,
8324
- calculatedPath: await Qe(t, String(e.treeNodeId), String(e.treeId), n)
8325
- }))), r = S.replace(/^\/+|\/+$/g, "");
8408
+ calculatedPath: await $e(t, String(e.treeNodeId), String(e.treeId), n)
8409
+ }))), r = b.replace(/^\/+|\/+$/g, "");
8326
8410
  for (let { candidate: t, calculatedPath: n } of e) {
8327
8411
  let e = n.replace(/^\/+|\/+$/g, "");
8328
8412
  if (e === r || r === "home" && (e === "" || e === "home")) {
8329
- _ = t, v = t;
8413
+ h = t, g = t;
8330
8414
  break;
8331
8415
  }
8332
8416
  }
8333
8417
  }
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);
8418
+ 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);
8419
+ if (!g) {
8420
+ let e = _ ? [h.id, _] : [h.id];
8421
+ g = await t.prepare(`SELECT id as treeNodeId, treeId, parentId FROM tree_nodes WHERE contentId = ? ${_ ? "AND treeId = ?" : ""} LIMIT 1`).get(...e);
8338
8422
  }
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 || {});
8423
+ let T = g?.treeId || _ || "main-nav", E = null;
8424
+ if (T) {
8425
+ 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));
8426
+ if (e?.dataJson) try {
8427
+ let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
8428
+ t.defaultLanguage ? E = String(t.defaultLanguage).trim() : t.language && (E = String(t.language).trim());
8429
+ } catch {}
8430
+ }
8431
+ let D = null;
8432
+ if (c) {
8433
+ if (c.defaultLanguage) D = String(c.defaultLanguage).trim();
8434
+ else if (c.dataJson) try {
8435
+ let e = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson;
8436
+ e.defaultLanguage ? D = String(e.defaultLanguage).trim() : e.language && (D = String(e.language).trim());
8437
+ } catch {}
8438
+ }
8439
+ 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";
8440
+ if (!s && !M) {
8441
+ let t = await f.get(j);
8442
+ if (t) return e.header("X-Cache", "HIT"), e.json(t);
8443
+ }
8444
+ let N = g?.parentId || null, ee = g?.treeNodeId ? await $e(t, String(g.treeNodeId), String(T), n) : `/${(h.slug || "").replace(/^\/+|\/+$/g, "")}`, P = {
8445
+ id: h.id,
8446
+ title: h.title,
8447
+ slug: h.slug,
8448
+ language: A,
8449
+ path: ee === "" ? "/" : ee,
8450
+ nodeType: h.contentType,
8451
+ createdAt: h.createdAt,
8452
+ updatedAt: h.updatedAt
8453
+ }, te = h.contentType || "node", F = p.nodes?.[te] || Object.values(p.nodes || {})[0] || {}, L = { ...F.fields || {} };
8454
+ F.tabs && Object.values(F.tabs).forEach((e) => {
8455
+ Object.assign(L, e.fields || {});
8351
8456
  });
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;
8457
+ let ne = {}, re = null, ie = null, ae = !1, R = {}, oe = s && h.draftDataJson || h.dataJson;
8458
+ if (oe) try {
8459
+ R = typeof oe == "string" ? JSON.parse(oe) : oe;
8355
8460
  } 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) => {
8461
+ 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;
8462
+ 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;
8463
+ 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);
8464
+ let U = await B(t, Ge(R, L));
8465
+ U = Ke(U), U = await qe(t, U, n), delete U.language;
8466
+ let ue = Qe(U);
8467
+ 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;
8468
+ 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";
8469
+ if (!s && (de || fe || pe && !me)) return e.json({ error: "Node is hidden, offline, or has never been published." }, 404);
8470
+ let he = [];
8471
+ if (g?.treeNodeId) {
8472
+ 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;
8473
+ he = n.map((e) => {
8369
8474
  let t = {}, n = s && e.draftDataJson || e.dataJson;
8370
8475
  if (!n) return null;
8371
8476
  try {
8372
8477
  t = (typeof n == "string" ? JSON.parse(n) : n) || {};
8373
8478
  } 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, "");
8479
+ 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
8480
  return !s && (i || !a) ? null : {
8376
8481
  treeNodeId: e.treeNodeId,
8377
8482
  id: e.id,
8378
8483
  title: e.title,
8379
8484
  slug: o,
8380
- language: e.language || "en",
8485
+ language: e.language?.trim() || A || null,
8381
8486
  path: `${r}/${o}`.replace(/\/+/g, "/"),
8382
8487
  nodeType: e.nodeType
8383
8488
  };
8384
8489
  }).filter(Boolean);
8385
8490
  }
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) => {
8491
+ P.children = he;
8492
+ 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
8493
  let r = e.region || "main", i = {};
8389
8494
  try {
8390
8495
  i = (typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson) || {};
8391
8496
  } catch {}
8392
- let a = i.hidden === !0 || i.hidden === 1 || i.hidden === "1" || i.hidden === "true", o = Ve(i.startShowingAt, i.stopShowingAt);
8497
+ let a = i.hidden === !0 || i.hidden === 1 || i.hidden === "1" || i.hidden === "true", o = He(i.startShowingAt, i.stopShowingAt);
8393
8498
  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, {
8499
+ 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);
8500
+ return d = await B(t, d), d = Ke(d), d = await qe(t, d, n), d.blockId = u, {
8396
8501
  region: r,
8397
8502
  block: {
8398
8503
  instanceId: e.id,
@@ -8402,8 +8507,8 @@ Re.get("/*", async (e) => {
8402
8507
  }
8403
8508
  };
8404
8509
  }));
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 = {
8510
+ for (let e of ye) e && (G[e.region] || (G[e.region] = [], ve[e.region] = { isInherited: !1 }), G[e.region].push(e.block));
8511
+ let K = {
8407
8512
  header: {
8408
8513
  label: "Header",
8409
8514
  inherit: "parent"
@@ -8412,33 +8517,33 @@ Re.get("/*", async (e) => {
8412
8517
  label: "Footer",
8413
8518
  inherit: "parent"
8414
8519
  },
8415
- ...(oe ? h.nodeLayouts?.[oe] || h.layouts?.[oe] : null)?.regions || { main: { label: "Content" } }
8520
+ ...(le ? p.nodeLayouts?.[le] || p.layouts?.[le] : null)?.regions || { main: { label: "Content" } }
8416
8521
  };
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] = {
8522
+ for (let [e, r] of Object.entries(K)) {
8523
+ let i = G[e] && G[e].length > 0, a = !!ne[e];
8524
+ 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) {
8525
+ let r = await We(t, N, e, p, s, n);
8526
+ if (r.blocks.length > 0 && (G[e] = r.blocks, ve[e] = {
8422
8527
  isInherited: !0,
8423
8528
  inheritedFromId: r.inheritedFromId,
8424
8529
  inheritedFromTitle: r.inheritedFromTitle
8425
- }, r.subRegions)) for (let [t, n] of Object.entries(r.subRegions)) t !== e && (U[t] = n, W[t] = {
8530
+ }, r.subRegions)) for (let [t, n] of Object.entries(r.subRegions)) t !== e && (G[t] = n, ve[t] = {
8426
8531
  isInherited: !0,
8427
8532
  inheritedFromId: r.inheritedFromId,
8428
8533
  inheritedFromTitle: r.inheritedFromTitle
8429
8534
  });
8430
8535
  }
8431
8536
  }
8432
- await Promise.all(Object.keys(U).map((e) => He(t, U[e], u)));
8433
- let ge = {
8537
+ await Promise.all(Object.keys(G).map((e) => Ue(t, G[e], u, A)));
8538
+ let q = {
8434
8539
  channelId: u || d,
8435
- treeId: D,
8436
- language: A.language,
8437
- node: A,
8438
- content: U,
8439
- regionMeta: W
8540
+ treeId: T,
8541
+ language: A,
8542
+ node: P,
8543
+ content: G,
8544
+ regionMeta: ve
8440
8545
  };
8441
- return !s && !m && (e.header("X-Cache", "MISS"), await tt(f, p, ge, et(e))), e.json(ge);
8546
+ return !s && !M && (e.header("X-Cache", "MISS"), await nt(f, j, q, tt(e))), e.json(q);
8442
8547
  } catch (t) {
8443
8548
  return console.error("[CMS Public API] Error fetching node by path:", t), e.json({
8444
8549
  error: "Failed to fetch JSON payload",
@@ -8448,8 +8553,8 @@ Re.get("/*", async (e) => {
8448
8553
  });
8449
8554
  //#endregion
8450
8555
  //#region server/routes/public/tree.ts
8451
- var nt = new e();
8452
- function rt(e, t) {
8556
+ var rt = new e();
8557
+ function it(e, t) {
8453
8558
  let n = /* @__PURE__ */ new Date();
8454
8559
  if (e && String(e).trim() !== "") {
8455
8560
  let t = new Date(e);
@@ -8461,93 +8566,103 @@ function rt(e, t) {
8461
8566
  }
8462
8567
  return !0;
8463
8568
  }
8464
- async function it(e, t, n, r) {
8569
+ async function at(e, t, n, r) {
8465
8570
  try {
8466
8571
  await e.set(t, n, r);
8467
8572
  } catch (e) {
8468
8573
  console.warn("[CMS Cache] Failed to write tree response to cache:", e);
8469
8574
  }
8470
8575
  }
8471
- nt.get("/:treeParam", async (e) => {
8576
+ rt.get("/:treeParam", async (e) => {
8472
8577
  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";
8578
+ 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
8579
  if (r && r !== "default" && r !== "all") {
8475
8580
  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
8581
  if (n) {
8582
+ n.defaultLanguage && (o = n.defaultLanguage.trim());
8477
8583
  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);
8584
+ if (!a && t) return e.json({ error: `Channel '${n.key || r}' is currently inactive` }, 404);
8479
8585
  }
8480
8586
  }
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);
8587
+ 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);
8588
+ if (c && Number(c.isHidden) === 1 && !a) return e.json({ error: `Tree '${n}' is hidden` }, 404);
8589
+ let l = null;
8590
+ if (c) {
8591
+ if (c.defaultLanguage) l = String(c.defaultLanguage).trim();
8592
+ else if (c.dataJson) try {
8593
+ let e = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson;
8594
+ e.defaultLanguage && (l = String(e.defaultLanguage).trim());
8595
+ } catch {}
8596
+ }
8597
+ let u = l || o || i?.trim() || null, d = I(e), f = `tree:${r}:${n}:${u || "default"}`, p = e.req.header("x-bypass-cache") === "true";
8598
+ if (!a && !p) {
8599
+ let t = await d.get(f);
8484
8600
  if (t) return e.header("X-Cache", "HIT"), e.json(t);
8485
8601
  }
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);
8602
+ let m = c?.id || (s ? Number(n) : null), h = {};
8603
+ if (c && c.dataJson) try {
8604
+ 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 || {};
8605
+ for (let [e, n] of Object.entries(t)) a[e]?.public === !0 && (h[e] = n);
8492
8606
  } catch (e) {
8493
8607
  console.warn("[CMS Public Tree API] Failed to parse tree dataJson", e);
8494
8608
  }
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 || [];
8609
+ let g = [];
8610
+ if (m !== null) {
8611
+ 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);
8612
+ g = Array.isArray(e) ? e : e?.results || [];
8499
8613
  }
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]);
8614
+ if ((!g || g.length === 0) && !c) return e.json({ error: `Tree '${n}' not found` }, 404);
8615
+ let _ = /* @__PURE__ */ new Map();
8616
+ for (let e of g) {
8617
+ let t = !e.parentId || e.parentId === "null" || e.parentId === "" ? null : e.parentId, n = t === null ? "__ROOT__" : String(t), r = _.get(n);
8618
+ r ? r.push(e) : _.set(n, [e]);
8505
8619
  }
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;
8620
+ let v = /* @__PURE__ */ new Map();
8621
+ for (let e of g) {
8622
+ let t = String(e.treeNodeId), n = a && e.draftDataJson ? e.draftDataJson : e.dataJson;
8509
8623
  if (!n) {
8510
- m.set(t, {});
8624
+ v.set(t, {});
8511
8625
  continue;
8512
8626
  }
8513
8627
  try {
8514
8628
  let e = typeof n == "string" ? JSON.parse(n) : n;
8515
- m.set(t, e && typeof e == "object" ? e : {});
8629
+ v.set(t, e && typeof e == "object" ? e : {});
8516
8630
  } catch {
8517
- m.set(t, {});
8631
+ v.set(t, {});
8518
8632
  }
8519
8633
  }
8520
- function h(e = null, t = "") {
8634
+ function y(e = null, t = "") {
8521
8635
  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 = {};
8636
+ return (_.get(n) || []).map((e) => {
8637
+ let n = v.get(String(e.treeNodeId)) || {}, r = {};
8524
8638
  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 = {
8639
+ 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
8640
  id: e.id,
8527
8641
  treeNodeId: e.treeNodeId,
8528
8642
  parentId: e.parentId || null,
8529
8643
  title: e.title,
8530
8644
  slug: c,
8531
- language: e.language || "en",
8645
+ language: d,
8532
8646
  path: l,
8533
8647
  nodeType: e.nodeType,
8534
8648
  hidden: o || !s ? 1 : 0,
8535
8649
  summary: r.summary || ""
8536
8650
  };
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);
8651
+ e.nodeType === "external-link" && (r.url && (f.url = r.url), r.target && (f.target = r.target));
8652
+ let p = l === "/" ? "" : l;
8653
+ return f.children = y(e.treeNodeId, p), f;
8654
+ }).filter((e) => a || !e.hidden);
8541
8655
  }
8542
- let g = {
8543
- treeId: l?.id || u,
8544
- key: l?.key || n,
8656
+ let b = {
8657
+ treeId: c?.id || m,
8658
+ key: c?.key || n,
8545
8659
  channelId: r,
8546
- label: l?.label || n,
8547
- ...d,
8548
- items: h(null)
8660
+ language: u,
8661
+ label: c?.label || n,
8662
+ ...h,
8663
+ items: y(null)
8549
8664
  };
8550
- return !i && !s && (e.header("X-Cache", "MISS"), await it(a, o, g, 300)), e.json(g);
8665
+ return !a && !p && (e.header("X-Cache", "MISS"), await at(d, f, b, 300)), e.json(b);
8551
8666
  } catch (t) {
8552
8667
  return console.error("[CMS Public Tree API] Error:", t), e.json({
8553
8668
  error: "Failed to fetch public tree",
@@ -8556,9 +8671,148 @@ nt.get("/:treeParam", async (e) => {
8556
8671
  }
8557
8672
  });
8558
8673
  //#endregion
8674
+ //#region server/routes/public/channel.ts
8675
+ var ot = new e();
8676
+ function st(e) {
8677
+ let t = Number(e?.env?.CMS_CHANNEL_CACHE_TTL);
8678
+ return Number.isFinite(t) && t >= 60 ? Math.floor(t) : 300;
8679
+ }
8680
+ async function ct(e, t, n, r) {
8681
+ try {
8682
+ await e.set(t, n, r);
8683
+ } catch (e) {
8684
+ console.warn("[CMS Cache] Failed to write channel response to cache:", e);
8685
+ }
8686
+ }
8687
+ function lt(e, t) {
8688
+ let n = {}, r = (e) => {
8689
+ if (!e || typeof e != "string") return;
8690
+ let n = t?.fieldSets?.[e] || t?.fieldsets?.[e] || t?.definitions?.[e] || t?.channels?.[e] || t?.[e];
8691
+ n?.fields && i(n.fields);
8692
+ }, i = (e) => {
8693
+ 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);
8694
+ };
8695
+ 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);
8696
+ return n;
8697
+ }
8698
+ function ut(e, t = {}) {
8699
+ let n = {}, r = Object.keys(t).length > 0;
8700
+ for (let [i, a] of Object.entries(e)) {
8701
+ if (i.endsWith("_meta") || [
8702
+ "disabledRegions",
8703
+ "hidden",
8704
+ "is_hidden",
8705
+ "isHidden",
8706
+ "status",
8707
+ "startShowingAt",
8708
+ "stopShowingAt",
8709
+ "dataJson",
8710
+ "draftDataJson"
8711
+ ].includes(i) || i.startsWith("_")) continue;
8712
+ let e = t[i];
8713
+ (!r || !e || e.public !== !1) && a != null && a !== "" && (n[i] = a);
8714
+ }
8715
+ return n;
8716
+ }
8717
+ function dt(e) {
8718
+ if (Array.isArray(e)) return e.map(dt);
8719
+ if (!e || typeof e != "object") return e;
8720
+ if (typeof e.id == "string" && e.id.startsWith("ast_") && typeof e.url == "string") {
8721
+ 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 ? {
8722
+ ...t,
8723
+ ...t.crops?.[r] || {}
8724
+ } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, dt({
8725
+ ...n,
8726
+ title: n?.title ?? e.title ?? "",
8727
+ alt: n?.alt ?? e.alt ?? "",
8728
+ description: n?.description ?? e.description ?? ""
8729
+ })])), { metadataOverrides: o, ...s } = e;
8730
+ return {
8731
+ ...s,
8732
+ title: i.title ?? e.title ?? "",
8733
+ alt: i.alt ?? e.alt ?? "",
8734
+ description: i.description ?? e.description ?? "",
8735
+ ...Object.keys(a).length > 0 ? { variants: a } : {}
8736
+ };
8737
+ }
8738
+ return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, dt(t)]));
8739
+ }
8740
+ async function ft(e, t) {
8741
+ if (typeof t == "string") {
8742
+ if (!t.includes("#node:") && !t.includes("data-node-id") && !t.includes("#asset:") && !t.includes("data-asset-id")) return t;
8743
+ let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set();
8744
+ for (let e of t.matchAll(/(?:#node:|data-node-id\s*=\s*["'])([^"'\s>]+)/gi)) n.add(e[1]);
8745
+ for (let e of t.matchAll(/(?:#asset:|data-asset-id\s*=\s*["'])([^"'\s>]+)/gi)) r.add(e[1]);
8746
+ if (n.size === 0 && r.size === 0) return t;
8747
+ 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();
8748
+ (Array.isArray(a) ? a : a?.results || []).forEach((e) => o.set(String(e.id), String(e.slug || "").replace(/^\/+|\/+$/g, "")));
8749
+ 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();
8750
+ 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) => {
8751
+ let n = (e, t) => {
8752
+ let n = e.match(RegExp(`\\b${t}\\s*=\\s*(["'])(.*?)\\1`, "i"));
8753
+ return n ? n[2] : void 0;
8754
+ }, r = n(t, "data-node-id"), i = n(t, "data-asset-id"), a = n(t, "href") || "";
8755
+ if (a.startsWith("mailto:")) return `<a ${t.replace(/\s+target\s*=\s*["'][^"']*["']/i, "")}>`;
8756
+ let s = i || a.match(/^#asset:(.+)$/i)?.[1], c = r || a.match(/^#node:(.+)$/i)?.[1];
8757
+ if (!c && !s) return e;
8758
+ if (s && !c) {
8759
+ let n = l.get(s);
8760
+ if (n) {
8761
+ let e = t;
8762
+ return /href\s*=\s*["'][^"']*["']/i.test(e) ? e = e.replace(/href\s*=\s*["'][^"']*["']/i, `href="${n}"`) : e += ` href="${n}"`, `<a ${e}>`;
8763
+ }
8764
+ return e;
8765
+ }
8766
+ let u = o.get(c), d = u === void 0 ? "#" : `/${u}`, f = t;
8767
+ return /href\s*=\s*["'][^"']*["']/i.test(f) ? f = f.replace(/href\s*=\s*["'][^"']*["']/i, `href="${d || "/"}"`) : f += ` href="${d || "/"}"`, `<a ${f}>`;
8768
+ });
8769
+ }
8770
+ if (Array.isArray(t)) return Promise.all(t.map((t) => ft(e, t)));
8771
+ if (t && typeof t == "object") {
8772
+ let n = await Promise.all(Object.entries(t).map(async ([t, n]) => [t, await ft(e, n)]));
8773
+ return Object.fromEntries(n);
8774
+ }
8775
+ return t;
8776
+ }
8777
+ ot.get("/:channelParam", async (e) => {
8778
+ try {
8779
+ 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);
8780
+ if (!r && !i) {
8781
+ let t = await o.get(a);
8782
+ if (t) return e.header("X-Cache", "HIT"), e.json(t);
8783
+ }
8784
+ 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));
8785
+ if (!s) return e.json({ error: `Channel '${n}' not found` }, 404);
8786
+ let c = s.status === "disabled" || s.status === "inactive" || s.isEnabled === 0 || s.isEnabled === !1;
8787
+ if (!r && c) return e.json({ error: `Channel '${s.key || n}' is currently inactive` }, 404);
8788
+ 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;
8789
+ if (m) try {
8790
+ p = typeof m == "string" ? JSON.parse(m) : m;
8791
+ } catch (e) {
8792
+ console.warn("[CMS Public Channel API] Failed to parse channel dataJson:", e);
8793
+ }
8794
+ let h = ut({
8795
+ ...p,
8796
+ ...s
8797
+ }, f);
8798
+ h = await B(t, h), h = dt(h), h = await ft(t, h);
8799
+ let g = {
8800
+ id: s.id,
8801
+ key: s.key,
8802
+ ...h
8803
+ };
8804
+ return !r && !i && (e.header("X-Cache", "MISS"), await ct(o, a, g, st(e))), e.json(g);
8805
+ } catch (t) {
8806
+ return console.error("[CMS Public Channel API] Error:", t), e.json({
8807
+ error: "Failed to fetch public channel",
8808
+ ...e.env?.ENVIRONMENT === "development" ? { details: t.message } : {}
8809
+ }, 500);
8810
+ }
8811
+ });
8812
+ //#endregion
8559
8813
  //#region server/routes/public/assets.ts
8560
- var at = new e();
8561
- function ot(e, t) {
8814
+ var pt = new e();
8815
+ function mt(e, t) {
8562
8816
  if (t === "webp") return "image/webp";
8563
8817
  if (t === "avif") return "image/avif";
8564
8818
  if (t === "jpeg" || t === "jpg") return "image/jpeg";
@@ -8566,7 +8820,7 @@ function ot(e, t) {
8566
8820
  let n = e.toLowerCase();
8567
8821
  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
8822
  }
8569
- at.get("/*", async (e) => {
8823
+ pt.get("/*", async (e) => {
8570
8824
  try {
8571
8825
  let t = e.req.path.replace(/^\/media\//, "").replace(/^\//, "");
8572
8826
  if (!t) return e.text("Asset key missing", 400);
@@ -8582,11 +8836,11 @@ at.get("/*", async (e) => {
8582
8836
  let e = await l.match(d);
8583
8837
  if (e) return e;
8584
8838
  }
8585
- let { storage: f, optimizer: p } = ie(e.env), m = await f.get(t);
8839
+ let { storage: f, optimizer: p } = ae(e.env), m = await f.get(t);
8586
8840
  if (!m) return e.text(`Asset not found: ${t}`, 404);
8587
8841
  if (!o) {
8588
8842
  let n = e.body(m, 200, {
8589
- "Content-Type": ot(t),
8843
+ "Content-Type": mt(t),
8590
8844
  "Cache-Control": "public, max-age=31536000, immutable"
8591
8845
  });
8592
8846
  return l && d && e.executionCtx?.waitUntil && e.executionCtx.waitUntil(l.put(d, n.clone())), n;
@@ -8600,7 +8854,7 @@ at.get("/*", async (e) => {
8600
8854
  key: t,
8601
8855
  env: e.env,
8602
8856
  req: e.req.raw
8603
- }), _ = ot(t, c), v = e.body(g, 200, {
8857
+ }), _ = mt(t, c), v = e.body(g, 200, {
8604
8858
  "Content-Type": _,
8605
8859
  "Cache-Control": "public, max-age=31536000, immutable"
8606
8860
  });
@@ -8611,8 +8865,8 @@ at.get("/*", async (e) => {
8611
8865
  });
8612
8866
  //#endregion
8613
8867
  //#region server/routes/public/paths.ts
8614
- var st = new e();
8615
- function ct(e, t) {
8868
+ var ht = new e();
8869
+ function gt(e, t) {
8616
8870
  let n = /* @__PURE__ */ new Date();
8617
8871
  if (e && String(e).trim() !== "") {
8618
8872
  let t = new Date(e);
@@ -8624,7 +8878,7 @@ function ct(e, t) {
8624
8878
  }
8625
8879
  return !0;
8626
8880
  }
8627
- st.get("/", async (e) => {
8881
+ ht.get("/", async (e) => {
8628
8882
  try {
8629
8883
  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
8884
  for (let e of n) {
@@ -8648,7 +8902,7 @@ st.get("/", async (e) => {
8648
8902
  function o(e = null, t = "") {
8649
8903
  let n = e == null || e === "" || e === "null" ? "__ROOT__" : String(e), s = i.get(n) || [];
8650
8904
  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);
8905
+ let n = a.get(String(e.treeNodeId)) || {}, i = e.status === "published" || e.status === "active", s = gt(n.startShowingAt, n.stopShowingAt);
8652
8906
  if (!i || !s) continue;
8653
8907
  let c = (e.slug || "").replace(/^\/+|\/+$/g, ""), l = c === "home" || c === "homee" ? "/" : `${t}/${c}`.replace(/\/+/g, "/");
8654
8908
  e.nodeType !== "external-link" && r.push(l);
@@ -8665,7 +8919,7 @@ st.get("/", async (e) => {
8665
8919
  });
8666
8920
  //#endregion
8667
8921
  //#region server/index.ts
8668
- var $ = new e(), lt = !1;
8922
+ var $ = new e(), _t = !1;
8669
8923
  $.use("*", t()), $.use("/media/*", t({
8670
8924
  origin: "*",
8671
8925
  allowMethods: [
@@ -8686,13 +8940,13 @@ $.use("*", t()), $.use("/media/*", t({
8686
8940
  let n = new URL(e.req.url), r = (e.req.header("host") || n.hostname).split(":")[0];
8687
8941
  e.set("currentDomain", r);
8688
8942
  let i = l(e);
8689
- if (e.set("db", i), !lt) try {
8690
- await _(i), lt = !0;
8943
+ if (e.set("db", i), !_t) try {
8944
+ await _(i), _t = !0;
8691
8945
  } catch (e) {
8692
8946
  console.error("❌ [CMS Server] Failed to initialize system tables on cold start:", e);
8693
8947
  }
8694
8948
  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) => {
8949
+ }), $.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
8950
  if (e.env?.ASSETS) {
8697
8951
  let t = await e.env.ASSETS.fetch(e.req.raw);
8698
8952
  if (t.status === 404) {
@@ -8704,4 +8958,4 @@ $.use("*", t()), $.use("/media/*", t({
8704
8958
  return t();
8705
8959
  });
8706
8960
  //#endregion
8707
- export { $ as app, $ as default, Oe as compileDefinitions, ke as getCmsDefinitions };
8961
+ export { $ as app, $ as default, ke as compileDefinitions, Ae as getCmsDefinitions };