@brightsideoy/kama 0.1.0-alpha.1

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 (3) hide show
  1. package/README.md +0 -0
  2. package/dist/index.js +2872 -0
  3. package/package.json +70 -0
package/dist/index.js ADDED
@@ -0,0 +1,2872 @@
1
+ import { serve as e } from "@hono/node-server";
2
+ import { Hono as t } from "hono";
3
+ import n from "yaml";
4
+ import r, { createReadStream as i, existsSync as a, mkdirSync as o, readFileSync as s, statSync as c, writeFileSync as l } from "node:fs";
5
+ import u, { dirname as d, join as f } from "node:path";
6
+ import { LRUCache as p } from "lru-cache";
7
+ //#region \0rolldown/runtime.js
8
+ var m = Object.create, h = Object.defineProperty, g = Object.getOwnPropertyDescriptor, _ = Object.getOwnPropertyNames, v = Object.getPrototypeOf, y = Object.prototype.hasOwnProperty, b = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t.exports), x = (e, t, n, r) => {
9
+ if (t && typeof t == "object" || typeof t == "function") for (var i = _(t), a = 0, o = i.length, s; a < o; a++) s = i[a], !y.call(e, s) && s !== n && h(e, s, {
10
+ get: ((e) => t[e]).bind(null, s),
11
+ enumerable: !(r = g(t, s)) || r.enumerable
12
+ });
13
+ return e;
14
+ }, S = (e, t, n) => (n = e == null ? {} : m(v(e)), x(t || !e || !e.__esModule || !y.call(e, "default") ? h(n, "default", {
15
+ value: e,
16
+ enumerable: !0
17
+ }) : n, e)), C = (e) => {
18
+ let t = {
19
+ origin: "*",
20
+ allowMethods: [
21
+ "GET",
22
+ "HEAD",
23
+ "PUT",
24
+ "POST",
25
+ "DELETE",
26
+ "PATCH",
27
+ "QUERY"
28
+ ],
29
+ allowHeaders: [],
30
+ exposeHeaders: [],
31
+ ...e
32
+ }, n = t.exposeHeaders?.length ? t.exposeHeaders.join(",") : void 0, r = t.allowHeaders?.length ? t.allowHeaders.join(",") : void 0, i = ((e) => typeof e == "string" ? e === "*" ? () => e : (t) => e === t ? t : null : typeof e == "function" ? e : (t) => e.includes(t) ? t : null)(t.origin), a = ((e) => {
33
+ if (typeof e == "function") return async (t, n) => (await e(t, n)).join(",");
34
+ if (Array.isArray(e)) {
35
+ let t = e.join(",");
36
+ return () => t;
37
+ }
38
+ return () => "";
39
+ })(t.allowMethods);
40
+ return async function(e, o) {
41
+ function s(t, n) {
42
+ e.res.headers.set(t, n);
43
+ }
44
+ let c = await i(e.req.header("origin") || "", e);
45
+ if (c && s("Access-Control-Allow-Origin", c), t.credentials && s("Access-Control-Allow-Credentials", "true"), n && s("Access-Control-Expose-Headers", n), e.req.method === "OPTIONS") {
46
+ t.origin !== "*" && s("Vary", "Origin"), t.maxAge != null && s("Access-Control-Max-Age", t.maxAge.toString());
47
+ let n = await a(e.req.header("origin") || "", e);
48
+ n && s("Access-Control-Allow-Methods", n);
49
+ let i = r;
50
+ if (!i) {
51
+ let t = e.req.header("Access-Control-Request-Headers");
52
+ t && (i = t.split(",").map((e) => e.trim()).join(","));
53
+ }
54
+ return i && (s("Access-Control-Allow-Headers", i), e.res.headers.append("Vary", "Access-Control-Request-Headers")), e.res.headers.delete("Content-Length"), e.res.headers.delete("Content-Type"), new Response(null, {
55
+ headers: e.res.headers,
56
+ status: 204,
57
+ statusText: "No Content"
58
+ });
59
+ }
60
+ await o(), t.origin !== "*" && e.header("Vary", "Origin", { append: !0 });
61
+ };
62
+ }, w = /* @__PURE__ */ b(((e, t) => {
63
+ t.exports = {};
64
+ })), T = w(), E = null;
65
+ function D() {
66
+ if (!E) {
67
+ let e = (0, T.createRequire)(import.meta.url), t = e("better-sqlite3"), n = e("node:path"), r = e("node:fs"), i = n.resolve(process.cwd(), "./data/cms.db");
68
+ r.mkdirSync(n.dirname(i), { recursive: !0 }), E = new t(i), E.pragma("journal_mode = WAL");
69
+ }
70
+ return E;
71
+ }
72
+ function O(e) {
73
+ let t = e?.env?.kama_db || e?.env?.DB;
74
+ if (t) return {
75
+ prepare(e) {
76
+ return {
77
+ async get(...n) {
78
+ return await t.prepare(e).bind(...n).first();
79
+ },
80
+ async all(...n) {
81
+ let { results: r } = await t.prepare(e).bind(...n).all();
82
+ return r || [];
83
+ },
84
+ async run(...n) {
85
+ let r = await t.prepare(e).bind(...n).run();
86
+ return {
87
+ lastInsertRowid: r.meta?.last_row_id,
88
+ changes: r.meta?.changes
89
+ };
90
+ }
91
+ };
92
+ },
93
+ async exec(e) {
94
+ await t.exec(e);
95
+ },
96
+ transaction(e) {
97
+ return (...t) => e(...t);
98
+ }
99
+ };
100
+ let n = D();
101
+ return {
102
+ prepare(e) {
103
+ let t = n.prepare(e);
104
+ return {
105
+ get(...e) {
106
+ return t.get(...e);
107
+ },
108
+ all(...e) {
109
+ return t.all(...e);
110
+ },
111
+ run(...e) {
112
+ let n = t.run(...e);
113
+ return {
114
+ lastInsertRowid: n.lastInsertRowid,
115
+ changes: n.changes
116
+ };
117
+ }
118
+ };
119
+ },
120
+ exec(e) {
121
+ n.exec(e);
122
+ },
123
+ transaction(e) {
124
+ let t = n.transaction(e);
125
+ return (...e) => t(...e);
126
+ }
127
+ };
128
+ }
129
+ //#endregion
130
+ //#region server/db/dynamic-sync.ts
131
+ async function k(e, t) {
132
+ try {
133
+ let n = await e.prepare(`PRAGMA table_info("${t}")`).all(), r = Array.isArray(n) ? n : n?.results || [];
134
+ return new Set(r.map((e) => e.name));
135
+ } catch {
136
+ return /* @__PURE__ */ new Set();
137
+ }
138
+ }
139
+ var A = {
140
+ 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 ",
141
+ 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 ",
142
+ 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 ",
143
+ 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 ",
144
+ 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 ",
145
+ 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 ",
146
+ 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 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 ",
147
+ 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 ",
148
+ 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 ",
149
+ 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 ",
150
+ node_revisions: "\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n nodeId INTEGER NOT NULL,\n version INTEGER NOT NULL DEFAULT 1,\n snapshotJson TEXT NOT NULL,\n createdById TEXT,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n FOREIGN KEY (nodeId) REFERENCES content_nodes(id) ON DELETE CASCADE,\n FOREIGN KEY (createdById) REFERENCES users(id) ON DELETE SET NULL\n ",
151
+ assets: "\n id TEXT PRIMARY KEY,\n filename TEXT NOT NULL,\n mimeType TEXT NOT NULL,\n sizeBytes INTEGER NOT NULL,\n storageKeyPrivate TEXT,\n cdnUrl TEXT,\n parentAssetId TEXT,\n cropCoordinatesJson TEXT,\n isSystemVariant INTEGER DEFAULT 0,\n dataJson TEXT DEFAULT '{}',\n createdById TEXT,\n createdAt TEXT DEFAULT CURRENT_TIMESTAMP,\n updatedAt TEXT DEFAULT CURRENT_TIMESTAMP,\n deletedAt TEXT,\n FOREIGN KEY (parentAssetId) REFERENCES assets(id) ON DELETE SET NULL,\n FOREIGN KEY (createdById) REFERENCES users(id) ON DELETE SET NULL\n ",
152
+ node_assets: "\n nodeId INTEGER NOT NULL,\n assetId TEXT NOT NULL,\n fieldKey TEXT NOT NULL,\n sortOrder INTEGER DEFAULT 0,\n PRIMARY KEY (nodeId, assetId, fieldKey),\n FOREIGN KEY (nodeId) REFERENCES content_nodes(id) ON DELETE CASCADE,\n FOREIGN KEY (assetId) REFERENCES assets(id) ON DELETE CASCADE\n "
153
+ }, j = [
154
+ "CREATE INDEX IF NOT EXISTS idx_sessions_user ON sessions(userId);",
155
+ "CREATE INDEX IF NOT EXISTS idx_sessions_expires ON sessions(expiresAt);",
156
+ "CREATE INDEX IF NOT EXISTS idx_channels_visibility ON channels(isHidden);",
157
+ "CREATE INDEX IF NOT EXISTS idx_trees_visibility ON trees(isHidden);",
158
+ "CREATE INDEX IF NOT EXISTS idx_content_nodes_visibility ON content_nodes(isHidden, status);",
159
+ "CREATE INDEX IF NOT EXISTS idx_content_nodes_slug ON content_nodes(slug);",
160
+ "CREATE INDEX IF NOT EXISTS idx_content_nodes_type ON content_nodes(contentType);",
161
+ "CREATE INDEX IF NOT EXISTS idx_content_nodes_deleted_updated ON content_nodes(deletedAt, updatedAt DESC);",
162
+ "CREATE INDEX IF NOT EXISTS idx_tree_nodes_hierarchy ON tree_nodes(treeId, parentId, sortOrder);",
163
+ "CREATE INDEX IF NOT EXISTS idx_tree_nodes_content ON tree_nodes(contentId, treeId);",
164
+ "CREATE INDEX IF NOT EXISTS idx_content_blocks_content ON content_blocks(contentId, isDraft, region, sortOrder);",
165
+ "CREATE INDEX IF NOT EXISTS idx_node_channels_channel ON node_channels(channelId, nodeId);",
166
+ "CREATE INDEX IF NOT EXISTS idx_node_channels_node ON node_channels(nodeId, channelId);",
167
+ "CREATE INDEX IF NOT EXISTS idx_node_assets_node_asset ON node_assets(nodeId, assetId);",
168
+ "CREATE INDEX IF NOT EXISTS idx_node_assets_asset_node ON node_assets(assetId, nodeId);",
169
+ "CREATE INDEX IF NOT EXISTS idx_node_revisions_node ON node_revisions(nodeId, version);",
170
+ "CREATE INDEX IF NOT EXISTS idx_assets_system_created ON assets(isSystemVariant, createdAt DESC);",
171
+ "CREATE INDEX IF NOT EXISTS idx_assets_system_mime ON assets(isSystemVariant, mimeType);",
172
+ "CREATE INDEX IF NOT EXISTS idx_assets_deleted ON assets(deletedAt);",
173
+ "CREATE INDEX IF NOT EXISTS idx_assets_parent ON assets(parentAssetId);"
174
+ ];
175
+ async function ee(e) {
176
+ try {
177
+ await e.prepare("PRAGMA foreign_keys = ON;").run();
178
+ } catch {}
179
+ for (let [t, n] of Object.entries(A)) await e.prepare(`CREATE TABLE IF NOT EXISTS "${t}" (${n});`).run();
180
+ for (let [t] of Object.entries(A)) {
181
+ let n = await k(e, t);
182
+ if (n.size > 0) {
183
+ if (t === "content_nodes" && !n.has("disabledRegionsJson")) try {
184
+ await e.prepare("ALTER TABLE \"content_nodes\" ADD COLUMN disabledRegionsJson TEXT DEFAULT '{}';").run();
185
+ } catch {}
186
+ if (t === "assets") {
187
+ if (!n.has("parentAssetId")) try {
188
+ await e.prepare("ALTER TABLE \"assets\" ADD COLUMN parentAssetId TEXT REFERENCES assets(id) ON DELETE SET NULL;").run();
189
+ } catch {}
190
+ if (!n.has("cropCoordinatesJson")) try {
191
+ await e.prepare("ALTER TABLE \"assets\" ADD COLUMN cropCoordinatesJson TEXT;").run();
192
+ } catch {}
193
+ }
194
+ }
195
+ }
196
+ for (let t of j) try {
197
+ await e.prepare(t).run();
198
+ } catch {}
199
+ await te(e);
200
+ }
201
+ async function te(e) {
202
+ try {
203
+ let t = await e.prepare("SELECT COUNT(*) as count FROM channels").get(), n = 1;
204
+ if (!t || t.count === 0) {
205
+ let t = await e.prepare("\n INSERT INTO channels (key, label, channelType, defaultLanguage, isHidden, dataJson)\n VALUES ('default-channel', 'Default Channel', 'website', 'en', 0, '{}')\n ").run();
206
+ n = Number(t?.lastInsertRowid || 1);
207
+ } else {
208
+ let t = await e.prepare("SELECT id FROM channels LIMIT 1").get();
209
+ t && (n = Number(t.id));
210
+ }
211
+ let r = await e.prepare("SELECT COUNT(*) as count FROM trees").get();
212
+ if (!r || r.count === 0) {
213
+ let t = await e.prepare("\n INSERT INTO trees (key, label, treeType, channelId, isHidden, dataJson)\n VALUES ('default-tree', 'Default Navigation', 'navigation', ?, 0, '{}')\n ").run(n), r = Number(t?.lastInsertRowid || 1);
214
+ await e.prepare("\n INSERT OR IGNORE INTO channel_trees (channelId, treeId, key)\n VALUES (?, ?, 'main')\n ").run(n, r);
215
+ }
216
+ } catch (e) {
217
+ console.warn("⚠️ [System Sync] Fallback warning:", e);
218
+ }
219
+ }
220
+ var ne = (() => {
221
+ let [e, t] = T.versions.node.split(".").map((e) => parseInt(e));
222
+ return e >= 23 || e === 22 && t >= 7 || e === 20 && t >= 18;
223
+ })(), M = (e, t = ne) => {
224
+ if (t) return T.Readable.toWeb(e);
225
+ let n, r = !1, i = () => {
226
+ e.off("data", o), e.off("error", s), e.off("end", c), e.off("close", c);
227
+ }, a = (e) => {
228
+ r || (r = !0, i(), e?.());
229
+ }, o = (t) => {
230
+ r || !n || (n.enqueue(t), (n.desiredSize ?? 0) <= 0 && e.pause());
231
+ }, s = (e) => {
232
+ a(() => {
233
+ n?.error(e);
234
+ });
235
+ }, c = () => {
236
+ a(() => {
237
+ n?.close();
238
+ });
239
+ };
240
+ return new ReadableStream({
241
+ start(t) {
242
+ n = t, e.on("data", o), e.on("error", s), e.on("end", c), e.on("close", c), e.pause();
243
+ },
244
+ pull() {
245
+ r || e.resume();
246
+ },
247
+ cancel() {
248
+ a();
249
+ let t = () => {};
250
+ e.on("error", t), e.once("close", () => e.off("error", t)), e.destroy();
251
+ }
252
+ });
253
+ }, N = (e, t = re) => {
254
+ let n = e.match(/\.([a-zA-Z0-9]+?)$/);
255
+ if (n) return t[n[1].toLowerCase()];
256
+ }, re = {
257
+ aac: "audio/aac",
258
+ avi: "video/x-msvideo",
259
+ avif: "image/avif",
260
+ av1: "video/av1",
261
+ bin: "application/octet-stream",
262
+ bmp: "image/bmp",
263
+ css: "text/css; charset=utf-8",
264
+ csv: "text/csv; charset=utf-8",
265
+ eot: "application/vnd.ms-fontobject",
266
+ epub: "application/epub+zip",
267
+ gif: "image/gif",
268
+ gz: "application/gzip",
269
+ htm: "text/html; charset=utf-8",
270
+ html: "text/html; charset=utf-8",
271
+ ico: "image/x-icon",
272
+ ics: "text/calendar; charset=utf-8",
273
+ jpeg: "image/jpeg",
274
+ jpg: "image/jpeg",
275
+ js: "text/javascript; charset=utf-8",
276
+ json: "application/json",
277
+ jsonld: "application/ld+json",
278
+ map: "application/json",
279
+ mid: "audio/x-midi",
280
+ midi: "audio/x-midi",
281
+ mjs: "text/javascript; charset=utf-8",
282
+ mp3: "audio/mpeg",
283
+ mp4: "video/mp4",
284
+ mpeg: "video/mpeg",
285
+ oga: "audio/ogg",
286
+ ogv: "video/ogg",
287
+ ogx: "application/ogg",
288
+ opus: "audio/opus",
289
+ otf: "font/otf",
290
+ pdf: "application/pdf",
291
+ png: "image/png",
292
+ rtf: "application/rtf",
293
+ svg: "image/svg+xml; charset=utf-8",
294
+ tif: "image/tiff",
295
+ tiff: "image/tiff",
296
+ ts: "video/mp2t",
297
+ ttf: "font/ttf",
298
+ txt: "text/plain; charset=utf-8",
299
+ wasm: "application/wasm",
300
+ webm: "video/webm",
301
+ weba: "audio/webm",
302
+ webmanifest: "application/manifest+json",
303
+ webp: "image/webp",
304
+ woff: "font/woff",
305
+ woff2: "font/woff2",
306
+ xhtml: "application/xhtml+xml; charset=utf-8",
307
+ xml: "application/xml; charset=utf-8",
308
+ zip: "application/zip",
309
+ "3gp": "video/3gpp",
310
+ "3g2": "video/3gpp2",
311
+ gltf: "model/gltf+json",
312
+ glb: "model/gltf-binary"
313
+ }, ie = /^\s*(?:text\/[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i, P = {
314
+ br: ".br",
315
+ zstd: ".zst",
316
+ gzip: ".gz"
317
+ }, ae = Object.keys(P), F = (e) => {
318
+ let t;
319
+ try {
320
+ t = c(e);
321
+ } catch {}
322
+ return t;
323
+ }, I = /^(?:bytes=)?(?!-$)(\d*)-(\d*)$/, L = (e) => {
324
+ let t = e.match(I);
325
+ if (!t) return;
326
+ let [, n, r] = t;
327
+ return n === "" ? {
328
+ type: "suffix",
329
+ length: Number(r)
330
+ } : r === "" ? {
331
+ type: "open-ended",
332
+ start: Number(n)
333
+ } : {
334
+ type: "bounded",
335
+ start: Number(n),
336
+ end: Number(r)
337
+ };
338
+ }, R = (e, t) => {
339
+ if (t === 0) return;
340
+ if (e.type === "suffix") return e.length === 0 ? void 0 : {
341
+ start: Math.max(t - e.length, 0),
342
+ end: t - 1
343
+ };
344
+ let n = e.type === "bounded" ? Math.min(e.end, t - 1) : t - 1;
345
+ if (!(e.start >= t || e.start > n)) return {
346
+ start: e.start,
347
+ end: n
348
+ };
349
+ }, oe = (e, t) => {
350
+ try {
351
+ return t(e);
352
+ } catch {
353
+ return e.replace(/(?:%[0-9A-Fa-f]{2})+/g, (e) => {
354
+ try {
355
+ return t(e);
356
+ } catch {
357
+ return e;
358
+ }
359
+ });
360
+ }
361
+ }, se = (e) => oe(e, decodeURI), ce = (e = { root: "" }) => {
362
+ let t = e.root || "", n = e.path;
363
+ return t !== "" && !a(t) && console.error(`serveStatic: root path '${t}' is not found, are you sure it's correct?`), async (r, a) => {
364
+ if (r.finalized) return a();
365
+ let o;
366
+ if (n) o = n;
367
+ else try {
368
+ if (o = se(r.req.path), /(?:^|[\/\\])\.{1,2}(?:$|[\/\\])|[\/\\]{2,}|\\/.test(o)) throw Error();
369
+ } catch {
370
+ return await e.onNotFound?.(r.req.path, r), a();
371
+ }
372
+ let s = f(t, !n && e.rewriteRequestPath ? e.rewriteRequestPath(o, r) : o), c = F(s);
373
+ if (c && c.isDirectory()) {
374
+ let t = e.index ?? "index.html";
375
+ s = f(s, t), c = F(s);
376
+ }
377
+ if (!c) return await e.onNotFound?.(s, r), a();
378
+ let l = N(s);
379
+ if (r.header("Content-Type", l || "application/octet-stream"), e.precompressed && (!l || l === "application/octet-stream" || ie.test(l))) {
380
+ let e = new Set(r.req.header("Accept-Encoding")?.split(",").map((e) => e.trim()));
381
+ for (let t of ae) {
382
+ if (!e.has(t)) continue;
383
+ let n = F(s + P[t]);
384
+ if (n) {
385
+ r.header("Content-Encoding", t), r.header("Vary", "Accept-Encoding", { append: !0 }), c = n, s += P[t];
386
+ break;
387
+ }
388
+ }
389
+ }
390
+ let u, d = c.size, p = r.req.header("range") || "";
391
+ if (r.header("Last-Modified", c.mtime.toUTCString()), r.req.method == "HEAD" || r.req.method == "OPTIONS") r.header("Content-Length", d.toString()), r.status(200), u = r.body(null);
392
+ else if (!p) r.header("Content-Length", d.toString()), u = r.body(M(i(s)), 200);
393
+ else {
394
+ r.header("Accept-Ranges", "bytes");
395
+ let e = R(L(p) ?? {
396
+ type: "open-ended",
397
+ start: 0
398
+ }, d);
399
+ if (!e) r.header("Content-Range", `bytes */${d}`), u = r.body(null, 416);
400
+ else {
401
+ let { start: t, end: n } = e, a = n - t + 1, o = i(s, {
402
+ start: t,
403
+ end: n
404
+ });
405
+ r.header("Content-Length", a.toString()), r.header("Content-Range", `bytes ${t}-${n}/${d}`), u = r.body(M(o), 206);
406
+ }
407
+ }
408
+ return await e.onFound?.(s, r), u;
409
+ };
410
+ };
411
+ //#endregion
412
+ //#region server/middleware/media-static.ts
413
+ function le() {
414
+ return async (e, t) => {
415
+ if (e.env?.MEDIA_BUCKET) {
416
+ let t = e.req.path.replace(/^\/media\//, ""), n = await e.env.MEDIA_BUCKET.get(t, { onlyIf: e.req.raw.headers });
417
+ if (!n) return e.text("Media File Not Found", 404);
418
+ let r = new Headers();
419
+ return n.writeHttpMetadata(r), n.httpEtag && r.set("ETag", n.httpEtag), r.set("Cache-Control", "public, max-age=31536000, immutable"), r.set("Access-Control-Allow-Origin", "*"), "body" in n && n.body === void 0 ? new Response(null, {
420
+ status: 304,
421
+ headers: r
422
+ }) : new Response(n.body, {
423
+ status: 200,
424
+ headers: r
425
+ });
426
+ }
427
+ return ce({
428
+ root: e.env?.LOCAL_MEDIA_PATH || "./public/media",
429
+ rewriteRequestPath: (e) => e.replace(/^\/media/, "")
430
+ })(e, t);
431
+ };
432
+ }
433
+ //#endregion
434
+ //#region server/cache/lru.ts
435
+ var ue = class {
436
+ cache;
437
+ constructor(e = 1e3, t = 3e5) {
438
+ this.cache = new p({
439
+ max: e,
440
+ ttl: t
441
+ });
442
+ }
443
+ async get(e) {
444
+ let t = this.cache.get(e);
445
+ return t === void 0 ? null : t;
446
+ }
447
+ async set(e, t, n) {
448
+ let r = n ? n * 1e3 : void 0;
449
+ this.cache.set(e, t, { ttl: r });
450
+ }
451
+ async delete(e) {
452
+ this.cache.delete(e);
453
+ }
454
+ async clear() {
455
+ this.cache.clear();
456
+ }
457
+ }, de = class {
458
+ kv;
459
+ constructor(e) {
460
+ this.kv = e;
461
+ }
462
+ async get(e) {
463
+ if (!this.kv) return null;
464
+ let t = await this.kv.get(e);
465
+ return t ? JSON.parse(t) : null;
466
+ }
467
+ async set(e, t, n = 300) {
468
+ this.kv && await this.kv.put(e, JSON.stringify(t), { expirationTtl: n });
469
+ }
470
+ async delete(e) {
471
+ this.kv && await this.kv.delete(e);
472
+ }
473
+ async clear() {}
474
+ }, fe = class {
475
+ async get() {
476
+ return null;
477
+ }
478
+ async set() {}
479
+ async delete() {}
480
+ async clear() {}
481
+ }, pe = null;
482
+ function z(e) {
483
+ let t = process.env.CACHE_DRIVER || "lru";
484
+ return t === "none" || t === "off" || t === "false" ? new fe() : e?.env?.CMS_CACHE_KV ? new de(e.env.CMS_CACHE_KV) : t === "lru" ? (pe ||= new ue(), pe) : new fe();
485
+ }
486
+ //#endregion
487
+ //#region server/utils/node-assets-interceptor.ts
488
+ function me(e) {
489
+ if (!e || typeof e != "object") return {
490
+ cleanedData: e,
491
+ assetRefs: []
492
+ };
493
+ let t = [], n = (e) => e ? typeof e == "string" && e.startsWith("ast_") ? e : typeof e == "object" && typeof e.id == "string" && e.id.startsWith("ast_") ? e.id : null : null, r = (e, i) => {
494
+ if (!e || typeof e != "object") return e;
495
+ if (Array.isArray(e)) return e.map((e, a) => {
496
+ let o = n(e);
497
+ return o && t.push({
498
+ assetId: o,
499
+ fieldKey: i,
500
+ sortOrder: a
501
+ }), typeof e == "object" && e ? r(e, `${i}[${a}]`) : e;
502
+ });
503
+ let a = {};
504
+ for (let o of Object.keys(e)) {
505
+ let s = e[o], c = i ? `${i}.${o}` : o, l = n(s);
506
+ l ? (t.push({
507
+ assetId: l,
508
+ fieldKey: c,
509
+ sortOrder: 0
510
+ }), a[o] = typeof s == "object" && s ? {
511
+ id: l,
512
+ url: s.url || "",
513
+ originalUrl: s.originalUrl || s.url || "",
514
+ parentAssetId: s.parentAssetId || null,
515
+ cropCoordinates: s.cropCoordinates || null,
516
+ variants: s.variants || void 0,
517
+ filename: s.filename || void 0,
518
+ mimeType: s.mimeType || void 0
519
+ } : l) : a[o] = Array.isArray(s) || s && typeof s == "object" ? r(s, c) : s;
520
+ }
521
+ return a;
522
+ };
523
+ return {
524
+ cleanedData: r(e, ""),
525
+ assetRefs: t
526
+ };
527
+ }
528
+ async function he(e, t, n) {
529
+ if (await e.prepare("DELETE FROM node_assets WHERE nodeId = ?").run(t), n.length === 0) return;
530
+ let r = /* @__PURE__ */ new Set();
531
+ for (let i of n) {
532
+ let n = `${t}:${i.assetId}:${i.fieldKey}`;
533
+ r.has(n) || (r.add(n), await e.prepare("\n INSERT OR IGNORE INTO node_assets (nodeId, assetId, fieldKey, sortOrder)\n VALUES (?, ?, ?, ?)\n ").run(t, i.assetId, i.fieldKey, i.sortOrder));
534
+ }
535
+ }
536
+ //#endregion
537
+ //#region server/utils/asset-hydrator.ts
538
+ function B(e) {
539
+ if (!e) return null;
540
+ if (typeof e == "string" && e.startsWith("ast_")) return e;
541
+ if (typeof e == "object" && e) {
542
+ if (typeof e.id == "string" && e.id.startsWith("ast_")) return e.id;
543
+ if (typeof e.id == "object") return B(e.id);
544
+ }
545
+ return null;
546
+ }
547
+ async function V(e, t) {
548
+ if (!t || typeof t != "object") return t;
549
+ let n = /* @__PURE__ */ new Set(), r = (e) => {
550
+ if (!e) return;
551
+ let t = B(e);
552
+ if (t) {
553
+ if (n.add(t), typeof e == "object" && e.parentAssetId) {
554
+ let t = B(e.parentAssetId);
555
+ t && n.add(t);
556
+ }
557
+ } else Array.isArray(e) ? e.forEach(r) : typeof e == "object" && Object.values(e).forEach(r);
558
+ };
559
+ if (r(t), n.size === 0) return t;
560
+ let i = Array.from(n).map(() => "?").join(","), a = await e.prepare(`
561
+ SELECT
562
+ a.id,
563
+ a.filename,
564
+ a.mimeType,
565
+ a.cdnUrl,
566
+ a.storageKeyPrivate,
567
+ a.parentAssetId,
568
+ a.cropCoordinatesJson,
569
+ p.cdnUrl AS parentCdnUrl,
570
+ p.storageKeyPrivate AS parentStorageKeyPrivate
571
+ FROM assets a
572
+ LEFT JOIN assets p ON a.parentAssetId = p.id
573
+ WHERE a.id IN (${i})
574
+ `).all(...Array.from(n)), o = Array.isArray(a) ? a : a?.results || [], s = await e.prepare(`
575
+ SELECT id, cdnUrl, storageKeyPrivate, filename, parentAssetId, cropCoordinatesJson
576
+ FROM assets
577
+ WHERE isSystemVariant = 1
578
+ AND (parentAssetId IN (${i}) OR ${Array.from(n).map(() => "filename LIKE ?").join(" OR ")})
579
+ `).all(...Array.from(n), ...Array.from(n).map((e) => `%${e}%`)), c = Array.isArray(s) ? s : s?.results || [], l = /* @__PURE__ */ new Map();
580
+ for (let e of c) {
581
+ let t = B(e.parentAssetId) || Array.from(n).find((t) => e.filename.includes(t));
582
+ if (!t) continue;
583
+ let r = e.filename.match(/^crop_([a-z0-9]+)_/i), i = r ? r[1] : "standard", a = null;
584
+ if (e.cropCoordinatesJson) try {
585
+ a = typeof e.cropCoordinatesJson == "string" ? JSON.parse(e.cropCoordinatesJson) : e.cropCoordinatesJson;
586
+ } catch {}
587
+ let o = e.cdnUrl || (e.storageKeyPrivate ? `/media/${e.storageKeyPrivate}` : "");
588
+ l.has(t) || l.set(t, {}), l.get(t)[i] = {
589
+ id: e.id,
590
+ url: o,
591
+ cropCoordinates: a
592
+ };
593
+ }
594
+ let u = /* @__PURE__ */ new Map();
595
+ for (let e of o) {
596
+ let t = e.cdnUrl || (e.storageKeyPrivate ? `/media/${e.storageKeyPrivate}` : ""), n = t;
597
+ e.parentAssetId && (e.parentCdnUrl || e.parentStorageKeyPrivate) && (n = e.parentCdnUrl || `/media/${e.parentStorageKeyPrivate}`);
598
+ let r = null;
599
+ if (e.cropCoordinatesJson) try {
600
+ r = typeof e.cropCoordinatesJson == "string" ? JSON.parse(e.cropCoordinatesJson) : e.cropCoordinatesJson;
601
+ } catch {}
602
+ let i = l.get(e.id);
603
+ u.set(e.id, {
604
+ id: e.id,
605
+ url: t,
606
+ originalUrl: n,
607
+ parentAssetId: B(e.parentAssetId) || null,
608
+ cropCoordinates: r,
609
+ variants: i && Object.keys(i).length > 0 ? i : void 0,
610
+ filename: e.filename,
611
+ mimeType: e.mimeType
612
+ });
613
+ }
614
+ let d = (e) => {
615
+ if (!e) return e;
616
+ let t = B(e);
617
+ if (t) {
618
+ let n = u.get(t) || {
619
+ id: t,
620
+ url: "",
621
+ originalUrl: ""
622
+ }, r = typeof e == "object" && e.variants ? e.variants : void 0, i = typeof e == "object" && e.cropCoordinates ? e.cropCoordinates : void 0;
623
+ return {
624
+ ...n,
625
+ id: t,
626
+ parentAssetId: n.parentAssetId ? B(n.parentAssetId) : null,
627
+ url: typeof e == "object" && e.url && !e.url.startsWith("blob:") ? e.url : n.url,
628
+ originalUrl: typeof e == "object" && e.originalUrl && !e.originalUrl.startsWith("blob:") ? e.originalUrl : n.originalUrl,
629
+ cropCoordinates: i || n.cropCoordinates || null,
630
+ variants: r || n.variants || void 0
631
+ };
632
+ }
633
+ if (Array.isArray(e)) return e.map(d);
634
+ if (typeof e == "object") {
635
+ let t = {};
636
+ for (let [n, r] of Object.entries(e)) t[n] = d(r);
637
+ return t;
638
+ }
639
+ return e;
640
+ };
641
+ return d(t);
642
+ }
643
+ //#endregion
644
+ //#region src/schemas/definitions.ts
645
+ function H(e = {}, t = {}) {
646
+ let n = {
647
+ ...e,
648
+ ...t
649
+ };
650
+ 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 = {
651
+ ...e.rules || {},
652
+ ...t.rules || {},
653
+ required: !0
654
+ }) : t.required === !1 || t.rules?.required === !1 ? (n.required = !1, n.rules = {
655
+ ...e.rules || {},
656
+ ...t.rules || {},
657
+ required: !1
658
+ }) : n.rules = {
659
+ ...e.rules || {},
660
+ ...t.rules || {}
661
+ }, n;
662
+ }
663
+ function ge() {
664
+ if (typeof process > "u" || !process?.versions?.node) return null;
665
+ try {
666
+ let e = (e) => {
667
+ let t = /* @__PURE__ */ new Map(), n = process.cwd(), i = [
668
+ u.resolve(n, "schemas", e),
669
+ u.resolve(n, "defaults/definitions", e),
670
+ u.resolve(n, "cms/definitions", e),
671
+ u.resolve(n, "definitions", e),
672
+ u.resolve(n, "src/schemas", e),
673
+ u.resolve(n, "node_modules/@brightsideoy/kama/defaults/definitions", e)
674
+ ];
675
+ for (let e of i) {
676
+ if (!r.existsSync(e)) continue;
677
+ let n = (e, i = "") => {
678
+ let a = r.readdirSync(e, { withFileTypes: !0 });
679
+ for (let r of a) {
680
+ let a = u.join(i, r.name), o = u.join(e, r.name);
681
+ r.isDirectory() ? n(o, a) : (r.name.endsWith(".yaml") || r.name.endsWith(".yml")) && (t.has(a) || t.set(a, o));
682
+ }
683
+ };
684
+ n(e);
685
+ }
686
+ return Array.from(t.values());
687
+ }, t = (t) => {
688
+ let i = {};
689
+ for (let a of e(t)) {
690
+ let e = u.basename(a, u.extname(a));
691
+ try {
692
+ i[e] = n.parse(r.readFileSync(a, "utf-8"));
693
+ } catch (e) {
694
+ console.warn(`[CMS Schema] Failed to parse ${a}:`, e);
695
+ }
696
+ }
697
+ return i;
698
+ }, i = (t) => {
699
+ let i = e(u.dirname(t)), a = u.basename(t), o = i.find((e) => u.basename(e) === a || u.basename(e) === a.replace(/\.yaml$/, ".yml"));
700
+ if (!o) return null;
701
+ try {
702
+ return n.parse(r.readFileSync(o, "utf-8"));
703
+ } catch {
704
+ return null;
705
+ }
706
+ };
707
+ return {
708
+ rawNodes: t("nodes"),
709
+ rawTrees: t("trees"),
710
+ rawBlocks: {
711
+ ...t("elements"),
712
+ ...t("blocks")
713
+ },
714
+ rawNodeLayouts: {
715
+ ...t("layouts"),
716
+ ...t("node-layouts")
717
+ },
718
+ rawBlockLayouts: t("block-layouts"),
719
+ rawFieldSets: t("field-sets"),
720
+ rawTemplates: t("templates"),
721
+ nodeTemplate: i("templates/node.yaml"),
722
+ treeTemplate: i("templates/tree.yaml"),
723
+ channelTemplate: i("channels/channel.yaml") || i("templates/channel.yaml"),
724
+ userTemplate: i("users/user.yaml") || i("templates/user.yaml")
725
+ };
726
+ } catch {
727
+ return null;
728
+ }
729
+ }
730
+ function _e(e) {
731
+ if (e && (Object.keys(e.rawNodes || {}).length > 0 || Object.keys(e.nodes || {}).length > 0)) return U(e);
732
+ let t = ge();
733
+ return t && Object.keys(t.rawNodes).length > 0 ? U(t) : U(null);
734
+ }
735
+ function U(e) {
736
+ if (!e) return {
737
+ nodes: {},
738
+ trees: {},
739
+ blocks: {},
740
+ nodeLayouts: {},
741
+ blockLayouts: {},
742
+ fieldSets: {},
743
+ nodeTemplate: null,
744
+ treeTemplate: null,
745
+ channelTemplate: null,
746
+ userTemplate: null
747
+ };
748
+ let { rawNodes: t = {}, rawTrees: n = {}, rawBlocks: r = {}, rawElements: i = {}, rawNodeLayouts: a = {}, rawBlockLayouts: o = {}, rawLayouts: s = {}, rawFieldSets: c = {}, rawTemplates: l = {}, nodeTemplate: u = null, treeTemplate: d = null, channelTemplate: f = null, userTemplate: p = null } = e, m = u?.fields || {}, h = {
749
+ ...l,
750
+ ...c
751
+ }, g = (e, t = "settings", n, r) => {
752
+ let i = {};
753
+ if (!Array.isArray(e)) return typeof e == "object" && e ? (Object.entries(e).forEach(([e, t]) => {
754
+ let n = i[e] || m[e] || {};
755
+ i[e] = H(n, t);
756
+ }), i) : {};
757
+ let a = (e) => {
758
+ let a = h[e] || h[`${e}-base`] || {};
759
+ r && typeof a == "object" && a && (r.inTree === void 0 && a.inTree !== void 0 && (r.inTree = a.inTree), r.inVault === void 0 && a.inVault !== void 0 && (r.inVault = a.inVault), r.hasCanvas === void 0 && a.hasCanvas !== void 0 && (r.hasCanvas = a.hasCanvas));
760
+ let o = a.fields || a, s = g(o, t, n, r);
761
+ if (a.tab && n) {
762
+ let t = a.tab.id || e, r = a.tab.label || a.label || t;
763
+ n[t] || (n[t] = {
764
+ label: r,
765
+ fields: {}
766
+ }), Object.entries(s).forEach(([e, r]) => {
767
+ let i = n[t].fields[e] || {};
768
+ n[t].fields[e] = H(i, r);
769
+ });
770
+ } else Object.entries(s).forEach(([e, t]) => {
771
+ let n = i[e] || {};
772
+ i[e] = H(n, t);
773
+ });
774
+ };
775
+ return e.forEach((e) => {
776
+ if (typeof e == "string") {
777
+ if (e.startsWith("fieldSet:")) a(e.replace("fieldSet:", "").trim());
778
+ else {
779
+ let t = i[e] || m[e] || {};
780
+ i[e] = H(t, {
781
+ type: "text",
782
+ label: e
783
+ });
784
+ }
785
+ } else if (typeof e == "object" && e) {
786
+ let [t, n] = Object.entries(e)[0];
787
+ if (t === "fieldSet") a(String(n));
788
+ else {
789
+ let e = i[t] || m[t] || {};
790
+ i[t] = H(e, typeof n == "object" && n ? n : {});
791
+ }
792
+ }
793
+ }), i;
794
+ }, _ = (e, t) => {
795
+ let n = {};
796
+ return !e || typeof e != "object" ? n : Array.isArray(e) ? (e.forEach((e) => {
797
+ if (typeof e == "object" && e.fieldSet) {
798
+ let r = String(e.fieldSet), i = h[r] || h[`${r}-base`] || {};
799
+ t && (t.inTree === void 0 && i.inTree !== void 0 && (t.inTree = i.inTree), t.inVault === void 0 && i.inVault !== void 0 && (t.inVault = i.inVault), t.hasCanvas === void 0 && i.hasCanvas !== void 0 && (t.hasCanvas = i.hasCanvas));
800
+ let a = i.tab?.id || r, o = i.tab?.label || i.label || a;
801
+ n[a] || (n[a] = {
802
+ label: o,
803
+ fields: {}
804
+ });
805
+ let s = g(i.fields || i, a, n, t);
806
+ Object.entries(s).forEach(([e, t]) => {
807
+ let r = n[a].fields[e] || {};
808
+ n[a].fields[e] = H(r, t);
809
+ });
810
+ }
811
+ }), n) : (Object.entries(e).forEach(([e, r]) => {
812
+ let i = typeof r == "string" ? r : r?.label || e, a = typeof r == "object" && r ? r.fields : [];
813
+ n[e] || (n[e] = {
814
+ label: i,
815
+ fields: {}
816
+ });
817
+ let o = g(a, e, n, t);
818
+ Object.entries(o).forEach(([t, r]) => {
819
+ let i = n[e].fields[t] || {};
820
+ n[e].fields[t] = H(i, r);
821
+ });
822
+ }), n);
823
+ }, v = {};
824
+ Object.entries(t).forEach(([e, t]) => {
825
+ u && (t.inTree === void 0 && u.inTree !== void 0 && (t.inTree = u.inTree), t.inVault === void 0 && u.inVault !== void 0 && (t.inVault = u.inVault), t.hasCanvas === void 0 && u.hasCanvas !== void 0 && (t.hasCanvas = u.hasCanvas));
826
+ let n = _(t.tabs, t), r = g(t.fields || [], "settings", n, t);
827
+ Array.isArray(t.fieldSets) && t.fieldSets.forEach((e) => {
828
+ let i = h[e] || h[`${e}-base`] || {};
829
+ t.inTree === void 0 && i.inTree !== void 0 && (t.inTree = i.inTree), t.inVault === void 0 && i.inVault !== void 0 && (t.inVault = i.inVault), t.hasCanvas === void 0 && i.hasCanvas !== void 0 && (t.hasCanvas = i.hasCanvas);
830
+ let a = i.fields || i, o = g(a, "settings", n, t);
831
+ if (i.tab) {
832
+ let t = i.tab.id || e, r = i.tab.label || i.label || t;
833
+ n[t] || (n[t] = {
834
+ label: r,
835
+ fields: {}
836
+ }), Object.entries(o).forEach(([e, r]) => {
837
+ let i = n[t].fields[e] || {};
838
+ n[t].fields[e] = H(i, r);
839
+ });
840
+ } else Object.entries(o).forEach(([e, t]) => {
841
+ let n = r[e] || m[e] || {};
842
+ r[e] = H(n, t);
843
+ });
844
+ }), Object.values(n).forEach((e) => {
845
+ Object.entries(e.fields).forEach(([e, t]) => {
846
+ let n = r[e] || {};
847
+ r[e] = H(n, t);
848
+ });
849
+ }), Object.keys(n).length === 0 && Object.keys(r).length > 0 && (n.settings = {
850
+ label: t.label || "Settings",
851
+ fields: r
852
+ }), v[e] = {
853
+ ...t,
854
+ id: t.id || e,
855
+ label: t.label || e,
856
+ inTree: t.inTree === !0 || String(t.inTree).toLowerCase() === "true",
857
+ inVault: t.inVault !== !1,
858
+ hasCanvas: t.hasCanvas === !0,
859
+ defaultLayout: t.defaultLayout,
860
+ tabs: n,
861
+ fields: r
862
+ };
863
+ });
864
+ let y = {};
865
+ Object.entries(n).forEach(([e, t]) => {
866
+ let n = _(t.tabs), r = g(t.fields || [], "settings", n);
867
+ Array.isArray(t.fieldSets) && t.fieldSets.forEach((e) => {
868
+ let t = h[e] || {}, i = t.fields || t, a = g(i, "settings", n);
869
+ Object.entries(a).forEach(([e, t]) => {
870
+ r[e] = H(r[e] || {}, t);
871
+ });
872
+ }), Object.values(n).forEach((e) => {
873
+ Object.entries(e.fields).forEach(([e, t]) => {
874
+ r[e] = H(r[e] || {}, t);
875
+ });
876
+ }), y[e] = {
877
+ ...t,
878
+ id: t.id || e,
879
+ label: t.label || e,
880
+ tabs: n,
881
+ fields: r
882
+ };
883
+ });
884
+ let b = {}, x = {
885
+ ...i,
886
+ ...r
887
+ };
888
+ Object.entries(x).forEach(([e, t]) => {
889
+ let n = g(t.fields || []);
890
+ Array.isArray(t.fieldSets) && t.fieldSets.forEach((e) => {
891
+ let t = h[e] || {}, r = t.fields || t, i = g(r);
892
+ Object.entries(i).forEach(([e, t]) => {
893
+ n[e] = H(n[e] || {}, t);
894
+ });
895
+ }), b[e] = {
896
+ ...t,
897
+ id: t.id || e,
898
+ label: t.label || e,
899
+ category: t.category || "Content",
900
+ fields: n
901
+ };
902
+ });
903
+ let S = {}, C = {
904
+ ...s,
905
+ ...a
906
+ };
907
+ Object.entries(C).forEach(([e, t]) => {
908
+ let n = _(t.tabs), r = g(t.fields || [], "settings", n);
909
+ S[e] = {
910
+ ...t,
911
+ id: t.id || e,
912
+ label: t.label || e,
913
+ layout: t.layout || {
914
+ columns: "1fr",
915
+ areas: [["content"]]
916
+ },
917
+ regions: t.regions || { content: { label: "Content" } },
918
+ fields: r,
919
+ tabs: n
920
+ };
921
+ });
922
+ let w = {};
923
+ Object.entries(o).forEach(([e, t]) => {
924
+ let n = _(t.tabs), r = g(t.fields || [], "settings", n);
925
+ w[e] = {
926
+ ...t,
927
+ id: t.id || e,
928
+ label: t.label || e,
929
+ layout: t.layout || {
930
+ columns: "1fr",
931
+ areas: [["main"]]
932
+ },
933
+ regions: t.regions || { main: { label: "Main Content" } },
934
+ fields: r,
935
+ tabs: n
936
+ };
937
+ });
938
+ let T = f?.fields || {};
939
+ Array.isArray(f?.fieldSets) && f?.fieldSets.forEach((e) => {
940
+ let t = h[e] || {}, n = t.fields || t, r = g(n);
941
+ Object.entries(r).forEach(([e, t]) => {
942
+ T[e] = H(T[e] || {}, t);
943
+ });
944
+ });
945
+ let E = f ? {
946
+ ...f,
947
+ fields: T
948
+ } : null, D = p?.fields || {};
949
+ Array.isArray(p?.fieldSets) && p?.fieldSets.forEach((e) => {
950
+ let t = h[e] || {}, n = t.fields || t, r = g(n);
951
+ Object.entries(r).forEach(([e, t]) => {
952
+ D[e] = H(D[e] || {}, t);
953
+ });
954
+ });
955
+ let O = p ? {
956
+ ...p,
957
+ fields: D
958
+ } : null;
959
+ return {
960
+ nodes: v,
961
+ trees: y,
962
+ blocks: b,
963
+ nodeLayouts: S,
964
+ blockLayouts: w,
965
+ fieldSets: h,
966
+ nodeTemplate: u || null,
967
+ treeTemplate: d || null,
968
+ channelTemplate: E,
969
+ userTemplate: O
970
+ };
971
+ }
972
+ //#endregion
973
+ //#region server/routes/admin/nodes.ts
974
+ var W = new t();
975
+ function ve(e) {
976
+ 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;
977
+ }
978
+ function ye(e) {
979
+ return +(e === !0 || e === 1 || e === "1" || e === "true");
980
+ }
981
+ function be(e) {
982
+ if (e == null || e === "null" || e === "" || typeof e == "string" && e.startsWith("draft-")) return null;
983
+ let t = Number(e);
984
+ return isNaN(t) ? null : t;
985
+ }
986
+ function xe(e) {
987
+ let t = { ...e };
988
+ for (let e of [
989
+ "id",
990
+ "treeNodeId",
991
+ "isNew",
992
+ "_isTreeDraft",
993
+ "_draftParentId",
994
+ "nodeType",
995
+ "contentType",
996
+ "title",
997
+ "slug",
998
+ "language",
999
+ "hidden",
1000
+ "is_hidden",
1001
+ "isHidden",
1002
+ "status",
1003
+ "createdById",
1004
+ "updatedById",
1005
+ "draftDataJson",
1006
+ "publishedDataJson",
1007
+ "publishedAt",
1008
+ "deletedAt",
1009
+ "channelNames",
1010
+ "treeNames",
1011
+ "hasUnpublishedChanges"
1012
+ ]) delete t[e];
1013
+ return t;
1014
+ }
1015
+ async function Se(e, t, n) {
1016
+ let r = {}, i = null;
1017
+ if (t) {
1018
+ 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 || [];
1019
+ for (let e of a) {
1020
+ let t = e.draftDataJson || e.dataJson;
1021
+ if (t) try {
1022
+ let e = typeof t == "string" ? JSON.parse(t) : t;
1023
+ !i && e.subpageLayoutId && e.subpageLayoutId !== "inherit" && (i = e.subpageLayoutId);
1024
+ for (let [t, n] of Object.entries(e)) n != null && n !== "" && r[t] === void 0 && (r[t] = n);
1025
+ } catch {}
1026
+ }
1027
+ }
1028
+ if (!i) {
1029
+ let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ?").get(n);
1030
+ if (t && t.dataJson) try {
1031
+ let e = typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson;
1032
+ e.subpageLayoutId && e.subpageLayoutId !== "inherit" && (i = e.subpageLayoutId);
1033
+ } catch {}
1034
+ }
1035
+ return {
1036
+ resolvedLayoutId: i,
1037
+ inheritedFields: r
1038
+ };
1039
+ }
1040
+ W.get("/", async (e) => {
1041
+ 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));
1042
+ if (n) {
1043
+ let r = Number(n);
1044
+ if (isNaN(r)) return e.json({ error: "Invalid Node ID" }, 400);
1045
+ let i = await t.prepare("SELECT * FROM content_nodes WHERE id = ?").get(r);
1046
+ if (!i) return e.json({ error: "Node not found" }, 404);
1047
+ let a = (i.status === "draft" || !i.status) && !!i.publishedAt, o = {
1048
+ id: i.id,
1049
+ title: i.title,
1050
+ slug: i.slug,
1051
+ language: i.language || "en",
1052
+ nodeType: i.contentType,
1053
+ contentType: i.contentType,
1054
+ isHidden: !!i.isHidden,
1055
+ status: i.status || "draft",
1056
+ publishedAt: i.publishedAt || null,
1057
+ hasUnpublishedChanges: a,
1058
+ deletedAt: i.deletedAt || null,
1059
+ createdById: i.createdById || null,
1060
+ updatedById: i.updatedById || null,
1061
+ createdAt: i.createdAt,
1062
+ updatedAt: i.updatedAt
1063
+ }, s = i.draftDataJson || i.dataJson;
1064
+ if (s) try {
1065
+ 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 = U(e.env?.BUNDLED_DEFINITIONS).nodes?.[i.contentType] || {}, l = n.layoutId || null;
1066
+ if (a) {
1067
+ let { resolvedLayoutId: e, inheritedFields: r } = await Se(t, a.parentId, a.treeId);
1068
+ (l === "inherit" || !l) && (l = e || c.defaultLayout || null);
1069
+ for (let [e, t] of Object.entries(r)) (n[e] === void 0 || n[e] === null || n[e] === "") && t !== void 0 && (n[e] = t);
1070
+ } else (l === "inherit" || !l) && (l = c.defaultLayout || null);
1071
+ let u = await V(t, xe(n));
1072
+ Object.assign(o, u), o.resolvedLayoutId = l;
1073
+ } catch {}
1074
+ let c = await t.prepare("SELECT channelId FROM node_channels WHERE nodeId = ?").all(r);
1075
+ o.channels = (Array.isArray(c) ? c : c?.results || []).map((e) => e.channelId);
1076
+ let l = await t.prepare("SELECT treeId, parentId, sortOrder FROM tree_nodes WHERE contentId = ?").all(r);
1077
+ o.trees = Array.isArray(l) ? l : l?.results || [];
1078
+ 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) => {
1079
+ let n = {};
1080
+ try {
1081
+ n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson || "{}") : e.dataJson || {}, n && typeof n == "object" && (n = await V(t, n));
1082
+ } catch {
1083
+ n = {};
1084
+ }
1085
+ let r = n.blockId || n._instanceId || e.instanceId || String(e.id), i = { ...n };
1086
+ return delete i._instanceId, {
1087
+ instanceId: String(r),
1088
+ blockId: String(r),
1089
+ componentId: e.elementType || e.componentId || "text-block",
1090
+ region: e.region !== void 0 && e.region !== null && String(e.region).trim() !== "" ? e.region : "content",
1091
+ data: i
1092
+ };
1093
+ }));
1094
+ return e.json({
1095
+ node: o,
1096
+ blocks: f
1097
+ });
1098
+ }
1099
+ let m = [], h = [o ? "(cn.deletedAt IS NOT NULL AND cn.deletedAt != '')" : "(cn.deletedAt IS NULL OR cn.deletedAt = '')"];
1100
+ if (a && a !== "all" && (h.push("EXISTS (SELECT 1 FROM node_channels nc WHERE nc.nodeId = cn.id AND nc.channelId = ?)"), m.push(Number(a) || a)), s && (h.push("\n EXISTS (\n SELECT 1 FROM node_assets na_f \n JOIN assets a_f ON a_f.id = na_f.assetId\n WHERE na_f.nodeId = cn.id \n AND (\n na_f.assetId = ? \n OR a_f.parentAssetId = ? \n OR a_f.id = (SELECT parentAssetId FROM assets WHERE id = ?)\n )\n )\n "), m.push(s, s, s)), r && r !== "all") {
1101
+ let e = r.split(",").map((e) => e.trim()).filter(Boolean);
1102
+ if (e.length > 0) {
1103
+ let t = e.map(() => "?").join(",");
1104
+ h.push(`cn.contentType IN (${t})`), m.push(...e);
1105
+ }
1106
+ }
1107
+ if (i && i.trim()) {
1108
+ h.push("(cn.title LIKE ? OR cn.slug LIKE ?)");
1109
+ let e = `%${i.trim()}%`;
1110
+ m.push(e, e);
1111
+ }
1112
+ let g = `WHERE ${h.join(" AND ")}`, _ = await t.prepare(`SELECT COUNT(*) as total FROM content_nodes cn ${g}`).get(...m), v = _ ? _.total : 0, y = "cn.updatedAt", b = {
1113
+ createdAt: "cn.createdAt",
1114
+ updatedAt: "cn.updatedAt",
1115
+ title: "LOWER(cn.title)",
1116
+ slug: "LOWER(cn.slug)",
1117
+ contentType: "LOWER(cn.contentType)",
1118
+ language: "LOWER(cn.language)",
1119
+ status: "LOWER(cn.status)",
1120
+ isHidden: "cn.isHidden"
1121
+ };
1122
+ b[c] && (y = b[c]);
1123
+ let x = `
1124
+ WITH filtered_nodes AS (
1125
+ SELECT cn.*
1126
+ FROM content_nodes cn
1127
+ ${g}
1128
+ ORDER BY ${y} ${l}
1129
+ LIMIT ? OFFSET ?
1130
+ )
1131
+ SELECT
1132
+ fn.*,
1133
+ COUNT(na.assetId) as assetCount
1134
+ FROM filtered_nodes fn
1135
+ LEFT JOIN node_assets na ON fn.id = na.nodeId
1136
+ GROUP BY fn.id
1137
+ ORDER BY ${y.replace("cn.", "fn.")} ${l}
1138
+ `, S = [
1139
+ ...m,
1140
+ f,
1141
+ p
1142
+ ], C = await t.prepare(x).all(...S), w = Array.isArray(C) ? C : C?.results || [], T = w.map((e) => e.id), E = {}, D = {};
1143
+ if (T.length > 0) {
1144
+ let e = T.map(() => "?").join(","), n = await t.prepare(`
1145
+ SELECT nc.nodeId, c.label
1146
+ FROM node_channels nc
1147
+ JOIN channels c ON nc.channelId = c.id
1148
+ WHERE nc.nodeId IN (${e})
1149
+ `).all(...T), r = Array.isArray(n) ? n : n?.results || [];
1150
+ for (let e of r) E[e.nodeId] || (E[e.nodeId] = []), E[e.nodeId].push(e.label);
1151
+ let i = await t.prepare(`
1152
+ SELECT tn.contentId as nodeId, t.label
1153
+ FROM tree_nodes tn
1154
+ JOIN trees t ON tn.treeId = t.id
1155
+ WHERE tn.contentId IN (${e})
1156
+ `).all(...T), a = Array.isArray(i) ? i : i?.results || [];
1157
+ for (let e of a) D[e.nodeId] || (D[e.nodeId] = []), D[e.nodeId].includes(e.label) || D[e.nodeId].push(e.label);
1158
+ }
1159
+ let O = await Promise.all(w.map(async (e) => {
1160
+ let n = (e.status === "draft" || !e.status) && !!e.publishedAt, r = {
1161
+ id: e.id,
1162
+ title: e.title,
1163
+ slug: e.slug,
1164
+ language: e.language || "en",
1165
+ contentType: e.contentType,
1166
+ nodeType: e.contentType,
1167
+ isHidden: !!e.isHidden,
1168
+ status: e.status || "draft",
1169
+ publishedAt: e.publishedAt || null,
1170
+ hasUnpublishedChanges: n,
1171
+ deletedAt: e.deletedAt || null,
1172
+ createdById: e.createdById || null,
1173
+ updatedById: e.updatedById || null,
1174
+ createdAt: e.createdAt,
1175
+ updatedAt: e.updatedAt,
1176
+ channelNames: E[e.id] || [],
1177
+ treeNames: D[e.id] || [],
1178
+ assetCount: e.assetCount || 0
1179
+ }, i = e.draftDataJson || e.dataJson;
1180
+ if (i) try {
1181
+ let e = typeof i == "string" ? JSON.parse(i) : i, n = await V(t, xe(e));
1182
+ Object.assign(r, n);
1183
+ } catch {}
1184
+ return r;
1185
+ }));
1186
+ return e.json({
1187
+ items: O,
1188
+ total: v,
1189
+ hasMore: p + O.length < v,
1190
+ offset: p,
1191
+ limit: f
1192
+ });
1193
+ }), W.post("/", async (e) => {
1194
+ 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 = xe(_), { cleanedData: y, assetRefs: b } = me(v), x = ye(d === void 0 ? f === void 0 ? p : f : d), S = c || "en", C = l || u || "page", w = e.get("user")?.id || null, T = a;
1195
+ if (a) {
1196
+ let n = await t.prepare("SELECT title, slug, contentType, language, draftDataJson, dataJson, publishedAt, status FROM content_nodes WHERE id = ?").get(a);
1197
+ 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 z(e).clear(), e.json({
1198
+ success: !0,
1199
+ id: a,
1200
+ status: n?.status || "published"
1201
+ });
1202
+ {
1203
+ let e = o === void 0 ? n?.title || "Untitled" : o, r = s === void 0 ? n?.slug ?? null : ve(s), i = C || n?.contentType || "page", c = S || n?.language || "en", l = n?.draftDataJson || n?.dataJson || "{}", u = {};
1204
+ try {
1205
+ u = JSON.parse(l);
1206
+ } catch {}
1207
+ let d = JSON.stringify({
1208
+ ...u,
1209
+ ...y
1210
+ });
1211
+ 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);
1212
+ }
1213
+ } else {
1214
+ let e = o || "Untitled", n = ve(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);
1215
+ T = Number(i.lastInsertRowid);
1216
+ }
1217
+ if (h !== void 0 && Array.isArray(h) && T) {
1218
+ await t.prepare("DELETE FROM node_channels WHERE nodeId = ?").run(T);
1219
+ let e = h.map((e) => typeof e == "object" && e ? e.id || e.channelId : e), n = [...new Set(e)].filter((e) => e && e !== "all").map((e) => Number(e) || e);
1220
+ if (n.length > 0) {
1221
+ let e = n.map(() => "(?, ?)").join(", "), r = n.flatMap((e) => [T, e]);
1222
+ await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...r);
1223
+ }
1224
+ }
1225
+ if (g !== void 0 && Array.isArray(g) && T) {
1226
+ await t.prepare("DELETE FROM tree_nodes WHERE contentId = ?").run(T);
1227
+ let e = /* @__PURE__ */ new Set(), n = [], r = [];
1228
+ for (let t of g) if (t && t.treeId) {
1229
+ let i = Number(t.treeId) || t.treeId;
1230
+ if (!e.has(i)) {
1231
+ e.add(i);
1232
+ let a = be(t.parentId ?? t._draftParentId ?? null), o = typeof t.sortOrder == "number" ? t.sortOrder : 0;
1233
+ n.push("(?, ?, ?, ?)"), r.push(i, T, a, o);
1234
+ }
1235
+ }
1236
+ n.length > 0 && await t.prepare(`INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder) VALUES ${n.join(", ")}`).run(...r);
1237
+ }
1238
+ let E = [];
1239
+ if (m !== void 0 && Array.isArray(m) && T) {
1240
+ await t.prepare("DELETE FROM content_blocks WHERE contentId = ? AND isDraft = 1").run(T);
1241
+ let e = [], n = [];
1242
+ for (let t = 0; t < m.length; t++) {
1243
+ 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 } = me({
1244
+ ...a,
1245
+ blockId: o,
1246
+ _instanceId: o
1247
+ });
1248
+ c.forEach((e) => {
1249
+ E.push({
1250
+ ...e,
1251
+ fieldKey: `blocks[${t}].${e.fieldKey}`
1252
+ });
1253
+ });
1254
+ let l = r.region !== void 0 && r.region !== null && String(r.region).trim() !== "" ? String(r.region) : "content";
1255
+ e.push("(?, ?, ?, ?, ?, 1)"), n.push(T, t, i, JSON.stringify(s), l);
1256
+ }
1257
+ e.length > 0 && await t.prepare(`INSERT INTO content_blocks (contentId, sortOrder, elementType, dataJson, region, isDraft) VALUES ${e.join(", ")}`).run(...n);
1258
+ }
1259
+ if (T) {
1260
+ let e = [...b, ...E];
1261
+ await he(t, T, e);
1262
+ }
1263
+ return await z(e).clear(), e.json({
1264
+ success: !0,
1265
+ id: T,
1266
+ status: "draft"
1267
+ });
1268
+ }), W.post("/publish", async (e) => {
1269
+ let t = e.get("db"), n = await e.req.json(), r = n.id || n.nodeId;
1270
+ if (!r || isNaN(Number(r))) return e.json({ error: "Node ID required for publishing" }, 400);
1271
+ let i = Number(r), a = e.get("user")?.id || null, o = await t.prepare("SELECT * FROM content_nodes WHERE id = ?").get(i);
1272
+ if (!o) return e.json({ error: "Node not found" }, 404);
1273
+ let s = o.draftDataJson || o.dataJson || "{}";
1274
+ await t.prepare("\n UPDATE content_nodes\n SET publishedDataJson = ?,\n dataJson = ?,\n publishedAt = CURRENT_TIMESTAMP,\n status = 'published',\n updatedById = ?,\n updatedAt = CURRENT_TIMESTAMP\n WHERE id = ?\n ").run(s, s, a, i), await t.prepare("DELETE FROM content_blocks WHERE contentId = ? AND isDraft = 0").run(i);
1275
+ let c = await t.prepare("SELECT * FROM content_blocks WHERE contentId = ? AND isDraft = 1 ORDER BY sortOrder ASC").all(i), l = Array.isArray(c) ? c : c?.results || [];
1276
+ if (l.length > 0) {
1277
+ let e = [], n = [];
1278
+ for (let t of l) {
1279
+ let r = t.region !== void 0 && t.region !== null && String(t.region).trim() !== "" ? String(t.region) : "content";
1280
+ e.push("(?, ?, ?, ?, ?, 0)"), n.push(i, t.sortOrder, t.elementType, t.dataJson, r);
1281
+ }
1282
+ await t.prepare(`INSERT INTO content_blocks (contentId, sortOrder, elementType, dataJson, region, isDraft) VALUES ${e.join(", ")}`).run(...n);
1283
+ }
1284
+ let u = ((await t.prepare("SELECT COUNT(*) as count FROM node_revisions WHERE nodeId = ?").get(i))?.count || 0) + 1, d = {
1285
+ version: u,
1286
+ publishedAt: (/* @__PURE__ */ new Date()).toISOString(),
1287
+ node: {
1288
+ ...o,
1289
+ dataJson: s
1290
+ },
1291
+ blocks: l
1292
+ };
1293
+ return await t.prepare("\n INSERT INTO node_revisions (nodeId, version, snapshotJson, createdById)\n VALUES (?, ?, ?, ?)\n ").run(i, u, JSON.stringify(d), a), await z(e).clear(), e.json({
1294
+ success: !0,
1295
+ id: i,
1296
+ status: "published",
1297
+ version: u,
1298
+ publishedAt: d.publishedAt
1299
+ });
1300
+ }), W.delete("/", async (e) => {
1301
+ let t = e.get("db"), n = e.req.query("id");
1302
+ if (!n) return e.json({ error: "Node ID required" }, 400);
1303
+ let r = Number(n);
1304
+ return await t.prepare("UPDATE content_nodes SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?").run(r), await z(e).clear(), e.json({
1305
+ success: !0,
1306
+ deletedNodeId: r
1307
+ });
1308
+ }), W.post("/restore", async (e) => {
1309
+ let t = e.get("db"), n = await e.req.json(), r = Number(n.id);
1310
+ return r ? (await t.prepare("UPDATE content_nodes SET deletedAt = NULL WHERE id = ?").run(r), await z(e).clear(), e.json({
1311
+ success: !0,
1312
+ restoredNodeId: r
1313
+ })) : e.json({ error: "Node ID required" }, 400);
1314
+ }), W.delete("/purge", async (e) => {
1315
+ let t = e.get("db"), n = e.req.query("id");
1316
+ if (!n) return e.json({ error: "Node ID required" }, 400);
1317
+ let r = Number(n);
1318
+ 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 z(e).clear(), e.json({
1319
+ success: !0,
1320
+ purgedNodeId: r
1321
+ });
1322
+ });
1323
+ //#endregion
1324
+ //#region server/routes/admin/trees.ts
1325
+ var G = new t();
1326
+ function Ce(e, t = null) {
1327
+ let n = [];
1328
+ for (let r = 0; r < e.length; r++) {
1329
+ let i = e[r];
1330
+ if (i && (i.treeNodeId || i.id)) {
1331
+ let e = i.treeNodeId || i.id;
1332
+ if (typeof e == "string" && e.startsWith("draft-")) continue;
1333
+ let a = Number(e);
1334
+ if (isNaN(a)) continue;
1335
+ n.push({
1336
+ id: a,
1337
+ parentId: t,
1338
+ sortOrder: r
1339
+ }), i.children && Array.isArray(i.children) && i.children.length > 0 && n.push(...Ce(i.children, a));
1340
+ }
1341
+ }
1342
+ return n;
1343
+ }
1344
+ function we(e) {
1345
+ if (e == null || e === "null" || e === "" || typeof e == "string" && e.startsWith("draft-")) return null;
1346
+ let t = Number(e);
1347
+ return isNaN(t) ? null : t;
1348
+ }
1349
+ function Te(e) {
1350
+ return +(e === !0 || e === 1 || e === "1" || e === "true");
1351
+ }
1352
+ G.get("/tree.json", async (e) => {
1353
+ try {
1354
+ let t = e.get("db"), n = e.req.query("treeId") || "main-nav", r = e.req.query("preview") === "true", i = 1;
1355
+ if (isNaN(Number(n))) {
1356
+ let e = await t.prepare("SELECT id FROM trees WHERE key = ?").get(n);
1357
+ if (e && e.id) i = Number(e.id);
1358
+ else {
1359
+ let e = await t.prepare("SELECT id FROM trees LIMIT 1").get();
1360
+ e && e.id && (i = Number(e.id));
1361
+ }
1362
+ } else i = Number(n);
1363
+ let a = await t.prepare("\n SELECT \n t.id as treeNodeId,\n t.treeId,\n t.contentId,\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.publishedAt,\n c.dataJson,\n c.draftDataJson,\n (SELECT COUNT(*) FROM node_assets WHERE nodeId = t.contentId) as assetCount\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(i), o = Array.isArray(a) ? a : a?.results || [], s = [], c = /* @__PURE__ */ new Set();
1364
+ for (let e of o) {
1365
+ let t = e.contentId;
1366
+ c.has(t) || (c.add(t), s.push(e));
1367
+ }
1368
+ function l(e = null) {
1369
+ return s.filter((t) => {
1370
+ let n = !t.parentId || t.parentId === "null" || t.parentId === "" ? null : t.parentId;
1371
+ return String(n) === String(!e || e === "null" || e === "" ? null : e);
1372
+ }).map((e) => {
1373
+ let t = {}, n = e.draftDataJson || e.dataJson;
1374
+ if (n) try {
1375
+ t = typeof n == "string" ? JSON.parse(n) : n, delete t._isTreeDraft, delete t._draftParentId, delete t.nodeType, delete t.contentType, delete t.title, delete t.slug, delete t.hidden, delete t.is_hidden, delete t.isHidden, delete t.status;
1376
+ } catch {}
1377
+ let { dataJson: r, draftDataJson: i, ...a } = e, o = {
1378
+ ...a,
1379
+ ...t
1380
+ }, s = !!e.isHidden || o.hidden === !0 || o.hidden === 1 || o.hidden === "true", c = (e.status === "draft" || !e.status) && !!e.publishedAt;
1381
+ return {
1382
+ ...o,
1383
+ id: e.contentId,
1384
+ treeNodeId: e.treeNodeId,
1385
+ parentId: e.parentId || null,
1386
+ language: e.language || "en",
1387
+ hidden: +!!s,
1388
+ isHidden: s,
1389
+ status: e.status || "draft",
1390
+ publishedAt: e.publishedAt || null,
1391
+ hasUnpublishedChanges: c,
1392
+ assetCount: e.assetCount || 0,
1393
+ children: l(e.treeNodeId)
1394
+ };
1395
+ }).filter((e) => r || !e.hidden);
1396
+ }
1397
+ return e.json(l(null));
1398
+ } catch (t) {
1399
+ return console.error("[CMS Tree API] GET Error:", t), e.json({ error: t.message || "Failed to fetch tree" }, 500);
1400
+ }
1401
+ }), G.post("/tree.json", async (e) => {
1402
+ try {
1403
+ let t = e.get("db"), n = await e.req.json(), r = n.treeId ? String(n.treeId).trim() : "main-nav", i = z(e), a = 1;
1404
+ if (isNaN(Number(r))) {
1405
+ let e = await t.prepare("SELECT id FROM trees WHERE key = ?").get(r);
1406
+ if (e && e.id) a = Number(e.id);
1407
+ else {
1408
+ let e = await t.prepare("SELECT id FROM trees LIMIT 1").get();
1409
+ e && e.id && (a = Number(e.id));
1410
+ }
1411
+ } else a = Number(r);
1412
+ if (n.tree && Array.isArray(n.tree)) {
1413
+ let r = Ce(n.tree, null);
1414
+ if (r.length > 0) for (let e = 0; e < r.length; e += 50) {
1415
+ let n = r.slice(e, e + 50), i = n.map((e) => e.id), o = i.map(() => "?").join(","), s = "UPDATE tree_nodes SET \n";
1416
+ s += "parentId = CASE id \n", n.forEach(() => {
1417
+ s += "WHEN ? THEN ? \n";
1418
+ }), s += "ELSE parentId END, \n", s += "sortOrder = CASE id \n", n.forEach(() => {
1419
+ s += "WHEN ? THEN ? \n";
1420
+ }), s += "ELSE sortOrder END \n", s += `WHERE id IN (${o}) AND treeId = ?`;
1421
+ let c = [];
1422
+ n.forEach((e) => {
1423
+ c.push(e.id, e.parentId);
1424
+ }), n.forEach((e) => {
1425
+ c.push(e.id, e.sortOrder);
1426
+ }), c.push(...i), c.push(a), await t.prepare(s).run(...c);
1427
+ }
1428
+ return await i.clear(), e.json({ success: !0 });
1429
+ }
1430
+ 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 = Te(n.isHidden === void 0 ? p.isHidden === void 0 ? p.hidden : p.isHidden : n.isHidden);
1431
+ 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;
1432
+ let h = we(l), g = e.get("user")?.id || null;
1433
+ if (o === "create") {
1434
+ let r = p.slug || n.slug || s, o = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
1435
+ if (o) {
1436
+ let n = h === null ? "tn.parentId IS NULL" : "tn.parentId = ?", r = h === null ? [a, o] : [
1437
+ a,
1438
+ h,
1439
+ o
1440
+ ];
1441
+ if (await t.prepare(`
1442
+ SELECT 1
1443
+ FROM tree_nodes tn
1444
+ INNER JOIN content_nodes cn ON tn.contentId = cn.id
1445
+ WHERE tn.treeId = ?
1446
+ AND ${n}
1447
+ AND cn.slug = ?
1448
+ AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
1449
+ LIMIT 1
1450
+ `).get(...r)) return e.json({
1451
+ error: `The slug '${o}' is already in use by another page in this section.`,
1452
+ field: "slug"
1453
+ }, 409);
1454
+ }
1455
+ 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);
1456
+ await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(a, d);
1457
+ 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 = [];
1458
+ n.channels && Array.isArray(n.channels) ? v = n.channels : n.channelId && n.channelId !== "all" && (v = [n.channelId]);
1459
+ let y = [...new Set(v)].filter((e) => e && e !== "all").map((e) => Number(e));
1460
+ if (y.length > 0) {
1461
+ let e = y.map(() => "(?, ?)").join(", "), n = y.flatMap((e) => [d, e]);
1462
+ await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...n);
1463
+ }
1464
+ return await i.clear(), e.json({
1465
+ success: !0,
1466
+ id: d,
1467
+ treeNodeId: _,
1468
+ status: "draft"
1469
+ }, 201);
1470
+ }
1471
+ if (o === "attach") {
1472
+ if (!u) return e.json({ error: "contentId is required for attach" }, 400);
1473
+ let n = await t.prepare("SELECT slug FROM content_nodes WHERE id = ?").get(u);
1474
+ if (n && n.slug) {
1475
+ let r = h === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = h === null ? [
1476
+ a,
1477
+ n.slug,
1478
+ u
1479
+ ] : [
1480
+ a,
1481
+ h,
1482
+ n.slug,
1483
+ u
1484
+ ];
1485
+ if (await t.prepare(`
1486
+ SELECT 1
1487
+ FROM tree_nodes tn
1488
+ INNER JOIN content_nodes cn ON tn.contentId = cn.id
1489
+ WHERE tn.treeId = ?
1490
+ AND ${r}
1491
+ AND cn.slug = ?
1492
+ AND cn.id != ?
1493
+ AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
1494
+ LIMIT 1
1495
+ `).get(...i)) return e.json({
1496
+ error: `Cannot attach. The slug '${n.slug}' is already in use by another page in this section.`,
1497
+ field: "slug"
1498
+ }, 409);
1499
+ }
1500
+ await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(a, u);
1501
+ 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);
1502
+ return await i.clear(), e.json({
1503
+ success: !0,
1504
+ treeNodeId: o
1505
+ });
1506
+ }
1507
+ if (o === "detach") {
1508
+ let r = n.treeNodeId || n.contentId;
1509
+ 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);
1510
+ }
1511
+ return e.json({ error: "Invalid payload or action" }, 400);
1512
+ } catch (t) {
1513
+ return console.error("[CMS Tree API] Error updating tree:", t), e.json({
1514
+ error: "Failed to update tree",
1515
+ details: t.message
1516
+ }, 500);
1517
+ }
1518
+ }), G.get("/trees.json", async (e) => {
1519
+ try {
1520
+ 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) => {
1521
+ let n = Number(t.treeId), r = Number(t.channelId);
1522
+ return e[n] || (e[n] = []), e[n].includes(r) || e[n].push(r), e;
1523
+ }, {}), o = r.map((e) => {
1524
+ let t = {};
1525
+ if (e.dataJson) try {
1526
+ t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
1527
+ } catch {}
1528
+ return {
1529
+ id: e.id,
1530
+ key: e.key,
1531
+ label: e.label,
1532
+ treeType: e.treeType ?? "",
1533
+ channelId: e.channelId || null,
1534
+ channels: a[e.id] || [],
1535
+ isHidden: !!e.isHidden,
1536
+ createdById: e.createdById || null,
1537
+ updatedById: e.updatedById || null,
1538
+ createdAt: e.createdAt,
1539
+ updatedAt: e.updatedAt,
1540
+ ...t
1541
+ };
1542
+ });
1543
+ return e.json(o);
1544
+ } catch {
1545
+ return e.json([]);
1546
+ }
1547
+ }), G.post("/trees.json", async (e) => {
1548
+ try {
1549
+ 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 };
1550
+ 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({
1551
+ error: `Tree API key "${o}" is already in use.`,
1552
+ field: "key"
1553
+ }, 409);
1554
+ let p = i;
1555
+ if (i) await t.prepare("\n UPDATE trees \n SET key = ?, label = ?, treeType = ?, channelId = ?, isHidden = ?, dataJson = ?, updatedById = ?, updatedAt = CURRENT_TIMESTAMP\n WHERE id = ?\n ").run(o, s, c, l, u, JSON.stringify(f), d, i);
1556
+ else {
1557
+ let e = await t.prepare("\n INSERT INTO trees (key, label, treeType, channelId, isHidden, dataJson, createdById, updatedById) \n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n ").run(o, s, c, l, u, JSON.stringify(f), d, d);
1558
+ p = Number(e.lastInsertRowid);
1559
+ }
1560
+ if (n.channels !== void 0 && Array.isArray(n.channels) && p) {
1561
+ await t.prepare("DELETE FROM channel_trees WHERE treeId = ?").run(p);
1562
+ let e = [...new Set(n.channels)].filter((e) => e && e !== "all").map((e) => Number(e) || e);
1563
+ if (e.length > 0) {
1564
+ let n = e.map(() => "(?, ?, ?)").join(", "), r = e.flatMap((e) => [
1565
+ e,
1566
+ p,
1567
+ "main"
1568
+ ]);
1569
+ await t.prepare(`INSERT OR IGNORE INTO channel_trees (channelId, treeId, key) VALUES ${n}`).run(...r);
1570
+ }
1571
+ }
1572
+ return await z(e).clear(), e.json({
1573
+ success: !0,
1574
+ id: p,
1575
+ key: o,
1576
+ label: s,
1577
+ treeType: c,
1578
+ channelId: l,
1579
+ channels: n.channels || [],
1580
+ isHidden: !!u,
1581
+ ...f
1582
+ });
1583
+ } catch (t) {
1584
+ return console.error("[API Trees] Error saving tree:", t), e.json({ error: t.message || "Failed to save tree" }, 500);
1585
+ }
1586
+ }), G.delete("/trees.json", async (e) => {
1587
+ let t = e.get("db"), n = e.req.query("id");
1588
+ if (!n) return e.json({ error: "Tree ID required" }, 400);
1589
+ let r = Number(n);
1590
+ try {
1591
+ 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 z(e).clear(), e.json({
1592
+ success: !0,
1593
+ deletedTreeId: r
1594
+ });
1595
+ } catch {
1596
+ return e.json({ error: "Failed to delete tree" }, 500);
1597
+ }
1598
+ });
1599
+ //#endregion
1600
+ //#region server/routes/admin/channels.ts
1601
+ var K = new t();
1602
+ K.get("/", async (e) => {
1603
+ try {
1604
+ 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) => {
1605
+ e[t.channelId] || (e[t.channelId] = []);
1606
+ let n = {};
1607
+ try {
1608
+ n = typeof t.metaJson == "string" ? JSON.parse(t.metaJson) : t.metaJson || {};
1609
+ } catch {}
1610
+ return e[t.channelId].push({
1611
+ treeId: t.treeId,
1612
+ key: t.key,
1613
+ meta: n
1614
+ }), e;
1615
+ }, {}), o = (r || []).map((e) => {
1616
+ let t = {};
1617
+ try {
1618
+ t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson || "{}") : e.dataJson || {};
1619
+ } catch {}
1620
+ return {
1621
+ ...e,
1622
+ ...t,
1623
+ isHidden: !!e.isHidden,
1624
+ trees: a[e.id] || []
1625
+ };
1626
+ }), s = e.env?.BUNDLED_DEFINITIONS, c = U(s)?.channelTemplate || {
1627
+ label: "Channel Settings",
1628
+ fields: {
1629
+ key: {
1630
+ type: "text",
1631
+ label: "Channel API Key",
1632
+ required: !0
1633
+ },
1634
+ label: {
1635
+ type: "text",
1636
+ label: "Channel Name",
1637
+ required: !0
1638
+ },
1639
+ channelType: {
1640
+ type: "text",
1641
+ label: "Channel Type"
1642
+ },
1643
+ domain: {
1644
+ type: "text",
1645
+ label: "Domain Hostname"
1646
+ },
1647
+ baseUrl: {
1648
+ type: "text",
1649
+ label: "Base URL"
1650
+ },
1651
+ defaultLanguage: {
1652
+ type: "text",
1653
+ label: "Default Language"
1654
+ }
1655
+ }
1656
+ };
1657
+ return e.json({
1658
+ schema: c,
1659
+ channels: o
1660
+ });
1661
+ } catch (t) {
1662
+ return console.error("[CMS Channels API] GET Error:", t), e.json({
1663
+ schema: null,
1664
+ channels: [],
1665
+ error: t.message
1666
+ }, 500);
1667
+ }
1668
+ }), K.post("/", async (e) => {
1669
+ try {
1670
+ 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;
1671
+ if (await t.prepare("SELECT id FROM channels WHERE key = ? AND id != ? LIMIT 1").get(y, i ?? -1)) return e.json({
1672
+ error: `Channel API key "${y}" is already in use.`,
1673
+ field: "key"
1674
+ }, 409);
1675
+ let w = i;
1676
+ 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);
1677
+ else {
1678
+ 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);
1679
+ w = Number(e.lastInsertRowid);
1680
+ }
1681
+ await t.prepare("DELETE FROM channel_trees WHERE channelId = ?").run(w);
1682
+ let T = x.filter((e) => e && e.treeId && e.key);
1683
+ if (T.length > 0) {
1684
+ let e = T.map(() => "(?, ?, ?, ?)").join(", "), n = T.flatMap((e) => [
1685
+ w,
1686
+ Number(e.treeId) || e.treeId,
1687
+ String(e.key).trim(),
1688
+ JSON.stringify(e.meta || {})
1689
+ ]);
1690
+ await t.prepare(`
1691
+ INSERT INTO channel_trees (channelId, treeId, key, metaJson)
1692
+ VALUES ${e}
1693
+ `).run(...n);
1694
+ }
1695
+ return await z(e).clear(), e.json({
1696
+ success: !0,
1697
+ id: w
1698
+ });
1699
+ } catch (t) {
1700
+ return console.error("[API Channels] Error saving channel:", t), e.json({
1701
+ error: "Failed to save channel",
1702
+ details: t.message
1703
+ }, 500);
1704
+ }
1705
+ }), K.delete("/", async (e) => {
1706
+ let t = e.get("db"), n = e.req.query("id");
1707
+ if (!n) return e.json({ error: "Channel ID required" }, 400);
1708
+ let r = Number(n);
1709
+ try {
1710
+ 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 z(e).clear(), e.json({
1711
+ success: !0,
1712
+ deletedSiteId: r
1713
+ });
1714
+ } catch (t) {
1715
+ return console.error("[API Channels] Error deleting channel:", t), e.json({
1716
+ error: "Failed to delete channel from database",
1717
+ details: t.message
1718
+ }, 500);
1719
+ }
1720
+ });
1721
+ //#endregion
1722
+ //#region server/routes/admin/schemas.ts
1723
+ var q = new t(), Ee = null, De = (e) => {
1724
+ try {
1725
+ if (!Ee) {
1726
+ let t = e.env?.BUNDLED_DEFINITIONS, n = _e(t), r = n.userTemplate || {
1727
+ id: "userTemplate",
1728
+ label: "User Account",
1729
+ fields: {
1730
+ email: {
1731
+ type: "email",
1732
+ label: "Email Address",
1733
+ required: !0
1734
+ },
1735
+ name: {
1736
+ type: "text",
1737
+ label: "Full Name",
1738
+ required: !0
1739
+ },
1740
+ globalRole: {
1741
+ type: "select",
1742
+ label: "Global Role",
1743
+ required: !0,
1744
+ default: "editor",
1745
+ options: [
1746
+ {
1747
+ label: "Superadmin",
1748
+ value: "superadmin"
1749
+ },
1750
+ {
1751
+ label: "Editor",
1752
+ value: "editor"
1753
+ },
1754
+ {
1755
+ label: "Viewer",
1756
+ value: "viewer"
1757
+ }
1758
+ ]
1759
+ }
1760
+ }
1761
+ };
1762
+ Ee = {
1763
+ channelTemplate: n.channelTemplate || null,
1764
+ treeTemplate: n.treeTemplate || null,
1765
+ userTemplate: r,
1766
+ channelSchemas: n.channels || n.channelSchemas || {},
1767
+ treeSchemas: n.trees || n.treeSchemas || {},
1768
+ nodes: n.nodes || n.nodeSchemas || {},
1769
+ blocks: n.blocks || n.elements || {},
1770
+ nodeLayouts: n.nodeLayouts || {},
1771
+ blockLayouts: n.blockLayouts || {}
1772
+ };
1773
+ }
1774
+ return e.json(Ee, 200, { "Cache-Control": "public, max-age=300, stale-while-revalidate=86400" });
1775
+ } catch (t) {
1776
+ return console.error("[CMS API] Error loading schemas:", t), e.json({
1777
+ error: "Failed to load schemas",
1778
+ details: t.message
1779
+ }, 500);
1780
+ }
1781
+ };
1782
+ q.get("/", De), q.get("/schemas.json", De);
1783
+ //#endregion
1784
+ //#region server/routes/admin/validation.ts
1785
+ var Oe = new t(), ke = {
1786
+ node: "content_nodes",
1787
+ nodes: "content_nodes",
1788
+ content_node: "content_nodes",
1789
+ content_nodes: "content_nodes",
1790
+ channel: "channels",
1791
+ channels: "channels",
1792
+ tree: "trees",
1793
+ trees: "trees",
1794
+ user: "users",
1795
+ users: "users",
1796
+ user_account: "user_accounts"
1797
+ }, Ae = {
1798
+ content_nodes: [
1799
+ "id",
1800
+ "title",
1801
+ "slug",
1802
+ "language",
1803
+ "contentType",
1804
+ "isHidden",
1805
+ "status",
1806
+ "createdById",
1807
+ "updatedById",
1808
+ "createdAt",
1809
+ "updatedAt"
1810
+ ],
1811
+ channels: [
1812
+ "id",
1813
+ "key",
1814
+ "label",
1815
+ "channelType",
1816
+ "domain",
1817
+ "baseUrl",
1818
+ "defaultLanguage",
1819
+ "isHidden",
1820
+ "createdById",
1821
+ "updatedById",
1822
+ "createdAt",
1823
+ "updatedAt"
1824
+ ],
1825
+ trees: [
1826
+ "id",
1827
+ "key",
1828
+ "label",
1829
+ "treeType",
1830
+ "channelId",
1831
+ "isHidden",
1832
+ "createdById",
1833
+ "updatedById",
1834
+ "createdAt",
1835
+ "updatedAt"
1836
+ ],
1837
+ users: [
1838
+ "id",
1839
+ "email",
1840
+ "name",
1841
+ "globalRole",
1842
+ "createdAt",
1843
+ "updatedAt"
1844
+ ],
1845
+ user_accounts: [
1846
+ "id",
1847
+ "userId",
1848
+ "provider",
1849
+ "providerAccountId",
1850
+ "passwordHash",
1851
+ "createdAt"
1852
+ ]
1853
+ };
1854
+ Oe.post("/validate-unique", async (e) => {
1855
+ try {
1856
+ let t = e.get("db"), { entityType: n, field: r, value: i, excludeId: a } = await e.req.json();
1857
+ if (!r || i == null || String(i).trim() === "") return e.json({ isUnique: !0 });
1858
+ let o = ke[n] || "content_nodes", s = r.replace(/[^a-zA-Z0-9_]/g, ""), c = (Ae[o] || Ae.content_nodes).includes(s), l = -1;
1859
+ if (a != null && String(a).trim() !== "") {
1860
+ let e = Number(a);
1861
+ l = isNaN(e) ? String(a) : e;
1862
+ }
1863
+ let u = "";
1864
+ u = c ? `SELECT id FROM ${o} WHERE "${s}" = ? AND id != ? LIMIT 1` : `SELECT id FROM ${o} WHERE json_extract(dataJson, '$.${s}') = ? AND id != ? LIMIT 1`;
1865
+ let d = await t.prepare(u).get(String(i).trim(), l);
1866
+ return e.json({ isUnique: !d });
1867
+ } catch (t) {
1868
+ return console.error("[API Validation] Error validating global uniqueness:", t), e.json({ error: "Failed to validate uniqueness" }, 500);
1869
+ }
1870
+ }), Oe.post("/validate-unique-sibling", async (e) => {
1871
+ try {
1872
+ let t = e.get("db"), { slug: n, treeId: r, parentId: i, excludeTreeNodeId: a } = await e.req.json();
1873
+ if (!n || !String(n).trim() || !r) return e.json({ isUnique: !0 });
1874
+ let o = String(n).trim().toLowerCase(), s = i === void 0 || i === "null" || i === "" ? null : i, c = s === null ? "tn.parentId IS NULL" : "tn.parentId = ?", l = s === null ? [r, o] : [
1875
+ r,
1876
+ s,
1877
+ o
1878
+ ], u = "";
1879
+ a && !String(a).startsWith("draft-") && (u = "AND tn.id != ? AND tn.contentId != ?", l.push(a, a));
1880
+ let d = `
1881
+ SELECT 1
1882
+ FROM tree_nodes tn
1883
+ INNER JOIN content_nodes cn ON tn.contentId = cn.id
1884
+ WHERE tn.treeId = ?
1885
+ AND ${c}
1886
+ AND cn.slug = ?
1887
+ ${u}
1888
+ LIMIT 1
1889
+ `, f = await t.prepare(d).get(...l);
1890
+ return e.json({ isUnique: !f });
1891
+ } catch (t) {
1892
+ return console.error("[Validation Endpoint] Error validating unique sibling:", t), e.json({ isUnique: !0 });
1893
+ }
1894
+ });
1895
+ //#endregion
1896
+ //#region server/routes/admin/stats.ts
1897
+ var je = new t();
1898
+ je.get("/", async (e) => {
1899
+ try {
1900
+ 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) => ({
1901
+ ...e,
1902
+ isHidden: !!e.isHidden
1903
+ })), d = await t.prepare("\n SELECT \n cn.id, \n cn.title, \n cn.slug, \n cn.contentType, \n cn.isHidden, \n cn.status, \n cn.updatedAt,\n GROUP_CONCAT(DISTINCT ch.label) as channelLabels,\n GROUP_CONCAT(DISTINCT t.label) as treeLabels\n FROM content_nodes cn\n LEFT JOIN node_channels nc ON cn.id = nc.nodeId\n LEFT JOIN channels ch ON nc.channelId = ch.id\n LEFT JOIN tree_nodes tn ON cn.id = tn.contentId\n LEFT JOIN trees t ON tn.treeId = t.id\n WHERE cn.status = 'draft' \n OR (cn.draftDataJson IS NOT NULL AND cn.draftDataJson != COALESCE(cn.publishedDataJson, ''))\n GROUP BY cn.id\n ORDER BY cn.updatedAt DESC\n LIMIT 10\n ").all(), f = (Array.isArray(d) ? d : d?.results || []).map((e) => ({
1904
+ id: e.id,
1905
+ title: e.title,
1906
+ slug: e.slug,
1907
+ contentType: e.contentType,
1908
+ status: e.status,
1909
+ updatedAt: e.updatedAt,
1910
+ isHidden: !!e.isHidden,
1911
+ channelNames: e.channelLabels ? e.channelLabels.split(",") : [],
1912
+ treeNames: e.treeLabels ? e.treeLabels.split(",") : []
1913
+ })), p = e.env?.BUNDLED_DEFINITIONS, m = _e(p), h = m.nodes || m.nodeSchemas || {}, g = c.map((e) => {
1914
+ let t = e.type || "node", n = h[t]?.label || t.charAt(0).toUpperCase() + t.slice(1);
1915
+ return {
1916
+ type: t,
1917
+ count: Number(e.count) || 0,
1918
+ label: n
1919
+ };
1920
+ });
1921
+ return e.json({
1922
+ total: r,
1923
+ published: i,
1924
+ hidden: a,
1925
+ totalChannels: Number(o?.totalChannels) || 0,
1926
+ totalTrees: Number(o?.totalTrees) || 0,
1927
+ totalUsers: Number(o?.totalUsers) || 0,
1928
+ byType: g,
1929
+ recentActivity: u,
1930
+ pendingNodes: f
1931
+ });
1932
+ } catch (t) {
1933
+ return console.error("[CMS Admin Stats API] Error fetching stats:", t), e.json({
1934
+ error: "Failed to fetch dashboard statistics",
1935
+ details: t.message
1936
+ }, 500);
1937
+ }
1938
+ });
1939
+ //#endregion
1940
+ //#region server/storage/provider.ts
1941
+ var Me = class {
1942
+ bucket;
1943
+ publicDomain;
1944
+ constructor(e, t) {
1945
+ this.bucket = e, this.publicDomain = t;
1946
+ }
1947
+ async upload(e, t = "uploads") {
1948
+ let n = e.name.split(".").pop()?.toLowerCase() || "bin", r = `${t}/${crypto.randomUUID().replace(/-/g, "")}.${n}`;
1949
+ return await this.bucket.put(r, await e.arrayBuffer(), { httpMetadata: { contentType: e.type } }), {
1950
+ key: r,
1951
+ url: `https://${this.publicDomain}/${r}`
1952
+ };
1953
+ }
1954
+ async delete(e) {
1955
+ await this.bucket.delete(e);
1956
+ }
1957
+ }, Ne = class {
1958
+ customStoragePath;
1959
+ constructor(e) {
1960
+ this.customStoragePath = e;
1961
+ }
1962
+ async upload(e, t = "uploads") {
1963
+ let n = await Promise.resolve().then(() => /* @__PURE__ */ S(w(), 1)), r = await import("node:path"), i = e.name.split(".").pop()?.toLowerCase() || "bin", a = `${t}/${crypto.randomUUID().replace(/-/g, "")}.${i}`, o = this.customStoragePath || "./public/media", s = r.resolve(process.cwd(), o), c = r.join(s, a);
1964
+ await n.mkdir(r.dirname(c), { recursive: !0 });
1965
+ let l = Buffer.from(await e.arrayBuffer());
1966
+ return await n.writeFile(c, l), {
1967
+ key: a,
1968
+ url: `/media/${a}`
1969
+ };
1970
+ }
1971
+ async delete(e) {
1972
+ let t = await Promise.resolve().then(() => /* @__PURE__ */ S(w(), 1)), n = await import("node:path"), r = this.customStoragePath || "./public/media", i = n.resolve(process.cwd(), r), a = n.join(i, e);
1973
+ try {
1974
+ await t.unlink(a);
1975
+ } catch (e) {
1976
+ if (e.code !== "ENOENT") throw e;
1977
+ }
1978
+ }
1979
+ };
1980
+ function Pe(e) {
1981
+ if (e.MEDIA_BUCKET) {
1982
+ let t = e.CDN_DOMAIN || "cdn.yourdomain.com";
1983
+ return new Me(e.MEDIA_BUCKET, t);
1984
+ }
1985
+ return new Ne(e.LOCAL_MEDIA_PATH);
1986
+ }
1987
+ //#endregion
1988
+ //#region server/routes/admin/assets.ts
1989
+ var J = new t();
1990
+ async function Y(e, t, n = []) {
1991
+ let r = e.prepare(t);
1992
+ if (typeof r.bind == "function") {
1993
+ let e = await r.bind(...n).all();
1994
+ return e?.results || e || [];
1995
+ }
1996
+ if (typeof r.all == "function") {
1997
+ let e = await r.all(...n);
1998
+ return Array.isArray(e) ? e : e?.results || [];
1999
+ }
2000
+ return [];
2001
+ }
2002
+ async function X(e, t, n = []) {
2003
+ let r = e.prepare(t);
2004
+ if (typeof r.bind == "function") return await r.bind(...n).run();
2005
+ if (typeof r.run == "function") return await r.run(...n);
2006
+ }
2007
+ function Z(e, t, n) {
2008
+ let r = e || (t ? `/media/${t}` : "");
2009
+ return r && n && r.startsWith(`https://${n}/`) && !r.includes("/media/") && (r = r.replace(`https://${n}/`, `https://${n}/media/`)), r;
2010
+ }
2011
+ J.get("/", async (e) => {
2012
+ try {
2013
+ let t = O(e), { search: n = "", type: r = "all", page: i = "1", limit: a = "24", sort: o = "createdAt", order: s = "DESC", nodeId: c, channelId: l, trashed: u } = e.req.query(), d = Math.max(1, parseInt(i, 10) || 1), f = Math.max(1, Math.min(100, parseInt(a, 10) || 24)), p = (d - 1) * f, m = {
2014
+ createdAt: "a.createdAt",
2015
+ updatedAt: "a.updatedAt",
2016
+ filename: "a.filename",
2017
+ mimeType: "a.mimeType",
2018
+ sizeBytes: "a.sizeBytes"
2019
+ }[o] || "a.createdAt", h = s.toUpperCase() === "ASC" ? "ASC" : "DESC", g = [], _ = ["(a.isSystemVariant = 0 OR a.isSystemVariant IS NULL)", u === "true" || u === "1" ? "(a.deletedAt IS NOT NULL AND a.deletedAt != '')" : "(a.deletedAt IS NULL OR a.deletedAt = '')"];
2020
+ if (c) {
2021
+ let e = await Y(t, "\n SELECT a.id, a.filename, a.isSystemVariant \n FROM node_assets na \n JOIN assets a ON na.assetId = a.id \n WHERE na.nodeId = ?\n ", [Number(c)]);
2022
+ if (e.length === 0) _.push("1 = 0");
2023
+ else {
2024
+ let t = e.map((e) => e.isSystemVariant ? `(
2025
+ a.id = '${e.id}' OR
2026
+ '${e.filename}' LIKE '%' || a.id || '%' OR
2027
+ '${e.filename}' LIKE 'crop_%' || REPLACE(REPLACE(REPLACE(a.filename, '.jpg', ''), '.png', ''), '.jpeg', '') || '%'
2028
+ )` : `a.id = '${e.id}'`).join(" OR ");
2029
+ _.push(`(${t})`);
2030
+ }
2031
+ }
2032
+ if (!c && l && l !== "all") {
2033
+ let e = Number(l) || l;
2034
+ _.push("(\n EXISTS (\n SELECT 1 FROM node_assets na_ch\n INNER JOIN node_channels nc_ch ON na_ch.nodeId = nc_ch.nodeId\n WHERE na_ch.assetId = a.id AND nc_ch.channelId = ?\n )\n OR NOT EXISTS (SELECT 1 FROM node_assets na_unused WHERE na_unused.assetId = a.id)\n )"), g.push(e);
2035
+ }
2036
+ n && n.trim() !== "" && (_.push("a.filename LIKE ?"), g.push(`%${n.trim()}%`)), r && r !== "all" && (r === "image" ? (_.push("a.mimeType LIKE ?"), g.push("image/%")) : r === "document" ? (_.push("(a.mimeType LIKE ? OR a.mimeType LIKE ? OR a.mimeType LIKE ?)"), g.push("application/pdf%", "application/msword%", "application/vnd%")) : r === "video" && (_.push("(a.mimeType LIKE ? OR a.mimeType LIKE ?)"), g.push("video/%", "audio/%")));
2037
+ let v = `
2038
+ SELECT a.id, a.filename, a.mimeType, a.sizeBytes, a.cdnUrl, a.storageKeyPrivate, a.createdAt, a.updatedAt, a.deletedAt, a.dataJson
2039
+ FROM assets a
2040
+ ${` WHERE ${_.join(" AND ")}`}
2041
+ ORDER BY ${m} ${h}
2042
+ LIMIT ? OFFSET ?
2043
+ `;
2044
+ g.push(f, p);
2045
+ let y = await Y(t, v, g), b = y.map((e) => e.id), x = /* @__PURE__ */ new Map();
2046
+ b.length > 0 && (await Y(t, `
2047
+ SELECT master.id AS assetId, COUNT(DISTINCT na.nodeId) AS count
2048
+ FROM assets master
2049
+ INNER JOIN node_assets na ON (
2050
+ na.assetId = master.id
2051
+ OR EXISTS (
2052
+ SELECT 1 FROM assets crop
2053
+ WHERE crop.id = na.assetId
2054
+ AND crop.isSystemVariant = 1
2055
+ AND (
2056
+ crop.filename LIKE 'crop_%' || REPLACE(REPLACE(REPLACE(master.filename, '.jpg', ''), '.png', ''), '.jpeg', '') || '%'
2057
+ OR crop.filename LIKE '%' || master.id || '%'
2058
+ )
2059
+ )
2060
+ )
2061
+ WHERE master.id IN (${b.map(() => "?").join(",")})
2062
+ GROUP BY master.id
2063
+ `, b)).forEach((e) => {
2064
+ x.set(String(e.assetId), e.count || 0);
2065
+ });
2066
+ let S = y.map((t) => {
2067
+ let n = {
2068
+ title: "",
2069
+ alt: ""
2070
+ };
2071
+ try {
2072
+ n = JSON.parse(t.dataJson || "{}");
2073
+ } catch {}
2074
+ let r = Z(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN);
2075
+ return {
2076
+ id: t.id,
2077
+ filename: t.filename || "Untitled Asset",
2078
+ mimeType: t.mimeType || "application/octet-stream",
2079
+ sizeBytes: t.sizeBytes || 0,
2080
+ title: n.title || "",
2081
+ alt: n.alt || "",
2082
+ createdAt: t.createdAt,
2083
+ updatedAt: t.updatedAt,
2084
+ deletedAt: t.deletedAt || null,
2085
+ usageCount: x.get(String(t.id)) || 0,
2086
+ url: r,
2087
+ originalUrl: r
2088
+ };
2089
+ });
2090
+ return e.json(S);
2091
+ } catch (t) {
2092
+ return console.error("❌ [Asset List Error]:", t), e.json({
2093
+ error: "Failed to fetch assets",
2094
+ details: t.message || String(t)
2095
+ }, 500);
2096
+ }
2097
+ }), J.post("/upload", async (e) => {
2098
+ try {
2099
+ let t = O(e), n = Pe(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;
2100
+ s && (await Y(t, "SELECT id FROM assets WHERE id = ?", [s])).length === 0 && (s = null);
2101
+ let c = r.cropCoordinates, l = null, u = null;
2102
+ if (c) {
2103
+ if (typeof c == "string") {
2104
+ l = c;
2105
+ try {
2106
+ u = JSON.parse(c);
2107
+ } catch {}
2108
+ } else l = JSON.stringify(c), u = c;
2109
+ }
2110
+ if (!i || !(i instanceof File)) return e.json({ error: "No file uploaded" }, 400);
2111
+ let d = crypto.randomUUID().replace(/-/g, "").slice(0, 12), f = `ast_${d}`, p = (/* @__PURE__ */ new Date()).toISOString().slice(0, 7).replace("-", "/"), m = a || i.name.startsWith("crop_"), h = m ? `kama/cache/${p}` : `kama/uploads/${p}`, g = await n.upload(i, h), _ = typeof g == "string" ? g : g?.key || g?.storageKeyPrivate || g?.storageKey || `${h}/${d}_${i.name}`;
2112
+ if (!_) throw Error("Storage provider failed to return a valid storage key");
2113
+ let v = e.env.CDN_DOMAIN, y = _.replace(/^\//, ""), b = v ? `https://${v}/media/${y}` : `/media/${y}`, x = i.type || "application/octet-stream", S = i.size || 0, C = e.get("userId"), w = typeof C == "string" && C.trim().length > 0 ? C : null;
2114
+ w && (await Y(t, "SELECT id FROM users WHERE id = ?", [w])).length === 0 && (w = null);
2115
+ let T = +!!m;
2116
+ await X(t, "\n INSERT INTO assets (id, filename, mimeType, sizeBytes, storageKeyPrivate, cdnUrl, createdById, isSystemVariant, parentAssetId, cropCoordinatesJson)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ", [
2117
+ f,
2118
+ i.name,
2119
+ x,
2120
+ S,
2121
+ _,
2122
+ b,
2123
+ w,
2124
+ T,
2125
+ s,
2126
+ l
2127
+ ]);
2128
+ let E = b;
2129
+ if (s) {
2130
+ let e = await Y(t, "SELECT cdnUrl, storageKeyPrivate FROM assets WHERE id = ?", [s]);
2131
+ e.length > 0 && (E = Z(e[0].cdnUrl, e[0].storageKeyPrivate, v));
2132
+ }
2133
+ return e.json({
2134
+ id: f,
2135
+ url: b,
2136
+ originalUrl: E,
2137
+ parentAssetId: s,
2138
+ cropCoordinates: u,
2139
+ filename: i.name,
2140
+ mimeType: x,
2141
+ usageCount: 0,
2142
+ isSystemVariant: !!T
2143
+ }, 201);
2144
+ } catch (t) {
2145
+ return console.error("❌ [Asset Upload Crash Details]:", t), e.json({
2146
+ error: "Upload failed",
2147
+ details: t.message || String(t)
2148
+ }, 500);
2149
+ }
2150
+ }), J.get("/:id/details", async (e) => {
2151
+ try {
2152
+ let t = O(e), n = e.req.param("id"), r = await Y(t, "SELECT * FROM assets WHERE id = ?", [n]);
2153
+ if (!r || r.length === 0) return e.json({ error: "Asset not found" }, 404);
2154
+ let i = r[0], a = i.filename ? i.filename.replace(/\.[^/.]+$/, "") : "", o = await Y(t, "\n SELECT DISTINCT cn.id, cn.title, cn.contentType, cn.slug, na.fieldKey, na.assetId \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 na.assetId = ?\n OR (crop.isSystemVariant = 1 AND (crop.filename LIKE ? OR crop.filename LIKE ?))\n ", [
2155
+ n,
2156
+ `crop_%${a}%`,
2157
+ `%${n}%`
2158
+ ]), s = await Y(t, "\n SELECT id, filename, mimeType, sizeBytes, cdnUrl, storageKeyPrivate, parentAssetId, cropCoordinatesJson, createdAt \n FROM assets \n WHERE isSystemVariant = 1 \n AND (parentAssetId = ? OR filename LIKE ? OR filename LIKE ?)\n ORDER BY createdAt DESC\n ", [
2159
+ n,
2160
+ `crop_%${a}%`,
2161
+ `%${n}%`
2162
+ ]), c = {
2163
+ title: "",
2164
+ alt: ""
2165
+ };
2166
+ try {
2167
+ c = JSON.parse(i.dataJson || "{}");
2168
+ } catch {}
2169
+ let l = Z(i.cdnUrl, i.storageKeyPrivate, e.env?.CDN_DOMAIN);
2170
+ return e.json({
2171
+ id: i.id,
2172
+ filename: i.filename,
2173
+ mimeType: i.mimeType,
2174
+ sizeBytes: i.sizeBytes,
2175
+ createdAt: i.createdAt,
2176
+ updatedAt: i.updatedAt,
2177
+ title: c.title || "",
2178
+ alt: c.alt || "",
2179
+ url: l,
2180
+ originalUrl: l,
2181
+ connectedNodes: o,
2182
+ variants: s.map((t) => {
2183
+ let n = null;
2184
+ if (t.cropCoordinatesJson) try {
2185
+ n = JSON.parse(t.cropCoordinatesJson);
2186
+ } catch {}
2187
+ return {
2188
+ id: t.id,
2189
+ filename: t.filename,
2190
+ mimeType: t.mimeType,
2191
+ sizeBytes: t.sizeBytes,
2192
+ createdAt: t.createdAt,
2193
+ parentAssetId: t.parentAssetId || i.id,
2194
+ cropCoordinates: n,
2195
+ url: Z(t.cdnUrl, t.storageKeyPrivate, e.env?.CDN_DOMAIN),
2196
+ originalUrl: l
2197
+ };
2198
+ })
2199
+ });
2200
+ } catch (t) {
2201
+ return console.error("❌ [Asset Details Error]:", t), e.json({ error: "Failed to load details" }, 500);
2202
+ }
2203
+ }), J.put("/:id", async (e) => {
2204
+ try {
2205
+ let t = O(e), n = e.req.param("id"), r = await e.req.json(), i = await Y(t, "SELECT filename, dataJson FROM assets WHERE id = ?", [n]);
2206
+ if (!i || i.length === 0) return e.json({ error: "Asset not found" }, 404);
2207
+ let a = i[0], o = {};
2208
+ try {
2209
+ o = JSON.parse(a.dataJson || "{}");
2210
+ } catch {}
2211
+ return r.title !== void 0 && (o.title = r.title), r.alt !== void 0 && (o.alt = r.alt), await X(t, "UPDATE assets SET filename = ?, dataJson = ?, updatedAt = CURRENT_TIMESTAMP WHERE id = ?", [
2212
+ r.filename === void 0 ? a.filename : r.filename,
2213
+ JSON.stringify(o),
2214
+ n
2215
+ ]), e.json({ success: !0 });
2216
+ } catch (t) {
2217
+ return console.error("❌ [Asset Update Error]:", t), e.json({ error: "Failed to update asset" }, 500);
2218
+ }
2219
+ }), J.delete("/:id", async (e) => {
2220
+ try {
2221
+ let t = O(e), n = e.req.param("id"), r = (await Y(t, "SELECT id, filename, isSystemVariant FROM assets WHERE id = ?", [n]))[0];
2222
+ return r ? (r.isSystemVariant ? await X(t, "UPDATE assets SET deletedAt = CURRENT_TIMESTAMP WHERE id = ?", [n]) : await X(t, "UPDATE assets\n SET deletedAt = CURRENT_TIMESTAMP\n WHERE id = ? OR parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
2223
+ n,
2224
+ n,
2225
+ `crop_%${r.filename ? r.filename.replace(/\.[^/.]+$/, "") : ""}%`,
2226
+ `%${n}%`
2227
+ ]), e.json({
2228
+ success: !0,
2229
+ id: n,
2230
+ trashed: !0
2231
+ })) : e.json({ error: "Asset not found" }, 404);
2232
+ } catch (t) {
2233
+ return console.error("❌ [Asset Soft Delete Error]:", t), e.json({
2234
+ error: "Failed to move asset to trash",
2235
+ details: t.message || String(t)
2236
+ }, 500);
2237
+ }
2238
+ }), J.post("/restore", async (e) => {
2239
+ try {
2240
+ let t = O(e), n = await e.req.json(), r = n.id || n.assetId;
2241
+ if (!r) return e.json({ error: "Asset ID required" }, 400);
2242
+ let i = (await Y(t, "SELECT id, filename FROM assets WHERE id = ?", [r]))[0];
2243
+ return i ? (await X(t, "UPDATE assets \n SET deletedAt = NULL \n WHERE id = ? OR parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
2244
+ r,
2245
+ r,
2246
+ `crop_%${i.filename ? i.filename.replace(/\.[^/.]+$/, "") : ""}%`,
2247
+ `%${r}%`
2248
+ ]), e.json({
2249
+ success: !0,
2250
+ id: r,
2251
+ restored: !0
2252
+ })) : e.json({ error: "Asset not found" }, 404);
2253
+ } catch (t) {
2254
+ return console.error("❌ [Asset Restore Error]:", t), e.json({
2255
+ error: "Failed to restore asset",
2256
+ details: t.message
2257
+ }, 500);
2258
+ }
2259
+ }), J.delete("/purge/:id", async (e) => {
2260
+ try {
2261
+ let t = O(e), n = Pe(e.env), r = e.req.param("id"), i = (await Y(t, "SELECT id, filename, storageKeyPrivate, isSystemVariant FROM assets WHERE id = ?", [r]))[0];
2262
+ if (!i) return e.json({ error: "Asset not found" }, 404);
2263
+ let a = [i];
2264
+ i.isSystemVariant || (a = [i, ...await Y(t, "SELECT id, storageKeyPrivate FROM assets \n WHERE parentAssetId = ? OR (isSystemVariant = 1 AND (filename LIKE ? OR filename LIKE ?))", [
2265
+ r,
2266
+ `crop_%${i.filename ? i.filename.replace(/\.[^/.]+$/, "") : ""}%`,
2267
+ `%${r}%`
2268
+ ])]);
2269
+ let o = a.map((e) => e.id);
2270
+ if (typeof n.delete == "function") {
2271
+ for (let e of a) if (e.storageKeyPrivate) try {
2272
+ await n.delete(e.storageKeyPrivate);
2273
+ } catch (t) {
2274
+ console.warn(`⚠️ Failed to purge storage file ${e.storageKeyPrivate}:`, t);
2275
+ }
2276
+ }
2277
+ let s = o.map(() => "?").join(",");
2278
+ return await X(t, `DELETE FROM node_assets WHERE assetId IN (${s})`, o), await X(t, `DELETE FROM assets WHERE id IN (${s})`, o), e.json({
2279
+ success: !0,
2280
+ id: r,
2281
+ purged: !0,
2282
+ isSingleVariant: !!i.isSystemVariant,
2283
+ deletedVariantsCount: a.length - 1
2284
+ });
2285
+ } catch (t) {
2286
+ return console.error("❌ [Asset Purge Error]:", t), e.json({
2287
+ error: "Failed to purge asset",
2288
+ details: t.message || String(t)
2289
+ }, 500);
2290
+ }
2291
+ });
2292
+ //#endregion
2293
+ //#region server/routes/public/node.ts
2294
+ var Fe = new t();
2295
+ function Q(e, t) {
2296
+ let n = /* @__PURE__ */ new Date();
2297
+ if (e && String(e).trim() !== "") {
2298
+ let t = new Date(e);
2299
+ if (!isNaN(t.getTime()) && n < t) return !1;
2300
+ }
2301
+ if (t && String(t).trim() !== "") {
2302
+ let e = new Date(t);
2303
+ if (!isNaN(e.getTime()) && n > e) return !1;
2304
+ }
2305
+ return !0;
2306
+ }
2307
+ async function Ie(e, t) {
2308
+ if (!t || typeof t != "object") return t;
2309
+ let n = { ...t };
2310
+ for (let [t, r] of Object.entries(n)) if (typeof r == "string" && r.startsWith("ast_")) try {
2311
+ let i = await e.prepare("SELECT * FROM assets WHERE id = ? AND deletedAt IS NULL").get(r);
2312
+ if (i) {
2313
+ let e = null;
2314
+ if (i.cropCoordinatesJson) try {
2315
+ e = typeof i.cropCoordinatesJson == "string" ? JSON.parse(i.cropCoordinatesJson) : i.cropCoordinatesJson;
2316
+ } catch {}
2317
+ n[t] = {
2318
+ id: i.id,
2319
+ url: i.cdnUrl || `/media/uploads/${i.filename}`,
2320
+ originalUrl: i.cdnUrl || `/media/uploads/${i.filename}`,
2321
+ parentAssetId: i.parentAssetId || null,
2322
+ cropCoordinates: e,
2323
+ filename: i.filename,
2324
+ mimeType: i.mimeType
2325
+ };
2326
+ }
2327
+ } catch {}
2328
+ else typeof r == "object" && r && !Array.isArray(r) && !r.url && (n[t] = await Ie(e, r));
2329
+ return n;
2330
+ }
2331
+ async function Le(e, t, n) {
2332
+ let r = t.filter((e) => e.componentId === "content-feed" || e.componentId === "article-list");
2333
+ for (let t of r) {
2334
+ 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];
2335
+ n && n !== "all" && (s += " AND id IN (SELECT nodeId FROM node_channels WHERE channelId = ?)", c.push(Number(n) || n));
2336
+ let l = "ORDER BY updatedAt DESC";
2337
+ o === "published_desc" || o === "createdAt" ? l = "ORDER BY createdAt DESC" : o === "title_asc" && (l = "ORDER BY LOWER(title) ASC");
2338
+ let u = `SELECT id, title, slug, language, dataJson, createdAt, updatedAt ${s} ${l} LIMIT ?`;
2339
+ c.push(a);
2340
+ try {
2341
+ let n = await e.prepare(u).all(...c), r = Array.isArray(n) ? n : n?.results || [];
2342
+ t.data.initialItems = r.map((e) => {
2343
+ let t = {};
2344
+ if (e.dataJson) try {
2345
+ t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
2346
+ } catch {}
2347
+ return Q(t.startShowingAt, t.stopShowingAt) ? {
2348
+ id: e.id,
2349
+ title: e.title,
2350
+ slug: e.slug,
2351
+ language: e.language || "en",
2352
+ createdAt: e.createdAt,
2353
+ updatedAt: e.updatedAt,
2354
+ excerpt: t.excerpt || "",
2355
+ image: t.image || t.coverImage || null,
2356
+ author: t.author || null
2357
+ } : null;
2358
+ }).filter(Boolean);
2359
+ } catch (e) {
2360
+ console.error("[CMS Hydration] Failed to hydrate content feed block", e), t.data.initialItems = [];
2361
+ }
2362
+ }
2363
+ }
2364
+ async function Re(e, t, n, r, i = !1) {
2365
+ if (!t) return { blocks: [] };
2366
+ 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 || [];
2367
+ if (!o || o.length === 0) return { blocks: [] };
2368
+ for (let t of o) {
2369
+ let a = +!!i, o = await e.prepare("\n SELECT * FROM content_blocks \n WHERE contentId = ? AND isDraft = ?\n ORDER BY sortOrder ASC\n ").all(t.contentId, a), s = Array.isArray(o) ? o : o?.results || [];
2370
+ if (s.length === 0 && !i && (o = await e.prepare("\n SELECT * FROM content_blocks \n WHERE contentId = ?\n ORDER BY sortOrder ASC\n ").all(t.contentId), s = Array.isArray(o) ? o : o?.results || []), s.filter((e) => e.region === n).length > 0) {
2371
+ let a = /* @__PURE__ */ new Set([n]), o = !0;
2372
+ for (; o;) {
2373
+ o = !1;
2374
+ for (let e of s) if (a.has(e.region)) {
2375
+ let t = {};
2376
+ try {
2377
+ t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
2378
+ } catch {}
2379
+ let n = String(e.id), r = String(t.blockId || t._instanceId || t.id || e.blockId);
2380
+ for (let e of s) {
2381
+ if (!e.region) continue;
2382
+ let t = e.region;
2383
+ a.has(t) || (t.startsWith(`${n}-`) || t.startsWith(`${n}_`) || r && r !== "undefined" && r !== "null" && (t.startsWith(`${r}-`) || t.startsWith(`${r}_`) || t.startsWith(r))) && (a.add(t), o = !0);
2384
+ }
2385
+ }
2386
+ }
2387
+ let c = {};
2388
+ for (let t of s) {
2389
+ if (!a.has(t.region)) continue;
2390
+ let o = {};
2391
+ try {
2392
+ o = typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson;
2393
+ } catch {}
2394
+ let s = o.hidden === !0 || o.hidden === 1 || o.hidden === "1" || o.hidden === "true", l = Q(o.startShowingAt, o.stopShowingAt);
2395
+ if (!i && (s || !l)) continue;
2396
+ 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 = ze(o, d);
2397
+ p = await V(e, p), p = await Ie(e, p), p.blockId = f;
2398
+ let m = t.region || n;
2399
+ c[m] || (c[m] = []), c[m].push({
2400
+ instanceId: t.id,
2401
+ blockId: f,
2402
+ componentId: u,
2403
+ data: p
2404
+ });
2405
+ }
2406
+ if (c[n] && c[n].length > 0) return {
2407
+ blocks: c[n],
2408
+ subRegions: c,
2409
+ inheritedFromId: String(t.contentId),
2410
+ inheritedFromTitle: t.title || t.slug
2411
+ };
2412
+ }
2413
+ }
2414
+ return { blocks: [] };
2415
+ }
2416
+ function ze(e, t = {}) {
2417
+ let n = {};
2418
+ for (let [r, i] of Object.entries(e)) {
2419
+ if (r === "disabledRegions" || r === "hidden" || r === "is_hidden" || r === "isHidden" || r === "status" || r === "startShowingAt" || r === "stopShowingAt" || r === "slug" || r === "title" || r === "id" || r.startsWith("_")) continue;
2420
+ let e = t[r];
2421
+ e ? e.public !== !1 && (n[r] = i) : n[r] = i;
2422
+ }
2423
+ return n;
2424
+ }
2425
+ async function Be(e, t, n) {
2426
+ if (!t) return "";
2427
+ 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 = [];
2428
+ for (let e of i) {
2429
+ let t = (e.slug || "").replace(/^\/+|\/+$/g, "");
2430
+ t === "home" || t === "homee" ? i.length === 1 && (a.length = 0) : t && a.push(t);
2431
+ }
2432
+ return "/" + a.join("/");
2433
+ }
2434
+ async function Ve(e, t, n, r, i) {
2435
+ let a = {}, o = null;
2436
+ if (t) {
2437
+ 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([
2438
+ "subpageLayoutId",
2439
+ "layoutId",
2440
+ "slug",
2441
+ "title",
2442
+ "id",
2443
+ "path",
2444
+ "treeNodeId",
2445
+ "nodeType",
2446
+ "contentType",
2447
+ "disabledRegions",
2448
+ "hidden",
2449
+ "status"
2450
+ ]);
2451
+ for (let e of i) {
2452
+ let t = r && e.draftDataJson ? e.draftDataJson : e.dataJson || e.draftDataJson;
2453
+ if (t) try {
2454
+ let e = typeof t == "string" ? JSON.parse(t) : t;
2455
+ !o && e.subpageLayoutId && e.subpageLayoutId !== "inherit" && (o = e.subpageLayoutId);
2456
+ for (let [t, n] of Object.entries(e)) n != null && n !== "" && n !== "inherit" && !s.has(t) && !t.startsWith("_") && a[t] === void 0 && (a[t] = n);
2457
+ } catch {}
2458
+ }
2459
+ }
2460
+ if (!o) {
2461
+ let t = await e.prepare("SELECT dataJson FROM trees WHERE id = ?").get(n);
2462
+ if (t && t.dataJson) try {
2463
+ let e = typeof t.dataJson == "string" ? JSON.parse(t.dataJson) : t.dataJson;
2464
+ e.subpageLayoutId && e.subpageLayoutId !== "inherit" && (o = e.subpageLayoutId);
2465
+ } catch {}
2466
+ }
2467
+ return {
2468
+ resolvedLayoutId: o,
2469
+ inheritedFields: a
2470
+ };
2471
+ }
2472
+ Fe.get("/*", async (e) => {
2473
+ try {
2474
+ 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));
2475
+ if (!s) return e.json({ error: `Channel '${i}' not found` }, 404);
2476
+ let c = s.status === "disabled" || s.status === "inactive" || s.isEnabled === 0 || s.isEnabled === !1;
2477
+ if (!o && c) return e.json({ error: `Channel '${s.key || i}' is currently inactive` }, 404);
2478
+ let l = s.id, u = s.key || i, d = z(e), f = `node:${l || u}:${a}:${r}`;
2479
+ if (!o) {
2480
+ let t = await d.get(f);
2481
+ if (t) return e.header("X-Cache", "HIT"), e.json(t);
2482
+ }
2483
+ let p = U(e.env?.BUNDLED_DEFINITIONS), m = !isNaN(Number(r)) && r.length > 0, h = null, g = null, _ = e.req.query("treeId");
2484
+ 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);
2485
+ else {
2486
+ let e = r.split("/"), n = e[e.length - 1], i = "/" + r.replace(/^\/+|\/+$/g, ""), a = `
2487
+ SELECT cn.*, tn.id as treeNodeId, tn.parentId, tn.treeId
2488
+ FROM content_nodes cn
2489
+ INNER JOIN tree_nodes tn ON cn.id = tn.contentId
2490
+ ${l === null ? "" : "INNER JOIN node_channels nc ON cn.id = nc.nodeId"}
2491
+ WHERE cn.slug = ? ${l === null ? "" : "AND nc.channelId = ?"}
2492
+ `, o = l === null ? [n] : [n, l], s = await t.prepare(a).all(...o), c = Array.isArray(s) ? s : s?.results || [];
2493
+ if (c.length > 0) for (let e of c) {
2494
+ let n = (await Be(t, e.treeNodeId, e.treeId)).replace(/^\/+|\/+$/g, ""), r = i.replace(/^\/+|\/+$/g, "");
2495
+ if (n === r || r === "home" && (n === "" || n === "home")) {
2496
+ h = e, g = e;
2497
+ break;
2498
+ }
2499
+ }
2500
+ !h && e.length === 1 && (h = l === null ? await t.prepare("SELECT * FROM content_nodes WHERE slug = ?").get(n) : await t.prepare("\n SELECT cn.* FROM content_nodes cn\n INNER JOIN node_channels nc ON cn.id = nc.nodeId\n WHERE cn.slug = ? AND nc.channelId = ?\n ").get(n, l));
2501
+ }
2502
+ if (!h) return e.json({ error: `Node '${r}' not found for Channel '${i}'` }, 404);
2503
+ if (!g) {
2504
+ let e = _ ? [h.id, _] : [h.id];
2505
+ g = await t.prepare(`
2506
+ SELECT id as treeNodeId, treeId, parentId
2507
+ FROM tree_nodes
2508
+ WHERE contentId = ? ${_ ? "AND treeId = ?" : ""}
2509
+ LIMIT 1
2510
+ `).get(...e);
2511
+ }
2512
+ let v = g?.treeId || _ || "main-nav", y = g?.parentId || null, b = g?.treeNodeId ? await Be(t, g.treeNodeId, v) : `/${(h.slug || "").replace(/^\/+|\/+$/g, "")}`, x = {
2513
+ id: h.id,
2514
+ title: h.title,
2515
+ slug: h.slug,
2516
+ language: h.language || a || "en",
2517
+ path: b === "" ? "/" : b,
2518
+ nodeType: h.contentType,
2519
+ createdAt: h.createdAt,
2520
+ updatedAt: h.updatedAt
2521
+ }, S = h.contentType || "node", C = p.nodes?.[S] || Object.values(p.nodes || {})[0] || {}, w = { ...C.fields || {} };
2522
+ C.tabs && Object.values(C.tabs).forEach((e) => {
2523
+ Object.assign(w, e.fields || {});
2524
+ });
2525
+ let T = {}, E = null, D = null, O = !1, k = {}, A = o && h.draftDataJson ? h.draftDataJson : h.dataJson || h.draftDataJson;
2526
+ if (A) try {
2527
+ k = typeof A == "string" ? JSON.parse(A) : A;
2528
+ } catch {}
2529
+ 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;
2530
+ let j = k.layoutId, ee = j && j !== "inherit", { resolvedLayoutId: te, inheritedFields: ne } = await Ve(t, y, v, o, w), M = ee ? j : te || C.defaultLayout || null;
2531
+ 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);
2532
+ let N = await V(t, ze(k, w));
2533
+ N = await Ie(t, N), x.slug = h.slug, x.title = h.title, Object.assign(x, N), x.layoutId = M;
2534
+ let re = !!h.isHidden || O, ie = !Q(E, D);
2535
+ if (!o && (re || ie)) return e.json({ error: "Node is hidden or outside its scheduled publishing window" }, 404);
2536
+ let P = [];
2537
+ if (g?.treeNodeId) {
2538
+ 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\n INNER JOIN content_nodes c ON t.contentId = c.id\n WHERE t.parentId = ? AND t.treeId = ?\n ORDER BY t.sortOrder ASC\n ").all(g.treeNodeId, v), n = Array.isArray(e) ? e : e?.results || [], r = x.path === "/" ? "" : x.path;
2539
+ P = n.map((e) => {
2540
+ let t = {}, n = o && e.draftDataJson ? e.draftDataJson : e.dataJson;
2541
+ try {
2542
+ t = typeof n == "string" ? JSON.parse(n) : n;
2543
+ } catch {}
2544
+ let i = !!e.isHidden || t.hidden === !0 || t.hidden === 1 || t.hidden === "1", a = Q(t.startShowingAt, t.stopShowingAt), s = (e.slug || "").replace(/^\/+|\/+$/g, "");
2545
+ return !o && (i || !a) ? null : {
2546
+ treeNodeId: e.treeNodeId,
2547
+ id: e.id,
2548
+ title: e.title,
2549
+ slug: s,
2550
+ language: e.language || "en",
2551
+ path: `${r}/${s}`.replace(/\/+/g, "/"),
2552
+ nodeType: e.nodeType
2553
+ };
2554
+ }).filter(Boolean);
2555
+ }
2556
+ x.children = P;
2557
+ let ae = +!!o, F = await t.prepare("\n SELECT * FROM content_blocks \n WHERE contentId = ? AND isDraft = ? \n ORDER BY sortOrder ASC\n ").all(h.id, ae), I = Array.isArray(F) ? F : F?.results || [];
2558
+ I.length === 0 && !o && (F = await t.prepare("\n SELECT * FROM content_blocks \n WHERE contentId = ?\n ORDER BY sortOrder ASC\n ").all(h.id), I = Array.isArray(F) ? F : F?.results || []);
2559
+ let L = {}, R = {};
2560
+ for (let e of I) {
2561
+ let n = e.region || "main";
2562
+ L[n] || (L[n] = [], R[n] = { isInherited: !1 });
2563
+ let r = {};
2564
+ try {
2565
+ r = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
2566
+ } catch {}
2567
+ let i = r.hidden === !0 || r.hidden === 1 || r.hidden === "1" || r.hidden === "true", a = Q(r.startShowingAt, r.stopShowingAt);
2568
+ if (!o && (i || !a)) continue;
2569
+ 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 = ze(r, c);
2570
+ u = await V(t, u), u.blockId = l, L[n].push({
2571
+ instanceId: e.id,
2572
+ blockId: l,
2573
+ componentId: s,
2574
+ data: u
2575
+ });
2576
+ }
2577
+ let oe = {
2578
+ header: {
2579
+ label: "Header",
2580
+ inherit: "parent"
2581
+ },
2582
+ footer: {
2583
+ label: "Footer",
2584
+ inherit: "parent"
2585
+ },
2586
+ ...(M ? p.nodeLayouts?.[M] || p.layouts?.[M] : null)?.regions || { main: { label: "Content" } }
2587
+ };
2588
+ for (let [e, n] of Object.entries(oe)) {
2589
+ let r = L[e] && L[e].length > 0, i = !!T[e];
2590
+ if (L[e] || (L[e] = [], R[e] = { isInherited: !1 }), (n?.inherit === "parent" || n?.inherit === !0 || n?.inherit === "true" || e === "header" || e === "footer") && !r && !i && y) {
2591
+ let n = await Re(t, y, e, p, o);
2592
+ if (n.blocks.length > 0 && (L[e] = n.blocks, R[e] = {
2593
+ isInherited: !0,
2594
+ inheritedFromId: n.inheritedFromId,
2595
+ inheritedFromTitle: n.inheritedFromTitle
2596
+ }, n.subRegions)) for (let [t, r] of Object.entries(n.subRegions)) t !== e && (L[t] = r, R[t] = {
2597
+ isInherited: !0,
2598
+ inheritedFromId: n.inheritedFromId,
2599
+ inheritedFromTitle: n.inheritedFromTitle
2600
+ });
2601
+ }
2602
+ }
2603
+ for (let e of Object.keys(L)) await Le(t, L[e], l);
2604
+ let se = {
2605
+ channelId: l || u,
2606
+ treeId: v,
2607
+ language: x.language,
2608
+ node: x,
2609
+ content: L,
2610
+ regionMeta: R
2611
+ };
2612
+ return o || (await d.set(f, se, 300), e.header("X-Cache", "MISS")), e.json(se);
2613
+ } catch (t) {
2614
+ return console.error("[CMS Public API] Error fetching node by path:", t), e.json({
2615
+ error: "Failed to fetch JSON payload",
2616
+ details: t.message
2617
+ }, 500);
2618
+ }
2619
+ });
2620
+ //#endregion
2621
+ //#region server/routes/public/tree.ts
2622
+ var He = new t();
2623
+ function Ue(e, t) {
2624
+ let n = /* @__PURE__ */ new Date();
2625
+ if (e && String(e).trim() !== "") {
2626
+ let t = new Date(e);
2627
+ if (!isNaN(t.getTime()) && n < t) return !1;
2628
+ }
2629
+ if (t && String(t).trim() !== "") {
2630
+ let e = new Date(t);
2631
+ if (!isNaN(e.getTime()) && n > e) return !1;
2632
+ }
2633
+ return !0;
2634
+ }
2635
+ He.get("/:treeParam", async (e) => {
2636
+ try {
2637
+ 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";
2638
+ if (r && r !== "default" && r !== "all") {
2639
+ 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));
2640
+ if (n) {
2641
+ let t = n.status === "disabled" || n.status === "inactive" || n.isEnabled === 0 || n.isEnabled === !1;
2642
+ if (!i && t) return e.json({ error: `Channel '${n.key || r}' is currently inactive` }, 404);
2643
+ }
2644
+ }
2645
+ let a = z(e), o = `tree:${r}:${n}`;
2646
+ if (!i) {
2647
+ let t = await a.get(o);
2648
+ if (t) return e.header("X-Cache", "HIT"), e.json(t);
2649
+ }
2650
+ 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);
2651
+ if (c && c.isHidden && !i) return e.json({ error: `Tree '${n}' is hidden` }, 404);
2652
+ let l = c?.id || (s ? Number(n) : null), u = {};
2653
+ if (c && c.dataJson) try {
2654
+ let t = typeof c.dataJson == "string" ? JSON.parse(c.dataJson) : c.dataJson, r = e.env?.BUNDLED_DEFINITIONS, i = U(r), a = (i.trees?.[c.treeType || n] || i.trees?.site || {}).fields || {};
2655
+ for (let [e, n] of Object.entries(t)) a[e]?.public === !0 && (u[e] = n);
2656
+ } catch (e) {
2657
+ console.warn("[CMS Public Tree API] Failed to parse tree dataJson", e);
2658
+ }
2659
+ let d = [];
2660
+ if (l !== null) {
2661
+ 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(l);
2662
+ d = Array.isArray(e) ? e : e?.results || [];
2663
+ }
2664
+ if ((!d || d.length === 0) && !c) return e.json({ error: `Tree '${n}' not found` }, 404);
2665
+ function f(e = null, t = "") {
2666
+ return (d || []).filter((t) => {
2667
+ let n = !t.parentId || t.parentId === "null" || t.parentId === "" ? null : t.parentId;
2668
+ return String(n) === String(!e || e === "null" || e === "" ? null : e);
2669
+ }).map((e) => {
2670
+ let n = {}, r = i && e.draftDataJson ? e.draftDataJson : e.dataJson;
2671
+ if (r) try {
2672
+ 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;
2673
+ } catch {}
2674
+ 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 = Ue(n.startShowingAt, n.stopShowingAt), c = (e.slug || "").replace(/^\/+|\/+$/g, ""), l = c === "home" || c === "homee" ? "/" : `${t}/${c}`.replace(/\/+/g, "/"), u = {
2675
+ id: e.id,
2676
+ treeNodeId: e.treeNodeId,
2677
+ parentId: e.parentId || null,
2678
+ title: e.title,
2679
+ slug: c,
2680
+ language: e.language || "en",
2681
+ path: l,
2682
+ nodeType: e.nodeType,
2683
+ hidden: o || !s ? 1 : 0,
2684
+ summary: n.summary || ""
2685
+ };
2686
+ e.nodeType === "external-link" && (n.url && (u.url = n.url), n.target && (u.target = n.target));
2687
+ let d = l === "/" ? "" : l;
2688
+ return u.children = f(e.treeNodeId, d), u;
2689
+ }).filter((e) => i || !e.hidden);
2690
+ }
2691
+ let p = {
2692
+ treeId: c?.id || l,
2693
+ key: c?.key || n,
2694
+ channelId: r,
2695
+ label: c?.label || n,
2696
+ ...u,
2697
+ items: f(null)
2698
+ };
2699
+ return i || (await a.set(o, p, 300), e.header("X-Cache", "MISS")), e.json(p);
2700
+ } catch (t) {
2701
+ return console.error("[CMS Public Tree API] Error:", t), e.json({
2702
+ error: "Failed to fetch public tree",
2703
+ details: t.message
2704
+ }, 500);
2705
+ }
2706
+ });
2707
+ //#endregion
2708
+ //#region server/routes/public/assets.ts
2709
+ var We = new t();
2710
+ function Ge(e, t) {
2711
+ if (t === "webp") return "image/webp";
2712
+ if (t === "avif") return "image/avif";
2713
+ if (t === "jpeg" || t === "jpg") return "image/jpeg";
2714
+ if (t === "png") return "image/png";
2715
+ let n = e.toLowerCase();
2716
+ 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";
2717
+ }
2718
+ We.get("/*", async (e) => {
2719
+ let t = e.req.path.replace(/^\/media\//, "").replace(/^\//, "");
2720
+ if (!t) return e.text("Asset key missing", 400);
2721
+ let n = e.env?.MEDIA_BUCKET, { w: r, h: i, q: c, f: u } = e.req.query(), p = !!(r || i || c || u), m = e.req.header("Via")?.includes("image-resizing") || e.req.header("User-Agent")?.includes("Cloudflare-ImgRen");
2722
+ if (n) {
2723
+ if (p && e.env?.CDN_DOMAIN && !m) {
2724
+ let n = r ? parseInt(r, 10) : void 0, a = i ? parseInt(i, 10) : void 0, o = c ? parseInt(c, 10) : 85, s = u || "auto", l = `https://${e.env.CDN_DOMAIN}/media/${t}`;
2725
+ try {
2726
+ let t = await fetch(l, {
2727
+ headers: { Accept: e.req.header("Accept") || "image/webp,image/avif,image/*,*/*;q=0.8" },
2728
+ cf: { image: {
2729
+ width: n,
2730
+ height: a,
2731
+ quality: o,
2732
+ format: s,
2733
+ fit: "cover",
2734
+ anim: !1
2735
+ } }
2736
+ });
2737
+ if (t.ok) return t;
2738
+ console.warn(`[Cloudflare Image] Resizing returned status ${t.status}. Falling back to raw R2 stream.`);
2739
+ } catch {
2740
+ console.warn("[Cloudflare Image] Resize fetch failed. Falling back to raw R2 stream.");
2741
+ }
2742
+ }
2743
+ let a = await n.get(t);
2744
+ if (!a && t.includes("/")) {
2745
+ let e = t.split("/").slice(1).join("/");
2746
+ a = await n.get(e);
2747
+ }
2748
+ if (a) {
2749
+ let t = new Headers();
2750
+ return a.writeHttpMetadata(t), t.set("etag", a.httpEtag), t.set("Cache-Control", "public, max-age=31536000, immutable"), e.body(a.body, 200, Object.fromEntries(t.entries()));
2751
+ }
2752
+ }
2753
+ let h = e.env?.LOCAL_MEDIA_PATH || "./public/media", g = f(process.cwd(), h, t);
2754
+ if (a(g)) try {
2755
+ if (!p) {
2756
+ let n = s(g);
2757
+ return e.body(n, 200, {
2758
+ "Content-Type": Ge(t),
2759
+ "Cache-Control": "public, max-age=86400"
2760
+ });
2761
+ }
2762
+ let n = r ? parseInt(r, 10) : "auto", m = i ? parseInt(i, 10) : "auto", _ = c ? parseInt(c, 10) : 80, v = u || "webp", y = `w${n}_h${m}_q${_}_f${v}_${t.replace(/[/\\?%*:|"<>]/g, "_")}`, b = f(process.cwd(), h, ".cache", y);
2763
+ if (a(b)) {
2764
+ let n = s(b);
2765
+ return e.body(n, 200, {
2766
+ "Content-Type": Ge(t, v),
2767
+ "Cache-Control": "public, max-age=31536000, immutable",
2768
+ "X-Local-Cache": "HIT"
2769
+ });
2770
+ }
2771
+ try {
2772
+ let r = (await import("sharp")).default, i = r(g), a = {};
2773
+ typeof n == "number" && (a.width = n), typeof m == "number" && (a.height = m), (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 }));
2774
+ let s = await i.toBuffer();
2775
+ return o(d(b), { recursive: !0 }), l(b, s), e.body(s, 200, {
2776
+ "Content-Type": Ge(t, v),
2777
+ "Cache-Control": "public, max-age=31536000, immutable",
2778
+ "X-Local-Cache": "MISS"
2779
+ });
2780
+ } catch {
2781
+ let n = s(g);
2782
+ return e.body(n, 200, {
2783
+ "Content-Type": Ge(t),
2784
+ "Cache-Control": "public, max-age=86400"
2785
+ });
2786
+ }
2787
+ } catch (e) {
2788
+ console.error("[Public Assets] Failed to process local media file:", e);
2789
+ }
2790
+ return e.text(`Asset not found: ${t}`, 404);
2791
+ });
2792
+ //#endregion
2793
+ //#region server/routes/public/paths.ts
2794
+ var Ke = new t();
2795
+ function qe(e, t) {
2796
+ let n = /* @__PURE__ */ new Date();
2797
+ if (e && String(e).trim() !== "") {
2798
+ let t = new Date(e);
2799
+ if (!isNaN(t.getTime()) && n < t) return !1;
2800
+ }
2801
+ if (t && String(t).trim() !== "") {
2802
+ let e = new Date(t);
2803
+ if (!isNaN(e.getTime()) && n > e) return !1;
2804
+ }
2805
+ return !0;
2806
+ }
2807
+ Ke.get("/", async (e) => {
2808
+ try {
2809
+ 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 = [];
2810
+ function i(e = null, t = "") {
2811
+ let a = n.filter((t) => {
2812
+ let n = !t.parentId || t.parentId === "null" || t.parentId === "" ? null : t.parentId;
2813
+ return String(n) === String(!e || e === "null" || e === "" ? null : e);
2814
+ });
2815
+ for (let e of a) {
2816
+ let n = {};
2817
+ if (e.dataJson) try {
2818
+ n = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
2819
+ } catch {}
2820
+ let a = e.status === "published" || e.status === "active", o = qe(n.startShowingAt, n.stopShowingAt);
2821
+ if (!a || !o) continue;
2822
+ let s = (e.slug || "").replace(/^\/+|\/+$/g, ""), c = s === "home" || s === "homee" ? "/" : `${t}/${s}`.replace(/\/+/g, "/");
2823
+ e.nodeType !== "external-link" && r.push(c);
2824
+ let l = c === "/" ? "" : c;
2825
+ i(e.treeNodeId, l);
2826
+ }
2827
+ }
2828
+ i(null);
2829
+ let a = [...new Set(r)];
2830
+ return e.json(a);
2831
+ } catch (t) {
2832
+ return console.error("[CMS Paths API] Error:", t), e.json({ error: "Failed to fetch paths" }, 500);
2833
+ }
2834
+ });
2835
+ //#endregion
2836
+ //#region server/index.ts
2837
+ var $ = new t(), Je = !1;
2838
+ if ($.use("*", C()), $.use("/media/*", C({
2839
+ origin: "*",
2840
+ allowMethods: [
2841
+ "GET",
2842
+ "HEAD",
2843
+ "OPTIONS"
2844
+ ],
2845
+ allowHeaders: [
2846
+ "Range",
2847
+ "User-Agent",
2848
+ "Accept"
2849
+ ],
2850
+ maxAge: 86400
2851
+ })), $.use("/media/*", async (e, t) => {
2852
+ await t(), e.header("Cache-Control", "public, max-age=31536000, immutable"), e.header("Access-Control-Allow-Origin", "*");
2853
+ }), $.use("*", async (e, t) => {
2854
+ if (e.req.path.startsWith("/media/")) return t();
2855
+ let n = new URL(e.req.url), r = (e.req.header("host") || n.hostname).split(":")[0];
2856
+ e.set("currentDomain", r);
2857
+ let i = O(e);
2858
+ if (e.set("db", i), !Je) try {
2859
+ await ee(i), Je = !0;
2860
+ } catch (e) {
2861
+ console.error("❌ [CMS Server] Failed to initialize system tables on cold start:", e);
2862
+ }
2863
+ await t();
2864
+ }), $.route("/media", We), $.use("/media/*", le()), $.route("/api/cms/nodes", W), $.route("/api/cms/nodes.json", W), $.route("/api/cms/formcsv", W), $.route("/api/cms/formcsv.json", W), $.route("/api/cms/stats", je), $.route("/api/cms/stats.json", je), $.route("/api/cms", G), $.route("/api/cms/channels", K), $.route("/api/cms/channels.json", K), $.route("/api/cms/schemas", q), $.route("/api/cms/schemas.json", q), $.route("/api/cms", Oe), $.route("/api/admin/assets", J), $.route("/api/v1/node", Fe), $.route("/api/v1/page", Fe), $.route("/api/v1/tree", He), $.route("/api/v1/all-paths", Ke), typeof process < "u" && process.versions?.node && import.meta.url === `file://${process.argv[1]}`) {
2865
+ let t = 4e3;
2866
+ console.log(`🚀 Fully Decoupled CMS API Server running on http://localhost:${t}`), e({
2867
+ fetch: $.fetch,
2868
+ port: t
2869
+ });
2870
+ }
2871
+ //#endregion
2872
+ export { $ as app, $ as default };