@brightsideoy/kama 0.1.0-alpha.158 → 0.1.0-alpha.159
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +48 -117
- package/content/definitions/node-layouts/landing-page.yml +2 -0
- package/content/definitions/node-layouts/single-column.yml +2 -0
- package/content/definitions/node-layouts/two-column.yml +2 -0
- package/dist/assets/{index-B-WxBAFU.js → index-DIxtk5i5.js} +1 -1
- package/dist/{dist-CBGESg3a.js → dist-BNkCx-o-.js} +82 -51
- package/dist/index.html +1 -1
- package/dist/index.js +82 -51
- package/dist/schema-compiler.js +23 -13
- package/package.json +1 -1
- package/templates/astro-starter/astro.config.mjs +10 -26
- package/templates/astro-starter/src/components/global/Footer.astro +24 -24
- package/templates/astro-starter/src/components/global/NavigationMenu.astro +86 -235
- package/templates/astro-starter/src/layouts/StandardLayout.astro +3 -2
- package/templates/astro-starter/src/pages/partials/footer.astro +69 -0
- package/templates/astro-starter/src/pages/partials/nav.astro +141 -0
- package/templates/kama-worker/index.js +19 -0
- package/templates/kama-worker/server.js +98 -0
|
@@ -4039,6 +4039,7 @@ var u = /* @__PURE__ */ o({
|
|
|
4039
4039
|
footer: {
|
|
4040
4040
|
label: "Footer",
|
|
4041
4041
|
inherit: "parent",
|
|
4042
|
+
purgeTargets: ["/partials/footer"],
|
|
4042
4043
|
disallowedBlocks: [
|
|
4043
4044
|
"hero",
|
|
4044
4045
|
"image_card",
|
|
@@ -4092,6 +4093,7 @@ var u = /* @__PURE__ */ o({
|
|
|
4092
4093
|
footer: {
|
|
4093
4094
|
label: "Footer",
|
|
4094
4095
|
inherit: "parent",
|
|
4096
|
+
purgeTargets: ["/partials/footer"],
|
|
4095
4097
|
disallowedBlocks: [
|
|
4096
4098
|
"hero",
|
|
4097
4099
|
"image_card",
|
|
@@ -4154,6 +4156,7 @@ var u = /* @__PURE__ */ o({
|
|
|
4154
4156
|
footer: {
|
|
4155
4157
|
label: "Footer",
|
|
4156
4158
|
inherit: "parent",
|
|
4159
|
+
purgeTargets: ["/partials/footer"],
|
|
4157
4160
|
disallowedBlocks: [
|
|
4158
4161
|
"hero",
|
|
4159
4162
|
"image_card",
|
|
@@ -6041,52 +6044,80 @@ var V = class {
|
|
|
6041
6044
|
console.warn("[CacheManager] Failed to purge internal worker cache:", e);
|
|
6042
6045
|
}
|
|
6043
6046
|
}
|
|
6044
|
-
purgeNode(e, t, n, r = !1) {
|
|
6045
|
-
let
|
|
6047
|
+
purgeNode(e, t, n, r = !1, i = []) {
|
|
6048
|
+
let a = (async () => {
|
|
6046
6049
|
try {
|
|
6047
|
-
let
|
|
6048
|
-
if (!
|
|
6049
|
-
let
|
|
6050
|
-
for (let e of
|
|
6050
|
+
let a = t.prepare("SELECT slug, status, language FROM content_nodes WHERE id = ?"), o = (typeof a.get == "function" ? await a.get(n) : (await a.bind(n).all())?.results?.[0]) || {};
|
|
6051
|
+
if (!o.slug) return;
|
|
6052
|
+
let s = t.prepare("\n SELECT c.id, c.key, c.baseUrl, c.defaultLanguage \n FROM node_channels nc \n JOIN channels c ON nc.channelId = c.id \n WHERE nc.nodeId = ?\n "), c = typeof s.all == "function" ? await s.all(n) : await s.bind(n).all(), l = Array.isArray(c) ? c : c?.results || [], u = l.length > 0 ? l[0]?.defaultLanguage?.trim() : null, d = o.language?.trim() || u || null, f = String(o.slug).replace(/^\/+|\/+$/g, ""), p = this.getEnv(e).frontendUrl, m = /* @__PURE__ */ new Set();
|
|
6053
|
+
for (let e of l) if (e.baseUrl && typeof e.baseUrl == "string" && e.baseUrl.trim() !== "") {
|
|
6051
6054
|
let t = e.baseUrl.trim();
|
|
6052
|
-
!t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`),
|
|
6055
|
+
!t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), m.add(t.replace(/\/+$/, ""));
|
|
6053
6056
|
}
|
|
6054
|
-
|
|
6055
|
-
let
|
|
6056
|
-
await this.purgeInternalWorkerCache(e, t, n,
|
|
6057
|
-
let
|
|
6058
|
-
for (let t of
|
|
6059
|
-
let n =
|
|
6060
|
-
if (
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6057
|
+
m.size === 0 && p && m.add(p);
|
|
6058
|
+
let h = t.prepare("\n SELECT DISTINCT a.cdnUrl, a.storageKeyPrivate\n FROM node_assets na\n JOIN assets a ON na.assetId = a.id\n WHERE na.nodeId = ?\n "), g = typeof h.all == "function" ? await h.all(n) : await h.bind(n).all(), _ = (Array.isArray(g) ? g : g?.results || []).map((t) => t.url || this.getSafeUrl(t.cdnUrl, t.storageKeyPrivate, this.getEnv(e).cdnDomain)).filter(Boolean);
|
|
6059
|
+
await this.purgeInternalWorkerCache(e, t, n, f, d);
|
|
6060
|
+
let v = this.getEnv(e).cdnDomain, { zoneId: y, apiToken: b } = this.getEnv(e), x = e.env?.BUNDLED_DEFINITIONS || {}, S = /* @__PURE__ */ new Set();
|
|
6061
|
+
if (i.length > 0 && x.layouts) for (let e of Object.values(x.layouts)) for (let t of i) {
|
|
6062
|
+
let n = e.regions?.[t];
|
|
6063
|
+
if (n) {
|
|
6064
|
+
let e = n.purgeTargets || n.purgeTarget;
|
|
6065
|
+
if (e) {
|
|
6066
|
+
let t = Array.isArray(e) ? e : [e];
|
|
6067
|
+
for (let e of t) typeof e == "string" && e.trim() && S.add(e.trim());
|
|
6068
|
+
}
|
|
6069
|
+
}
|
|
6070
|
+
}
|
|
6071
|
+
for (let t of m) {
|
|
6072
|
+
let n = f === "home" || !f ? t : `${t}/${f}`, i = [n, `${n}/`];
|
|
6073
|
+
r && i.push(`${t}/partials/nav`);
|
|
6074
|
+
for (let e of S) {
|
|
6075
|
+
let n = e.startsWith("/") ? e : `/${e}`;
|
|
6076
|
+
i.push(`${t}${n}`);
|
|
6077
|
+
}
|
|
6078
|
+
let a = d ? `&lang=${d}` : "";
|
|
6079
|
+
if (l.length > 0) for (let e of l) e.id && i.push(`https://${v}/api/v1/node/${f}?channelId=${e.id}${a}`), e.key && i.push(`https://${v}/api/v1/node/${f}?channelId=${e.key}${a}`), r && (e.id && i.push(`https://${v}/api/v1/tree/main-nav?channelId=${e.id}`), e.key && i.push(`https://${v}/api/v1/tree/main-nav?channelId=${e.key}`));
|
|
6080
|
+
else i.push(`https://${v}/api/v1/node/${f}${d ? `?lang=${d}` : ""}`), r && i.push(`https://${v}/api/v1/tree/main-nav`);
|
|
6081
|
+
for (let e of _) e && i.push(`${t}${e.startsWith("/") ? e : `/${e}`}`);
|
|
6082
|
+
if (await this.callAstroPurge(e, { urls: i }, t), y && b && !this.isLocalEnv(e, t) && fetch(`https://api.cloudflare.com/client/v4/zones/${y}/purge_cache`, {
|
|
6064
6083
|
method: "POST",
|
|
6065
6084
|
headers: {
|
|
6066
|
-
Authorization: `Bearer ${
|
|
6085
|
+
Authorization: `Bearer ${b}`,
|
|
6067
6086
|
"Content-Type": "application/json"
|
|
6068
6087
|
},
|
|
6069
6088
|
body: JSON.stringify({ files: i })
|
|
6070
|
-
}).catch(() => {}),
|
|
6089
|
+
}).catch(() => {}), r) {
|
|
6090
|
+
let e = `${t}/partials/nav?_warmer=${Date.now()}`;
|
|
6091
|
+
console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
|
|
6092
|
+
"X-Cache-Warmer": "true",
|
|
6093
|
+
"User-Agent": "Kama-Cache-Warmer/1.0"
|
|
6094
|
+
} }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
|
|
6095
|
+
} else {
|
|
6071
6096
|
let e = `${n}${n.includes("?") ? "&" : "?"} _warmer=${Date.now()}`;
|
|
6072
6097
|
console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
|
|
6073
6098
|
"X-Cache-Warmer": "true",
|
|
6074
6099
|
"User-Agent": "Kama-Cache-Warmer/1.0"
|
|
6075
6100
|
} }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
|
|
6076
6101
|
}
|
|
6102
|
+
for (let e of S) {
|
|
6103
|
+
let n = `${t}${e.startsWith("/") ? e : `/${e}`}?_warmer=${Date.now()}`;
|
|
6104
|
+
console.log(`[CacheManager] Prewarming custom target: ${n}`), fetch(n, { headers: {
|
|
6105
|
+
"X-Cache-Warmer": "true",
|
|
6106
|
+
"User-Agent": "Kama-Cache-Warmer/1.0"
|
|
6107
|
+
} }).catch(() => {});
|
|
6108
|
+
}
|
|
6077
6109
|
}
|
|
6078
|
-
r && await this.purgeGlobalCacheDirect(e, t);
|
|
6079
6110
|
} catch (e) {
|
|
6080
6111
|
console.warn("[CacheManager] Dynamic purgeNode failed:", e);
|
|
6081
6112
|
}
|
|
6082
6113
|
})();
|
|
6083
|
-
this.dispatch(e,
|
|
6114
|
+
this.dispatch(e, a);
|
|
6084
6115
|
}
|
|
6085
6116
|
purgeAsset(e, t, n) {
|
|
6086
6117
|
let r = (async () => {
|
|
6087
6118
|
try {
|
|
6088
6119
|
let r = t.prepare("\n SELECT DISTINCT cn.id\n FROM node_assets na\n INNER JOIN content_nodes cn ON na.nodeId = cn.id\n LEFT JOIN assets crop ON na.assetId = crop.id\n WHERE cn.status = 'published' AND (\n na.assetId = ? OR crop.parentAssetId = ? OR crop.id = (SELECT parentAssetId FROM assets WHERE id = ?)\n )\n "), i = typeof r.all == "function" ? await r.all(n, n, n) : await r.bind(n, n, n).all(), a = Array.isArray(i) ? i : i?.results || [];
|
|
6089
|
-
for (let n of a) n.id && this.purgeNode(e, t, n.id, !1);
|
|
6120
|
+
for (let n of a) n.id && this.purgeNode(e, t, n.id, !1, []);
|
|
6090
6121
|
} catch (e) {
|
|
6091
6122
|
console.warn("[CacheManager] purgeAsset failed:", e);
|
|
6092
6123
|
}
|
|
@@ -6529,7 +6560,7 @@ H.get("/", async (e) => {
|
|
|
6529
6560
|
await he(t, n, i);
|
|
6530
6561
|
}
|
|
6531
6562
|
}
|
|
6532
|
-
return await I(e).clear(),
|
|
6563
|
+
return await I(e).clear(), e.json({
|
|
6533
6564
|
success: !0,
|
|
6534
6565
|
id: D,
|
|
6535
6566
|
status: "draft",
|
|
@@ -6746,7 +6777,7 @@ W.get("/tree.json", async (e) => {
|
|
|
6746
6777
|
c.push(e.id, e.sortOrder);
|
|
6747
6778
|
}), c.push(...i), c.push(o), await t.prepare(s).run(...c);
|
|
6748
6779
|
}
|
|
6749
|
-
return await i.clear(), a.
|
|
6780
|
+
return await i.clear(), r.length > 0 && a.purgeNode(e, t, r[0].id, !0), e.json({
|
|
6750
6781
|
success: !0,
|
|
6751
6782
|
reorderedCount: r.length
|
|
6752
6783
|
});
|
|
@@ -6755,9 +6786,9 @@ W.get("/tree.json", async (e) => {
|
|
|
6755
6786
|
delete m._isTreeDraft, delete m._draftParentId, delete m.isNew, delete m.nodeType, delete m.contentType, delete m.title, delete m.slug, delete m.hidden, delete m.is_hidden, delete m.isHidden, delete m.status;
|
|
6756
6787
|
let g = G(u), _ = e.get("user")?.id || null;
|
|
6757
6788
|
if (s === "create") {
|
|
6758
|
-
let r = m.slug || n.slug || c,
|
|
6759
|
-
if (
|
|
6760
|
-
let r = g === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = n.contentId || n.id ? Number(n.contentId || n.id) : null,
|
|
6789
|
+
let r = m.slug || n.slug || c, a = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
|
|
6790
|
+
if (a) {
|
|
6791
|
+
let r = g === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = n.contentId || n.id ? Number(n.contentId || n.id) : null, s = `
|
|
6761
6792
|
SELECT 1
|
|
6762
6793
|
FROM tree_nodes tn
|
|
6763
6794
|
INNER JOIN content_nodes cn ON tn.contentId = cn.id
|
|
@@ -6765,51 +6796,51 @@ W.get("/tree.json", async (e) => {
|
|
|
6765
6796
|
AND ${r}
|
|
6766
6797
|
AND cn.slug = ?
|
|
6767
6798
|
AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
|
|
6768
|
-
`, c = g === null ? [o,
|
|
6799
|
+
`, c = g === null ? [o, a] : [
|
|
6769
6800
|
o,
|
|
6770
6801
|
g,
|
|
6771
|
-
|
|
6802
|
+
a
|
|
6772
6803
|
];
|
|
6773
|
-
if (i && !isNaN(i) && (
|
|
6774
|
-
error: `The slug '${
|
|
6804
|
+
if (i && !isNaN(i) && (s += " AND cn.id != ?", c.push(i)), s += " LIMIT 1", await t.prepare(s).get(...c)) return e.json({
|
|
6805
|
+
error: `The slug '${a}' is already in use by another page in this section.`,
|
|
6775
6806
|
field: "slug"
|
|
6776
6807
|
}, 409);
|
|
6777
6808
|
}
|
|
6778
|
-
let
|
|
6779
|
-
if (!
|
|
6809
|
+
let s = m.language?.trim() || n.language?.trim() || null;
|
|
6810
|
+
if (!s) {
|
|
6780
6811
|
let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ?").get(o);
|
|
6781
6812
|
if (e?.dataJson) try {
|
|
6782
6813
|
let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
|
|
6783
|
-
t.defaultLanguage && (
|
|
6814
|
+
t.defaultLanguage && (s = t.defaultLanguage.trim());
|
|
6784
6815
|
} catch {}
|
|
6785
6816
|
}
|
|
6786
|
-
if (!
|
|
6817
|
+
if (!s) {
|
|
6787
6818
|
let e = [];
|
|
6788
6819
|
if (n.channels && Array.isArray(n.channels) ? e = n.channels : n.channelId && n.channelId !== "all" && (e = [n.channelId]), e.length > 0) {
|
|
6789
6820
|
let n = Number(e[0]);
|
|
6790
6821
|
if (!isNaN(n)) {
|
|
6791
6822
|
let e = await t.prepare("SELECT defaultLanguage FROM channels WHERE id = ?").get(n);
|
|
6792
|
-
e?.defaultLanguage && (
|
|
6823
|
+
e?.defaultLanguage && (s = e.defaultLanguage.trim());
|
|
6793
6824
|
}
|
|
6794
6825
|
}
|
|
6795
6826
|
}
|
|
6796
|
-
let
|
|
6797
|
-
await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o,
|
|
6798
|
-
let
|
|
6827
|
+
let u = JSON.stringify(m), d = await t.prepare("\n INSERT INTO content_nodes (contentType, title, slug, language, isHidden, status, draftDataJson, dataJson, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, 'draft', ?, NULL, ?, ?)\n ").run(l || "page", c || "Untitled", a, s, h, u, _, _), f = Number(d.lastInsertRowid);
|
|
6828
|
+
await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, f);
|
|
6829
|
+
let p = g === null ? "parentId IS NULL" : "parentId = ?", v = g === null ? [o] : [o, g], y = (await t.prepare(`
|
|
6799
6830
|
SELECT COALESCE(MAX(sortOrder), -1) + 1 as nextSort
|
|
6800
6831
|
FROM tree_nodes
|
|
6801
|
-
WHERE treeId = ? AND ${
|
|
6802
|
-
`).get(...
|
|
6803
|
-
n.channels && Array.isArray(n.channels) ?
|
|
6804
|
-
let
|
|
6805
|
-
if (
|
|
6806
|
-
let e =
|
|
6832
|
+
WHERE treeId = ? AND ${p}
|
|
6833
|
+
`).get(...v))?.nextSort ?? 0, b = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, ?)\n ").run(o, f, g, y), x = Number(b.lastInsertRowid), S = [];
|
|
6834
|
+
n.channels && Array.isArray(n.channels) ? S = n.channels : n.channelId && n.channelId !== "all" && (S = [n.channelId]);
|
|
6835
|
+
let C = [...new Set(S)].filter((e) => e && e !== "all").map((e) => Number(e));
|
|
6836
|
+
if (C.length > 0) {
|
|
6837
|
+
let e = C.map(() => "(?, ?)").join(", "), n = C.flatMap((e) => [f, e]);
|
|
6807
6838
|
await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...n);
|
|
6808
6839
|
}
|
|
6809
|
-
return await i.clear(),
|
|
6840
|
+
return await i.clear(), e.json({
|
|
6810
6841
|
success: !0,
|
|
6811
|
-
id:
|
|
6812
|
-
treeNodeId:
|
|
6842
|
+
id: f,
|
|
6843
|
+
treeNodeId: x,
|
|
6813
6844
|
status: "draft"
|
|
6814
6845
|
}, 201);
|
|
6815
6846
|
}
|
|
@@ -6844,14 +6875,14 @@ W.get("/tree.json", async (e) => {
|
|
|
6844
6875
|
}
|
|
6845
6876
|
await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, d);
|
|
6846
6877
|
let r = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, 0)\n ").run(o, d, g), s = Number(r.lastInsertRowid);
|
|
6847
|
-
return await i.clear(), a.
|
|
6878
|
+
return await i.clear(), a.purgeNode(e, t, d, !0), e.json({
|
|
6848
6879
|
success: !0,
|
|
6849
6880
|
treeNodeId: s
|
|
6850
6881
|
});
|
|
6851
6882
|
}
|
|
6852
6883
|
if (s === "detach") {
|
|
6853
6884
|
let r = n.treeNodeId || n.contentId;
|
|
6854
|
-
return r ? (await t.prepare("\n UPDATE tree_nodes \n SET parentId = (SELECT parentId FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?) \n WHERE parentId = ? AND treeId = ?\n ").run(r, r, o, r, o), await t.prepare("DELETE FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?").run(r, r, o), await i.clear(), a.
|
|
6885
|
+
return r ? (await t.prepare("\n UPDATE tree_nodes \n SET parentId = (SELECT parentId FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?) \n WHERE parentId = ? AND treeId = ?\n ").run(r, r, o, r, o), await t.prepare("DELETE FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?").run(r, r, o), await i.clear(), a.purgeNode(e, t, r, !0), e.json({ success: !0 })) : e.json({ error: "treeNodeId or contentId required for detach" }, 400);
|
|
6855
6886
|
}
|
|
6856
6887
|
return e.json({ error: "Invalid payload or action" }, 400);
|
|
6857
6888
|
} catch (t) {
|
|
@@ -6915,7 +6946,7 @@ W.get("/tree.json", async (e) => {
|
|
|
6915
6946
|
await t.prepare(`INSERT OR IGNORE INTO channel_trees (channelId, treeId, key) VALUES ${n}`).run(...r);
|
|
6916
6947
|
}
|
|
6917
6948
|
}
|
|
6918
|
-
return await
|
|
6949
|
+
return await cache.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
|
|
6919
6950
|
success: !0,
|
|
6920
6951
|
id: p,
|
|
6921
6952
|
key: o,
|
package/dist/index.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<title>KAMA</title>
|
|
7
7
|
<link rel="icon" href="/favicon.png">
|
|
8
8
|
<link rel="apple-touch-icon" sizes="180x180" href="/favicon.png">
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-DIxtk5i5.js"></script>
|
|
10
10
|
<link rel="stylesheet" crossorigin href="/assets/index-C5TmJVER.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
package/dist/index.js
CHANGED
|
@@ -4041,6 +4041,7 @@ var u = /* @__PURE__ */ o({
|
|
|
4041
4041
|
footer: {
|
|
4042
4042
|
label: "Footer",
|
|
4043
4043
|
inherit: "parent",
|
|
4044
|
+
purgeTargets: ["/partials/footer"],
|
|
4044
4045
|
disallowedBlocks: [
|
|
4045
4046
|
"hero",
|
|
4046
4047
|
"image_card",
|
|
@@ -4094,6 +4095,7 @@ var u = /* @__PURE__ */ o({
|
|
|
4094
4095
|
footer: {
|
|
4095
4096
|
label: "Footer",
|
|
4096
4097
|
inherit: "parent",
|
|
4098
|
+
purgeTargets: ["/partials/footer"],
|
|
4097
4099
|
disallowedBlocks: [
|
|
4098
4100
|
"hero",
|
|
4099
4101
|
"image_card",
|
|
@@ -4156,6 +4158,7 @@ var u = /* @__PURE__ */ o({
|
|
|
4156
4158
|
footer: {
|
|
4157
4159
|
label: "Footer",
|
|
4158
4160
|
inherit: "parent",
|
|
4161
|
+
purgeTargets: ["/partials/footer"],
|
|
4159
4162
|
disallowedBlocks: [
|
|
4160
4163
|
"hero",
|
|
4161
4164
|
"image_card",
|
|
@@ -6059,52 +6062,80 @@ var V = class {
|
|
|
6059
6062
|
console.warn("[CacheManager] Failed to purge internal worker cache:", e);
|
|
6060
6063
|
}
|
|
6061
6064
|
}
|
|
6062
|
-
purgeNode(e, t, n, r = !1) {
|
|
6063
|
-
let
|
|
6065
|
+
purgeNode(e, t, n, r = !1, i = []) {
|
|
6066
|
+
let a = (async () => {
|
|
6064
6067
|
try {
|
|
6065
|
-
let
|
|
6066
|
-
if (!
|
|
6067
|
-
let
|
|
6068
|
-
for (let e of
|
|
6068
|
+
let a = t.prepare("SELECT slug, status, language FROM content_nodes WHERE id = ?"), o = (typeof a.get == "function" ? await a.get(n) : (await a.bind(n).all())?.results?.[0]) || {};
|
|
6069
|
+
if (!o.slug) return;
|
|
6070
|
+
let s = t.prepare("\n SELECT c.id, c.key, c.baseUrl, c.defaultLanguage \n FROM node_channels nc \n JOIN channels c ON nc.channelId = c.id \n WHERE nc.nodeId = ?\n "), c = typeof s.all == "function" ? await s.all(n) : await s.bind(n).all(), l = Array.isArray(c) ? c : c?.results || [], u = l.length > 0 ? l[0]?.defaultLanguage?.trim() : null, d = o.language?.trim() || u || null, f = String(o.slug).replace(/^\/+|\/+$/g, ""), p = this.getEnv(e).frontendUrl, m = /* @__PURE__ */ new Set();
|
|
6071
|
+
for (let e of l) if (e.baseUrl && typeof e.baseUrl == "string" && e.baseUrl.trim() !== "") {
|
|
6069
6072
|
let t = e.baseUrl.trim();
|
|
6070
|
-
!t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`),
|
|
6073
|
+
!t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), m.add(t.replace(/\/+$/, ""));
|
|
6071
6074
|
}
|
|
6072
|
-
|
|
6073
|
-
let
|
|
6074
|
-
await this.purgeInternalWorkerCache(e, t, n,
|
|
6075
|
-
let
|
|
6076
|
-
for (let t of
|
|
6077
|
-
let n =
|
|
6078
|
-
if (
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6075
|
+
m.size === 0 && p && m.add(p);
|
|
6076
|
+
let h = t.prepare("\n SELECT DISTINCT a.cdnUrl, a.storageKeyPrivate\n FROM node_assets na\n JOIN assets a ON na.assetId = a.id\n WHERE na.nodeId = ?\n "), g = typeof h.all == "function" ? await h.all(n) : await h.bind(n).all(), _ = (Array.isArray(g) ? g : g?.results || []).map((t) => t.url || this.getSafeUrl(t.cdnUrl, t.storageKeyPrivate, this.getEnv(e).cdnDomain)).filter(Boolean);
|
|
6077
|
+
await this.purgeInternalWorkerCache(e, t, n, f, d);
|
|
6078
|
+
let v = this.getEnv(e).cdnDomain, { zoneId: y, apiToken: b } = this.getEnv(e), x = e.env?.BUNDLED_DEFINITIONS || {}, S = /* @__PURE__ */ new Set();
|
|
6079
|
+
if (i.length > 0 && x.layouts) for (let e of Object.values(x.layouts)) for (let t of i) {
|
|
6080
|
+
let n = e.regions?.[t];
|
|
6081
|
+
if (n) {
|
|
6082
|
+
let e = n.purgeTargets || n.purgeTarget;
|
|
6083
|
+
if (e) {
|
|
6084
|
+
let t = Array.isArray(e) ? e : [e];
|
|
6085
|
+
for (let e of t) typeof e == "string" && e.trim() && S.add(e.trim());
|
|
6086
|
+
}
|
|
6087
|
+
}
|
|
6088
|
+
}
|
|
6089
|
+
for (let t of m) {
|
|
6090
|
+
let n = f === "home" || !f ? t : `${t}/${f}`, i = [n, `${n}/`];
|
|
6091
|
+
r && i.push(`${t}/partials/nav`);
|
|
6092
|
+
for (let e of S) {
|
|
6093
|
+
let n = e.startsWith("/") ? e : `/${e}`;
|
|
6094
|
+
i.push(`${t}${n}`);
|
|
6095
|
+
}
|
|
6096
|
+
let a = d ? `&lang=${d}` : "";
|
|
6097
|
+
if (l.length > 0) for (let e of l) e.id && i.push(`https://${v}/api/v1/node/${f}?channelId=${e.id}${a}`), e.key && i.push(`https://${v}/api/v1/node/${f}?channelId=${e.key}${a}`), r && (e.id && i.push(`https://${v}/api/v1/tree/main-nav?channelId=${e.id}`), e.key && i.push(`https://${v}/api/v1/tree/main-nav?channelId=${e.key}`));
|
|
6098
|
+
else i.push(`https://${v}/api/v1/node/${f}${d ? `?lang=${d}` : ""}`), r && i.push(`https://${v}/api/v1/tree/main-nav`);
|
|
6099
|
+
for (let e of _) e && i.push(`${t}${e.startsWith("/") ? e : `/${e}`}`);
|
|
6100
|
+
if (await this.callAstroPurge(e, { urls: i }, t), y && b && !this.isLocalEnv(e, t) && fetch(`https://api.cloudflare.com/client/v4/zones/${y}/purge_cache`, {
|
|
6082
6101
|
method: "POST",
|
|
6083
6102
|
headers: {
|
|
6084
|
-
Authorization: `Bearer ${
|
|
6103
|
+
Authorization: `Bearer ${b}`,
|
|
6085
6104
|
"Content-Type": "application/json"
|
|
6086
6105
|
},
|
|
6087
6106
|
body: JSON.stringify({ files: i })
|
|
6088
|
-
}).catch(() => {}),
|
|
6107
|
+
}).catch(() => {}), r) {
|
|
6108
|
+
let e = `${t}/partials/nav?_warmer=${Date.now()}`;
|
|
6109
|
+
console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
|
|
6110
|
+
"X-Cache-Warmer": "true",
|
|
6111
|
+
"User-Agent": "Kama-Cache-Warmer/1.0"
|
|
6112
|
+
} }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
|
|
6113
|
+
} else {
|
|
6089
6114
|
let e = `${n}${n.includes("?") ? "&" : "?"} _warmer=${Date.now()}`;
|
|
6090
6115
|
console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
|
|
6091
6116
|
"X-Cache-Warmer": "true",
|
|
6092
6117
|
"User-Agent": "Kama-Cache-Warmer/1.0"
|
|
6093
6118
|
} }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
|
|
6094
6119
|
}
|
|
6120
|
+
for (let e of S) {
|
|
6121
|
+
let n = `${t}${e.startsWith("/") ? e : `/${e}`}?_warmer=${Date.now()}`;
|
|
6122
|
+
console.log(`[CacheManager] Prewarming custom target: ${n}`), fetch(n, { headers: {
|
|
6123
|
+
"X-Cache-Warmer": "true",
|
|
6124
|
+
"User-Agent": "Kama-Cache-Warmer/1.0"
|
|
6125
|
+
} }).catch(() => {});
|
|
6126
|
+
}
|
|
6095
6127
|
}
|
|
6096
|
-
r && await this.purgeGlobalCacheDirect(e, t);
|
|
6097
6128
|
} catch (e) {
|
|
6098
6129
|
console.warn("[CacheManager] Dynamic purgeNode failed:", e);
|
|
6099
6130
|
}
|
|
6100
6131
|
})();
|
|
6101
|
-
this.dispatch(e,
|
|
6132
|
+
this.dispatch(e, a);
|
|
6102
6133
|
}
|
|
6103
6134
|
purgeAsset(e, t, n) {
|
|
6104
6135
|
let r = (async () => {
|
|
6105
6136
|
try {
|
|
6106
6137
|
let r = t.prepare("\n SELECT DISTINCT cn.id\n FROM node_assets na\n INNER JOIN content_nodes cn ON na.nodeId = cn.id\n LEFT JOIN assets crop ON na.assetId = crop.id\n WHERE cn.status = 'published' AND (\n na.assetId = ? OR crop.parentAssetId = ? OR crop.id = (SELECT parentAssetId FROM assets WHERE id = ?)\n )\n "), i = typeof r.all == "function" ? await r.all(n, n, n) : await r.bind(n, n, n).all(), a = Array.isArray(i) ? i : i?.results || [];
|
|
6107
|
-
for (let n of a) n.id && this.purgeNode(e, t, n.id, !1);
|
|
6138
|
+
for (let n of a) n.id && this.purgeNode(e, t, n.id, !1, []);
|
|
6108
6139
|
} catch (e) {
|
|
6109
6140
|
console.warn("[CacheManager] purgeAsset failed:", e);
|
|
6110
6141
|
}
|
|
@@ -6547,7 +6578,7 @@ H.get("/", async (e) => {
|
|
|
6547
6578
|
await he(t, n, i);
|
|
6548
6579
|
}
|
|
6549
6580
|
}
|
|
6550
|
-
return await I(e).clear(),
|
|
6581
|
+
return await I(e).clear(), e.json({
|
|
6551
6582
|
success: !0,
|
|
6552
6583
|
id: D,
|
|
6553
6584
|
status: "draft",
|
|
@@ -6766,7 +6797,7 @@ W.get("/tree.json", async (e) => {
|
|
|
6766
6797
|
c.push(e.id, e.sortOrder);
|
|
6767
6798
|
}), c.push(...i), c.push(o), await t.prepare(s).run(...c);
|
|
6768
6799
|
}
|
|
6769
|
-
return await i.clear(), a.
|
|
6800
|
+
return await i.clear(), r.length > 0 && a.purgeNode(e, t, r[0].id, !0), e.json({
|
|
6770
6801
|
success: !0,
|
|
6771
6802
|
reorderedCount: r.length
|
|
6772
6803
|
});
|
|
@@ -6775,9 +6806,9 @@ W.get("/tree.json", async (e) => {
|
|
|
6775
6806
|
delete m._isTreeDraft, delete m._draftParentId, delete m.isNew, delete m.nodeType, delete m.contentType, delete m.title, delete m.slug, delete m.hidden, delete m.is_hidden, delete m.isHidden, delete m.status;
|
|
6776
6807
|
let g = G(u), _ = e.get("user")?.id || null;
|
|
6777
6808
|
if (s === "create") {
|
|
6778
|
-
let r = m.slug || n.slug || c,
|
|
6779
|
-
if (
|
|
6780
|
-
let r = g === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = n.contentId || n.id ? Number(n.contentId || n.id) : null,
|
|
6809
|
+
let r = m.slug || n.slug || c, a = r ? String(r).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") : null;
|
|
6810
|
+
if (a) {
|
|
6811
|
+
let r = g === null ? "tn.parentId IS NULL" : "tn.parentId = ?", i = n.contentId || n.id ? Number(n.contentId || n.id) : null, s = `
|
|
6781
6812
|
SELECT 1
|
|
6782
6813
|
FROM tree_nodes tn
|
|
6783
6814
|
INNER JOIN content_nodes cn ON tn.contentId = cn.id
|
|
@@ -6785,51 +6816,51 @@ W.get("/tree.json", async (e) => {
|
|
|
6785
6816
|
AND ${r}
|
|
6786
6817
|
AND cn.slug = ?
|
|
6787
6818
|
AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
|
|
6788
|
-
`, c = g === null ? [o,
|
|
6819
|
+
`, c = g === null ? [o, a] : [
|
|
6789
6820
|
o,
|
|
6790
6821
|
g,
|
|
6791
|
-
|
|
6822
|
+
a
|
|
6792
6823
|
];
|
|
6793
|
-
if (i && !isNaN(i) && (
|
|
6794
|
-
error: `The slug '${
|
|
6824
|
+
if (i && !isNaN(i) && (s += " AND cn.id != ?", c.push(i)), s += " LIMIT 1", await t.prepare(s).get(...c)) return e.json({
|
|
6825
|
+
error: `The slug '${a}' is already in use by another page in this section.`,
|
|
6795
6826
|
field: "slug"
|
|
6796
6827
|
}, 409);
|
|
6797
6828
|
}
|
|
6798
|
-
let
|
|
6799
|
-
if (!
|
|
6829
|
+
let s = m.language?.trim() || n.language?.trim() || null;
|
|
6830
|
+
if (!s) {
|
|
6800
6831
|
let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ?").get(o);
|
|
6801
6832
|
if (e?.dataJson) try {
|
|
6802
6833
|
let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
|
|
6803
|
-
t.defaultLanguage && (
|
|
6834
|
+
t.defaultLanguage && (s = t.defaultLanguage.trim());
|
|
6804
6835
|
} catch {}
|
|
6805
6836
|
}
|
|
6806
|
-
if (!
|
|
6837
|
+
if (!s) {
|
|
6807
6838
|
let e = [];
|
|
6808
6839
|
if (n.channels && Array.isArray(n.channels) ? e = n.channels : n.channelId && n.channelId !== "all" && (e = [n.channelId]), e.length > 0) {
|
|
6809
6840
|
let n = Number(e[0]);
|
|
6810
6841
|
if (!isNaN(n)) {
|
|
6811
6842
|
let e = await t.prepare("SELECT defaultLanguage FROM channels WHERE id = ?").get(n);
|
|
6812
|
-
e?.defaultLanguage && (
|
|
6843
|
+
e?.defaultLanguage && (s = e.defaultLanguage.trim());
|
|
6813
6844
|
}
|
|
6814
6845
|
}
|
|
6815
6846
|
}
|
|
6816
|
-
let
|
|
6817
|
-
await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o,
|
|
6818
|
-
let
|
|
6847
|
+
let u = JSON.stringify(m), d = await t.prepare("\n INSERT INTO content_nodes (contentType, title, slug, language, isHidden, status, draftDataJson, dataJson, createdById, updatedById)\n VALUES (?, ?, ?, ?, ?, 'draft', ?, NULL, ?, ?)\n ").run(l || "page", c || "Untitled", a, s, h, u, _, _), f = Number(d.lastInsertRowid);
|
|
6848
|
+
await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, f);
|
|
6849
|
+
let p = g === null ? "parentId IS NULL" : "parentId = ?", v = g === null ? [o] : [o, g], y = (await t.prepare(`
|
|
6819
6850
|
SELECT COALESCE(MAX(sortOrder), -1) + 1 as nextSort
|
|
6820
6851
|
FROM tree_nodes
|
|
6821
|
-
WHERE treeId = ? AND ${
|
|
6822
|
-
`).get(...
|
|
6823
|
-
n.channels && Array.isArray(n.channels) ?
|
|
6824
|
-
let
|
|
6825
|
-
if (
|
|
6826
|
-
let e =
|
|
6852
|
+
WHERE treeId = ? AND ${p}
|
|
6853
|
+
`).get(...v))?.nextSort ?? 0, b = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, ?)\n ").run(o, f, g, y), x = Number(b.lastInsertRowid), S = [];
|
|
6854
|
+
n.channels && Array.isArray(n.channels) ? S = n.channels : n.channelId && n.channelId !== "all" && (S = [n.channelId]);
|
|
6855
|
+
let C = [...new Set(S)].filter((e) => e && e !== "all").map((e) => Number(e));
|
|
6856
|
+
if (C.length > 0) {
|
|
6857
|
+
let e = C.map(() => "(?, ?)").join(", "), n = C.flatMap((e) => [f, e]);
|
|
6827
6858
|
await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...n);
|
|
6828
6859
|
}
|
|
6829
|
-
return await i.clear(),
|
|
6860
|
+
return await i.clear(), e.json({
|
|
6830
6861
|
success: !0,
|
|
6831
|
-
id:
|
|
6832
|
-
treeNodeId:
|
|
6862
|
+
id: f,
|
|
6863
|
+
treeNodeId: x,
|
|
6833
6864
|
status: "draft"
|
|
6834
6865
|
}, 201);
|
|
6835
6866
|
}
|
|
@@ -6864,14 +6895,14 @@ W.get("/tree.json", async (e) => {
|
|
|
6864
6895
|
}
|
|
6865
6896
|
await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, d);
|
|
6866
6897
|
let r = await t.prepare("\n INSERT INTO tree_nodes (treeId, contentId, parentId, sortOrder)\n VALUES (?, ?, ?, 0)\n ").run(o, d, g), s = Number(r.lastInsertRowid);
|
|
6867
|
-
return await i.clear(), a.
|
|
6898
|
+
return await i.clear(), a.purgeNode(e, t, d, !0), e.json({
|
|
6868
6899
|
success: !0,
|
|
6869
6900
|
treeNodeId: s
|
|
6870
6901
|
});
|
|
6871
6902
|
}
|
|
6872
6903
|
if (s === "detach") {
|
|
6873
6904
|
let r = n.treeNodeId || n.contentId;
|
|
6874
|
-
return r ? (await t.prepare("\n UPDATE tree_nodes \n SET parentId = (SELECT parentId FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?) \n WHERE parentId = ? AND treeId = ?\n ").run(r, r, o, r, o), await t.prepare("DELETE FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?").run(r, r, o), await i.clear(), a.
|
|
6905
|
+
return r ? (await t.prepare("\n UPDATE tree_nodes \n SET parentId = (SELECT parentId FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?) \n WHERE parentId = ? AND treeId = ?\n ").run(r, r, o, r, o), await t.prepare("DELETE FROM tree_nodes WHERE (id = ? OR contentId = ?) AND treeId = ?").run(r, r, o), await i.clear(), a.purgeNode(e, t, r, !0), e.json({ success: !0 })) : e.json({ error: "treeNodeId or contentId required for detach" }, 400);
|
|
6875
6906
|
}
|
|
6876
6907
|
return e.json({ error: "Invalid payload or action" }, 400);
|
|
6877
6908
|
} catch (t) {
|
|
@@ -6935,7 +6966,7 @@ W.get("/tree.json", async (e) => {
|
|
|
6935
6966
|
await t.prepare(`INSERT OR IGNORE INTO channel_trees (channelId, treeId, key) VALUES ${n}`).run(...r);
|
|
6936
6967
|
}
|
|
6937
6968
|
}
|
|
6938
|
-
return await
|
|
6969
|
+
return await cache.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
|
|
6939
6970
|
success: !0,
|
|
6940
6971
|
id: p,
|
|
6941
6972
|
key: o,
|
package/dist/schema-compiler.js
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { fileURLToPath as e, pathToFileURL as t } from "node:url";
|
|
2
2
|
import { existsSync as n, mkdirSync as r, readFileSync as i, writeFileSync as a } from "node:fs";
|
|
3
|
-
import { dirname as o, join as s } from "node:path";
|
|
3
|
+
import { dirname as o, join as s, resolve as c } from "node:path";
|
|
4
4
|
//#region scripts/schema-compiler.ts
|
|
5
|
-
var
|
|
6
|
-
|
|
7
|
-
let
|
|
5
|
+
var l = e(import.meta.url), u = o(l);
|
|
6
|
+
function d(e = process.cwd()) {
|
|
7
|
+
let t = e;
|
|
8
|
+
for (; t !== c(t, "..");) {
|
|
9
|
+
if (n(s(t, "content", "definitions"))) return t;
|
|
10
|
+
t = c(t, "..");
|
|
11
|
+
}
|
|
12
|
+
return process.cwd();
|
|
13
|
+
}
|
|
14
|
+
async function f() {
|
|
15
|
+
let e = d();
|
|
16
|
+
process.chdir(e);
|
|
17
|
+
let o = !1;
|
|
8
18
|
try {
|
|
9
19
|
JSON.parse(i(s(e, "package.json"), "utf-8")).name === "@brightsideoy/kama" && (o = !0);
|
|
10
20
|
} catch {}
|
|
@@ -16,23 +26,23 @@ async function u() {
|
|
|
16
26
|
let t = s(e, "kama-worker");
|
|
17
27
|
n(t) || r(t, { recursive: !0 }), c = s(t, "bundled-definitions.js");
|
|
18
28
|
}
|
|
19
|
-
let
|
|
20
|
-
if (n(
|
|
21
|
-
else if (n(
|
|
29
|
+
let l, f = s(u, "../server/schema/engine.ts"), p = s(u, "../dist/index.js");
|
|
30
|
+
if (n(f)) l = (await import(t(f).href)).compileDefinitions;
|
|
31
|
+
else if (n(p)) l = (await import(t(p).href)).compileDefinitions;
|
|
22
32
|
else try {
|
|
23
|
-
|
|
33
|
+
l = (await import("./dist-BNkCx-o-.js")).compileDefinitions;
|
|
24
34
|
} catch (e) {
|
|
25
35
|
console.error("❌ Could not resolve Kama Schema Engine:", e), process.exit(1);
|
|
26
36
|
}
|
|
27
|
-
|
|
28
|
-
let
|
|
29
|
-
const defs = ${JSON.stringify(
|
|
37
|
+
l || (console.error("❌ compileDefinitions function missing from resolved module"), process.exit(1));
|
|
38
|
+
let m = l(), h = Object.keys(m?.nodes || {}).length, g = Object.keys(m?.blocks || {}).length, _ = `// AUTO-GENERATED BUNDLE - DO NOT EDIT
|
|
39
|
+
const defs = ${JSON.stringify(m, null, 2)};
|
|
30
40
|
export const BUNDLED_DEFINITIONS = defs;
|
|
31
41
|
export default defs;
|
|
32
42
|
`;
|
|
33
|
-
a(c,
|
|
43
|
+
a(c, _, "utf-8"), console.log(`✅ Schema securely compiled using engine.ts to ${c} (${h} nodes, ${g} blocks)`);
|
|
34
44
|
}
|
|
35
|
-
|
|
45
|
+
f().catch((e) => {
|
|
36
46
|
console.error("❌ Schema Compiler Runtime Error:", e), process.exit(1);
|
|
37
47
|
});
|
|
38
48
|
//#endregion
|