@brightsideoy/kama 0.1.0-alpha.59 → 0.1.0-alpha.61

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.
package/dist/index.js CHANGED
@@ -6930,23 +6930,23 @@ async function ai(e, t, n) {
6930
6930
  }
6931
6931
  //#endregion
6932
6932
  //#region server/utils/asset-hydrator.ts
6933
- function J(e) {
6933
+ function oi(e) {
6934
6934
  if (!e) return null;
6935
6935
  if (typeof e == "string" && e.startsWith("ast_")) return e;
6936
6936
  if (typeof e == "object" && e) {
6937
6937
  if (typeof e.id == "string" && e.id.startsWith("ast_")) return e.id;
6938
- if (typeof e.id == "object") return J(e.id);
6938
+ if (typeof e.id == "object") return oi(e.id);
6939
6939
  }
6940
6940
  return null;
6941
6941
  }
6942
- async function oi(e, t) {
6942
+ async function si(e, t) {
6943
6943
  if (!t || typeof t != "object") return t;
6944
6944
  let n = /* @__PURE__ */ new Set(), r = (e) => {
6945
6945
  if (!e) return;
6946
- let t = J(e);
6946
+ let t = oi(e);
6947
6947
  if (t) {
6948
6948
  if (n.add(t), typeof e == "object" && e.parentAssetId) {
6949
- let t = J(e.parentAssetId);
6949
+ let t = oi(e.parentAssetId);
6950
6950
  t && n.add(t);
6951
6951
  }
6952
6952
  } else Array.isArray(e) ? e.forEach(r) : typeof e == "object" && Object.values(e).forEach(r);
@@ -6975,7 +6975,7 @@ async function oi(e, t) {
6975
6975
  AND (parentAssetId IN (${i}) OR ${Array.from(n).map(() => "filename LIKE ?").join(" OR ")})
6976
6976
  `).all(...Array.from(n), ...Array.from(n).map((e) => `%${e}%`)), c = Array.isArray(s) ? s : s?.results || [], l = /* @__PURE__ */ new Map();
6977
6977
  for (let e of c) {
6978
- let t = J(e.parentAssetId) || Array.from(n).find((t) => e.filename.includes(t));
6978
+ let t = oi(e.parentAssetId) || Array.from(n).find((t) => e.filename.includes(t));
6979
6979
  if (!t) continue;
6980
6980
  let r = e.filename.match(/^crop_([a-z0-9]+)_/i), i = r ? r[1] : "standard", a = null;
6981
6981
  if (e.cropCoordinatesJson) try {
@@ -7010,7 +7010,7 @@ async function oi(e, t) {
7010
7010
  id: e.id,
7011
7011
  url: t,
7012
7012
  originalUrl: n,
7013
- parentAssetId: J(e.parentAssetId) || null,
7013
+ parentAssetId: oi(e.parentAssetId) || null,
7014
7014
  cropCoordinates: r,
7015
7015
  variants: i && Object.keys(i).length > 0 ? i : void 0,
7016
7016
  filename: e.filename,
@@ -7022,7 +7022,7 @@ async function oi(e, t) {
7022
7022
  }
7023
7023
  let d = (e) => {
7024
7024
  if (!e) return e;
7025
- let t = J(e);
7025
+ let t = oi(e);
7026
7026
  if (t) {
7027
7027
  let n = u.get(t) || {
7028
7028
  id: t,
@@ -7032,7 +7032,7 @@ async function oi(e, t) {
7032
7032
  return {
7033
7033
  ...n,
7034
7034
  id: t,
7035
- parentAssetId: n.parentAssetId ? J(n.parentAssetId) : null,
7035
+ parentAssetId: n.parentAssetId ? oi(n.parentAssetId) : null,
7036
7036
  url: typeof e == "object" && e.url && !e.url.startsWith("blob:") ? e.url : n.url,
7037
7037
  originalUrl: typeof e == "object" && e.originalUrl && !e.originalUrl.startsWith("blob:") ? e.originalUrl : n.originalUrl,
7038
7038
  cropCoordinates: i || n.cropCoordinates || null,
@@ -7052,7 +7052,7 @@ async function oi(e, t) {
7052
7052
  }
7053
7053
  //#endregion
7054
7054
  //#region src/schemas/definitions.ts
7055
- function Y(e = {}, t = {}) {
7055
+ function J(e = {}, t = {}) {
7056
7056
  let n = {
7057
7057
  ...e,
7058
7058
  ...t
@@ -7070,7 +7070,7 @@ function Y(e = {}, t = {}) {
7070
7070
  ...t.rules || {}
7071
7071
  }, n;
7072
7072
  }
7073
- function si() {
7073
+ function ci() {
7074
7074
  if (typeof process > "u" || !process?.versions?.node) return null;
7075
7075
  try {
7076
7076
  let e = (e) => {
@@ -7137,12 +7137,12 @@ function si() {
7137
7137
  return null;
7138
7138
  }
7139
7139
  }
7140
- function ci(e) {
7141
- if (e && (Object.keys(e.rawNodes || {}).length > 0 || Object.keys(e.nodes || {}).length > 0)) return li(e);
7142
- let t = si();
7143
- return t && Object.keys(t.rawNodes).length > 0 ? li(t) : li(null);
7144
- }
7145
7140
  function li(e) {
7141
+ if (e && (Object.keys(e.rawNodes || {}).length > 0 || Object.keys(e.nodes || {}).length > 0)) return ui(e);
7142
+ let t = ci();
7143
+ return t && Object.keys(t.rawNodes).length > 0 ? ui(t) : ui(null);
7144
+ }
7145
+ function ui(e) {
7146
7146
  if (!e) return {
7147
7147
  nodes: {},
7148
7148
  trees: {},
@@ -7162,7 +7162,7 @@ function li(e) {
7162
7162
  let i = {};
7163
7163
  if (!Array.isArray(e)) return typeof e == "object" && e ? (Object.entries(e).forEach(([e, t]) => {
7164
7164
  let n = i[e] || m[e] || {};
7165
- i[e] = Y(n, t);
7165
+ i[e] = J(n, t);
7166
7166
  }), i) : {};
7167
7167
  let a = (e) => {
7168
7168
  let a = h[e] || h[`${e}-base`] || {};
@@ -7175,11 +7175,11 @@ function li(e) {
7175
7175
  fields: {}
7176
7176
  }), Object.entries(s).forEach(([e, r]) => {
7177
7177
  let i = n[t].fields[e] || {};
7178
- n[t].fields[e] = Y(i, r);
7178
+ n[t].fields[e] = J(i, r);
7179
7179
  });
7180
7180
  } else Object.entries(s).forEach(([e, t]) => {
7181
7181
  let n = i[e] || {};
7182
- i[e] = Y(n, t);
7182
+ i[e] = J(n, t);
7183
7183
  });
7184
7184
  };
7185
7185
  return e.forEach((e) => {
@@ -7187,7 +7187,7 @@ function li(e) {
7187
7187
  if (e.startsWith("fieldSet:")) a(e.replace("fieldSet:", "").trim());
7188
7188
  else {
7189
7189
  let t = i[e] || m[e] || {};
7190
- i[e] = Y(t, {
7190
+ i[e] = J(t, {
7191
7191
  type: "text",
7192
7192
  label: e
7193
7193
  });
@@ -7197,7 +7197,7 @@ function li(e) {
7197
7197
  if (t === "fieldSet") a(String(n));
7198
7198
  else {
7199
7199
  let e = i[t] || m[t] || {};
7200
- i[t] = Y(e, typeof n == "object" && n ? n : {});
7200
+ i[t] = J(e, typeof n == "object" && n ? n : {});
7201
7201
  }
7202
7202
  }
7203
7203
  }), i;
@@ -7215,7 +7215,7 @@ function li(e) {
7215
7215
  let s = g(i.fields || i, a, n, t);
7216
7216
  Object.entries(s).forEach(([e, t]) => {
7217
7217
  let r = n[a].fields[e] || {};
7218
- n[a].fields[e] = Y(r, t);
7218
+ n[a].fields[e] = J(r, t);
7219
7219
  });
7220
7220
  }
7221
7221
  }), n) : (Object.entries(e).forEach(([e, r]) => {
@@ -7227,7 +7227,7 @@ function li(e) {
7227
7227
  let o = g(a, e, n, t);
7228
7228
  Object.entries(o).forEach(([t, r]) => {
7229
7229
  let i = n[e].fields[t] || {};
7230
- n[e].fields[t] = Y(i, r);
7230
+ n[e].fields[t] = J(i, r);
7231
7231
  });
7232
7232
  }), n);
7233
7233
  }, v = {};
@@ -7245,16 +7245,16 @@ function li(e) {
7245
7245
  fields: {}
7246
7246
  }), Object.entries(o).forEach(([e, r]) => {
7247
7247
  let i = n[t].fields[e] || {};
7248
- n[t].fields[e] = Y(i, r);
7248
+ n[t].fields[e] = J(i, r);
7249
7249
  });
7250
7250
  } else Object.entries(o).forEach(([e, t]) => {
7251
7251
  let n = r[e] || m[e] || {};
7252
- r[e] = Y(n, t);
7252
+ r[e] = J(n, t);
7253
7253
  });
7254
7254
  }), Object.values(n).forEach((e) => {
7255
7255
  Object.entries(e.fields).forEach(([e, t]) => {
7256
7256
  let n = r[e] || {};
7257
- r[e] = Y(n, t);
7257
+ r[e] = J(n, t);
7258
7258
  });
7259
7259
  }), Object.keys(n).length === 0 && Object.keys(r).length > 0 && (n.settings = {
7260
7260
  label: t.label || "Settings",
@@ -7277,11 +7277,11 @@ function li(e) {
7277
7277
  Array.isArray(t.fieldSets) && t.fieldSets.forEach((e) => {
7278
7278
  let t = h[e] || {}, i = t.fields || t, a = g(i, "settings", n);
7279
7279
  Object.entries(a).forEach(([e, t]) => {
7280
- r[e] = Y(r[e] || {}, t);
7280
+ r[e] = J(r[e] || {}, t);
7281
7281
  });
7282
7282
  }), Object.values(n).forEach((e) => {
7283
7283
  Object.entries(e.fields).forEach(([e, t]) => {
7284
- r[e] = Y(r[e] || {}, t);
7284
+ r[e] = J(r[e] || {}, t);
7285
7285
  });
7286
7286
  }), y[e] = {
7287
7287
  ...t,
@@ -7300,7 +7300,7 @@ function li(e) {
7300
7300
  Array.isArray(t.fieldSets) && t.fieldSets.forEach((e) => {
7301
7301
  let t = h[e] || {}, r = t.fields || t, i = g(r);
7302
7302
  Object.entries(i).forEach(([e, t]) => {
7303
- n[e] = Y(n[e] || {}, t);
7303
+ n[e] = J(n[e] || {}, t);
7304
7304
  });
7305
7305
  }), b[e] = {
7306
7306
  ...t,
@@ -7349,7 +7349,7 @@ function li(e) {
7349
7349
  Array.isArray(f?.fieldSets) && f?.fieldSets.forEach((e) => {
7350
7350
  let t = h[e] || {}, n = t.fields || t, r = g(n);
7351
7351
  Object.entries(r).forEach(([e, t]) => {
7352
- T[e] = Y(T[e] || {}, t);
7352
+ T[e] = J(T[e] || {}, t);
7353
7353
  });
7354
7354
  });
7355
7355
  let E = f ? {
@@ -7359,7 +7359,7 @@ function li(e) {
7359
7359
  Array.isArray(p?.fieldSets) && p?.fieldSets.forEach((e) => {
7360
7360
  let t = h[e] || {}, n = t.fields || t, r = g(n);
7361
7361
  Object.entries(r).forEach(([e, t]) => {
7362
- D[e] = Y(D[e] || {}, t);
7362
+ D[e] = J(D[e] || {}, t);
7363
7363
  });
7364
7364
  });
7365
7365
  let O = p ? {
@@ -7380,9 +7380,108 @@ function li(e) {
7380
7380
  };
7381
7381
  }
7382
7382
  //#endregion
7383
- //#region server/routes/admin/nodes.ts
7384
- var X = new e();
7385
- async function ui(e, t, n = []) {
7383
+ //#region server/services/cache-manager.ts
7384
+ var Y = class {
7385
+ zoneId;
7386
+ apiToken;
7387
+ frontendUrl;
7388
+ constructor(e) {
7389
+ this.zoneId = e.CLOUDFLARE_ZONE_ID, this.apiToken = e.CLOUDFLARE_API_TOKEN, this.frontendUrl = (e.PUBLIC_FRONTEND_URL || "https://kama.t3cloud.eu").replace(/\/+$/, "");
7390
+ }
7391
+ dispatch(e, t) {
7392
+ !this.zoneId || !this.apiToken || (e.executionCtx && typeof e.executionCtx.waitUntil == "function" ? e.executionCtx.waitUntil(t) : t.catch((e) => console.warn("[CacheManager Warn]:", e)));
7393
+ }
7394
+ purgeAndWarmSlug(e, t, n = []) {
7395
+ let r = (async () => {
7396
+ try {
7397
+ let e = t.replace(/^\/+|\/+$/g, ""), r = e === "home" || !e ? this.frontendUrl : `${this.frontendUrl}/${e}`, i = [r, `${r}/`];
7398
+ for (let e of n) {
7399
+ if (!e) continue;
7400
+ let t = e.startsWith("/") ? e : `/${e}`;
7401
+ i.push(`${this.frontendUrl}${t}`);
7402
+ }
7403
+ console.log(`[CacheManager] Purging ${i.length} edge URLs for: ${e}`);
7404
+ let a = await fetch(`https://api.cloudflare.com/client/v4/zones/${this.zoneId}/purge_cache`, {
7405
+ method: "POST",
7406
+ headers: {
7407
+ Authorization: `Bearer ${this.apiToken}`,
7408
+ "Content-Type": "application/json"
7409
+ },
7410
+ body: JSON.stringify({ files: i })
7411
+ });
7412
+ if (!a.ok) {
7413
+ console.error(`[CacheManager] Purge failed: ${await a.text()}`);
7414
+ return;
7415
+ }
7416
+ fetch(r, { headers: { "X-Cache-Warmer": "true" } }).catch(() => {});
7417
+ } catch (e) {
7418
+ console.error("[CacheManager] Critical error during slug purge:", e);
7419
+ }
7420
+ })();
7421
+ this.dispatch(e, r);
7422
+ }
7423
+ purgeGlobalCache(e) {
7424
+ let t = (async () => {
7425
+ try {
7426
+ console.log("[CacheManager] Purging ENTIRE edge cache.");
7427
+ let e = await fetch(`https://api.cloudflare.com/client/v4/zones/${this.zoneId}/purge_cache`, {
7428
+ method: "POST",
7429
+ headers: {
7430
+ Authorization: `Bearer ${this.apiToken}`,
7431
+ "Content-Type": "application/json"
7432
+ },
7433
+ body: JSON.stringify({ purge_everything: !0 })
7434
+ });
7435
+ if (!e.ok) {
7436
+ console.error(`[CacheManager] Global purge failed: ${await e.text()}`);
7437
+ return;
7438
+ }
7439
+ fetch(this.frontendUrl, { headers: { "X-Cache-Warmer": "true" } }).catch(() => {});
7440
+ } catch (e) {
7441
+ console.error("[CacheManager] Critical error during global purge:", e);
7442
+ }
7443
+ })();
7444
+ this.dispatch(e, t);
7445
+ }
7446
+ purgeSmart(e, t, n, r, i = []) {
7447
+ let a = (async () => {
7448
+ let e = r;
7449
+ !e && n && (e = (await t.prepare("SELECT slug FROM content_nodes WHERE id = ?").get(n))?.slug), e && (await t.prepare("SELECT 1 FROM tree_nodes WHERE contentId = ? LIMIT 1").get(n) ? await this.purgeGlobalCacheDirect() : await this.purgeAndWarmSlugDirect(e, i));
7450
+ })();
7451
+ this.dispatch(e, a);
7452
+ }
7453
+ async purgeGlobalCacheDirect() {
7454
+ try {
7455
+ await fetch(`https://api.cloudflare.com/client/v4/zones/${this.zoneId}/purge_cache`, {
7456
+ method: "POST",
7457
+ headers: {
7458
+ Authorization: `Bearer ${this.apiToken}`,
7459
+ "Content-Type": "application/json"
7460
+ },
7461
+ body: JSON.stringify({ purge_everything: !0 })
7462
+ }), fetch(this.frontendUrl, { headers: { "X-Cache-Warmer": "true" } }).catch(() => {});
7463
+ } catch {}
7464
+ }
7465
+ async purgeAndWarmSlugDirect(e, t = []) {
7466
+ try {
7467
+ let n = e.replace(/^\/+|\/+$/g, ""), r = n === "home" || !n ? this.frontendUrl : `${this.frontendUrl}/${n}`, i = [r, `${r}/`];
7468
+ for (let e of t) {
7469
+ if (!e) continue;
7470
+ let t = e.startsWith("/") ? e : `/${e}`;
7471
+ i.push(`${this.frontendUrl}${t}`);
7472
+ }
7473
+ await fetch(`https://api.cloudflare.com/client/v4/zones/${this.zoneId}/purge_cache`, {
7474
+ method: "POST",
7475
+ headers: {
7476
+ Authorization: `Bearer ${this.apiToken}`,
7477
+ "Content-Type": "application/json"
7478
+ },
7479
+ body: JSON.stringify({ files: i })
7480
+ }), fetch(r, { headers: { "X-Cache-Warmer": "true" } }).catch(() => {});
7481
+ } catch {}
7482
+ }
7483
+ }, X = new e();
7484
+ async function di(e, t, n = []) {
7386
7485
  let r = e.prepare(t);
7387
7486
  if (typeof r.bind == "function") {
7388
7487
  let e = await r.bind(...n).all();
@@ -7394,23 +7493,30 @@ async function ui(e, t, n = []) {
7394
7493
  }
7395
7494
  return [];
7396
7495
  }
7397
- async function di(e, t, n = []) {
7496
+ async function fi(e, t, n = []) {
7398
7497
  let r = e.prepare(t);
7399
7498
  if (typeof r.bind == "function") return r.bind(...n).run();
7400
7499
  if (typeof r.run == "function") return r.run(...n);
7401
7500
  }
7402
- function fi(e) {
7501
+ async function pi(e, t) {
7502
+ try {
7503
+ return (await di(e, "\n SELECT DISTINCT a.url\n FROM node_assets na\n JOIN assets a ON na.assetId = a.id\n WHERE na.nodeId = ? AND a.url IS NOT NULL AND a.url != ''\n ", [t])).map((e) => e.url).filter(Boolean);
7504
+ } catch {
7505
+ return [];
7506
+ }
7507
+ }
7508
+ function mi(e) {
7403
7509
  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;
7404
7510
  }
7405
- function pi(e) {
7511
+ function hi(e) {
7406
7512
  return +(e === !0 || e === 1 || e === "1" || e === "true");
7407
7513
  }
7408
- function mi(e) {
7514
+ function gi(e) {
7409
7515
  if (e == null || e === "null" || e === "" || typeof e == "string" && e.startsWith("draft-")) return null;
7410
7516
  let t = Number(e);
7411
7517
  return isNaN(t) ? null : t;
7412
7518
  }
7413
- function hi(e) {
7519
+ function _i(e) {
7414
7520
  let t = { ...e };
7415
7521
  for (let e of [
7416
7522
  "id",
@@ -7439,17 +7545,17 @@ function hi(e) {
7439
7545
  ]) delete t[e];
7440
7546
  return t;
7441
7547
  }
7442
- function gi(e, t = /* @__PURE__ */ new Set()) {
7443
- return e ? typeof e == "string" ? (e.startsWith("ast_") && t.add(e), t) : Array.isArray(e) ? (e.forEach((e) => gi(e, t)), t) : (typeof e == "object" && Object.values(e).forEach((e) => gi(e, t)), t) : t;
7548
+ function vi(e, t = /* @__PURE__ */ new Set()) {
7549
+ return e ? typeof e == "string" ? (e.startsWith("ast_") && t.add(e), t) : Array.isArray(e) ? (e.forEach((e) => vi(e, t)), t) : (typeof e == "object" && Object.values(e).forEach((e) => vi(e, t)), t) : t;
7444
7550
  }
7445
- async function _i(e, t, n) {
7551
+ async function yi(e, t, n) {
7446
7552
  for (let r of n) {
7447
- let n = (await ui(e, "\n SELECT id, storageKeyPrivate, isSystemVariant, parentAssetId, filename\n FROM assets WHERE id = ?\n ", [r]))[0];
7448
- if (!n || (await ui(e, "SELECT 1 FROM node_assets WHERE assetId = ? LIMIT 1", [n.id])).length > 0) continue;
7553
+ let n = (await di(e, "\n SELECT id, storageKeyPrivate, isSystemVariant, parentAssetId, filename\n FROM assets WHERE id = ?\n ", [r]))[0];
7554
+ if (!n || (await di(e, "SELECT 1 FROM node_assets WHERE assetId = ? LIMIT 1", [n.id])).length > 0) continue;
7449
7555
  let i = [n];
7450
7556
  if (!n.isSystemVariant) {
7451
- let t = await ui(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);
7452
- if (r.length > 0 && (await ui(e, `SELECT DISTINCT assetId FROM node_assets WHERE assetId IN (${r.map(() => "?").join(",")})`, r)).length > 0) continue;
7557
+ let t = await di(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);
7558
+ if (r.length > 0 && (await di(e, `SELECT DISTINCT assetId FROM node_assets WHERE assetId IN (${r.map(() => "?").join(",")})`, r)).length > 0) continue;
7453
7559
  i = [n, ...t];
7454
7560
  }
7455
7561
  for (let e of i) if (e.storageKeyPrivate) try {
@@ -7458,10 +7564,10 @@ async function _i(e, t, n) {
7458
7564
  console.warn(`[Asset Cleanup] Failed to delete ${e.storageKeyPrivate}:`, t);
7459
7565
  }
7460
7566
  let a = i.map((e) => e.id), o = a.map(() => "?").join(",");
7461
- await di(e, `DELETE FROM node_assets WHERE assetId IN (${o})`, a), await di(e, `DELETE FROM assets WHERE id IN (${o})`, a);
7567
+ await fi(e, `DELETE FROM node_assets WHERE assetId IN (${o})`, a), await fi(e, `DELETE FROM assets WHERE id IN (${o})`, a);
7462
7568
  }
7463
7569
  }
7464
- async function vi(e, t, n) {
7570
+ async function bi(e, t, n) {
7465
7571
  let r = {}, i = null;
7466
7572
  if (t) {
7467
7573
  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 || [];
@@ -7486,33 +7592,6 @@ async function vi(e, t, n) {
7486
7592
  inheritedFields: r
7487
7593
  };
7488
7594
  }
7489
- async function yi(e, t) {
7490
- let n = e.CLOUDFLARE_ZONE_ID, r = e.CLOUDFLARE_API_TOKEN, i = e.PUBLIC_FRONTEND_URL || "https://kama.t3cloud.eu";
7491
- if (!n || !r) {
7492
- console.warn("[Cache] Skipping purge: Missing CLOUDFLARE_ZONE_ID or CLOUDFLARE_API_TOKEN in environment.");
7493
- return;
7494
- }
7495
- try {
7496
- let e = t.replace(/^\/+|\/+$/g, ""), a = e === "home" || !e ? i : `${i}/${e}`, o = [a, `${a}/`];
7497
- console.log(`[Cache] Purging edge cache for: ${o.join(", ")}`);
7498
- let s = await fetch(`https://api.cloudflare.com/client/v4/zones/${n}/purge_cache`, {
7499
- method: "POST",
7500
- headers: {
7501
- Authorization: `Bearer ${r}`,
7502
- "Content-Type": "application/json"
7503
- },
7504
- body: JSON.stringify({ files: o })
7505
- });
7506
- if (!s.ok) {
7507
- let e = await s.text();
7508
- console.error(`[Cache] Purge failed: ${e}`);
7509
- return;
7510
- }
7511
- fetch(a, { headers: { "X-Cache-Warmer": "true" } }).catch((e) => console.error(`[Cache] Warming failed for ${a}:`, e));
7512
- } catch (e) {
7513
- console.error("[Cache] Critical error during cache purge:", e);
7514
- }
7515
- }
7516
7595
  X.get("/", async (e) => {
7517
7596
  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));
7518
7597
  if (n) {
@@ -7538,13 +7617,13 @@ X.get("/", async (e) => {
7538
7617
  updatedAt: i.updatedAt
7539
7618
  }, s = i.draftDataJson || i.dataJson;
7540
7619
  if (s) try {
7541
- 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 = li(e.env?.BUNDLED_DEFINITIONS).nodes?.[i.contentType] || {}, l = n.layoutId || null;
7620
+ 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 = ui(e.env?.BUNDLED_DEFINITIONS).nodes?.[i.contentType] || {}, l = n.layoutId || null;
7542
7621
  if (a) {
7543
- let { resolvedLayoutId: e, inheritedFields: r } = await vi(t, a.parentId, a.treeId);
7622
+ let { resolvedLayoutId: e, inheritedFields: r } = await bi(t, a.parentId, a.treeId);
7544
7623
  (l === "inherit" || !l) && (l = e || c.defaultLayout || null);
7545
7624
  for (let [e, t] of Object.entries(r)) (n[e] === void 0 || n[e] === null || n[e] === "") && t !== void 0 && (n[e] = t);
7546
7625
  } else (l === "inherit" || !l) && (l = c.defaultLayout || null);
7547
- let u = await oi(t, hi(n));
7626
+ let u = await si(t, _i(n));
7548
7627
  Object.assign(o, u), o.resolvedLayoutId = l;
7549
7628
  } catch {}
7550
7629
  let c = await t.prepare("SELECT channelId FROM node_channels WHERE nodeId = ?").all(r);
@@ -7554,7 +7633,7 @@ X.get("/", async (e) => {
7554
7633
  let u = await t.prepare("\n SELECT * FROM content_blocks \n WHERE contentId = ? AND isDraft = 1 \n ORDER BY sortOrder ASC\n ").all(r), d = Array.isArray(u) ? u : u?.results || [], f = await Promise.all(d.map(async (e) => {
7555
7634
  let n = {};
7556
7635
  try {
7557
- n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson || "{}") : e.dataJson || {}, n && typeof n == "object" && (n = await oi(t, n));
7636
+ n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson || "{}") : e.dataJson || {}, n && typeof n == "object" && (n = await si(t, n));
7558
7637
  } catch {
7559
7638
  n = {};
7560
7639
  }
@@ -7629,7 +7708,7 @@ X.get("/", async (e) => {
7629
7708
  FROM tree_nodes tn
7630
7709
  JOIN trees t ON tn.treeId = t.id
7631
7710
  WHERE tn.contentId IN (${e})
7632
- `).all(...T), a = Array.isArray(i) ? i : i?.results || [];
7711
+ `).all(...T), a = Array.isArray(i) ? i : a?.results || [];
7633
7712
  for (let e of a) D[e.nodeId] || (D[e.nodeId] = []), D[e.nodeId].includes(e.label) || D[e.nodeId].push(e.label);
7634
7713
  }
7635
7714
  let O = await Promise.all(w.map(async (e) => {
@@ -7654,7 +7733,7 @@ X.get("/", async (e) => {
7654
7733
  assetCount: e.assetCount || 0
7655
7734
  }, i = e.draftDataJson || e.dataJson;
7656
7735
  if (i) try {
7657
- let e = typeof i == "string" ? JSON.parse(i) : i, n = await oi(t, hi(e));
7736
+ let e = typeof i == "string" ? JSON.parse(i) : i, n = await si(t, _i(e));
7658
7737
  Object.assign(r, n);
7659
7738
  } catch {}
7660
7739
  return r;
@@ -7667,27 +7746,33 @@ X.get("/", async (e) => {
7667
7746
  limit: f
7668
7747
  });
7669
7748
  }), X.post("/", async (e) => {
7670
- 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, v = hi(_), { cleanedData: y, assetRefs: b } = ii(v), x = pi(d === void 0 ? f === void 0 ? p : f : d), S = c || "en", C = l || u || "page", w = e.get("user")?.id || null, T = a, E = /* @__PURE__ */ new Set();
7749
+ 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, v = _i(_), { cleanedData: y, assetRefs: b } = ii(v), x = hi(d === void 0 ? f === void 0 ? p : f : d), S = c || "en", C = l || u || "page", w = e.get("user")?.id || null, T = a, E = /* @__PURE__ */ new Set();
7671
7750
  if (a) {
7672
7751
  let n = await t.prepare("SELECT title, slug, contentType, language, draftDataJson, dataJson, publishedAt, status FROM content_nodes WHERE id = ?").get(a), r = n?.draftDataJson || n?.dataJson || "{}";
7673
7752
  try {
7674
- gi(typeof r == "string" ? JSON.parse(r) : r, E);
7753
+ vi(typeof r == "string" ? JSON.parse(r) : r, E);
7675
7754
  } catch {}
7676
7755
  if (m !== void 0) {
7677
7756
  let e = await t.prepare("SELECT dataJson FROM content_blocks WHERE contentId = ? AND isDraft = 1").all(a);
7678
7757
  (Array.isArray(e) ? e : e?.results || []).forEach((e) => {
7679
7758
  try {
7680
- gi(typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson, E);
7759
+ vi(typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson, E);
7681
7760
  } catch {}
7682
7761
  });
7683
7762
  }
7684
- if (m === void 0 && o === void 0 && s === void 0 && h === void 0 && g === void 0 && Object.keys(v).length === 0) return await t.prepare("\n UPDATE content_nodes \n SET isHidden = ?, \n updatedById = ?, \n updatedAt = CURRENT_TIMESTAMP\n WHERE id = ?\n ").run(x, w, a), await q(e).clear(), n?.status === "published" && n.slug && e.executionCtx.waitUntil(yi(e.env, n.slug)), e.json({
7685
- success: !0,
7686
- id: a,
7687
- status: n?.status || "published"
7688
- });
7763
+ if (m === void 0 && o === void 0 && s === void 0 && h === void 0 && g === void 0 && Object.keys(v).length === 0) {
7764
+ if (await t.prepare("\n UPDATE content_nodes \n SET isHidden = ?, \n updatedById = ?, \n updatedAt = CURRENT_TIMESTAMP\n WHERE id = ?\n ").run(x, w, a), await q(e).clear(), n?.status === "published") {
7765
+ let r = await pi(t, a);
7766
+ new Y(e.env).purgeSmart(e, t, a, n.slug, r);
7767
+ }
7768
+ return e.json({
7769
+ success: !0,
7770
+ id: a,
7771
+ status: n?.status || "published"
7772
+ });
7773
+ }
7689
7774
  {
7690
- let e = o === void 0 ? n?.title || "Untitled" : o, r = s === void 0 ? n?.slug ?? null : fi(s), i = C || n?.contentType || "page", c = S || n?.language || "en", l = n?.draftDataJson || n?.dataJson || "{}", u = {};
7775
+ let e = o === void 0 ? n?.title || "Untitled" : o, r = s === void 0 ? n?.slug ?? null : mi(s), i = C || n?.contentType || "page", c = S || n?.language || "en", l = n?.draftDataJson || n?.dataJson || "{}", u = {};
7691
7776
  try {
7692
7777
  u = JSON.parse(l);
7693
7778
  } catch {}
@@ -7698,7 +7783,7 @@ X.get("/", async (e) => {
7698
7783
  await t.prepare("\n UPDATE content_nodes \n SET title = ?, \n slug = ?, \n language = ?,\n contentType = ?, \n isHidden = ?, \n status = 'draft', \n draftDataJson = ?, \n updatedById = ?, \n updatedAt = CURRENT_TIMESTAMP\n WHERE id = ?\n ").run(e, r, c, i, x, d, w, a);
7699
7784
  }
7700
7785
  } else {
7701
- let e = o || "Untitled", n = fi(s), r = JSON.stringify(y), i = await t.prepare("\n INSERT INTO content_nodes (contentType, title, slug, language, isHidden, status, draftDataJson, dataJson, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, 'draft', ?, NULL, ?, ?)\n ").run(C, e, n, S, x, r, w, w);
7786
+ let e = o || "Untitled", n = mi(s), r = JSON.stringify(y), i = await t.prepare("\n INSERT INTO content_nodes (contentType, title, slug, language, isHidden, status, draftDataJson, dataJson, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, 'draft', ?, NULL, ?, ?)\n ").run(C, e, n, S, x, r, w, w);
7702
7787
  T = Number(i.lastInsertRowid);
7703
7788
  }
7704
7789
  if (h !== void 0 && Array.isArray(h) && T) {
@@ -7716,7 +7801,7 @@ X.get("/", async (e) => {
7716
7801
  let i = Number(t.treeId) || t.treeId;
7717
7802
  if (!e.has(i)) {
7718
7803
  e.add(i);
7719
- let a = mi(t.parentId ?? t._draftParentId ?? null), o = typeof t.sortOrder == "number" ? t.sortOrder : 0;
7804
+ let a = gi(t.parentId ?? t._draftParentId ?? null), o = typeof t.sortOrder == "number" ? t.sortOrder : 0;
7720
7805
  n.push("(?, ?, ?, ?)"), r.push(i, T, a, o);
7721
7806
  }
7722
7807
  }
@@ -7747,7 +7832,7 @@ X.get("/", async (e) => {
7747
7832
  let n = [...b, ...D];
7748
7833
  await ai(t, T, n);
7749
7834
  let r = new Set(n.map((e) => e.assetId)), i = new Set([...E].filter((e) => !r.has(e)));
7750
- i.size > 0 && await _i(t, ri(e.env), i);
7835
+ i.size > 0 && await yi(t, ri(e.env), i);
7751
7836
  }
7752
7837
  return await q(e).clear(), e.json({
7753
7838
  success: !0,
@@ -7779,7 +7864,9 @@ X.get("/", async (e) => {
7779
7864
  },
7780
7865
  blocks: l
7781
7866
  };
7782
- return await t.prepare("\n INSERT INTO node_revisions (nodeId, version, snapshotJson, createdById)\n VALUES (?, ?, ?, ?)\n ").run(i, u, JSON.stringify(d), a), await q(e).clear(), o.slug && e.executionCtx.waitUntil(yi(e.env, o.slug)), e.json({
7867
+ await t.prepare("\n INSERT INTO node_revisions (nodeId, version, snapshotJson, createdById)\n VALUES (?, ?, ?, ?)\n ").run(i, u, JSON.stringify(d), a), await q(e).clear();
7868
+ let f = await pi(t, i);
7869
+ return new Y(e.env).purgeSmart(e, t, i, o.slug, f), e.json({
7783
7870
  success: !0,
7784
7871
  id: i,
7785
7872
  status: "published",
@@ -7790,7 +7877,11 @@ X.get("/", async (e) => {
7790
7877
  let t = e.get("db"), n = e.req.query("id");
7791
7878
  if (!n) return e.json({ error: "Node ID required" }, 400);
7792
7879
  let r = Number(n), i = await t.prepare("SELECT slug, status FROM content_nodes WHERE id = ?").get(r);
7793
- return await t.prepare("UPDATE content_nodes SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?").run(r), await q(e).clear(), i && i.status === "published" && i.slug && e.executionCtx.waitUntil(yi(e.env, i.slug)), e.json({
7880
+ if (await t.prepare("UPDATE content_nodes SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?").run(r), await q(e).clear(), i && i.status === "published") {
7881
+ let n = await pi(t, r);
7882
+ new Y(e.env).purgeSmart(e, t, r, i.slug, n);
7883
+ }
7884
+ return e.json({
7794
7885
  success: !0,
7795
7886
  deletedNodeId: r
7796
7887
  });
@@ -7798,23 +7889,27 @@ X.get("/", async (e) => {
7798
7889
  let t = e.get("db"), n = await e.req.json(), r = Number(n.id);
7799
7890
  if (!r) return e.json({ error: "Node ID required" }, 400);
7800
7891
  let i = await t.prepare("SELECT slug, status FROM content_nodes WHERE id = ?").get(r);
7801
- return await t.prepare("UPDATE content_nodes SET deletedAt = NULL WHERE id = ?").run(r), await q(e).clear(), i && i.status === "published" && i.slug && e.executionCtx.waitUntil(yi(e.env, i.slug)), e.json({
7892
+ if (await t.prepare("UPDATE content_nodes SET deletedAt = NULL WHERE id = ?").run(r), await q(e).clear(), i && i.status === "published") {
7893
+ let n = await pi(t, r);
7894
+ new Y(e.env).purgeSmart(e, t, r, i.slug, n);
7895
+ }
7896
+ return e.json({
7802
7897
  success: !0,
7803
7898
  restoredNodeId: r
7804
7899
  });
7805
7900
  }), X.delete("/purge", async (e) => {
7806
7901
  let t = e.get("db"), n = e.req.query("id");
7807
7902
  if (!n) return e.json({ error: "Node ID required" }, 400);
7808
- let r = Number(n), i = await t.prepare("SELECT slug, status FROM content_nodes WHERE id = ?").get(r);
7809
- return 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 q(e).clear(), i && i.status === "published" && i.slug && e.executionCtx.waitUntil(yi(e.env, i.slug)), e.json({
7903
+ let r = Number(n), i = await t.prepare("SELECT slug, status FROM content_nodes WHERE id = ?").get(r), a = await pi(t, r);
7904
+ return 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 q(e).clear(), i && i.status === "published" && new Y(e.env).purgeSmart(e, t, r, i.slug, a), e.json({
7810
7905
  success: !0,
7811
7906
  purgedNodeId: r
7812
7907
  });
7813
7908
  });
7814
7909
  //#endregion
7815
7910
  //#region server/routes/admin/trees.ts
7816
- var bi = new e();
7817
- function xi(e, t = null) {
7911
+ var xi = new e();
7912
+ function Si(e, t = null) {
7818
7913
  let n = [];
7819
7914
  for (let r = 0; r < e.length; r++) {
7820
7915
  let i = e[r];
@@ -7827,20 +7922,20 @@ function xi(e, t = null) {
7827
7922
  id: a,
7828
7923
  parentId: t,
7829
7924
  sortOrder: r
7830
- }), i.children && Array.isArray(i.children) && i.children.length > 0 && n.push(...xi(i.children, a));
7925
+ }), i.children && Array.isArray(i.children) && i.children.length > 0 && n.push(...Si(i.children, a));
7831
7926
  }
7832
7927
  }
7833
7928
  return n;
7834
7929
  }
7835
- function Si(e) {
7930
+ function Ci(e) {
7836
7931
  if (e == null || e === "null" || e === "" || typeof e == "string" && e.startsWith("draft-")) return null;
7837
7932
  let t = Number(e);
7838
7933
  return isNaN(t) ? null : t;
7839
7934
  }
7840
- function Ci(e) {
7935
+ function wi(e) {
7841
7936
  return +(e === !0 || e === 1 || e === "1" || e === "true");
7842
7937
  }
7843
- bi.get("/tree.json", async (e) => {
7938
+ xi.get("/tree.json", async (e) => {
7844
7939
  try {
7845
7940
  let t = e.get("db"), n = e.req.query("treeId") || "main-nav", r = e.req.query("preview") === "true", i = 1;
7846
7941
  if (isNaN(Number(n))) {
@@ -7889,45 +7984,45 @@ bi.get("/tree.json", async (e) => {
7889
7984
  } catch (t) {
7890
7985
  return console.error("[CMS Tree API] GET Error:", t), e.json({ error: t.message || "Failed to fetch tree" }, 500);
7891
7986
  }
7892
- }), bi.post("/tree.json", async (e) => {
7987
+ }), xi.post("/tree.json", async (e) => {
7893
7988
  try {
7894
- let t = e.get("db"), n = await e.req.json(), r = n.treeId ? String(n.treeId).trim() : "main-nav", i = q(e), a = 1;
7989
+ let t = e.get("db"), n = await e.req.json(), r = n.treeId ? String(n.treeId).trim() : "main-nav", i = q(e), a = new Y(e.env), o = 1;
7895
7990
  if (isNaN(Number(r))) {
7896
7991
  let e = await t.prepare("SELECT id FROM trees WHERE key = ?").get(r);
7897
- if (e && e.id) a = Number(e.id);
7992
+ if (e && e.id) o = Number(e.id);
7898
7993
  else {
7899
7994
  let e = await t.prepare("SELECT id FROM trees LIMIT 1").get();
7900
- e && e.id && (a = Number(e.id));
7995
+ e && e.id && (o = Number(e.id));
7901
7996
  }
7902
- } else a = Number(r);
7997
+ } else o = Number(r);
7903
7998
  if (n.tree && Array.isArray(n.tree)) {
7904
- let r = xi(n.tree, null);
7999
+ let r = Si(n.tree, null);
7905
8000
  if (r.length > 0) for (let e = 0; e < r.length; e += 50) {
7906
- let n = r.slice(e, e + 50), i = n.map((e) => e.id), o = i.map(() => "?").join(","), s = "UPDATE tree_nodes SET \n";
8001
+ let n = r.slice(e, e + 50), i = n.map((e) => e.id), a = i.map(() => "?").join(","), s = "UPDATE tree_nodes SET \n";
7907
8002
  s += "parentId = CASE id \n", n.forEach(() => {
7908
8003
  s += "WHEN ? THEN ? \n";
7909
8004
  }), s += "ELSE parentId END, \n", s += "sortOrder = CASE id \n", n.forEach(() => {
7910
8005
  s += "WHEN ? THEN ? \n";
7911
- }), s += "ELSE sortOrder END \n", s += `WHERE id IN (${o}) AND treeId = ?`;
8006
+ }), s += "ELSE sortOrder END \n", s += `WHERE id IN (${a}) AND treeId = ?`;
7912
8007
  let c = [];
7913
8008
  n.forEach((e) => {
7914
8009
  c.push(e.id, e.parentId);
7915
8010
  }), n.forEach((e) => {
7916
8011
  c.push(e.id, e.sortOrder);
7917
- }), c.push(...i), c.push(a), await t.prepare(s).run(...c);
8012
+ }), c.push(...i), c.push(o), await t.prepare(s).run(...c);
7918
8013
  }
7919
- return await i.clear(), e.json({ success: !0 });
7920
- }
7921
- let { action: o, title: s, nodeType: c, parentId: l, contentId: u, nodeData: d = {}, pageData: f = {} } = n, p = Object.keys(d).length > 0 ? { ...d } : { ...f }, m = Ci(n.isHidden === void 0 ? p.isHidden === void 0 ? p.hidden : p.isHidden : n.isHidden);
7922
- delete p._isTreeDraft, delete p._draftParentId, delete p.isNew, delete p.nodeType, delete p.contentType, delete p.title, delete p.slug, delete p.hidden, delete p.is_hidden, delete p.isHidden, delete p.status;
7923
- let h = Si(l), g = e.get("user")?.id || null;
7924
- if (o === "create") {
7925
- let r = p.slug || n.slug || s, o = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
7926
- if (o) {
7927
- let n = h === null ? "tn.parentId IS NULL" : "tn.parentId = ?", r = h === null ? [a, o] : [
7928
- a,
7929
- h,
7930
- o
8014
+ return await i.clear(), a.purgeGlobalCache(e), e.json({ success: !0 });
8015
+ }
8016
+ 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 = wi(n.isHidden === void 0 ? m.isHidden === void 0 ? m.hidden : m.isHidden : n.isHidden);
8017
+ 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;
8018
+ let g = Ci(u), _ = e.get("user")?.id || null;
8019
+ if (s === "create") {
8020
+ let r = m.slug || n.slug || c, s = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
8021
+ if (s) {
8022
+ let n = g === null ? "tn.parentId IS NULL" : "tn.parentId = ?", r = g === null ? [o, s] : [
8023
+ o,
8024
+ g,
8025
+ s
7931
8026
  ];
7932
8027
  if (await t.prepare(`
7933
8028
  SELECT 1
@@ -7939,39 +8034,39 @@ bi.get("/tree.json", async (e) => {
7939
8034
  AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
7940
8035
  LIMIT 1
7941
8036
  `).get(...r)) return e.json({
7942
- error: `The slug '${o}' is already in use by another page in this section.`,
8037
+ error: `The slug '${s}' is already in use by another page in this section.`,
7943
8038
  field: "slug"
7944
8039
  }, 409);
7945
8040
  }
7946
- let l = JSON.stringify(p), u = await t.prepare("\n INSERT INTO content_nodes (contentType, title, slug, language, isHidden, status, draftDataJson, dataJson, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, 'draft', ?, NULL, ?, ?)\n ").run(c || "page", s || "Untitled", o, p.language || n.language || "en", m, l, g, g), d = Number(u.lastInsertRowid);
7947
- await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(a, d);
7948
- let f = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, 0)\n ").run(a, d, h), _ = Number(f.lastInsertRowid), v = [];
7949
- n.channels && Array.isArray(n.channels) ? v = n.channels : n.channelId && n.channelId !== "all" && (v = [n.channelId]);
7950
- let y = [...new Set(v)].filter((e) => e && e !== "all").map((e) => Number(e));
7951
- if (y.length > 0) {
7952
- let e = y.map(() => "(?, ?)").join(", "), n = y.flatMap((e) => [d, e]);
8041
+ 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);
8042
+ await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, f);
8043
+ let p = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, 0)\n ").run(o, f, g), v = Number(p.lastInsertRowid), y = [];
8044
+ n.channels && Array.isArray(n.channels) ? y = n.channels : n.channelId && n.channelId !== "all" && (y = [n.channelId]);
8045
+ let b = [...new Set(y)].filter((e) => e && e !== "all").map((e) => Number(e));
8046
+ if (b.length > 0) {
8047
+ let e = b.map(() => "(?, ?)").join(", "), n = b.flatMap((e) => [f, e]);
7953
8048
  await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...n);
7954
8049
  }
7955
- return await i.clear(), e.json({
8050
+ return await i.clear(), a.purgeGlobalCache(e), e.json({
7956
8051
  success: !0,
7957
- id: d,
7958
- treeNodeId: _,
8052
+ id: f,
8053
+ treeNodeId: v,
7959
8054
  status: "draft"
7960
8055
  }, 201);
7961
8056
  }
7962
- if (o === "attach") {
7963
- if (!u) return e.json({ error: "contentId is required for attach" }, 400);
7964
- let n = await t.prepare("SELECT slug FROM content_nodes WHERE id = ?").get(u);
8057
+ if (s === "attach") {
8058
+ if (!d) return e.json({ error: "contentId is required for attach" }, 400);
8059
+ let n = await t.prepare("SELECT slug FROM content_nodes WHERE id = ?").get(d);
7965
8060
  if (n && n.slug) {
7966
- let r = h === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = h === null ? [
7967
- a,
8061
+ let r = g === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = g === null ? [
8062
+ o,
7968
8063
  n.slug,
7969
- u
8064
+ d
7970
8065
  ] : [
7971
- a,
7972
- h,
8066
+ o,
8067
+ g,
7973
8068
  n.slug,
7974
- u
8069
+ d
7975
8070
  ];
7976
8071
  if (await t.prepare(`
7977
8072
  SELECT 1
@@ -7988,16 +8083,16 @@ bi.get("/tree.json", async (e) => {
7988
8083
  field: "slug"
7989
8084
  }, 409);
7990
8085
  }
7991
- await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(a, u);
7992
- let r = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, 0)\n ").run(a, u, h), o = Number(r.lastInsertRowid);
7993
- return await i.clear(), e.json({
8086
+ await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, d);
8087
+ let r = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, 0)\n ").run(o, d, g), s = Number(r.lastInsertRowid);
8088
+ return await i.clear(), a.purgeGlobalCache(e), e.json({
7994
8089
  success: !0,
7995
- treeNodeId: o
8090
+ treeNodeId: s
7996
8091
  });
7997
8092
  }
7998
- if (o === "detach") {
8093
+ if (s === "detach") {
7999
8094
  let r = n.treeNodeId || n.contentId;
8000
- return r ? (await t.prepare("\n UPDATE tree_nodes \n SET parentId = (SELECT parentId FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?) \n WHERE parentId = ? AND treeId = ?\n ").run(r, r, a, r, a), await t.prepare("DELETE FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?").run(r, r, a), await i.clear(), e.json({ success: !0 })) : e.json({ error: "treeNodeId or contentId required for detach" }, 400);
8095
+ return r ? (await t.prepare("\n UPDATE tree_nodes \n SET parentId = (SELECT parentId FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?) \n WHERE parentId = ? AND treeId = ?\n ").run(r, r, o, r, o), await t.prepare("DELETE FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?").run(r, r, o), await i.clear(), a.purgeGlobalCache(e), e.json({ success: !0 })) : e.json({ error: "treeNodeId or contentId required for detach" }, 400);
8001
8096
  }
8002
8097
  return e.json({ error: "Invalid payload or action" }, 400);
8003
8098
  } catch (t) {
@@ -8006,7 +8101,7 @@ bi.get("/tree.json", async (e) => {
8006
8101
  details: t.message
8007
8102
  }, 500);
8008
8103
  }
8009
- }), bi.get("/trees.json", async (e) => {
8104
+ }), xi.get("/trees.json", async (e) => {
8010
8105
  try {
8011
8106
  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) => {
8012
8107
  let n = Number(t.treeId), r = Number(t.channelId);
@@ -8035,7 +8130,7 @@ bi.get("/tree.json", async (e) => {
8035
8130
  } catch {
8036
8131
  return e.json([]);
8037
8132
  }
8038
- }), bi.post("/trees.json", async (e) => {
8133
+ }), xi.post("/trees.json", async (e) => {
8039
8134
  try {
8040
8135
  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 };
8041
8136
  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({
@@ -8060,7 +8155,7 @@ bi.get("/tree.json", async (e) => {
8060
8155
  await t.prepare(`INSERT OR IGNORE INTO channel_trees (channelId, treeId, key) VALUES ${n}`).run(...r);
8061
8156
  }
8062
8157
  }
8063
- return await q(e).clear(), e.json({
8158
+ return await q(e).clear(), new Y(e.env).purgeGlobalCache(e), e.json({
8064
8159
  success: !0,
8065
8160
  id: p,
8066
8161
  key: o,
@@ -8074,12 +8169,12 @@ bi.get("/tree.json", async (e) => {
8074
8169
  } catch (t) {
8075
8170
  return console.error("[API Trees] Error saving tree:", t), e.json({ error: t.message || "Failed to save tree" }, 500);
8076
8171
  }
8077
- }), bi.delete("/trees.json", async (e) => {
8172
+ }), xi.delete("/trees.json", async (e) => {
8078
8173
  let t = e.get("db"), n = e.req.query("id");
8079
8174
  if (!n) return e.json({ error: "Tree ID required" }, 400);
8080
8175
  let r = Number(n);
8081
8176
  try {
8082
- 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 q(e).clear(), e.json({
8177
+ 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 q(e).clear(), new Y(e.env).purgeGlobalCache(e), e.json({
8083
8178
  success: !0,
8084
8179
  deletedTreeId: r
8085
8180
  });
@@ -8089,8 +8184,8 @@ bi.get("/tree.json", async (e) => {
8089
8184
  });
8090
8185
  //#endregion
8091
8186
  //#region server/routes/admin/channels.ts
8092
- var wi = new e();
8093
- wi.get("/", async (e) => {
8187
+ var Ti = new e();
8188
+ Ti.get("/", async (e) => {
8094
8189
  try {
8095
8190
  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) => {
8096
8191
  e[t.channelId] || (e[t.channelId] = []);
@@ -8114,7 +8209,7 @@ wi.get("/", async (e) => {
8114
8209
  isHidden: !!e.isHidden,
8115
8210
  trees: a[e.id] || []
8116
8211
  };
8117
- }), s = e.env?.BUNDLED_DEFINITIONS, c = li(s)?.channelTemplate || {
8212
+ }), s = e.env?.BUNDLED_DEFINITIONS, c = ui(s)?.channelTemplate || {
8118
8213
  label: "Channel Settings",
8119
8214
  fields: {
8120
8215
  key: {
@@ -8156,7 +8251,7 @@ wi.get("/", async (e) => {
8156
8251
  error: t.message
8157
8252
  }, 500);
8158
8253
  }
8159
- }), wi.post("/", async (e) => {
8254
+ }), Ti.post("/", async (e) => {
8160
8255
  try {
8161
8256
  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;
8162
8257
  if (await t.prepare("SELECT id FROM channels WHERE key = ? AND id != ? LIMIT 1").get(y, i ?? -1)) return e.json({
@@ -8183,7 +8278,7 @@ wi.get("/", async (e) => {
8183
8278
  VALUES ${e}
8184
8279
  `).run(...n);
8185
8280
  }
8186
- return await q(e).clear(), e.json({
8281
+ return await q(e).clear(), new Y(e.env).purgeGlobalCache(e), e.json({
8187
8282
  success: !0,
8188
8283
  id: w
8189
8284
  });
@@ -8193,12 +8288,12 @@ wi.get("/", async (e) => {
8193
8288
  details: t.message
8194
8289
  }, 500);
8195
8290
  }
8196
- }), wi.delete("/", async (e) => {
8291
+ }), Ti.delete("/", async (e) => {
8197
8292
  let t = e.get("db"), n = e.req.query("id");
8198
8293
  if (!n) return e.json({ error: "Channel ID required" }, 400);
8199
8294
  let r = Number(n);
8200
8295
  try {
8201
- 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 q(e).clear(), e.json({
8296
+ 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 q(e).clear(), new Y(e.env).purgeGlobalCache(e), e.json({
8202
8297
  success: !0,
8203
8298
  deletedSiteId: r
8204
8299
  });
@@ -8211,10 +8306,10 @@ wi.get("/", async (e) => {
8211
8306
  });
8212
8307
  //#endregion
8213
8308
  //#region server/routes/admin/schemas.ts
8214
- var Ti = new e(), Ei = null, Di = (e) => {
8309
+ var Ei = new e(), Di = null, Oi = (e) => {
8215
8310
  try {
8216
- if (!Ei) {
8217
- let t = ci(e.env?.BUNDLED_DEFINITIONS || Ar), n = t.userTemplate || {
8311
+ if (!Di) {
8312
+ let t = li(e.env?.BUNDLED_DEFINITIONS || Ar), n = t.userTemplate || {
8218
8313
  id: "userTemplate",
8219
8314
  label: "User Account",
8220
8315
  fields: {
@@ -8250,7 +8345,7 @@ var Ti = new e(), Ei = null, Di = (e) => {
8250
8345
  }
8251
8346
  }
8252
8347
  };
8253
- Ei = {
8348
+ Di = {
8254
8349
  channelTemplate: t.channelTemplate || null,
8255
8350
  treeTemplate: t.treeTemplate || null,
8256
8351
  userTemplate: n,
@@ -8262,7 +8357,7 @@ var Ti = new e(), Ei = null, Di = (e) => {
8262
8357
  blockLayouts: t.blockLayouts || {}
8263
8358
  };
8264
8359
  }
8265
- return e.json(Ei, 200, { "Cache-Control": "public, max-age=300, stale-while-revalidate=86400" });
8360
+ return e.json(Di, 200, { "Cache-Control": "public, max-age=300, stale-while-revalidate=86400" });
8266
8361
  } catch (t) {
8267
8362
  return console.error("[CMS API] Error loading schemas:", t), e.json({
8268
8363
  error: "Failed to load schemas",
@@ -8270,10 +8365,10 @@ var Ti = new e(), Ei = null, Di = (e) => {
8270
8365
  }, 500);
8271
8366
  }
8272
8367
  };
8273
- Ti.get("/", Di), Ti.get("/schemas.json", Di);
8368
+ Ei.get("/", Oi), Ei.get("/schemas.json", Oi);
8274
8369
  //#endregion
8275
8370
  //#region server/routes/admin/validation.ts
8276
- var Oi = new e(), ki = {
8371
+ var ki = new e(), Ai = {
8277
8372
  node: "content_nodes",
8278
8373
  nodes: "content_nodes",
8279
8374
  content_node: "content_nodes",
@@ -8285,7 +8380,7 @@ var Oi = new e(), ki = {
8285
8380
  user: "users",
8286
8381
  users: "users",
8287
8382
  user_account: "user_accounts"
8288
- }, Ai = {
8383
+ }, ji = {
8289
8384
  content_nodes: [
8290
8385
  "id",
8291
8386
  "title",
@@ -8342,11 +8437,11 @@ var Oi = new e(), ki = {
8342
8437
  "createdAt"
8343
8438
  ]
8344
8439
  };
8345
- Oi.post("/validate-unique", async (e) => {
8440
+ ki.post("/validate-unique", async (e) => {
8346
8441
  try {
8347
8442
  let t = e.get("db"), { entityType: n, field: r, value: i, excludeId: a } = await e.req.json();
8348
8443
  if (!r || i == null || String(i).trim() === "") return e.json({ isUnique: !0 });
8349
- let o = ki[n] || "content_nodes", s = r.replace(/[^a-zA-Z0-9_]/g, ""), c = (Ai[o] || Ai.content_nodes).includes(s), l = -1;
8444
+ let o = Ai[n] || "content_nodes", s = r.replace(/[^a-zA-Z0-9_]/g, ""), c = (ji[o] || ji.content_nodes).includes(s), l = -1;
8350
8445
  if (a != null && String(a).trim() !== "") {
8351
8446
  let e = Number(a);
8352
8447
  l = isNaN(e) ? String(a) : e;
@@ -8358,7 +8453,7 @@ Oi.post("/validate-unique", async (e) => {
8358
8453
  } catch (t) {
8359
8454
  return console.error("[API Validation] Error validating global uniqueness:", t), e.json({ error: "Failed to validate uniqueness" }, 500);
8360
8455
  }
8361
- }), Oi.post("/validate-unique-sibling", async (e) => {
8456
+ }), ki.post("/validate-unique-sibling", async (e) => {
8362
8457
  try {
8363
8458
  let t = e.get("db"), { slug: n, treeId: r, parentId: i, excludeTreeNodeId: a } = await e.req.json();
8364
8459
  if (!n || !String(n).trim() || !r) return e.json({ isUnique: !0 });
@@ -8385,8 +8480,8 @@ Oi.post("/validate-unique", async (e) => {
8385
8480
  });
8386
8481
  //#endregion
8387
8482
  //#region server/routes/admin/stats.ts
8388
- var ji = new e();
8389
- ji.get("/", async (e) => {
8483
+ var Mi = new e();
8484
+ Mi.get("/", async (e) => {
8390
8485
  try {
8391
8486
  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 ").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 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 ORDER BY updatedAt DESC \n LIMIT 5\n ").all(), u = (Array.isArray(l) ? l : l?.results || []).map((e) => ({
8392
8487
  ...e,
@@ -8401,7 +8496,7 @@ ji.get("/", async (e) => {
8401
8496
  isHidden: !!e.isHidden,
8402
8497
  channelNames: e.channelLabels ? e.channelLabels.split(",") : [],
8403
8498
  treeNames: e.treeLabels ? e.treeLabels.split(",") : []
8404
- })), p = e.env?.BUNDLED_DEFINITIONS, m = ci(p), h = m.nodes || m.nodeSchemas || {}, g = c.map((e) => {
8499
+ })), p = e.env?.BUNDLED_DEFINITIONS, m = li(p), h = m.nodes || m.nodeSchemas || {}, g = c.map((e) => {
8405
8500
  let t = e.type || "node", n = h[t]?.label || t.charAt(0).toUpperCase() + t.slice(1);
8406
8501
  return {
8407
8502
  type: t,
@@ -8442,15 +8537,28 @@ async function Q(e, t, n = []) {
8442
8537
  }
8443
8538
  return [];
8444
8539
  }
8445
- async function Mi(e, t, n = []) {
8540
+ async function Ni(e, t, n = []) {
8446
8541
  let r = e.prepare(t);
8447
8542
  if (typeof r.bind == "function") return await r.bind(...n).run();
8448
8543
  if (typeof r.run == "function") return await r.run(...n);
8449
8544
  }
8450
- function Ni(e, t, n) {
8545
+ function Pi(e, t, n) {
8451
8546
  let r = e || (t ? `/media/${t}` : "");
8452
8547
  return r && n && r.startsWith(`https://${n}/`) && !r.includes("/media/") && (r = r.replace(`https://${n}/`, `https://${n}/media/`)), r;
8453
8548
  }
8549
+ async function Fi(e, t, n) {
8550
+ let r = new Y(e.env), i = await Q(t, "\n SELECT cdnUrl, storageKeyPrivate\n FROM assets\n WHERE id = ? OR parentAssetId = ?\n ", [n, n]), a = [];
8551
+ for (let t of i) {
8552
+ let n = Pi(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN);
8553
+ n && a.push(n);
8554
+ }
8555
+ let o = await Q(t, "\n SELECT DISTINCT cn.id, cn.slug, cn.status\n FROM node_assets na\n INNER JOIN content_nodes cn ON na.nodeId = cn.id\n LEFT JOIN assets crop ON na.assetId = crop.id\n WHERE cn.status = 'published' AND (\n na.assetId = ?\n OR crop.parentAssetId = ?\n OR crop.id = (SELECT parentAssetId FROM assets WHERE id = ?)\n )\n ", [
8556
+ n,
8557
+ n,
8558
+ n
8559
+ ]);
8560
+ if (o.length !== 0) for (let n of o) n.id && r.purgeSmart(e, t, n.id, n.slug, a);
8561
+ }
8454
8562
  Z.get("/", async (e) => {
8455
8563
  try {
8456
8564
  let t = u(e), { search: n = "", type: r = "all", page: i = "1", limit: a = "24", sort: o = "createdAt", order: s = "DESC", nodeId: c, channelId: l, trashed: d } = e.req.query(), f = Math.max(1, parseInt(i, 10) || 1), p = Math.max(1, Math.min(100, parseInt(a, 10) || 24)), m = (f - 1) * p, h = {
@@ -8518,7 +8626,7 @@ Z.get("/", async (e) => {
8518
8626
  ...JSON.parse(t.dataJson || "{}")
8519
8627
  };
8520
8628
  } catch {}
8521
- let r = Ni(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN);
8629
+ let r = Pi(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN);
8522
8630
  return {
8523
8631
  id: t.id,
8524
8632
  filename: t.filename || "Untitled Asset",
@@ -8561,7 +8669,7 @@ Z.get("/", async (e) => {
8561
8669
  let y = e.env.CDN_DOMAIN, b = v.replace(/^\//, ""), x = y ? `https://${y}/media/${b}` : `/media/${b}`, S = i.type || "application/octet-stream", C = i.size || 0, w = e.get("userId"), T = typeof w == "string" && w.trim().length > 0 ? w : null;
8562
8670
  T && (await Q(t, "SELECT id FROM users WHERE id = ?", [T])).length === 0 && (T = null);
8563
8671
  let E = +!!h;
8564
- await Mi(t, "\n INSERT INTO assets (id, filename, mimeType, sizeBytes, storageKeyPrivate, cdnUrl, createdById, isSystemVariant, parentAssetId, cropCoordinatesJson)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ", [
8672
+ await Ni(t, "\n INSERT INTO assets (id, filename, mimeType, sizeBytes, storageKeyPrivate, cdnUrl, createdById, isSystemVariant, parentAssetId, cropCoordinatesJson)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ", [
8565
8673
  p,
8566
8674
  i.name,
8567
8675
  S,
@@ -8575,8 +8683,8 @@ Z.get("/", async (e) => {
8575
8683
  ]);
8576
8684
  let D = x;
8577
8685
  if (s) {
8578
- let e = await Q(t, "SELECT cdnUrl, storageKeyPrivate FROM assets WHERE id = ?", [s]);
8579
- e.length > 0 && (D = Ni(e[0].cdnUrl, e[0].storageKeyPrivate, y));
8686
+ let n = await Q(t, "SELECT cdnUrl, storageKeyPrivate FROM assets WHERE id = ?", [s]);
8687
+ n.length > 0 && (D = Pi(n[0].cdnUrl, n[0].storageKeyPrivate, y)), await Fi(e, t, s);
8580
8688
  }
8581
8689
  return e.json({
8582
8690
  id: p,
@@ -8618,7 +8726,7 @@ Z.get("/", async (e) => {
8618
8726
  ...JSON.parse(i.dataJson || "{}")
8619
8727
  };
8620
8728
  } catch {}
8621
- let l = Ni(i.cdnUrl, i.storageKeyPrivate, e.env?.CDN_DOMAIN);
8729
+ let l = Pi(i.cdnUrl, i.storageKeyPrivate, e.env?.CDN_DOMAIN);
8622
8730
  return e.json({
8623
8731
  id: i.id,
8624
8732
  filename: i.filename,
@@ -8645,7 +8753,7 @@ Z.get("/", async (e) => {
8645
8753
  createdAt: t.createdAt,
8646
8754
  parentAssetId: t.parentAssetId || i.id,
8647
8755
  cropCoordinates: n,
8648
- url: Ni(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN),
8756
+ url: Pi(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN),
8649
8757
  originalUrl: l
8650
8758
  };
8651
8759
  })
@@ -8661,18 +8769,18 @@ Z.get("/", async (e) => {
8661
8769
  try {
8662
8770
  o = JSON.parse(a.dataJson || "{}");
8663
8771
  } catch {}
8664
- return r.title !== void 0 && (o.title = r.title), r.alt !== void 0 && (o.alt = r.alt), r.description !== void 0 && (o.description = r.description), await Mi(t, "UPDATE assets SET filename = ?, dataJson = ?, updatedAt = CURRENT_TIMESTAMP WHERE id = ?", [
8772
+ return r.title !== void 0 && (o.title = r.title), r.alt !== void 0 && (o.alt = r.alt), r.description !== void 0 && (o.description = r.description), await Ni(t, "UPDATE assets SET filename = ?, dataJson = ?, updatedAt = CURRENT_TIMESTAMP WHERE id = ?", [
8665
8773
  r.filename === void 0 ? a.filename : r.filename,
8666
8774
  JSON.stringify(o),
8667
8775
  n
8668
- ]), e.json({ success: !0 });
8776
+ ]), await Fi(e, t, n), e.json({ success: !0 });
8669
8777
  } catch (t) {
8670
8778
  return console.error("❌ [Asset Update Error]:", t), e.json({ error: "Failed to update asset" }, 500);
8671
8779
  }
8672
8780
  }), Z.delete("/:id", async (e) => {
8673
8781
  try {
8674
8782
  let t = u(e), n = e.req.param("id"), r = (await Q(t, "SELECT id, filename, isSystemVariant FROM assets WHERE id = ?", [n]))[0];
8675
- return r ? (r.isSystemVariant ? await Mi(t, "UPDATE assets SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?", [n]) : await Mi(t, "UPDATE assets\n SET deletedAt = CURRENT_TIMESTAMP\n WHERE id = ? OR parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
8783
+ return r ? (await Fi(e, t, n), r.isSystemVariant ? await Ni(t, "UPDATE assets SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?", [n]) : await Ni(t, "UPDATE assets\n SET deletedAt = CURRENT_TIMESTAMP\n WHERE id = ? OR parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
8676
8784
  n,
8677
8785
  n,
8678
8786
  `crop_%${r.filename ? r.filename.replace(/\.[^/.]+$/, "") : ""}%`,
@@ -8693,12 +8801,12 @@ Z.get("/", async (e) => {
8693
8801
  let t = u(e), n = await e.req.json(), r = n.id || n.assetId;
8694
8802
  if (!r) return e.json({ error: "Asset ID required" }, 400);
8695
8803
  let i = (await Q(t, "SELECT id, filename FROM assets WHERE id = ?", [r]))[0];
8696
- return i ? (await Mi(t, "UPDATE assets \n SET deletedAt = NULL \n WHERE id = ? OR parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
8804
+ return i ? (await Ni(t, "UPDATE assets \n SET deletedAt = NULL \n WHERE id = ? OR parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
8697
8805
  r,
8698
8806
  r,
8699
8807
  `crop_%${i.filename ? i.filename.replace(/\.[^/.]+$/, "") : ""}%`,
8700
8808
  `%${r}%`
8701
- ]), e.json({
8809
+ ]), await Fi(e, t, r), e.json({
8702
8810
  success: !0,
8703
8811
  id: r,
8704
8812
  restored: !0
@@ -8713,6 +8821,7 @@ Z.get("/", async (e) => {
8713
8821
  try {
8714
8822
  let t = u(e), n = ri(e.env), r = e.req.param("id"), i = (await Q(t, "SELECT id, filename, storageKeyPrivate, isSystemVariant FROM assets WHERE id = ?", [r]))[0];
8715
8823
  if (!i) return e.json({ error: "Asset not found" }, 404);
8824
+ await Fi(e, t, r);
8716
8825
  let a = [i];
8717
8826
  i.isSystemVariant || (a = [i, ...await Q(t, "SELECT id, storageKeyPrivate FROM assets \n WHERE parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
8718
8827
  r,
@@ -8728,7 +8837,7 @@ Z.get("/", async (e) => {
8728
8837
  }
8729
8838
  }
8730
8839
  let s = o.map(() => "?").join(",");
8731
- return await Mi(t, `DELETE FROM node_assets WHERE assetId IN (${s})`, o), await Mi(t, `DELETE FROM assets WHERE id IN (${s})`, o), e.json({
8840
+ return await Ni(t, `DELETE FROM node_assets WHERE assetId IN (${s})`, o), await Ni(t, `DELETE FROM assets WHERE id IN (${s})`, o), e.json({
8732
8841
  success: !0,
8733
8842
  id: r,
8734
8843
  purged: !0,
@@ -8744,8 +8853,8 @@ Z.get("/", async (e) => {
8744
8853
  });
8745
8854
  //#endregion
8746
8855
  //#region server/routes/public/node.ts
8747
- var Pi = new e();
8748
- function Fi(e, t) {
8856
+ var Ii = new e();
8857
+ function Li(e, t) {
8749
8858
  let n = /* @__PURE__ */ new Date();
8750
8859
  if (e && String(e).trim() !== "") {
8751
8860
  let t = new Date(e);
@@ -8757,7 +8866,7 @@ function Fi(e, t) {
8757
8866
  }
8758
8867
  return !0;
8759
8868
  }
8760
- async function Ii(e, t) {
8869
+ async function Ri(e, t) {
8761
8870
  if (!t || typeof t != "object") return t;
8762
8871
  let n = { ...t };
8763
8872
  for (let [t, r] of Object.entries(n)) if (typeof r == "string" && r.startsWith("ast_")) try {
@@ -8778,10 +8887,10 @@ async function Ii(e, t) {
8778
8887
  };
8779
8888
  }
8780
8889
  } catch {}
8781
- else typeof r == "object" && r && !Array.isArray(r) && !r.url && (n[t] = await Ii(e, r));
8890
+ else typeof r == "object" && r && !Array.isArray(r) && !r.url && (n[t] = await Ri(e, r));
8782
8891
  return n;
8783
8892
  }
8784
- async function Li(e, t, n) {
8893
+ async function zi(e, t, n) {
8785
8894
  let r = t.filter((e) => e.componentId === "content-feed" || e.componentId === "article-list");
8786
8895
  for (let t of r) {
8787
8896
  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];
@@ -8797,7 +8906,7 @@ async function Li(e, t, n) {
8797
8906
  if (e.dataJson) try {
8798
8907
  t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
8799
8908
  } catch {}
8800
- return Fi(t.startShowingAt, t.stopShowingAt) ? {
8909
+ return Li(t.startShowingAt, t.stopShowingAt) ? {
8801
8910
  id: e.id,
8802
8911
  title: e.title,
8803
8912
  slug: e.slug,
@@ -8814,7 +8923,7 @@ async function Li(e, t, n) {
8814
8923
  }
8815
8924
  }
8816
8925
  }
8817
- async function Ri(e, t, n, r, i = !1) {
8926
+ async function Bi(e, t, n, r, i = !1) {
8818
8927
  if (!t) return { blocks: [] };
8819
8928
  let a = 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\n FROM tree_nodes t\n INNER JOIN content_nodes c ON t.contentId = c.id\n WHERE t.id = ? OR c.id = ?\n UNION ALL\n SELECT t.id, t.contentId, c.title, c.slug, t.parentId, 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 * FROM ancestor_path ORDER BY level ASC\n ").all(t, t), o = Array.isArray(a) ? a : a?.results || [];
8820
8929
  if (!o || o.length === 0) return { blocks: [] };
@@ -8844,10 +8953,10 @@ async function Ri(e, t, n, r, i = !1) {
8844
8953
  try {
8845
8954
  o = (typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson) || {};
8846
8955
  } catch {}
8847
- let s = o.hidden === !0 || o.hidden === 1 || o.hidden === "1" || o.hidden === "true", l = Fi(o.startShowingAt, o.stopShowingAt);
8956
+ let s = o.hidden === !0 || o.hidden === 1 || o.hidden === "1" || o.hidden === "true", l = Li(o.startShowingAt, o.stopShowingAt);
8848
8957
  if (!i && (s || !l)) continue;
8849
- let u = t.elementType || t.componentId || "text-block", d = r.blocks?.[u]?.fields || r.elements?.[u]?.fields || r.components?.[u]?.fields || {}, f = String(o.blockId || o._instanceId || o.id || t.blockId || t.id), p = zi(o, d);
8850
- p = await oi(e, p), p = await Ii(e, p), p = Bi(p), p.blockId = f;
8958
+ let u = t.elementType || t.componentId || "text-block", d = r.blocks?.[u]?.fields || r.elements?.[u]?.fields || r.components?.[u]?.fields || {}, f = String(o.blockId || o._instanceId || o.id || t.blockId || t.id), p = Vi(o, d);
8959
+ p = await si(e, p), p = await Ri(e, p), p = Hi(p), p.blockId = f;
8851
8960
  let m = t.region || n;
8852
8961
  c[m] || (c[m] = []), c[m].push({
8853
8962
  instanceId: t.id,
@@ -8866,7 +8975,7 @@ async function Ri(e, t, n, r, i = !1) {
8866
8975
  }
8867
8976
  return { blocks: [] };
8868
8977
  }
8869
- function zi(e, t = {}) {
8978
+ function Vi(e, t = {}) {
8870
8979
  let n = {};
8871
8980
  for (let [r, i] of Object.entries(e)) {
8872
8981
  if (r.endsWith("_meta") || r === "disabledRegions" || r === "hidden" || r === "is_hidden" || r === "isHidden" || r === "status" || r === "startShowingAt" || r === "stopShowingAt" || r === "slug" || r === "title" || r === "id" || r.startsWith("_")) continue;
@@ -8875,14 +8984,14 @@ function zi(e, t = {}) {
8875
8984
  }
8876
8985
  return n;
8877
8986
  }
8878
- function Bi(e) {
8879
- if (Array.isArray(e)) return e.map(Bi);
8987
+ function Hi(e) {
8988
+ if (Array.isArray(e)) return e.map(Hi);
8880
8989
  if (!e || typeof e != "object") return e;
8881
8990
  if (typeof e.id == "string" && e.id.startsWith("ast_") && typeof e.url == "string") {
8882
8991
  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 ? {
8883
8992
  ...t,
8884
8993
  ...t.crops?.[r] || {}
8885
- } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, Bi({
8994
+ } : t, a = Object.fromEntries(Object.entries(n).filter(([, t]) => t?.id !== e.id).map(([t, n]) => [t, Hi({
8886
8995
  ...n,
8887
8996
  title: n?.title ?? e.title ?? "",
8888
8997
  alt: n?.alt ?? e.alt ?? "",
@@ -8896,9 +9005,9 @@ function Bi(e) {
8896
9005
  ...Object.keys(a).length > 0 ? { variants: a } : {}
8897
9006
  };
8898
9007
  }
8899
- return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, Bi(t)]));
9008
+ return Object.fromEntries(Object.entries(e).map(([e, t]) => [e, Hi(t)]));
8900
9009
  }
8901
- async function Vi(e, t) {
9010
+ async function Ui(e, t) {
8902
9011
  if (typeof t == "string") {
8903
9012
  if (!t.includes("#node:") && !t.includes("data-node-id") && !t.includes("#asset:") && !t.includes("data-asset-id")) return t;
8904
9013
  let n = /* @__PURE__ */ new Set();
@@ -8915,7 +9024,7 @@ async function Vi(e, t) {
8915
9024
  let t = n[1], r = t.match(/data-node-id=["']([^"']+)["']/i), i = t.match(/data-tree-id=["']([^"']+)["']/i);
8916
9025
  if (!r || !i) continue;
8917
9026
  let a = await e.prepare("SELECT id as treeNodeId FROM tree_nodes WHERE contentId = ? AND treeId = ? LIMIT 1").get(r[1], i[1]);
8918
- a?.treeNodeId && u.set(`${r[1]}:${i[1]}`, await Wi(e, String(a.treeNodeId), i[1]));
9027
+ a?.treeNodeId && u.set(`${r[1]}:${i[1]}`, await Ki(e, String(a.treeNodeId), i[1]));
8919
9028
  }
8920
9029
  return t.replace(d, (e, t) => {
8921
9030
  let n = t.match(/data-node-id=["']([^"']+)["']/i), r = t.match(/data-asset-id=["']([^"']+)["']/i), i = t.match(/href=["']([^"']+)["']/i);
@@ -8930,18 +9039,18 @@ async function Vi(e, t) {
8930
9039
  return i ? `<a${t.replace(/href=["'][^"']*["']/i, `href="${g || "/"}"`)}>` : e;
8931
9040
  });
8932
9041
  }
8933
- if (Array.isArray(t)) return Promise.all(t.map((t) => Vi(e, t)));
9042
+ if (Array.isArray(t)) return Promise.all(t.map((t) => Ui(e, t)));
8934
9043
  if (t && typeof t == "object") {
8935
9044
  if (typeof t.href == "string" && (t.href.startsWith("#node:") || t.href.startsWith("#asset:"))) return {
8936
9045
  ...t,
8937
- href: await Hi(e, t)
9046
+ href: await Wi(e, t)
8938
9047
  };
8939
- let n = await Promise.all(Object.entries(t).map(async ([t, n]) => [t, await Vi(e, n)]));
9048
+ let n = await Promise.all(Object.entries(t).map(async ([t, n]) => [t, await Ui(e, n)]));
8940
9049
  return Object.fromEntries(n);
8941
9050
  }
8942
9051
  return t;
8943
9052
  }
8944
- async function Hi(e, t) {
9053
+ async function Wi(e, t) {
8945
9054
  let n = t.href.match(/^#node:(.+)$/), r = t.href.match(/^#asset:(.+)$/);
8946
9055
  if (r) {
8947
9056
  let t = await e.prepare("SELECT cdnUrl, storageKeyPrivate FROM assets WHERE id = ?").get(r[1]);
@@ -8952,14 +9061,14 @@ async function Hi(e, t) {
8952
9061
  if (t.treeId) {
8953
9062
  let n = await e.prepare("SELECT id as treeNodeId FROM tree_nodes WHERE contentId = ? AND treeId = ? LIMIT 1").get(i, t.treeId);
8954
9063
  if (n?.treeNodeId) {
8955
- let r = await Wi(e, String(n.treeNodeId), String(t.treeId));
9064
+ let r = await Ki(e, String(n.treeNodeId), String(t.treeId));
8956
9065
  if (r) return r;
8957
9066
  }
8958
9067
  }
8959
9068
  let a = await e.prepare("SELECT slug FROM content_nodes WHERE id = ?").get(i);
8960
9069
  return a?.slug ? `/${String(a.slug).replace(/^\/+|\/+$/g, "")}` : "#";
8961
9070
  }
8962
- function Ui(e) {
9071
+ function Gi(e) {
8963
9072
  let t = e.socialImage;
8964
9073
  if (!t || typeof t != "object") return null;
8965
9074
  let n = (e, t) => {
@@ -8990,7 +9099,7 @@ function Ui(e) {
8990
9099
  ])
8991
9100
  };
8992
9101
  }
8993
- async function Wi(e, t, n) {
9102
+ async function Ki(e, t, n) {
8994
9103
  if (!t) return "";
8995
9104
  let r = await e.prepare("\n WITH RECURSIVE ancestor_path(id, parentId, slug, level) AS (\n SELECT t.id, t.parentId, c.slug, 0\n FROM tree_nodes t\n INNER JOIN content_nodes c ON t.contentId = c.id\n WHERE t.id = ? AND t.treeId = ?\n UNION ALL\n SELECT t.id, t.parentId, c.slug, 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 WHERE t.treeId = ?\n )\n SELECT slug FROM ancestor_path ORDER BY level DESC\n ").all(t, n, n), i = Array.isArray(r) ? r : r?.results || [], a = [];
8996
9105
  for (let e of i) {
@@ -8999,7 +9108,7 @@ async function Wi(e, t, n) {
8999
9108
  }
9000
9109
  return "/" + a.join("/");
9001
9110
  }
9002
- async function Gi(e, t, n, r, i) {
9111
+ async function qi(e, t, n, r, i) {
9003
9112
  let a = {}, o = null;
9004
9113
  if (t) {
9005
9114
  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\n FROM tree_nodes t\n INNER JOIN content_nodes c ON t.contentId = c.id\n WHERE t.id = ? OR c.id = ?\n UNION ALL\n SELECT t.id, t.contentId, c.title, c.slug, t.parentId, 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 c.dataJson, c.draftDataJson \n FROM ancestor_path ap\n INNER JOIN content_nodes c ON ap.contentId = c.id\n ORDER BY ap.level ASC\n ").all(t, t), i = Array.isArray(n) ? n : n?.results || [], s = /* @__PURE__ */ new Set([
@@ -9037,7 +9146,7 @@ async function Gi(e, t, n, r, i) {
9037
9146
  inheritedFields: a
9038
9147
  };
9039
9148
  }
9040
- Pi.get("/*", async (e) => {
9149
+ Ii.get("/*", async (e) => {
9041
9150
  try {
9042
9151
  let t = e.get("db"), n = new URL(e.req.url).pathname.match(/\/node\/(.+)$/), r = (n ? n[1] : "home").replace(/^\/+|\/+$/g, ""), i = e.req.query("channelId") || e.req.query("channel") || "1", a = e.req.query("lang") || "en", o = e.req.query("preview") === "true", s = isNaN(Number(i)) ? await t.prepare("SELECT * FROM channels WHERE key = ?").get(i) : await t.prepare("SELECT * FROM channels WHERE id = ?").get(Number(i));
9043
9152
  if (!s) return e.json({ error: `Channel '${i}' not found` }, 404);
@@ -9048,7 +9157,7 @@ Pi.get("/*", async (e) => {
9048
9157
  let t = await d.get(f);
9049
9158
  if (t) return e.header("X-Cache", "HIT"), e.json(t);
9050
9159
  }
9051
- let p = li(e.env?.BUNDLED_DEFINITIONS), m = !isNaN(Number(r)) && r.length > 0, h = null, g = null, _ = e.req.query("treeId");
9160
+ let p = ui(e.env?.BUNDLED_DEFINITIONS), m = !isNaN(Number(r)) && r.length > 0, h = null, g = null, _ = e.req.query("treeId");
9052
9161
  if (m) h = l === null ? await t.prepare("SELECT * FROM content_nodes WHERE id = ?").get(Number(r)) : await t.prepare("\n SELECT cn.* \n FROM content_nodes cn\n INNER JOIN node_channels nc ON cn.id = nc.nodeId\n WHERE cn.id = ? AND nc.channelId = ?\n ").get(Number(r), l);
9053
9162
  else {
9054
9163
  let e = r.split("/"), n = e[e.length - 1], i = "/" + r.replace(/^\/+|\/+$/g, ""), a = `
@@ -9059,7 +9168,7 @@ Pi.get("/*", async (e) => {
9059
9168
  WHERE cn.slug = ? ${l === null ? "" : "AND nc.channelId = ?"}
9060
9169
  `, o = l === null ? [n] : [n, l], s = await t.prepare(a).all(...o), c = Array.isArray(s) ? s : s?.results || [];
9061
9170
  if (c.length > 0) for (let e of c) {
9062
- let n = (await Wi(t, e.treeNodeId, e.treeId)).replace(/^\/+|\/+$/g, ""), r = i.replace(/^\/+|\/+$/g, "");
9171
+ let n = (await Ki(t, e.treeNodeId, e.treeId)).replace(/^\/+|\/+$/g, ""), r = i.replace(/^\/+|\/+$/g, "");
9063
9172
  if (n === r || r === "home" && (n === "" || n === "home")) {
9064
9173
  h = e, g = e;
9065
9174
  break;
@@ -9077,7 +9186,7 @@ Pi.get("/*", async (e) => {
9077
9186
  LIMIT 1
9078
9187
  `).get(...e);
9079
9188
  }
9080
- let v = g?.treeId || _ || "main-nav", y = g?.parentId || null, b = g?.treeNodeId ? await Wi(t, g.treeNodeId, v) : `/${(h.slug || "").replace(/^\/+|\/+$/g, "")}`, x = {
9189
+ let v = g?.treeId || _ || "main-nav", y = g?.parentId || null, b = g?.treeNodeId ? await Ki(t, g.treeNodeId, v) : `/${(h.slug || "").replace(/^\/+|\/+$/g, "")}`, x = {
9081
9190
  id: h.id,
9082
9191
  title: h.title,
9083
9192
  slug: h.slug,
@@ -9095,13 +9204,13 @@ Pi.get("/*", async (e) => {
9095
9204
  k = typeof A == "string" ? JSON.parse(A) : A;
9096
9205
  } catch {}
9097
9206
  k.disabledRegions && (T = k.disabledRegions), O = k.hidden === !0 || k.hidden === 1 || k.hidden === "1" || k.hidden === "true", E = k.startShowingAt || null, D = k.stopShowingAt || null;
9098
- let j = k.layoutId, ee = j && j !== "inherit", { resolvedLayoutId: te, inheritedFields: ne } = await Gi(t, y, v, o, w), re = ee ? j : te || C.defaultLayout || null;
9207
+ let j = k.layoutId, ee = j && j !== "inherit", { resolvedLayoutId: te, inheritedFields: ne } = await qi(t, y, v, o, w), re = ee ? j : te || C.defaultLayout || null;
9099
9208
  for (let [e, t] of Object.entries(ne)) (k[e] === void 0 || k[e] === null || k[e] === "" || k[e] === "inherit") && t !== void 0 && (k[e] = t);
9100
- let M = await oi(t, zi(k, w));
9101
- M = await Ii(t, M), M = Bi(M), M = await Vi(t, M);
9102
- let ie = Ui(M);
9209
+ let M = await si(t, Vi(k, w));
9210
+ M = await Ri(t, M), M = Hi(M), M = await Ui(t, M);
9211
+ let ie = Gi(M);
9103
9212
  delete M.socialImage, delete M.fbImage, delete M.xImage, delete M.whatsappImage, ie && (M.socialImages = ie), x.slug = h.slug, x.title = h.title, Object.assign(x, M), x.layoutId = re;
9104
- let ae = !!h.isHidden || O, oe = !Fi(E, D);
9213
+ let ae = !!h.isHidden || O, oe = !Li(E, D);
9105
9214
  if (!o && (ae || oe)) return e.json({ error: "Node is hidden or outside its scheduled publishing window" }, 404);
9106
9215
  let se = [];
9107
9216
  if (g?.treeNodeId) {
@@ -9111,7 +9220,7 @@ Pi.get("/*", async (e) => {
9111
9220
  try {
9112
9221
  t = (typeof n == "string" ? JSON.parse(n) : n) || {};
9113
9222
  } catch {}
9114
- let i = !!e.isHidden || t.hidden === !0 || t.hidden === 1 || t.hidden === "1", a = Fi(t.startShowingAt, t.stopShowingAt), s = (e.slug || "").replace(/^\/+|\/+$/g, "");
9223
+ let i = !!e.isHidden || t.hidden === !0 || t.hidden === 1 || t.hidden === "1", a = Li(t.startShowingAt, t.stopShowingAt), s = (e.slug || "").replace(/^\/+|\/+$/g, "");
9115
9224
  return !o && (i || !a) ? null : {
9116
9225
  treeNodeId: e.treeNodeId,
9117
9226
  id: e.id,
@@ -9134,10 +9243,10 @@ Pi.get("/*", async (e) => {
9134
9243
  try {
9135
9244
  r = (typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson) || {};
9136
9245
  } catch {}
9137
- let i = r.hidden === !0 || r.hidden === 1 || r.hidden === "1" || r.hidden === "true", a = Fi(r.startShowingAt, r.stopShowingAt);
9246
+ let i = r.hidden === !0 || r.hidden === 1 || r.hidden === "1" || r.hidden === "true", a = Li(r.startShowingAt, r.stopShowingAt);
9138
9247
  if (!o && (i || !a)) continue;
9139
- let s = e.elementType || e.componentId || "text-block", c = p.blocks?.[s]?.fields || p.elements?.[s]?.fields || p.components?.[s]?.fields || {}, l = String(r.blockId || r._instanceId || r.id || e.blockId || e.id), u = zi(r, c);
9140
- u = await oi(t, u), u = Bi(u), u = await Vi(t, u), u.blockId = l, P[n].push({
9248
+ let s = e.elementType || e.componentId || "text-block", c = p.blocks?.[s]?.fields || p.elements?.[s]?.fields || p.components?.[s]?.fields || {}, l = String(r.blockId || r._instanceId || r.id || e.blockId || e.id), u = Vi(r, c);
9249
+ u = await si(t, u), u = Hi(u), u = await Ui(t, u), u.blockId = l, P[n].push({
9141
9250
  instanceId: e.id,
9142
9251
  blockId: l,
9143
9252
  componentId: s,
@@ -9158,7 +9267,7 @@ Pi.get("/*", async (e) => {
9158
9267
  for (let [e, n] of Object.entries(ue)) {
9159
9268
  let r = P[e] && P[e].length > 0, i = !!T[e];
9160
9269
  if (P[e] || (P[e] = [], F[e] = { isInherited: !1 }), (n?.inherit === "parent" || n?.inherit === !0 || n?.inherit === "true" || e === "header" || e === "footer") && !r && !i && y) {
9161
- let n = await Ri(t, y, e, p, o);
9270
+ let n = await Bi(t, y, e, p, o);
9162
9271
  if (n.blocks.length > 0 && (P[e] = n.blocks, F[e] = {
9163
9272
  isInherited: !0,
9164
9273
  inheritedFromId: n.inheritedFromId,
@@ -9170,7 +9279,7 @@ Pi.get("/*", async (e) => {
9170
9279
  });
9171
9280
  }
9172
9281
  }
9173
- for (let e of Object.keys(P)) await Li(t, P[e], l);
9282
+ for (let e of Object.keys(P)) await zi(t, P[e], l);
9174
9283
  let de = {
9175
9284
  channelId: l || u,
9176
9285
  treeId: v,
@@ -9189,8 +9298,8 @@ Pi.get("/*", async (e) => {
9189
9298
  });
9190
9299
  //#endregion
9191
9300
  //#region server/routes/public/tree.ts
9192
- var Ki = new e();
9193
- function qi(e, t) {
9301
+ var Ji = new e();
9302
+ function Yi(e, t) {
9194
9303
  let n = /* @__PURE__ */ new Date();
9195
9304
  if (e && String(e).trim() !== "") {
9196
9305
  let t = new Date(e);
@@ -9202,7 +9311,7 @@ function qi(e, t) {
9202
9311
  }
9203
9312
  return !0;
9204
9313
  }
9205
- Ki.get("/:treeParam", async (e) => {
9314
+ Ji.get("/:treeParam", async (e) => {
9206
9315
  try {
9207
9316
  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";
9208
9317
  if (r && r !== "default" && r !== "all") {
@@ -9221,7 +9330,7 @@ Ki.get("/:treeParam", async (e) => {
9221
9330
  if (c && c.isHidden && !i) return e.json({ error: `Tree '${n}' is hidden` }, 404);
9222
9331
  let l = c?.id || (s ? Number(n) : null), u = {};
9223
9332
  if (c && c.dataJson) try {
9224
- let t = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson, r = e.env?.BUNDLED_DEFINITIONS, i = li(r), a = (i.trees?.[c.treeType || n] || i.trees?.site || {}).fields || {};
9333
+ let t = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson, r = e.env?.BUNDLED_DEFINITIONS, i = ui(r), a = (i.trees?.[c.treeType || n] || i.trees?.site || {}).fields || {};
9225
9334
  for (let [e, n] of Object.entries(t)) a[e]?.public === !0 && (u[e] = n);
9226
9335
  } catch (e) {
9227
9336
  console.warn("[CMS Public Tree API] Failed to parse tree dataJson", e);
@@ -9241,7 +9350,7 @@ Ki.get("/:treeParam", async (e) => {
9241
9350
  if (r) try {
9242
9351
  n = typeof r == "string" ? JSON.parse(r) : r, delete n._isTreeDraft, delete n._draftParentId, delete n.isNew, delete n.hidden, delete n.is_hidden, delete n.isHidden, delete n.status;
9243
9352
  } catch {}
9244
- let a = !i && (e.status === "draft" || e.status === "new"), o = !!e.isHidden || a || n.hidden === !0 || n.hidden === 1 || n.hidden === "1" || n.hidden === "true", s = qi(n.startShowingAt, n.stopShowingAt), c = (e.slug || "").replace(/^\/+|\/+$/g, ""), l = c === "home" || c === "homee" ? "/" : `${t}/${c}`.replace(/\/+/g, "/"), u = {
9353
+ let a = !i && (e.status === "draft" || e.status === "new"), o = !!e.isHidden || a || n.hidden === !0 || n.hidden === 1 || n.hidden === "1" || n.hidden === "true", s = Yi(n.startShowingAt, n.stopShowingAt), c = (e.slug || "").replace(/^\/+|\/+$/g, ""), l = c === "home" || c === "homee" ? "/" : `${t}/${c}`.replace(/\/+/g, "/"), u = {
9245
9354
  id: e.id,
9246
9355
  treeNodeId: e.treeNodeId,
9247
9356
  parentId: e.parentId || null,
@@ -9276,8 +9385,8 @@ Ki.get("/:treeParam", async (e) => {
9276
9385
  });
9277
9386
  //#endregion
9278
9387
  //#region server/routes/public/assets.ts
9279
- var Ji = new e();
9280
- function Yi(e, t) {
9388
+ var Xi = new e();
9389
+ function Zi(e, t) {
9281
9390
  if (t === "webp") return "image/webp";
9282
9391
  if (t === "avif") return "image/avif";
9283
9392
  if (t === "jpeg" || t === "jpg") return "image/jpeg";
@@ -9285,7 +9394,7 @@ function Yi(e, t) {
9285
9394
  let n = e.toLowerCase();
9286
9395
  return n.endsWith(".jpg") || n.endsWith(".jpeg") ? "image/jpeg" : n.endsWith(".png") ? "image/png" : n.endsWith(".webp") ? "image/webp" : n.endsWith(".gif") ? "image/gif" : n.endsWith(".svg") ? "image/svg+xml" : n.endsWith(".pdf") ? "application/pdf" : n.endsWith(".mp4") ? "video/mp4" : n.endsWith(".webm") ? "video/webm" : "application/octet-stream";
9287
9396
  }
9288
- Ji.get("/*", async (e) => {
9397
+ Xi.get("/*", async (e) => {
9289
9398
  let t = e.req.path.replace(/^\/media\//, "").replace(/^\//, "");
9290
9399
  if (!t) return e.text("Asset key missing", 400);
9291
9400
  let n = e.env?.MEDIA_BUCKET, { w: r, h: i, q: a, f: o } = e.req.query(), s = !!(r || i || a || o), c = e.req.header("Via")?.includes("image-resizing") || e.req.header("User-Agent")?.includes("Cloudflare-ImgRen");
@@ -9331,7 +9440,7 @@ Ji.get("/*", async (e) => {
9331
9440
  if (!s) {
9332
9441
  let n = u(g);
9333
9442
  return e.body(n, 200, {
9334
- "Content-Type": Yi(t),
9443
+ "Content-Type": Zi(t),
9335
9444
  "Cache-Control": "public, max-age=86400"
9336
9445
  });
9337
9446
  }
@@ -9339,7 +9448,7 @@ Ji.get("/*", async (e) => {
9339
9448
  if (l(b)) {
9340
9449
  let n = u(b);
9341
9450
  return e.body(n, 200, {
9342
- "Content-Type": Yi(t, v),
9451
+ "Content-Type": Zi(t, v),
9343
9452
  "Cache-Control": "public, max-age=31536000, immutable",
9344
9453
  "X-Local-Cache": "HIT"
9345
9454
  });
@@ -9352,14 +9461,14 @@ Ji.get("/*", async (e) => {
9352
9461
  typeof n == "number" && (a.width = n), typeof c == "number" && (a.height = c), (a.width || a.height) && (a.fit = "cover", i = i.resize(a)), v === "webp" ? i = i.webp({ quality: typeof _ == "number" ? _ : 80 }) : v === "avif" ? i = i.avif({ quality: typeof _ == "number" ? _ : 70 }) : v === "jpeg" || v === "jpg" ? i = i.jpeg({ quality: typeof _ == "number" ? _ : 80 }) : v === "png" && (i = i.png({ quality: typeof _ == "number" ? _ : 80 }));
9353
9462
  let o = await i.toBuffer();
9354
9463
  return d(m(b), { recursive: !0 }), f(b, o), e.body(o, 200, {
9355
- "Content-Type": Yi(t, v),
9464
+ "Content-Type": Zi(t, v),
9356
9465
  "Cache-Control": "public, max-age=31536000, immutable",
9357
9466
  "X-Local-Cache": "MISS"
9358
9467
  });
9359
9468
  } catch {
9360
9469
  let n = u(g);
9361
9470
  return e.body(n, 200, {
9362
- "Content-Type": Yi(t),
9471
+ "Content-Type": Zi(t),
9363
9472
  "Cache-Control": "public, max-age=86400"
9364
9473
  });
9365
9474
  }
@@ -9370,8 +9479,8 @@ Ji.get("/*", async (e) => {
9370
9479
  });
9371
9480
  //#endregion
9372
9481
  //#region server/routes/public/paths.ts
9373
- var Xi = new e();
9374
- function Zi(e, t) {
9482
+ var Qi = new e();
9483
+ function $i(e, t) {
9375
9484
  let n = /* @__PURE__ */ new Date();
9376
9485
  if (e && String(e).trim() !== "") {
9377
9486
  let t = new Date(e);
@@ -9383,7 +9492,7 @@ function Zi(e, t) {
9383
9492
  }
9384
9493
  return !0;
9385
9494
  }
9386
- Xi.get("/", async (e) => {
9495
+ Qi.get("/", async (e) => {
9387
9496
  try {
9388
9497
  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 ").all(), n = Array.isArray(t) ? t : t?.results || [], r = [];
9389
9498
  function i(e = null, t = "") {
@@ -9396,7 +9505,7 @@ Xi.get("/", async (e) => {
9396
9505
  if (e.dataJson) try {
9397
9506
  n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
9398
9507
  } catch {}
9399
- let a = e.status === "published" || e.status === "active", o = Zi(n.startShowingAt, n.stopShowingAt);
9508
+ let a = e.status === "published" || e.status === "active", o = $i(n.startShowingAt, n.stopShowingAt);
9400
9509
  if (!a || !o) continue;
9401
9510
  let s = (e.slug || "").replace(/^\/+|\/+$/g, ""), c = s === "home" || s === "homee" ? "/" : `${t}/${s}`.replace(/\/+/g, "/");
9402
9511
  e.nodeType !== "external-link" && r.push(c);
@@ -9413,7 +9522,7 @@ Xi.get("/", async (e) => {
9413
9522
  });
9414
9523
  //#endregion
9415
9524
  //#region server/index.ts
9416
- var $ = new e(), Qi = !1;
9525
+ var $ = new e(), ea = !1;
9417
9526
  $.use("*", o()), $.use("/media/*", o({
9418
9527
  origin: "*",
9419
9528
  allowMethods: [
@@ -9434,13 +9543,13 @@ $.use("*", o()), $.use("/media/*", o({
9434
9543
  let n = new URL(e.req.url), r = (e.req.header("host") || n.hostname).split(":")[0];
9435
9544
  e.set("currentDomain", r);
9436
9545
  let i = u(e);
9437
- if (e.set("db", i), !Qi) try {
9438
- await Pr(i), Qi = !0;
9546
+ if (e.set("db", i), !ea) try {
9547
+ await Pr(i), ea = !0;
9439
9548
  } catch (e) {
9440
9549
  console.error("❌ [CMS Server] Failed to initialize system tables on cold start:", e);
9441
9550
  }
9442
9551
  await t();
9443
- }), $.route("/media", Ji), $.use("/media/*", Lr()), $.route("/api/cms/nodes", X), $.route("/api/cms/nodes.json", X), $.route("/api/cms/formcsv", X), $.route("/api/cms/formcsv.json", X), $.route("/api/cms/stats", ji), $.route("/api/cms/stats.json", ji), $.route("/api/cms", bi), $.route("/api/cms/channels", wi), $.route("/api/cms/channels.json", wi), $.route("/api/cms/schemas", Ti), $.route("/api/cms/schemas.json", Ti), $.route("/api/cms", Oi), $.route("/api/admin/assets", Z), $.route("/api/v1/node", Pi), $.route("/api/v1/page", Pi), $.route("/api/v1/tree", Ki), $.route("/api/v1/all-paths", Xi), $.get("*", async (e) => {
9552
+ }), $.route("/media", Xi), $.use("/media/*", Lr()), $.route("/api/cms/nodes", X), $.route("/api/cms/nodes.json", X), $.route("/api/cms/formcsv", X), $.route("/api/cms/formcsv.json", X), $.route("/api/cms/stats", Mi), $.route("/api/cms/stats.json", Mi), $.route("/api/cms", xi), $.route("/api/cms/channels", Ti), $.route("/api/cms/channels.json", Ti), $.route("/api/cms/schemas", Ei), $.route("/api/cms/schemas.json", Ei), $.route("/api/cms", ki), $.route("/api/admin/assets", Z), $.route("/api/v1/node", Ii), $.route("/api/v1/page", Ii), $.route("/api/v1/tree", Ji), $.route("/api/v1/all-paths", Qi), $.get("*", async (e) => {
9444
9553
  if (e.env?.ASSETS) {
9445
9554
  let t = await e.env.ASSETS.fetch(e.req.raw);
9446
9555
  if (t.status === 404) {