@sonicjs-cms/core 2.0.2 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-O46XKBFM.js → chunk-3LZ6TLPC.js} +14 -24
- package/dist/chunk-3LZ6TLPC.js.map +1 -0
- package/dist/{chunk-ALOS2CBJ.cjs → chunk-3SPQ3J4N.cjs} +14 -24
- package/dist/chunk-3SPQ3J4N.cjs.map +1 -0
- package/dist/{chunk-EGFHFM4N.cjs → chunk-5APKEYFK.cjs} +5 -5
- package/dist/{chunk-EGFHFM4N.cjs.map → chunk-5APKEYFK.cjs.map} +1 -1
- package/dist/{chunk-UL32L2KV.cjs → chunk-BRPONFW6.cjs} +123 -3
- package/dist/chunk-BRPONFW6.cjs.map +1 -0
- package/dist/{chunk-SGGHTIWV.js → chunk-CQ2VMJQO.js} +228 -45
- package/dist/chunk-CQ2VMJQO.js.map +1 -0
- package/dist/{chunk-P2PTTBO5.js → chunk-RYQCT2IV.js} +3 -3
- package/dist/{chunk-P2PTTBO5.js.map → chunk-RYQCT2IV.js.map} +1 -1
- package/dist/{chunk-7G6XT62S.cjs → chunk-RZW752PE.cjs} +325 -142
- package/dist/chunk-RZW752PE.cjs.map +1 -0
- package/dist/{chunk-XJETEIRU.js → chunk-WKGONLHK.js} +123 -4
- package/dist/chunk-WKGONLHK.js.map +1 -0
- package/dist/index.cjs +58 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7 -11
- package/dist/index.js.map +1 -1
- package/dist/routes.cjs +23 -23
- package/dist/routes.js +3 -3
- package/dist/templates.cjs +18 -18
- package/dist/templates.js +2 -2
- package/dist/utils.cjs +11 -11
- package/dist/utils.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-7G6XT62S.cjs.map +0 -1
- package/dist/chunk-ALOS2CBJ.cjs.map +0 -1
- package/dist/chunk-O46XKBFM.js.map +0 -1
- package/dist/chunk-SGGHTIWV.js.map +0 -1
- package/dist/chunk-UL32L2KV.cjs.map +0 -1
- package/dist/chunk-XJETEIRU.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getCacheService, CACHE_CONFIGS, getLogger } from './chunk-LH4Z7QID.js';
|
|
2
|
-
import { requireAuth, isPluginActive, requireRole, AuthManager, logActivity
|
|
2
|
+
import { requireAuth, isPluginActive, requireRole, AuthManager, logActivity } from './chunk-M6FPVS7E.js';
|
|
3
3
|
import { PluginService, MigrationService } from './chunk-CDBVZEWR.js';
|
|
4
|
-
import { init_admin_layout_catalyst_template, renderDesignPage, renderCheckboxPage, renderFAQList, renderTestimonialsList, renderCodeExamplesList, renderAlert, renderTable, renderPagination, renderConfirmationDialog, getConfirmationDialogScript, renderAdminLayoutCatalyst, renderAdminLayout, adminLayoutV2, renderForm } from './chunk-
|
|
5
|
-
import { QueryFilterBuilder, sanitizeInput, getCoreVersion, escapeHtml } from './chunk-
|
|
4
|
+
import { init_admin_layout_catalyst_template, renderDesignPage, renderCheckboxPage, renderFAQList, renderTestimonialsList, renderCodeExamplesList, renderAlert, renderTable, renderPagination, renderConfirmationDialog, getConfirmationDialogScript, renderAdminLayoutCatalyst, renderAdminLayout, adminLayoutV2, renderForm } from './chunk-3LZ6TLPC.js';
|
|
5
|
+
import { QueryFilterBuilder, sanitizeInput, getCoreVersion, escapeHtml } from './chunk-WKGONLHK.js';
|
|
6
6
|
import { metricsTracker } from './chunk-FICTAGD4.js';
|
|
7
7
|
import { Hono } from 'hono';
|
|
8
8
|
import { cors } from 'hono/cors';
|
|
@@ -916,10 +916,17 @@ apiMediaRoutes.post("/create-folder", async (c) => {
|
|
|
916
916
|
}
|
|
917
917
|
const checkStmt = c.env.DB.prepare("SELECT COUNT(*) as count FROM media WHERE folder = ? AND deleted_at IS NULL");
|
|
918
918
|
const existingFolder = await checkStmt.bind(folderName).first();
|
|
919
|
+
if (existingFolder && existingFolder.count > 0) {
|
|
920
|
+
return c.json({
|
|
921
|
+
success: false,
|
|
922
|
+
error: `Folder "${folderName}" already exists`
|
|
923
|
+
}, 400);
|
|
924
|
+
}
|
|
919
925
|
return c.json({
|
|
920
926
|
success: true,
|
|
921
|
-
message: `Folder "${folderName}"
|
|
922
|
-
folder: folderName
|
|
927
|
+
message: `Folder "${folderName}" is ready. Upload files to this folder to make it appear in the media library.`,
|
|
928
|
+
folder: folderName,
|
|
929
|
+
note: "Folders appear automatically when you upload files to them"
|
|
923
930
|
});
|
|
924
931
|
} catch (error) {
|
|
925
932
|
console.error("Create folder error:", error);
|
|
@@ -2031,9 +2038,36 @@ function renderRegisterPage(data) {
|
|
|
2031
2038
|
</html>
|
|
2032
2039
|
`;
|
|
2033
2040
|
}
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2041
|
+
var authValidationService = {
|
|
2042
|
+
/**
|
|
2043
|
+
* Build registration schema dynamically based on auth settings
|
|
2044
|
+
* For now, returns a static schema with standard fields
|
|
2045
|
+
*/
|
|
2046
|
+
async buildRegistrationSchema(_db) {
|
|
2047
|
+
return z.object({
|
|
2048
|
+
email: z.string().email("Valid email is required"),
|
|
2049
|
+
password: z.string().min(8, "Password must be at least 8 characters"),
|
|
2050
|
+
username: z.string().min(3, "Username must be at least 3 characters").optional(),
|
|
2051
|
+
firstName: z.string().min(1, "First name is required").optional(),
|
|
2052
|
+
lastName: z.string().min(1, "Last name is required").optional()
|
|
2053
|
+
});
|
|
2054
|
+
},
|
|
2055
|
+
/**
|
|
2056
|
+
* Generate default values for optional fields
|
|
2057
|
+
*/
|
|
2058
|
+
generateDefaultValue(field, data) {
|
|
2059
|
+
switch (field) {
|
|
2060
|
+
case "username":
|
|
2061
|
+
return data.email ? data.email.split("@")[0] : `user${Date.now()}`;
|
|
2062
|
+
case "firstName":
|
|
2063
|
+
return "User";
|
|
2064
|
+
case "lastName":
|
|
2065
|
+
return data.email ? data.email.split("@")[0] : "Account";
|
|
2066
|
+
default:
|
|
2067
|
+
return "";
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
};
|
|
2037
2071
|
|
|
2038
2072
|
// src/routes/auth.ts
|
|
2039
2073
|
var authRoutes = new Hono();
|
|
@@ -2317,7 +2351,7 @@ authRoutes.post("/register/form", async (c) => {
|
|
|
2317
2351
|
Account created successfully! Redirecting to admin dashboard...
|
|
2318
2352
|
<script>
|
|
2319
2353
|
setTimeout(() => {
|
|
2320
|
-
window.location.href = '/admin/
|
|
2354
|
+
window.location.href = '/admin/dashboard';
|
|
2321
2355
|
}, 2000);
|
|
2322
2356
|
</script>
|
|
2323
2357
|
</div>
|
|
@@ -2385,7 +2419,7 @@ authRoutes.post("/login/form", async (c) => {
|
|
|
2385
2419
|
</div>
|
|
2386
2420
|
<script>
|
|
2387
2421
|
setTimeout(() => {
|
|
2388
|
-
window.location.href = '/admin/
|
|
2422
|
+
window.location.href = '/admin/dashboard';
|
|
2389
2423
|
}, 2000);
|
|
2390
2424
|
</script>
|
|
2391
2425
|
</div>
|
|
@@ -2678,7 +2712,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
2678
2712
|
maxAge: 60 * 60 * 24
|
|
2679
2713
|
// 24 hours
|
|
2680
2714
|
});
|
|
2681
|
-
return c.redirect("/admin/
|
|
2715
|
+
return c.redirect("/admin/dashboard?welcome=true");
|
|
2682
2716
|
} catch (error) {
|
|
2683
2717
|
console.error("Accept invitation error:", error);
|
|
2684
2718
|
return c.json({ error: "Failed to accept invitation" }, 500);
|
|
@@ -7987,7 +8021,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
7987
8021
|
}));
|
|
7988
8022
|
}
|
|
7989
8023
|
});
|
|
7990
|
-
userRoutes.get("/users",
|
|
8024
|
+
userRoutes.get("/users", async (c) => {
|
|
7991
8025
|
const db = c.env.DB;
|
|
7992
8026
|
const user = c.get("user");
|
|
7993
8027
|
try {
|
|
@@ -8106,7 +8140,7 @@ userRoutes.get("/users", requirePermission("users.read"), async (c) => {
|
|
|
8106
8140
|
}), 500);
|
|
8107
8141
|
}
|
|
8108
8142
|
});
|
|
8109
|
-
userRoutes.get("/users/new",
|
|
8143
|
+
userRoutes.get("/users/new", async (c) => {
|
|
8110
8144
|
const user = c.get("user");
|
|
8111
8145
|
try {
|
|
8112
8146
|
const pageData = {
|
|
@@ -8127,7 +8161,7 @@ userRoutes.get("/users/new", requirePermission("users.create"), async (c) => {
|
|
|
8127
8161
|
}), 500);
|
|
8128
8162
|
}
|
|
8129
8163
|
});
|
|
8130
|
-
userRoutes.post("/users/new",
|
|
8164
|
+
userRoutes.post("/users/new", async (c) => {
|
|
8131
8165
|
const db = c.env.DB;
|
|
8132
8166
|
const user = c.get("user");
|
|
8133
8167
|
try {
|
|
@@ -8227,7 +8261,7 @@ userRoutes.post("/users/new", requirePermission("users.create"), async (c) => {
|
|
|
8227
8261
|
}));
|
|
8228
8262
|
}
|
|
8229
8263
|
});
|
|
8230
|
-
userRoutes.get("/users/:id",
|
|
8264
|
+
userRoutes.get("/users/:id", async (c) => {
|
|
8231
8265
|
if (c.req.path.endsWith("/edit")) {
|
|
8232
8266
|
return c.notFound();
|
|
8233
8267
|
}
|
|
@@ -8278,7 +8312,7 @@ userRoutes.get("/users/:id", requirePermission("users.read"), async (c) => {
|
|
|
8278
8312
|
return c.json({ error: "Failed to fetch user" }, 500);
|
|
8279
8313
|
}
|
|
8280
8314
|
});
|
|
8281
|
-
userRoutes.get("/users/:id/edit",
|
|
8315
|
+
userRoutes.get("/users/:id/edit", async (c) => {
|
|
8282
8316
|
const db = c.env.DB;
|
|
8283
8317
|
const user = c.get("user");
|
|
8284
8318
|
const userId = c.req.param("id");
|
|
@@ -8332,7 +8366,7 @@ userRoutes.get("/users/:id/edit", requirePermission("users.update"), async (c) =
|
|
|
8332
8366
|
}), 500);
|
|
8333
8367
|
}
|
|
8334
8368
|
});
|
|
8335
|
-
userRoutes.put("/users/:id",
|
|
8369
|
+
userRoutes.put("/users/:id", async (c) => {
|
|
8336
8370
|
const db = c.env.DB;
|
|
8337
8371
|
const user = c.get("user");
|
|
8338
8372
|
const userId = c.req.param("id");
|
|
@@ -8418,7 +8452,7 @@ userRoutes.put("/users/:id", requirePermission("users.update"), async (c) => {
|
|
|
8418
8452
|
}));
|
|
8419
8453
|
}
|
|
8420
8454
|
});
|
|
8421
|
-
userRoutes.delete("/users/:id",
|
|
8455
|
+
userRoutes.delete("/users/:id", async (c) => {
|
|
8422
8456
|
const db = c.env.DB;
|
|
8423
8457
|
const user = c.get("user");
|
|
8424
8458
|
const userId = c.req.param("id");
|
|
@@ -8479,7 +8513,7 @@ userRoutes.delete("/users/:id", requirePermission("users.delete"), async (c) =>
|
|
|
8479
8513
|
return c.json({ error: "Failed to delete user" }, 500);
|
|
8480
8514
|
}
|
|
8481
8515
|
});
|
|
8482
|
-
userRoutes.post("/invite-user",
|
|
8516
|
+
userRoutes.post("/invite-user", async (c) => {
|
|
8483
8517
|
const db = c.env.DB;
|
|
8484
8518
|
const user = c.get("user");
|
|
8485
8519
|
try {
|
|
@@ -8555,7 +8589,7 @@ userRoutes.post("/invite-user", requirePermission("users.create"), async (c) =>
|
|
|
8555
8589
|
return c.json({ error: "Failed to send user invitation" }, 500);
|
|
8556
8590
|
}
|
|
8557
8591
|
});
|
|
8558
|
-
userRoutes.post("/resend-invitation/:id",
|
|
8592
|
+
userRoutes.post("/resend-invitation/:id", async (c) => {
|
|
8559
8593
|
const db = c.env.DB;
|
|
8560
8594
|
const user = c.get("user");
|
|
8561
8595
|
const userId = c.req.param("id");
|
|
@@ -8604,7 +8638,7 @@ userRoutes.post("/resend-invitation/:id", requirePermission("users.create"), asy
|
|
|
8604
8638
|
return c.json({ error: "Failed to resend invitation" }, 500);
|
|
8605
8639
|
}
|
|
8606
8640
|
});
|
|
8607
|
-
userRoutes.delete("/cancel-invitation/:id",
|
|
8641
|
+
userRoutes.delete("/cancel-invitation/:id", async (c) => {
|
|
8608
8642
|
const db = c.env.DB;
|
|
8609
8643
|
const user = c.get("user");
|
|
8610
8644
|
const userId = c.req.param("id");
|
|
@@ -8638,7 +8672,7 @@ userRoutes.delete("/cancel-invitation/:id", requirePermission("users.delete"), a
|
|
|
8638
8672
|
return c.json({ error: "Failed to cancel invitation" }, 500);
|
|
8639
8673
|
}
|
|
8640
8674
|
});
|
|
8641
|
-
userRoutes.get("/activity-logs",
|
|
8675
|
+
userRoutes.get("/activity-logs", async (c) => {
|
|
8642
8676
|
const db = c.env.DB;
|
|
8643
8677
|
const user = c.get("user");
|
|
8644
8678
|
try {
|
|
@@ -8744,7 +8778,7 @@ userRoutes.get("/activity-logs", requirePermission("activity.read"), async (c) =
|
|
|
8744
8778
|
return c.html(renderActivityLogsPage(pageData));
|
|
8745
8779
|
}
|
|
8746
8780
|
});
|
|
8747
|
-
userRoutes.get("/activity-logs/export",
|
|
8781
|
+
userRoutes.get("/activity-logs/export", async (c) => {
|
|
8748
8782
|
const db = c.env.DB;
|
|
8749
8783
|
const user = c.get("user");
|
|
8750
8784
|
try {
|
|
@@ -9302,11 +9336,12 @@ function renderMediaLibraryPage(data) {
|
|
|
9302
9336
|
</div>
|
|
9303
9337
|
|
|
9304
9338
|
<!-- Upload Form -->
|
|
9305
|
-
<form
|
|
9339
|
+
<form
|
|
9306
9340
|
id="upload-form"
|
|
9307
9341
|
hx-post="/admin/media/upload"
|
|
9308
9342
|
hx-encoding="multipart/form-data"
|
|
9309
9343
|
hx-target="#upload-results"
|
|
9344
|
+
hx-on::after-request="if(event.detail.successful) { setTimeout(() => { window.location.href = '/admin/media?t=' + Date.now(); }, 1500); }"
|
|
9310
9345
|
class="space-y-4"
|
|
9311
9346
|
>
|
|
9312
9347
|
<!-- Drag and Drop Zone -->
|
|
@@ -10189,21 +10224,23 @@ adminMediaRoutes.get("/", async (c) => {
|
|
|
10189
10224
|
const { results } = await stmt.bind(...params).all();
|
|
10190
10225
|
const foldersStmt = db.prepare(`
|
|
10191
10226
|
SELECT folder, COUNT(*) as count, SUM(size) as totalSize
|
|
10192
|
-
FROM media
|
|
10193
|
-
|
|
10227
|
+
FROM media
|
|
10228
|
+
WHERE deleted_at IS NULL
|
|
10229
|
+
GROUP BY folder
|
|
10194
10230
|
ORDER BY folder
|
|
10195
10231
|
`);
|
|
10196
10232
|
const { results: folders } = await foldersStmt.all();
|
|
10197
10233
|
const typesStmt = db.prepare(`
|
|
10198
|
-
SELECT
|
|
10199
|
-
CASE
|
|
10234
|
+
SELECT
|
|
10235
|
+
CASE
|
|
10200
10236
|
WHEN mime_type LIKE 'image/%' THEN 'images'
|
|
10201
10237
|
WHEN mime_type LIKE 'video/%' THEN 'videos'
|
|
10202
10238
|
WHEN mime_type IN ('application/pdf', 'text/plain') THEN 'documents'
|
|
10203
10239
|
ELSE 'other'
|
|
10204
10240
|
END as type,
|
|
10205
10241
|
COUNT(*) as count
|
|
10206
|
-
FROM media
|
|
10242
|
+
FROM media
|
|
10243
|
+
WHERE deleted_at IS NULL
|
|
10207
10244
|
GROUP BY type
|
|
10208
10245
|
`);
|
|
10209
10246
|
const { results: types } = await typesStmt.all();
|
|
@@ -10479,6 +10516,18 @@ adminMediaRoutes.post("/upload", async (c) => {
|
|
|
10479
10516
|
}
|
|
10480
10517
|
const uploadResults = [];
|
|
10481
10518
|
const errors = [];
|
|
10519
|
+
console.log("[MEDIA UPLOAD] c.env keys:", Object.keys(c.env));
|
|
10520
|
+
console.log("[MEDIA UPLOAD] MEDIA_BUCKET defined?", !!c.env.MEDIA_BUCKET);
|
|
10521
|
+
console.log("[MEDIA UPLOAD] MEDIA_BUCKET type:", typeof c.env.MEDIA_BUCKET);
|
|
10522
|
+
if (!c.env.MEDIA_BUCKET) {
|
|
10523
|
+
console.error("[MEDIA UPLOAD] MEDIA_BUCKET is not available! Available env keys:", Object.keys(c.env));
|
|
10524
|
+
return c.html(html`
|
|
10525
|
+
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
|
|
10526
|
+
Media storage (R2) is not configured. Please check your wrangler.toml configuration.
|
|
10527
|
+
<br><small>Debug: Available bindings: ${Object.keys(c.env).join(", ")}</small>
|
|
10528
|
+
</div>
|
|
10529
|
+
`);
|
|
10530
|
+
}
|
|
10482
10531
|
for (const file of files) {
|
|
10483
10532
|
try {
|
|
10484
10533
|
const validation = fileValidationSchema2.safeParse({
|
|
@@ -16249,7 +16298,7 @@ router.get("/stats", async (c) => {
|
|
|
16249
16298
|
}
|
|
16250
16299
|
let contentCount = 0;
|
|
16251
16300
|
try {
|
|
16252
|
-
const contentStmt = db.prepare("SELECT COUNT(*) as count FROM content
|
|
16301
|
+
const contentStmt = db.prepare("SELECT COUNT(*) as count FROM content");
|
|
16253
16302
|
const contentResult = await contentStmt.first();
|
|
16254
16303
|
contentCount = contentResult?.count || 0;
|
|
16255
16304
|
} catch (error) {
|
|
@@ -17845,11 +17894,13 @@ adminCollectionsRoutes.post("/", async (c) => {
|
|
|
17845
17894
|
now,
|
|
17846
17895
|
now
|
|
17847
17896
|
).run();
|
|
17848
|
-
|
|
17849
|
-
|
|
17850
|
-
|
|
17851
|
-
|
|
17852
|
-
|
|
17897
|
+
if (c.env.CACHE_KV) {
|
|
17898
|
+
try {
|
|
17899
|
+
await c.env.CACHE_KV.delete("cache:collections:all");
|
|
17900
|
+
await c.env.CACHE_KV.delete(`cache:collection:${name}`);
|
|
17901
|
+
} catch (e) {
|
|
17902
|
+
console.error("Error clearing cache:", e);
|
|
17903
|
+
}
|
|
17853
17904
|
}
|
|
17854
17905
|
if (isHtmx) {
|
|
17855
17906
|
return c.html(html`
|
|
@@ -18222,7 +18273,7 @@ function renderSettingsPage(data) {
|
|
|
18222
18273
|
// Migration functions
|
|
18223
18274
|
window.refreshMigrationStatus = async function() {
|
|
18224
18275
|
try {
|
|
18225
|
-
const response = await fetch('/admin/api/migrations/status');
|
|
18276
|
+
const response = await fetch('/admin/settings/api/migrations/status');
|
|
18226
18277
|
const result = await response.json();
|
|
18227
18278
|
|
|
18228
18279
|
if (result.success) {
|
|
@@ -18250,7 +18301,7 @@ function renderSettingsPage(data) {
|
|
|
18250
18301
|
btn.innerHTML = 'Running...';
|
|
18251
18302
|
|
|
18252
18303
|
try {
|
|
18253
|
-
const response = await fetch('/admin/api/migrations/run', {
|
|
18304
|
+
const response = await fetch('/admin/settings/api/migrations/run', {
|
|
18254
18305
|
method: 'POST'
|
|
18255
18306
|
});
|
|
18256
18307
|
const result = await response.json();
|
|
@@ -18271,7 +18322,7 @@ function renderSettingsPage(data) {
|
|
|
18271
18322
|
|
|
18272
18323
|
window.validateSchema = async function() {
|
|
18273
18324
|
try {
|
|
18274
|
-
const response = await fetch('/admin/api/migrations/validate');
|
|
18325
|
+
const response = await fetch('/admin/settings/api/migrations/validate');
|
|
18275
18326
|
const result = await response.json();
|
|
18276
18327
|
|
|
18277
18328
|
if (result.success) {
|
|
@@ -18349,7 +18400,7 @@ function renderSettingsPage(data) {
|
|
|
18349
18400
|
// Database Tools functions
|
|
18350
18401
|
window.refreshDatabaseStats = async function() {
|
|
18351
18402
|
try {
|
|
18352
|
-
const response = await fetch('/admin/database-tools/
|
|
18403
|
+
const response = await fetch('/admin/settings/api/database-tools/stats');
|
|
18353
18404
|
const result = await response.json();
|
|
18354
18405
|
|
|
18355
18406
|
if (result.success) {
|
|
@@ -18370,7 +18421,7 @@ function renderSettingsPage(data) {
|
|
|
18370
18421
|
btn.innerHTML = 'Creating Backup...';
|
|
18371
18422
|
|
|
18372
18423
|
try {
|
|
18373
|
-
const response = await fetch('/admin/database-tools/
|
|
18424
|
+
const response = await fetch('/admin/settings/api/database-tools/backup', {
|
|
18374
18425
|
method: 'POST'
|
|
18375
18426
|
});
|
|
18376
18427
|
const result = await response.json();
|
|
@@ -18409,7 +18460,7 @@ function renderSettingsPage(data) {
|
|
|
18409
18460
|
btn.innerHTML = 'Truncating...';
|
|
18410
18461
|
|
|
18411
18462
|
try {
|
|
18412
|
-
const response = await fetch('/admin/database-tools/
|
|
18463
|
+
const response = await fetch('/admin/settings/api/database-tools/truncate', {
|
|
18413
18464
|
method: 'POST',
|
|
18414
18465
|
headers: {
|
|
18415
18466
|
'Content-Type': 'application/json'
|
|
@@ -18440,7 +18491,7 @@ function renderSettingsPage(data) {
|
|
|
18440
18491
|
|
|
18441
18492
|
window.validateDatabase = async function() {
|
|
18442
18493
|
try {
|
|
18443
|
-
const response = await fetch('/admin/database-tools/
|
|
18494
|
+
const response = await fetch('/admin/settings/api/database-tools/validate');
|
|
18444
18495
|
const result = await response.json();
|
|
18445
18496
|
|
|
18446
18497
|
if (result.success) {
|
|
@@ -19294,7 +19345,7 @@ function renderMigrationSettings(settings) {
|
|
|
19294
19345
|
if (typeof refreshMigrationStatus === 'undefined') {
|
|
19295
19346
|
window.refreshMigrationStatus = async function() {
|
|
19296
19347
|
try {
|
|
19297
|
-
const response = await fetch('/admin/api/migrations/status');
|
|
19348
|
+
const response = await fetch('/admin/settings/api/migrations/status');
|
|
19298
19349
|
const result = await response.json();
|
|
19299
19350
|
|
|
19300
19351
|
if (result.success) {
|
|
@@ -19767,6 +19818,138 @@ adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
|
|
|
19767
19818
|
}, 500);
|
|
19768
19819
|
}
|
|
19769
19820
|
});
|
|
19821
|
+
adminSettingsRoutes.get("/api/database-tools/stats", async (c) => {
|
|
19822
|
+
try {
|
|
19823
|
+
const db = c.env.DB;
|
|
19824
|
+
const tablesQuery = await db.prepare(`
|
|
19825
|
+
SELECT name FROM sqlite_master
|
|
19826
|
+
WHERE type='table'
|
|
19827
|
+
AND name NOT LIKE 'sqlite_%'
|
|
19828
|
+
AND name NOT LIKE '_cf_%'
|
|
19829
|
+
ORDER BY name
|
|
19830
|
+
`).all();
|
|
19831
|
+
const tables = tablesQuery.results || [];
|
|
19832
|
+
let totalRows = 0;
|
|
19833
|
+
const tableStats = await Promise.all(
|
|
19834
|
+
tables.map(async (table) => {
|
|
19835
|
+
try {
|
|
19836
|
+
const countResult = await db.prepare(`SELECT COUNT(*) as count FROM ${table.name}`).first();
|
|
19837
|
+
const rowCount = countResult?.count || 0;
|
|
19838
|
+
totalRows += rowCount;
|
|
19839
|
+
return {
|
|
19840
|
+
name: table.name,
|
|
19841
|
+
rowCount
|
|
19842
|
+
};
|
|
19843
|
+
} catch (error) {
|
|
19844
|
+
console.error(`Error counting rows in ${table.name}:`, error);
|
|
19845
|
+
return {
|
|
19846
|
+
name: table.name,
|
|
19847
|
+
rowCount: 0
|
|
19848
|
+
};
|
|
19849
|
+
}
|
|
19850
|
+
})
|
|
19851
|
+
);
|
|
19852
|
+
const estimatedSizeBytes = totalRows * 1024;
|
|
19853
|
+
const databaseSizeMB = (estimatedSizeBytes / (1024 * 1024)).toFixed(2);
|
|
19854
|
+
return c.json({
|
|
19855
|
+
success: true,
|
|
19856
|
+
data: {
|
|
19857
|
+
totalTables: tables.length,
|
|
19858
|
+
totalRows,
|
|
19859
|
+
databaseSize: `${databaseSizeMB} MB (estimated)`,
|
|
19860
|
+
tables: tableStats
|
|
19861
|
+
}
|
|
19862
|
+
});
|
|
19863
|
+
} catch (error) {
|
|
19864
|
+
console.error("Error fetching database stats:", error);
|
|
19865
|
+
return c.json({
|
|
19866
|
+
success: false,
|
|
19867
|
+
error: "Failed to fetch database statistics"
|
|
19868
|
+
}, 500);
|
|
19869
|
+
}
|
|
19870
|
+
});
|
|
19871
|
+
adminSettingsRoutes.get("/api/database-tools/validate", async (c) => {
|
|
19872
|
+
try {
|
|
19873
|
+
const db = c.env.DB;
|
|
19874
|
+
const integrityResult = await db.prepare("PRAGMA integrity_check").first();
|
|
19875
|
+
const isValid = integrityResult?.integrity_check === "ok";
|
|
19876
|
+
return c.json({
|
|
19877
|
+
success: true,
|
|
19878
|
+
data: {
|
|
19879
|
+
valid: isValid,
|
|
19880
|
+
message: isValid ? "Database integrity check passed" : "Database integrity check failed"
|
|
19881
|
+
}
|
|
19882
|
+
});
|
|
19883
|
+
} catch (error) {
|
|
19884
|
+
console.error("Error validating database:", error);
|
|
19885
|
+
return c.json({
|
|
19886
|
+
success: false,
|
|
19887
|
+
error: "Failed to validate database"
|
|
19888
|
+
}, 500);
|
|
19889
|
+
}
|
|
19890
|
+
});
|
|
19891
|
+
adminSettingsRoutes.post("/api/database-tools/backup", async (c) => {
|
|
19892
|
+
try {
|
|
19893
|
+
const user = c.get("user");
|
|
19894
|
+
if (!user || user.role !== "admin") {
|
|
19895
|
+
return c.json({
|
|
19896
|
+
success: false,
|
|
19897
|
+
error: "Unauthorized. Admin access required."
|
|
19898
|
+
}, 403);
|
|
19899
|
+
}
|
|
19900
|
+
return c.json({
|
|
19901
|
+
success: true,
|
|
19902
|
+
message: "Database backup feature coming soon. Use Cloudflare Dashboard for backups."
|
|
19903
|
+
});
|
|
19904
|
+
} catch (error) {
|
|
19905
|
+
console.error("Error creating backup:", error);
|
|
19906
|
+
return c.json({
|
|
19907
|
+
success: false,
|
|
19908
|
+
error: "Failed to create backup"
|
|
19909
|
+
}, 500);
|
|
19910
|
+
}
|
|
19911
|
+
});
|
|
19912
|
+
adminSettingsRoutes.post("/api/database-tools/truncate", async (c) => {
|
|
19913
|
+
try {
|
|
19914
|
+
const user = c.get("user");
|
|
19915
|
+
if (!user || user.role !== "admin") {
|
|
19916
|
+
return c.json({
|
|
19917
|
+
success: false,
|
|
19918
|
+
error: "Unauthorized. Admin access required."
|
|
19919
|
+
}, 403);
|
|
19920
|
+
}
|
|
19921
|
+
const body = await c.req.json();
|
|
19922
|
+
const tablesToTruncate = body.tables || [];
|
|
19923
|
+
if (!Array.isArray(tablesToTruncate) || tablesToTruncate.length === 0) {
|
|
19924
|
+
return c.json({
|
|
19925
|
+
success: false,
|
|
19926
|
+
error: "No tables specified for truncation"
|
|
19927
|
+
}, 400);
|
|
19928
|
+
}
|
|
19929
|
+
const db = c.env.DB;
|
|
19930
|
+
const results = [];
|
|
19931
|
+
for (const tableName of tablesToTruncate) {
|
|
19932
|
+
try {
|
|
19933
|
+
await db.prepare(`DELETE FROM ${tableName}`).run();
|
|
19934
|
+
results.push({ table: tableName, success: true });
|
|
19935
|
+
} catch (error) {
|
|
19936
|
+
console.error(`Error truncating ${tableName}:`, error);
|
|
19937
|
+
results.push({ table: tableName, success: false, error: String(error) });
|
|
19938
|
+
}
|
|
19939
|
+
}
|
|
19940
|
+
return c.json({
|
|
19941
|
+
success: true,
|
|
19942
|
+
message: `Truncated ${results.filter((r) => r.success).length} of ${tablesToTruncate.length} tables`,
|
|
19943
|
+
results
|
|
19944
|
+
});
|
|
19945
|
+
} catch (error) {
|
|
19946
|
+
console.error("Error truncating tables:", error);
|
|
19947
|
+
return c.json({
|
|
19948
|
+
success: false,
|
|
19949
|
+
error: "Failed to truncate tables"
|
|
19950
|
+
}, 500);
|
|
19951
|
+
}
|
|
19952
|
+
});
|
|
19770
19953
|
adminSettingsRoutes.post("/", async (c) => {
|
|
19771
19954
|
try {
|
|
19772
19955
|
const formData = await c.req.formData();
|
|
@@ -19819,5 +20002,5 @@ var ROUTES_INFO = {
|
|
|
19819
20002
|
};
|
|
19820
20003
|
|
|
19821
20004
|
export { ROUTES_INFO, adminCheckboxRoutes, adminCollectionsRoutes, adminDesignRoutes, adminLogsRoutes, adminMediaRoutes, adminPluginRoutes, adminSettingsRoutes, admin_api_default, admin_code_examples_default, admin_content_default, admin_faq_default, admin_testimonials_default, api_content_crud_default, api_default, api_media_default, api_system_default, auth_default, router, userRoutes };
|
|
19822
|
-
//# sourceMappingURL=chunk-
|
|
19823
|
-
//# sourceMappingURL=chunk-
|
|
20005
|
+
//# sourceMappingURL=chunk-CQ2VMJQO.js.map
|
|
20006
|
+
//# sourceMappingURL=chunk-CQ2VMJQO.js.map
|