@brightsideoy/kama 0.1.0-alpha.157 → 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/content/definitions/nodes/page.yaml +0 -16
- package/dist/assets/index-C5TmJVER.css +1 -0
- package/dist/assets/index-DIxtk5i5.js +164 -0
- package/dist/{dist-mic4UZBb.js → dist-BNkCx-o-.js} +82 -87
- package/dist/index.html +2 -2
- package/dist/index.js +82 -87
- 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
- package/dist/assets/index-BesA3e7A.js +0 -164
- package/dist/assets/index-D6yHZ_u1.css +0 -1
|
@@ -1852,24 +1852,6 @@ var u = /* @__PURE__ */ o({
|
|
|
1852
1852
|
},
|
|
1853
1853
|
required: !0
|
|
1854
1854
|
},
|
|
1855
|
-
logoText: {
|
|
1856
|
-
label: "Logo Text",
|
|
1857
|
-
type: "text",
|
|
1858
|
-
required: !1,
|
|
1859
|
-
public: !0,
|
|
1860
|
-
inherits: "logoText",
|
|
1861
|
-
rules: { required: !1 }
|
|
1862
|
-
},
|
|
1863
|
-
logoImage: {
|
|
1864
|
-
label: "Logo Image",
|
|
1865
|
-
type: "image",
|
|
1866
|
-
maxPreviewWidth: "300px",
|
|
1867
|
-
multiple: !1,
|
|
1868
|
-
allowedTypes: ["image/svg"],
|
|
1869
|
-
public: !0,
|
|
1870
|
-
inherits: "logoImage",
|
|
1871
|
-
rules: {}
|
|
1872
|
-
},
|
|
1873
1855
|
layoutId: {
|
|
1874
1856
|
label: "Page Layout",
|
|
1875
1857
|
type: "layout-select",
|
|
@@ -2198,24 +2180,6 @@ var u = /* @__PURE__ */ o({
|
|
|
2198
2180
|
},
|
|
2199
2181
|
required: !0
|
|
2200
2182
|
},
|
|
2201
|
-
logoText: {
|
|
2202
|
-
label: "Logo Text",
|
|
2203
|
-
type: "text",
|
|
2204
|
-
required: !1,
|
|
2205
|
-
public: !0,
|
|
2206
|
-
inherits: "logoText",
|
|
2207
|
-
rules: { required: !1 }
|
|
2208
|
-
},
|
|
2209
|
-
logoImage: {
|
|
2210
|
-
label: "Logo Image",
|
|
2211
|
-
type: "image",
|
|
2212
|
-
maxPreviewWidth: "300px",
|
|
2213
|
-
multiple: !1,
|
|
2214
|
-
allowedTypes: ["image/svg"],
|
|
2215
|
-
public: !0,
|
|
2216
|
-
inherits: "logoImage",
|
|
2217
|
-
rules: {}
|
|
2218
|
-
},
|
|
2219
2183
|
layoutId: {
|
|
2220
2184
|
label: "Page Layout",
|
|
2221
2185
|
type: "layout-select",
|
|
@@ -4075,6 +4039,7 @@ var u = /* @__PURE__ */ o({
|
|
|
4075
4039
|
footer: {
|
|
4076
4040
|
label: "Footer",
|
|
4077
4041
|
inherit: "parent",
|
|
4042
|
+
purgeTargets: ["/partials/footer"],
|
|
4078
4043
|
disallowedBlocks: [
|
|
4079
4044
|
"hero",
|
|
4080
4045
|
"image_card",
|
|
@@ -4128,6 +4093,7 @@ var u = /* @__PURE__ */ o({
|
|
|
4128
4093
|
footer: {
|
|
4129
4094
|
label: "Footer",
|
|
4130
4095
|
inherit: "parent",
|
|
4096
|
+
purgeTargets: ["/partials/footer"],
|
|
4131
4097
|
disallowedBlocks: [
|
|
4132
4098
|
"hero",
|
|
4133
4099
|
"image_card",
|
|
@@ -4190,6 +4156,7 @@ var u = /* @__PURE__ */ o({
|
|
|
4190
4156
|
footer: {
|
|
4191
4157
|
label: "Footer",
|
|
4192
4158
|
inherit: "parent",
|
|
4159
|
+
purgeTargets: ["/partials/footer"],
|
|
4193
4160
|
disallowedBlocks: [
|
|
4194
4161
|
"hero",
|
|
4195
4162
|
"image_card",
|
|
@@ -6077,52 +6044,80 @@ var V = class {
|
|
|
6077
6044
|
console.warn("[CacheManager] Failed to purge internal worker cache:", e);
|
|
6078
6045
|
}
|
|
6079
6046
|
}
|
|
6080
|
-
purgeNode(e, t, n, r = !1) {
|
|
6081
|
-
let
|
|
6047
|
+
purgeNode(e, t, n, r = !1, i = []) {
|
|
6048
|
+
let a = (async () => {
|
|
6082
6049
|
try {
|
|
6083
|
-
let
|
|
6084
|
-
if (!
|
|
6085
|
-
let
|
|
6086
|
-
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() !== "") {
|
|
6087
6054
|
let t = e.baseUrl.trim();
|
|
6088
|
-
!t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`),
|
|
6055
|
+
!t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), m.add(t.replace(/\/+$/, ""));
|
|
6056
|
+
}
|
|
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
|
+
}
|
|
6089
6070
|
}
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
for (let e of
|
|
6099
|
-
|
|
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`, {
|
|
6100
6083
|
method: "POST",
|
|
6101
6084
|
headers: {
|
|
6102
|
-
Authorization: `Bearer ${
|
|
6085
|
+
Authorization: `Bearer ${b}`,
|
|
6103
6086
|
"Content-Type": "application/json"
|
|
6104
6087
|
},
|
|
6105
6088
|
body: JSON.stringify({ files: i })
|
|
6106
|
-
}).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 {
|
|
6107
6096
|
let e = `${n}${n.includes("?") ? "&" : "?"} _warmer=${Date.now()}`;
|
|
6108
6097
|
console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
|
|
6109
6098
|
"X-Cache-Warmer": "true",
|
|
6110
6099
|
"User-Agent": "Kama-Cache-Warmer/1.0"
|
|
6111
6100
|
} }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
|
|
6112
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
|
+
}
|
|
6113
6109
|
}
|
|
6114
|
-
r && await this.purgeGlobalCacheDirect(e, t);
|
|
6115
6110
|
} catch (e) {
|
|
6116
6111
|
console.warn("[CacheManager] Dynamic purgeNode failed:", e);
|
|
6117
6112
|
}
|
|
6118
6113
|
})();
|
|
6119
|
-
this.dispatch(e,
|
|
6114
|
+
this.dispatch(e, a);
|
|
6120
6115
|
}
|
|
6121
6116
|
purgeAsset(e, t, n) {
|
|
6122
6117
|
let r = (async () => {
|
|
6123
6118
|
try {
|
|
6124
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 || [];
|
|
6125
|
-
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, []);
|
|
6126
6121
|
} catch (e) {
|
|
6127
6122
|
console.warn("[CacheManager] purgeAsset failed:", e);
|
|
6128
6123
|
}
|
|
@@ -6565,7 +6560,7 @@ H.get("/", async (e) => {
|
|
|
6565
6560
|
await he(t, n, i);
|
|
6566
6561
|
}
|
|
6567
6562
|
}
|
|
6568
|
-
return await I(e).clear(),
|
|
6563
|
+
return await I(e).clear(), e.json({
|
|
6569
6564
|
success: !0,
|
|
6570
6565
|
id: D,
|
|
6571
6566
|
status: "draft",
|
|
@@ -6782,7 +6777,7 @@ W.get("/tree.json", async (e) => {
|
|
|
6782
6777
|
c.push(e.id, e.sortOrder);
|
|
6783
6778
|
}), c.push(...i), c.push(o), await t.prepare(s).run(...c);
|
|
6784
6779
|
}
|
|
6785
|
-
return await i.clear(), a.
|
|
6780
|
+
return await i.clear(), r.length > 0 && a.purgeNode(e, t, r[0].id, !0), e.json({
|
|
6786
6781
|
success: !0,
|
|
6787
6782
|
reorderedCount: r.length
|
|
6788
6783
|
});
|
|
@@ -6791,9 +6786,9 @@ W.get("/tree.json", async (e) => {
|
|
|
6791
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;
|
|
6792
6787
|
let g = G(u), _ = e.get("user")?.id || null;
|
|
6793
6788
|
if (s === "create") {
|
|
6794
|
-
let r = m.slug || n.slug || c,
|
|
6795
|
-
if (
|
|
6796
|
-
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 = `
|
|
6797
6792
|
SELECT 1
|
|
6798
6793
|
FROM tree_nodes tn
|
|
6799
6794
|
INNER JOIN content_nodes cn ON tn.contentId = cn.id
|
|
@@ -6801,51 +6796,51 @@ W.get("/tree.json", async (e) => {
|
|
|
6801
6796
|
AND ${r}
|
|
6802
6797
|
AND cn.slug = ?
|
|
6803
6798
|
AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
|
|
6804
|
-
`, c = g === null ? [o,
|
|
6799
|
+
`, c = g === null ? [o, a] : [
|
|
6805
6800
|
o,
|
|
6806
6801
|
g,
|
|
6807
|
-
|
|
6802
|
+
a
|
|
6808
6803
|
];
|
|
6809
|
-
if (i && !isNaN(i) && (
|
|
6810
|
-
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.`,
|
|
6811
6806
|
field: "slug"
|
|
6812
6807
|
}, 409);
|
|
6813
6808
|
}
|
|
6814
|
-
let
|
|
6815
|
-
if (!
|
|
6809
|
+
let s = m.language?.trim() || n.language?.trim() || null;
|
|
6810
|
+
if (!s) {
|
|
6816
6811
|
let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ?").get(o);
|
|
6817
6812
|
if (e?.dataJson) try {
|
|
6818
6813
|
let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
|
|
6819
|
-
t.defaultLanguage && (
|
|
6814
|
+
t.defaultLanguage && (s = t.defaultLanguage.trim());
|
|
6820
6815
|
} catch {}
|
|
6821
6816
|
}
|
|
6822
|
-
if (!
|
|
6817
|
+
if (!s) {
|
|
6823
6818
|
let e = [];
|
|
6824
6819
|
if (n.channels && Array.isArray(n.channels) ? e = n.channels : n.channelId && n.channelId !== "all" && (e = [n.channelId]), e.length > 0) {
|
|
6825
6820
|
let n = Number(e[0]);
|
|
6826
6821
|
if (!isNaN(n)) {
|
|
6827
6822
|
let e = await t.prepare("SELECT defaultLanguage FROM channels WHERE id = ?").get(n);
|
|
6828
|
-
e?.defaultLanguage && (
|
|
6823
|
+
e?.defaultLanguage && (s = e.defaultLanguage.trim());
|
|
6829
6824
|
}
|
|
6830
6825
|
}
|
|
6831
6826
|
}
|
|
6832
|
-
let
|
|
6833
|
-
await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o,
|
|
6834
|
-
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(`
|
|
6835
6830
|
SELECT COALESCE(MAX(sortOrder), -1) + 1 as nextSort
|
|
6836
6831
|
FROM tree_nodes
|
|
6837
|
-
WHERE treeId = ? AND ${
|
|
6838
|
-
`).get(...
|
|
6839
|
-
n.channels && Array.isArray(n.channels) ?
|
|
6840
|
-
let
|
|
6841
|
-
if (
|
|
6842
|
-
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]);
|
|
6843
6838
|
await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...n);
|
|
6844
6839
|
}
|
|
6845
|
-
return await i.clear(),
|
|
6840
|
+
return await i.clear(), e.json({
|
|
6846
6841
|
success: !0,
|
|
6847
|
-
id:
|
|
6848
|
-
treeNodeId:
|
|
6842
|
+
id: f,
|
|
6843
|
+
treeNodeId: x,
|
|
6849
6844
|
status: "draft"
|
|
6850
6845
|
}, 201);
|
|
6851
6846
|
}
|
|
@@ -6880,14 +6875,14 @@ W.get("/tree.json", async (e) => {
|
|
|
6880
6875
|
}
|
|
6881
6876
|
await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, d);
|
|
6882
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);
|
|
6883
|
-
return await i.clear(), a.
|
|
6878
|
+
return await i.clear(), a.purgeNode(e, t, d, !0), e.json({
|
|
6884
6879
|
success: !0,
|
|
6885
6880
|
treeNodeId: s
|
|
6886
6881
|
});
|
|
6887
6882
|
}
|
|
6888
6883
|
if (s === "detach") {
|
|
6889
6884
|
let r = n.treeNodeId || n.contentId;
|
|
6890
|
-
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);
|
|
6891
6886
|
}
|
|
6892
6887
|
return e.json({ error: "Invalid payload or action" }, 400);
|
|
6893
6888
|
} catch (t) {
|
|
@@ -6951,7 +6946,7 @@ W.get("/tree.json", async (e) => {
|
|
|
6951
6946
|
await t.prepare(`INSERT OR IGNORE INTO channel_trees (channelId, treeId, key) VALUES ${n}`).run(...r);
|
|
6952
6947
|
}
|
|
6953
6948
|
}
|
|
6954
|
-
return await
|
|
6949
|
+
return await cache.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
|
|
6955
6950
|
success: !0,
|
|
6956
6951
|
id: p,
|
|
6957
6952
|
key: o,
|
package/dist/index.html
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
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-
|
|
10
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-DIxtk5i5.js"></script>
|
|
10
|
+
<link rel="stylesheet" crossorigin href="/assets/index-C5TmJVER.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
13
13
|
<div id="app"></div>
|
package/dist/index.js
CHANGED
|
@@ -1854,24 +1854,6 @@ var u = /* @__PURE__ */ o({
|
|
|
1854
1854
|
},
|
|
1855
1855
|
required: !0
|
|
1856
1856
|
},
|
|
1857
|
-
logoText: {
|
|
1858
|
-
label: "Logo Text",
|
|
1859
|
-
type: "text",
|
|
1860
|
-
required: !1,
|
|
1861
|
-
public: !0,
|
|
1862
|
-
inherits: "logoText",
|
|
1863
|
-
rules: { required: !1 }
|
|
1864
|
-
},
|
|
1865
|
-
logoImage: {
|
|
1866
|
-
label: "Logo Image",
|
|
1867
|
-
type: "image",
|
|
1868
|
-
maxPreviewWidth: "300px",
|
|
1869
|
-
multiple: !1,
|
|
1870
|
-
allowedTypes: ["image/svg"],
|
|
1871
|
-
public: !0,
|
|
1872
|
-
inherits: "logoImage",
|
|
1873
|
-
rules: {}
|
|
1874
|
-
},
|
|
1875
1857
|
layoutId: {
|
|
1876
1858
|
label: "Page Layout",
|
|
1877
1859
|
type: "layout-select",
|
|
@@ -2200,24 +2182,6 @@ var u = /* @__PURE__ */ o({
|
|
|
2200
2182
|
},
|
|
2201
2183
|
required: !0
|
|
2202
2184
|
},
|
|
2203
|
-
logoText: {
|
|
2204
|
-
label: "Logo Text",
|
|
2205
|
-
type: "text",
|
|
2206
|
-
required: !1,
|
|
2207
|
-
public: !0,
|
|
2208
|
-
inherits: "logoText",
|
|
2209
|
-
rules: { required: !1 }
|
|
2210
|
-
},
|
|
2211
|
-
logoImage: {
|
|
2212
|
-
label: "Logo Image",
|
|
2213
|
-
type: "image",
|
|
2214
|
-
maxPreviewWidth: "300px",
|
|
2215
|
-
multiple: !1,
|
|
2216
|
-
allowedTypes: ["image/svg"],
|
|
2217
|
-
public: !0,
|
|
2218
|
-
inherits: "logoImage",
|
|
2219
|
-
rules: {}
|
|
2220
|
-
},
|
|
2221
2185
|
layoutId: {
|
|
2222
2186
|
label: "Page Layout",
|
|
2223
2187
|
type: "layout-select",
|
|
@@ -4077,6 +4041,7 @@ var u = /* @__PURE__ */ o({
|
|
|
4077
4041
|
footer: {
|
|
4078
4042
|
label: "Footer",
|
|
4079
4043
|
inherit: "parent",
|
|
4044
|
+
purgeTargets: ["/partials/footer"],
|
|
4080
4045
|
disallowedBlocks: [
|
|
4081
4046
|
"hero",
|
|
4082
4047
|
"image_card",
|
|
@@ -4130,6 +4095,7 @@ var u = /* @__PURE__ */ o({
|
|
|
4130
4095
|
footer: {
|
|
4131
4096
|
label: "Footer",
|
|
4132
4097
|
inherit: "parent",
|
|
4098
|
+
purgeTargets: ["/partials/footer"],
|
|
4133
4099
|
disallowedBlocks: [
|
|
4134
4100
|
"hero",
|
|
4135
4101
|
"image_card",
|
|
@@ -4192,6 +4158,7 @@ var u = /* @__PURE__ */ o({
|
|
|
4192
4158
|
footer: {
|
|
4193
4159
|
label: "Footer",
|
|
4194
4160
|
inherit: "parent",
|
|
4161
|
+
purgeTargets: ["/partials/footer"],
|
|
4195
4162
|
disallowedBlocks: [
|
|
4196
4163
|
"hero",
|
|
4197
4164
|
"image_card",
|
|
@@ -6095,52 +6062,80 @@ var V = class {
|
|
|
6095
6062
|
console.warn("[CacheManager] Failed to purge internal worker cache:", e);
|
|
6096
6063
|
}
|
|
6097
6064
|
}
|
|
6098
|
-
purgeNode(e, t, n, r = !1) {
|
|
6099
|
-
let
|
|
6065
|
+
purgeNode(e, t, n, r = !1, i = []) {
|
|
6066
|
+
let a = (async () => {
|
|
6100
6067
|
try {
|
|
6101
|
-
let
|
|
6102
|
-
if (!
|
|
6103
|
-
let
|
|
6104
|
-
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() !== "") {
|
|
6105
6072
|
let t = e.baseUrl.trim();
|
|
6106
|
-
!t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`),
|
|
6073
|
+
!t.startsWith("http://") && !t.startsWith("https://") && (t = `https://${t}`), m.add(t.replace(/\/+$/, ""));
|
|
6074
|
+
}
|
|
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
|
+
}
|
|
6107
6088
|
}
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
for (let e of
|
|
6117
|
-
|
|
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`, {
|
|
6118
6101
|
method: "POST",
|
|
6119
6102
|
headers: {
|
|
6120
|
-
Authorization: `Bearer ${
|
|
6103
|
+
Authorization: `Bearer ${b}`,
|
|
6121
6104
|
"Content-Type": "application/json"
|
|
6122
6105
|
},
|
|
6123
6106
|
body: JSON.stringify({ files: i })
|
|
6124
|
-
}).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 {
|
|
6125
6114
|
let e = `${n}${n.includes("?") ? "&" : "?"} _warmer=${Date.now()}`;
|
|
6126
6115
|
console.log(`[CacheManager] Prewarming cache at: ${e}`), fetch(e, { headers: {
|
|
6127
6116
|
"X-Cache-Warmer": "true",
|
|
6128
6117
|
"User-Agent": "Kama-Cache-Warmer/1.0"
|
|
6129
6118
|
} }).catch((e) => console.warn("[CacheManager] Prewarm fetch error:", e));
|
|
6130
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
|
+
}
|
|
6131
6127
|
}
|
|
6132
|
-
r && await this.purgeGlobalCacheDirect(e, t);
|
|
6133
6128
|
} catch (e) {
|
|
6134
6129
|
console.warn("[CacheManager] Dynamic purgeNode failed:", e);
|
|
6135
6130
|
}
|
|
6136
6131
|
})();
|
|
6137
|
-
this.dispatch(e,
|
|
6132
|
+
this.dispatch(e, a);
|
|
6138
6133
|
}
|
|
6139
6134
|
purgeAsset(e, t, n) {
|
|
6140
6135
|
let r = (async () => {
|
|
6141
6136
|
try {
|
|
6142
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 || [];
|
|
6143
|
-
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, []);
|
|
6144
6139
|
} catch (e) {
|
|
6145
6140
|
console.warn("[CacheManager] purgeAsset failed:", e);
|
|
6146
6141
|
}
|
|
@@ -6583,7 +6578,7 @@ H.get("/", async (e) => {
|
|
|
6583
6578
|
await he(t, n, i);
|
|
6584
6579
|
}
|
|
6585
6580
|
}
|
|
6586
|
-
return await I(e).clear(),
|
|
6581
|
+
return await I(e).clear(), e.json({
|
|
6587
6582
|
success: !0,
|
|
6588
6583
|
id: D,
|
|
6589
6584
|
status: "draft",
|
|
@@ -6802,7 +6797,7 @@ W.get("/tree.json", async (e) => {
|
|
|
6802
6797
|
c.push(e.id, e.sortOrder);
|
|
6803
6798
|
}), c.push(...i), c.push(o), await t.prepare(s).run(...c);
|
|
6804
6799
|
}
|
|
6805
|
-
return await i.clear(), a.
|
|
6800
|
+
return await i.clear(), r.length > 0 && a.purgeNode(e, t, r[0].id, !0), e.json({
|
|
6806
6801
|
success: !0,
|
|
6807
6802
|
reorderedCount: r.length
|
|
6808
6803
|
});
|
|
@@ -6811,9 +6806,9 @@ W.get("/tree.json", async (e) => {
|
|
|
6811
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;
|
|
6812
6807
|
let g = G(u), _ = e.get("user")?.id || null;
|
|
6813
6808
|
if (s === "create") {
|
|
6814
|
-
let r = m.slug || n.slug || c,
|
|
6815
|
-
if (
|
|
6816
|
-
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 = `
|
|
6817
6812
|
SELECT 1
|
|
6818
6813
|
FROM tree_nodes tn
|
|
6819
6814
|
INNER JOIN content_nodes cn ON tn.contentId = cn.id
|
|
@@ -6821,51 +6816,51 @@ W.get("/tree.json", async (e) => {
|
|
|
6821
6816
|
AND ${r}
|
|
6822
6817
|
AND cn.slug = ?
|
|
6823
6818
|
AND (cn.deletedAt IS NULL OR cn.deletedAt = '')
|
|
6824
|
-
`, c = g === null ? [o,
|
|
6819
|
+
`, c = g === null ? [o, a] : [
|
|
6825
6820
|
o,
|
|
6826
6821
|
g,
|
|
6827
|
-
|
|
6822
|
+
a
|
|
6828
6823
|
];
|
|
6829
|
-
if (i && !isNaN(i) && (
|
|
6830
|
-
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.`,
|
|
6831
6826
|
field: "slug"
|
|
6832
6827
|
}, 409);
|
|
6833
6828
|
}
|
|
6834
|
-
let
|
|
6835
|
-
if (!
|
|
6829
|
+
let s = m.language?.trim() || n.language?.trim() || null;
|
|
6830
|
+
if (!s) {
|
|
6836
6831
|
let e = await t.prepare("SELECT dataJson FROM trees WHERE id = ?").get(o);
|
|
6837
6832
|
if (e?.dataJson) try {
|
|
6838
6833
|
let t = typeof e.dataJson == "string" ? JSON.parse(e.dataJson) : e.dataJson;
|
|
6839
|
-
t.defaultLanguage && (
|
|
6834
|
+
t.defaultLanguage && (s = t.defaultLanguage.trim());
|
|
6840
6835
|
} catch {}
|
|
6841
6836
|
}
|
|
6842
|
-
if (!
|
|
6837
|
+
if (!s) {
|
|
6843
6838
|
let e = [];
|
|
6844
6839
|
if (n.channels && Array.isArray(n.channels) ? e = n.channels : n.channelId && n.channelId !== "all" && (e = [n.channelId]), e.length > 0) {
|
|
6845
6840
|
let n = Number(e[0]);
|
|
6846
6841
|
if (!isNaN(n)) {
|
|
6847
6842
|
let e = await t.prepare("SELECT defaultLanguage FROM channels WHERE id = ?").get(n);
|
|
6848
|
-
e?.defaultLanguage && (
|
|
6843
|
+
e?.defaultLanguage && (s = e.defaultLanguage.trim());
|
|
6849
6844
|
}
|
|
6850
6845
|
}
|
|
6851
6846
|
}
|
|
6852
|
-
let
|
|
6853
|
-
await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o,
|
|
6854
|
-
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(`
|
|
6855
6850
|
SELECT COALESCE(MAX(sortOrder), -1) + 1 as nextSort
|
|
6856
6851
|
FROM tree_nodes
|
|
6857
|
-
WHERE treeId = ? AND ${
|
|
6858
|
-
`).get(...
|
|
6859
|
-
n.channels && Array.isArray(n.channels) ?
|
|
6860
|
-
let
|
|
6861
|
-
if (
|
|
6862
|
-
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]);
|
|
6863
6858
|
await t.prepare(`INSERT OR IGNORE INTO node_channels (nodeId, channelId) VALUES ${e}`).run(...n);
|
|
6864
6859
|
}
|
|
6865
|
-
return await i.clear(),
|
|
6860
|
+
return await i.clear(), e.json({
|
|
6866
6861
|
success: !0,
|
|
6867
|
-
id:
|
|
6868
|
-
treeNodeId:
|
|
6862
|
+
id: f,
|
|
6863
|
+
treeNodeId: x,
|
|
6869
6864
|
status: "draft"
|
|
6870
6865
|
}, 201);
|
|
6871
6866
|
}
|
|
@@ -6900,14 +6895,14 @@ W.get("/tree.json", async (e) => {
|
|
|
6900
6895
|
}
|
|
6901
6896
|
await t.prepare("DELETE FROM tree_nodes WHERE treeId = ? AND contentId = ?").run(o, d);
|
|
6902
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);
|
|
6903
|
-
return await i.clear(), a.
|
|
6898
|
+
return await i.clear(), a.purgeNode(e, t, d, !0), e.json({
|
|
6904
6899
|
success: !0,
|
|
6905
6900
|
treeNodeId: s
|
|
6906
6901
|
});
|
|
6907
6902
|
}
|
|
6908
6903
|
if (s === "detach") {
|
|
6909
6904
|
let r = n.treeNodeId || n.contentId;
|
|
6910
|
-
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);
|
|
6911
6906
|
}
|
|
6912
6907
|
return e.json({ error: "Invalid payload or action" }, 400);
|
|
6913
6908
|
} catch (t) {
|
|
@@ -6971,7 +6966,7 @@ W.get("/tree.json", async (e) => {
|
|
|
6971
6966
|
await t.prepare(`INSERT OR IGNORE INTO channel_trees (channelId, treeId, key) VALUES ${n}`).run(...r);
|
|
6972
6967
|
}
|
|
6973
6968
|
}
|
|
6974
|
-
return await
|
|
6969
|
+
return await cache.clear(), new V(e.env).purgeGlobalCache(e, t), e.json({
|
|
6975
6970
|
success: !0,
|
|
6976
6971
|
id: p,
|
|
6977
6972
|
key: o,
|