@sonicjs-cms/core 2.6.0 → 2.8.0
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/{app-DV27cjPy.d.cts → app-CYEm1ytG.d.cts} +1 -0
- package/dist/{app-DV27cjPy.d.ts → app-CYEm1ytG.d.ts} +1 -0
- package/dist/{chunk-7DL5SPPX.js → chunk-34QIAULP.js} +4 -4
- package/dist/{chunk-7DL5SPPX.js.map → chunk-34QIAULP.js.map} +1 -1
- package/dist/{chunk-EYWR6UA2.js → chunk-3E76TKR5.js} +3 -3
- package/dist/{chunk-EYWR6UA2.js.map → chunk-3E76TKR5.js.map} +1 -1
- package/dist/{chunk-IIRVZSP2.cjs → chunk-5CENPGR2.cjs} +219 -14
- package/dist/chunk-5CENPGR2.cjs.map +1 -0
- package/dist/{chunk-YMTTGHEK.cjs → chunk-5HMR2SJW.cjs} +4 -4
- package/dist/{chunk-YMTTGHEK.cjs.map → chunk-5HMR2SJW.cjs.map} +1 -1
- package/dist/{chunk-YHW27CBV.cjs → chunk-6FHNRRJ3.cjs} +190 -2
- package/dist/chunk-6FHNRRJ3.cjs.map +1 -0
- package/dist/{chunk-F6GZURXJ.js → chunk-BAWMAS5S.js} +5478 -1459
- package/dist/chunk-BAWMAS5S.js.map +1 -0
- package/dist/{chunk-F332TENF.js → chunk-CJYFSKH7.js} +4 -190
- package/dist/chunk-CJYFSKH7.js.map +1 -0
- package/dist/{chunk-3YNNVSMC.js → chunk-G44QUVNM.js} +90 -2
- package/dist/chunk-G44QUVNM.js.map +1 -0
- package/dist/{chunk-T3YIKW2A.cjs → chunk-GPTMGUFN.cjs} +4 -4
- package/dist/{chunk-T3YIKW2A.cjs.map → chunk-GPTMGUFN.cjs.map} +1 -1
- package/dist/chunk-H7AMQWVI.js +2466 -0
- package/dist/chunk-H7AMQWVI.js.map +1 -0
- package/dist/{chunk-CLIH2T74.js → chunk-J5WGMRSU.js} +189 -3
- package/dist/chunk-J5WGMRSU.js.map +1 -0
- package/dist/{chunk-EVZOVYLO.js → chunk-JDFPB6UW.js} +219 -14
- package/dist/chunk-JDFPB6UW.js.map +1 -0
- package/dist/{chunk-Y72M3MVX.cjs → chunk-MNFY6DWY.cjs} +13 -200
- package/dist/chunk-MNFY6DWY.cjs.map +1 -0
- package/dist/chunk-S6K2H2TS.cjs +2470 -0
- package/dist/chunk-S6K2H2TS.cjs.map +1 -0
- package/dist/{chunk-BZC4FYW7.cjs → chunk-SHCYIZAN.cjs} +16 -2
- package/dist/chunk-SHCYIZAN.cjs.map +1 -0
- package/dist/{chunk-KA2PDJNB.js → chunk-VCH6HXVP.js} +16 -2
- package/dist/chunk-VCH6HXVP.js.map +1 -0
- package/dist/{chunk-7FOAMNTI.cjs → chunk-VNLR35GO.cjs} +90 -2
- package/dist/chunk-VNLR35GO.cjs.map +1 -0
- package/dist/{chunk-N7TDLOUE.cjs → chunk-YE2MU7CN.cjs} +5234 -1210
- package/dist/chunk-YE2MU7CN.cjs.map +1 -0
- package/dist/index.cjs +2086 -674
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1973 -561
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +23 -23
- package/dist/middleware.d.cts +1 -1
- package/dist/middleware.d.ts +1 -1
- package/dist/middleware.js +2 -2
- package/dist/migrations-7JGSFOCM.cjs +13 -0
- package/dist/{migrations-QNYAWQLB.cjs.map → migrations-7JGSFOCM.cjs.map} +1 -1
- package/dist/migrations-YB77VTVF.js +4 -0
- package/dist/{migrations-R6NQBKQV.js.map → migrations-YB77VTVF.js.map} +1 -1
- package/dist/{plugin-bootstrap-CB-xaBfK.d.ts → plugin-bootstrap-C7Mj00Ud.d.ts} +2455 -1
- package/dist/{plugin-bootstrap-U-cw9jn3.d.cts → plugin-bootstrap-DKB5f8-E.d.cts} +2455 -1
- package/dist/plugins.cjs +14 -14
- package/dist/plugins.js +2 -2
- package/dist/routes.cjs +39 -27
- package/dist/routes.d.cts +126 -53
- package/dist/routes.d.ts +126 -53
- package/dist/routes.js +7 -7
- package/dist/services.cjs +14 -14
- package/dist/services.d.cts +1 -1
- package/dist/services.d.ts +1 -1
- package/dist/services.js +2 -2
- package/dist/templates.cjs +25 -17
- package/dist/templates.d.cts +21 -1
- package/dist/templates.d.ts +21 -1
- package/dist/templates.js +2 -2
- package/dist/utils.cjs +14 -14
- package/dist/utils.js +1 -1
- package/migrations/014_fix_plugin_registry.sql +1 -1
- package/migrations/020_add_email_plugin.sql +1 -1
- package/migrations/026_add_otp_login.sql +1 -1
- package/migrations/029_add_forms_system.sql +184 -0
- package/migrations/030_add_turnstile_to_forms.sql +14 -0
- package/package.json +2 -2
- package/dist/chunk-3YNNVSMC.js.map +0 -1
- package/dist/chunk-63K7XXRX.cjs +0 -76
- package/dist/chunk-63K7XXRX.cjs.map +0 -1
- package/dist/chunk-7FOAMNTI.cjs.map +0 -1
- package/dist/chunk-BZC4FYW7.cjs.map +0 -1
- package/dist/chunk-CLIH2T74.js.map +0 -1
- package/dist/chunk-EVZOVYLO.js.map +0 -1
- package/dist/chunk-F332TENF.js.map +0 -1
- package/dist/chunk-F6GZURXJ.js.map +0 -1
- package/dist/chunk-IIRVZSP2.cjs.map +0 -1
- package/dist/chunk-KA2PDJNB.js.map +0 -1
- package/dist/chunk-KAOWRIFD.js +0 -74
- package/dist/chunk-KAOWRIFD.js.map +0 -1
- package/dist/chunk-N7TDLOUE.cjs.map +0 -1
- package/dist/chunk-Y72M3MVX.cjs.map +0 -1
- package/dist/chunk-YHW27CBV.cjs.map +0 -1
- package/dist/migrations-QNYAWQLB.cjs +0 -13
- package/dist/migrations-R6NQBKQV.js +0 -4
- package/migrations/025_rename_mdxeditor_to_easy_mdx.sql +0 -22
- /package/migrations/{029_ai_search_plugin.sql → 031_ai_search_plugin.sql} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
3
|
+
var chunkYE2MU7CN_cjs = require('./chunk-YE2MU7CN.cjs');
|
|
4
|
+
var chunkVNLR35GO_cjs = require('./chunk-VNLR35GO.cjs');
|
|
5
|
+
var chunkGPTMGUFN_cjs = require('./chunk-GPTMGUFN.cjs');
|
|
6
6
|
var chunkMPT5PA6U_cjs = require('./chunk-MPT5PA6U.cjs');
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
var
|
|
7
|
+
var chunk5CENPGR2_cjs = require('./chunk-5CENPGR2.cjs');
|
|
8
|
+
var chunkS6K2H2TS_cjs = require('./chunk-S6K2H2TS.cjs');
|
|
9
|
+
var chunkSHCYIZAN_cjs = require('./chunk-SHCYIZAN.cjs');
|
|
10
|
+
var chunkMNFY6DWY_cjs = require('./chunk-MNFY6DWY.cjs');
|
|
11
|
+
var chunk6FHNRRJ3_cjs = require('./chunk-6FHNRRJ3.cjs');
|
|
12
|
+
var chunk5HMR2SJW_cjs = require('./chunk-5HMR2SJW.cjs');
|
|
13
13
|
require('./chunk-P3XDZL6Q.cjs');
|
|
14
14
|
var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
|
|
15
15
|
var chunkKYGRJCZM_cjs = require('./chunk-KYGRJCZM.cjs');
|
|
16
16
|
require('./chunk-IGJUBJBW.cjs');
|
|
17
17
|
var hono = require('hono');
|
|
18
|
-
var html = require('hono/html');
|
|
19
18
|
var cookie = require('hono/cookie');
|
|
20
19
|
var zod = require('zod');
|
|
21
20
|
var d1 = require('drizzle-orm/d1');
|
|
@@ -235,7 +234,7 @@ var DatabaseToolsService = class {
|
|
|
235
234
|
};
|
|
236
235
|
|
|
237
236
|
// src/templates/pages/admin-database-table.template.ts
|
|
238
|
-
|
|
237
|
+
chunkSHCYIZAN_cjs.init_admin_layout_catalyst_template();
|
|
239
238
|
function renderDatabaseTablePage(data) {
|
|
240
239
|
const totalPages = Math.ceil(data.totalRows / data.pageSize);
|
|
241
240
|
const startRow = (data.currentPage - 1) * data.pageSize + 1;
|
|
@@ -484,7 +483,7 @@ function renderDatabaseTablePage(data) {
|
|
|
484
483
|
user: data.user,
|
|
485
484
|
content: pageContent
|
|
486
485
|
};
|
|
487
|
-
return
|
|
486
|
+
return chunkSHCYIZAN_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
488
487
|
}
|
|
489
488
|
function generatePageNumbers(currentPage, totalPages) {
|
|
490
489
|
const pages = [];
|
|
@@ -558,9 +557,9 @@ function formatCellValue(value) {
|
|
|
558
557
|
|
|
559
558
|
// src/plugins/core-plugins/database-tools-plugin/admin-routes.ts
|
|
560
559
|
function createDatabaseToolsAdminRoutes() {
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
|
|
560
|
+
const router3 = new hono.Hono();
|
|
561
|
+
router3.use("*", chunkGPTMGUFN_cjs.requireAuth());
|
|
562
|
+
router3.get("/api/stats", async (c) => {
|
|
564
563
|
try {
|
|
565
564
|
const user = c.get("user");
|
|
566
565
|
if (!user || user.role !== "admin") {
|
|
@@ -584,7 +583,7 @@ function createDatabaseToolsAdminRoutes() {
|
|
|
584
583
|
}, 500);
|
|
585
584
|
}
|
|
586
585
|
});
|
|
587
|
-
|
|
586
|
+
router3.post("/api/truncate", async (c) => {
|
|
588
587
|
try {
|
|
589
588
|
const user = c.get("user");
|
|
590
589
|
if (!user || user.role !== "admin") {
|
|
@@ -621,7 +620,7 @@ function createDatabaseToolsAdminRoutes() {
|
|
|
621
620
|
}, 500);
|
|
622
621
|
}
|
|
623
622
|
});
|
|
624
|
-
|
|
623
|
+
router3.post("/api/backup", async (c) => {
|
|
625
624
|
try {
|
|
626
625
|
const user = c.get("user");
|
|
627
626
|
if (!user || user.role !== "admin") {
|
|
@@ -648,7 +647,7 @@ function createDatabaseToolsAdminRoutes() {
|
|
|
648
647
|
}, 500);
|
|
649
648
|
}
|
|
650
649
|
});
|
|
651
|
-
|
|
650
|
+
router3.get("/api/validate", async (c) => {
|
|
652
651
|
try {
|
|
653
652
|
const user = c.get("user");
|
|
654
653
|
if (!user || user.role !== "admin") {
|
|
@@ -672,7 +671,7 @@ function createDatabaseToolsAdminRoutes() {
|
|
|
672
671
|
}, 500);
|
|
673
672
|
}
|
|
674
673
|
});
|
|
675
|
-
|
|
674
|
+
router3.get("/api/tables/:tableName", async (c) => {
|
|
676
675
|
try {
|
|
677
676
|
const user = c.get("user");
|
|
678
677
|
if (!user || user.role !== "admin") {
|
|
@@ -701,7 +700,7 @@ function createDatabaseToolsAdminRoutes() {
|
|
|
701
700
|
}, 500);
|
|
702
701
|
}
|
|
703
702
|
});
|
|
704
|
-
|
|
703
|
+
router3.get("/tables/:tableName", async (c) => {
|
|
705
704
|
try {
|
|
706
705
|
const user = c.get("user");
|
|
707
706
|
if (!user || user.role !== "admin") {
|
|
@@ -737,7 +736,7 @@ function createDatabaseToolsAdminRoutes() {
|
|
|
737
736
|
return c.text(`Error: ${error}`, 500);
|
|
738
737
|
}
|
|
739
738
|
});
|
|
740
|
-
return
|
|
739
|
+
return router3;
|
|
741
740
|
}
|
|
742
741
|
|
|
743
742
|
// src/plugins/core-plugins/seed-data-plugin/services/seed-data-service.ts
|
|
@@ -1027,7 +1026,7 @@ var SeedDataService = class {
|
|
|
1027
1026
|
function createSeedDataAdminRoutes() {
|
|
1028
1027
|
const routes = new hono.Hono();
|
|
1029
1028
|
routes.get("/", async (c) => {
|
|
1030
|
-
const
|
|
1029
|
+
const html = `
|
|
1031
1030
|
<!DOCTYPE html>
|
|
1032
1031
|
<html>
|
|
1033
1032
|
<head>
|
|
@@ -1270,7 +1269,7 @@ function createSeedDataAdminRoutes() {
|
|
|
1270
1269
|
</body>
|
|
1271
1270
|
</html>
|
|
1272
1271
|
`;
|
|
1273
|
-
return c.html(
|
|
1272
|
+
return c.html(html);
|
|
1274
1273
|
});
|
|
1275
1274
|
routes.post("/generate", async (c) => {
|
|
1276
1275
|
try {
|
|
@@ -1307,7 +1306,7 @@ function createSeedDataAdminRoutes() {
|
|
|
1307
1306
|
return routes;
|
|
1308
1307
|
}
|
|
1309
1308
|
function createEmailPlugin() {
|
|
1310
|
-
const builder =
|
|
1309
|
+
const builder = chunk6FHNRRJ3_cjs.PluginBuilder.create({
|
|
1311
1310
|
name: "email",
|
|
1312
1311
|
version: "1.0.0-beta.1",
|
|
1313
1312
|
description: "Send transactional emails using Resend"
|
|
@@ -1321,253 +1320,6 @@ function createEmailPlugin() {
|
|
|
1321
1320
|
compatibility: "^2.0.0"
|
|
1322
1321
|
});
|
|
1323
1322
|
const emailRoutes = new hono.Hono();
|
|
1324
|
-
emailRoutes.get("/settings", async (c) => {
|
|
1325
|
-
const user = c.get("user");
|
|
1326
|
-
const db = c.env.DB;
|
|
1327
|
-
const plugin = await db.prepare(`
|
|
1328
|
-
SELECT settings FROM plugins WHERE id = 'email'
|
|
1329
|
-
`).first();
|
|
1330
|
-
const settings = plugin?.settings ? JSON.parse(plugin.settings) : {};
|
|
1331
|
-
const contentHTML = await html.html`
|
|
1332
|
-
<div class="p-8">
|
|
1333
|
-
<!-- Header -->
|
|
1334
|
-
<div class="mb-8">
|
|
1335
|
-
<h1 class="text-3xl font-bold text-zinc-950 dark:text-white mb-2">Email Settings</h1>
|
|
1336
|
-
<p class="text-zinc-600 dark:text-zinc-400">Configure Resend API for sending transactional emails</p>
|
|
1337
|
-
</div>
|
|
1338
|
-
|
|
1339
|
-
<!-- Settings Form -->
|
|
1340
|
-
<div class="max-w-3xl">
|
|
1341
|
-
<!-- Main Settings Card -->
|
|
1342
|
-
<div class="rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6 mb-6">
|
|
1343
|
-
<h2 class="text-xl font-semibold text-zinc-950 dark:text-white mb-4">Resend Configuration</h2>
|
|
1344
|
-
|
|
1345
|
-
<form id="emailSettingsForm" class="space-y-6">
|
|
1346
|
-
<!-- API Key -->
|
|
1347
|
-
<div>
|
|
1348
|
-
<label for="apiKey" class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">
|
|
1349
|
-
Resend API Key <span class="text-red-500">*</span>
|
|
1350
|
-
</label>
|
|
1351
|
-
<input
|
|
1352
|
-
type="password"
|
|
1353
|
-
id="apiKey"
|
|
1354
|
-
name="apiKey"
|
|
1355
|
-
value="${settings.apiKey || ""}"
|
|
1356
|
-
class="w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400"
|
|
1357
|
-
placeholder="re_..."
|
|
1358
|
-
required
|
|
1359
|
-
/>
|
|
1360
|
-
<p class="text-xs text-zinc-500 dark:text-zinc-400 mt-1">
|
|
1361
|
-
Get your API key from <a href="https://resend.com/api-keys" target="_blank" class="text-indigo-600 dark:text-indigo-400 hover:underline">resend.com/api-keys</a>
|
|
1362
|
-
</p>
|
|
1363
|
-
</div>
|
|
1364
|
-
|
|
1365
|
-
<!-- From Email -->
|
|
1366
|
-
<div>
|
|
1367
|
-
<label for="fromEmail" class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">
|
|
1368
|
-
From Email <span class="text-red-500">*</span>
|
|
1369
|
-
</label>
|
|
1370
|
-
<input
|
|
1371
|
-
type="email"
|
|
1372
|
-
id="fromEmail"
|
|
1373
|
-
name="fromEmail"
|
|
1374
|
-
value="${settings.fromEmail || ""}"
|
|
1375
|
-
class="w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400"
|
|
1376
|
-
placeholder="noreply@yourdomain.com"
|
|
1377
|
-
required
|
|
1378
|
-
/>
|
|
1379
|
-
<p class="text-xs text-zinc-500 dark:text-zinc-400 mt-1">
|
|
1380
|
-
Must be a verified domain in Resend
|
|
1381
|
-
</p>
|
|
1382
|
-
</div>
|
|
1383
|
-
|
|
1384
|
-
<!-- From Name -->
|
|
1385
|
-
<div>
|
|
1386
|
-
<label for="fromName" class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">
|
|
1387
|
-
From Name <span class="text-red-500">*</span>
|
|
1388
|
-
</label>
|
|
1389
|
-
<input
|
|
1390
|
-
type="text"
|
|
1391
|
-
id="fromName"
|
|
1392
|
-
name="fromName"
|
|
1393
|
-
value="${settings.fromName || ""}"
|
|
1394
|
-
class="w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400"
|
|
1395
|
-
placeholder="Your App Name"
|
|
1396
|
-
required
|
|
1397
|
-
/>
|
|
1398
|
-
</div>
|
|
1399
|
-
|
|
1400
|
-
<!-- Reply To -->
|
|
1401
|
-
<div>
|
|
1402
|
-
<label for="replyTo" class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">
|
|
1403
|
-
Reply-To Email
|
|
1404
|
-
</label>
|
|
1405
|
-
<input
|
|
1406
|
-
type="email"
|
|
1407
|
-
id="replyTo"
|
|
1408
|
-
name="replyTo"
|
|
1409
|
-
value="${settings.replyTo || ""}"
|
|
1410
|
-
class="w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400"
|
|
1411
|
-
placeholder="support@yourdomain.com"
|
|
1412
|
-
/>
|
|
1413
|
-
</div>
|
|
1414
|
-
|
|
1415
|
-
<!-- Logo URL -->
|
|
1416
|
-
<div>
|
|
1417
|
-
<label for="logoUrl" class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">
|
|
1418
|
-
Logo URL
|
|
1419
|
-
</label>
|
|
1420
|
-
<input
|
|
1421
|
-
type="url"
|
|
1422
|
-
id="logoUrl"
|
|
1423
|
-
name="logoUrl"
|
|
1424
|
-
value="${settings.logoUrl || ""}"
|
|
1425
|
-
class="w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400"
|
|
1426
|
-
placeholder="https://yourdomain.com/logo.png"
|
|
1427
|
-
/>
|
|
1428
|
-
<p class="text-xs text-zinc-500 dark:text-zinc-400 mt-1">
|
|
1429
|
-
Logo to display in email templates
|
|
1430
|
-
</p>
|
|
1431
|
-
</div>
|
|
1432
|
-
|
|
1433
|
-
<!-- Action Buttons -->
|
|
1434
|
-
<div class="flex gap-3 pt-4">
|
|
1435
|
-
<button
|
|
1436
|
-
type="submit"
|
|
1437
|
-
class="inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm"
|
|
1438
|
-
>
|
|
1439
|
-
Save Settings
|
|
1440
|
-
</button>
|
|
1441
|
-
<button
|
|
1442
|
-
type="button"
|
|
1443
|
-
id="testEmailBtn"
|
|
1444
|
-
class="inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm"
|
|
1445
|
-
>
|
|
1446
|
-
Send Test Email
|
|
1447
|
-
</button>
|
|
1448
|
-
<button
|
|
1449
|
-
type="button"
|
|
1450
|
-
id="resetBtn"
|
|
1451
|
-
class="inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm"
|
|
1452
|
-
>
|
|
1453
|
-
Reset
|
|
1454
|
-
</button>
|
|
1455
|
-
</div>
|
|
1456
|
-
</form>
|
|
1457
|
-
</div>
|
|
1458
|
-
|
|
1459
|
-
<!-- Status Message -->
|
|
1460
|
-
<div id="statusMessage" class="hidden rounded-xl p-4 mb-6"></div>
|
|
1461
|
-
|
|
1462
|
-
<!-- Info Card -->
|
|
1463
|
-
<div class="rounded-xl bg-indigo-50 dark:bg-indigo-950/30 ring-1 ring-indigo-100 dark:ring-indigo-900/50 p-6">
|
|
1464
|
-
<h3 class="font-semibold text-indigo-900 dark:text-indigo-300 mb-3">
|
|
1465
|
-
📧 Email Templates Included
|
|
1466
|
-
</h3>
|
|
1467
|
-
<ul class="text-sm text-indigo-800 dark:text-indigo-200 space-y-2">
|
|
1468
|
-
<li>✓ Registration confirmation</li>
|
|
1469
|
-
<li>✓ Email verification</li>
|
|
1470
|
-
<li>✓ Password reset</li>
|
|
1471
|
-
<li>✓ One-time code (2FA)</li>
|
|
1472
|
-
</ul>
|
|
1473
|
-
<p class="text-xs text-indigo-700 dark:text-indigo-300 mt-4">
|
|
1474
|
-
Templates are code-based and can be customized by editing the plugin files.
|
|
1475
|
-
</p>
|
|
1476
|
-
</div>
|
|
1477
|
-
</div>
|
|
1478
|
-
</div>
|
|
1479
|
-
|
|
1480
|
-
<script>
|
|
1481
|
-
// Form submission handler
|
|
1482
|
-
document.getElementById('emailSettingsForm').addEventListener('submit', async (e) => {
|
|
1483
|
-
e.preventDefault()
|
|
1484
|
-
const formData = new FormData(e.target)
|
|
1485
|
-
const data = Object.fromEntries(formData.entries())
|
|
1486
|
-
|
|
1487
|
-
const statusEl = document.getElementById('statusMessage')
|
|
1488
|
-
|
|
1489
|
-
try {
|
|
1490
|
-
const response = await fetch('/admin/plugins/email/settings', {
|
|
1491
|
-
method: 'POST',
|
|
1492
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1493
|
-
body: JSON.stringify(data)
|
|
1494
|
-
})
|
|
1495
|
-
|
|
1496
|
-
if (response.ok) {
|
|
1497
|
-
statusEl.className = 'rounded-xl bg-green-50 dark:bg-green-950/30 ring-1 ring-green-100 dark:ring-green-900/50 p-4 mb-6 text-green-900 dark:text-green-200'
|
|
1498
|
-
statusEl.innerHTML = '✅ Settings saved successfully!'
|
|
1499
|
-
statusEl.classList.remove('hidden')
|
|
1500
|
-
setTimeout(() => statusEl.classList.add('hidden'), 3000)
|
|
1501
|
-
} else {
|
|
1502
|
-
throw new Error('Failed to save settings')
|
|
1503
|
-
}
|
|
1504
|
-
} catch (error) {
|
|
1505
|
-
statusEl.className = 'rounded-xl bg-red-50 dark:bg-red-950/30 ring-1 ring-red-100 dark:ring-red-900/50 p-4 mb-6 text-red-900 dark:text-red-200'
|
|
1506
|
-
statusEl.innerHTML = '❌ Failed to save settings. Please try again.'
|
|
1507
|
-
statusEl.classList.remove('hidden')
|
|
1508
|
-
}
|
|
1509
|
-
})
|
|
1510
|
-
|
|
1511
|
-
// Test email handler
|
|
1512
|
-
document.getElementById('testEmailBtn').addEventListener('click', async () => {
|
|
1513
|
-
// Prompt for destination email
|
|
1514
|
-
const toEmail = prompt('Enter destination email address for test:')
|
|
1515
|
-
if (!toEmail) return
|
|
1516
|
-
|
|
1517
|
-
// Basic email validation
|
|
1518
|
-
if (!toEmail.match(/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/)) {
|
|
1519
|
-
alert('Please enter a valid email address')
|
|
1520
|
-
return
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
const statusEl = document.getElementById('statusMessage')
|
|
1524
|
-
|
|
1525
|
-
statusEl.className = 'rounded-xl bg-indigo-50 dark:bg-indigo-950/30 ring-1 ring-indigo-100 dark:ring-indigo-900/50 p-4 mb-6 text-indigo-900 dark:text-indigo-200'
|
|
1526
|
-
statusEl.innerHTML = \`📧 Sending test email to \${toEmail}...\`
|
|
1527
|
-
statusEl.classList.remove('hidden')
|
|
1528
|
-
|
|
1529
|
-
try {
|
|
1530
|
-
const response = await fetch('/admin/plugins/email/test', {
|
|
1531
|
-
method: 'POST',
|
|
1532
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1533
|
-
body: JSON.stringify({ toEmail })
|
|
1534
|
-
})
|
|
1535
|
-
|
|
1536
|
-
const data = await response.json()
|
|
1537
|
-
|
|
1538
|
-
if (response.ok) {
|
|
1539
|
-
statusEl.className = 'rounded-xl bg-green-50 dark:bg-green-950/30 ring-1 ring-green-100 dark:ring-green-900/50 p-4 mb-6 text-green-900 dark:text-green-200'
|
|
1540
|
-
statusEl.innerHTML = \`✅ \${data.message || 'Test email sent! Check your inbox.'}\`
|
|
1541
|
-
} else {
|
|
1542
|
-
statusEl.className = 'rounded-xl bg-red-50 dark:bg-red-950/30 ring-1 ring-red-100 dark:ring-red-900/50 p-4 mb-6 text-red-900 dark:text-red-200'
|
|
1543
|
-
statusEl.innerHTML = \`❌ \${data.error || 'Failed to send test email. Check your settings.'}\`
|
|
1544
|
-
}
|
|
1545
|
-
} catch (error) {
|
|
1546
|
-
statusEl.className = 'rounded-xl bg-red-50 dark:bg-red-950/30 ring-1 ring-red-100 dark:ring-red-900/50 p-4 mb-6 text-red-900 dark:text-red-200'
|
|
1547
|
-
statusEl.innerHTML = '❌ Network error. Please try again.'
|
|
1548
|
-
}
|
|
1549
|
-
})
|
|
1550
|
-
|
|
1551
|
-
// Reset button handler
|
|
1552
|
-
document.getElementById('resetBtn').addEventListener('click', () => {
|
|
1553
|
-
document.getElementById('emailSettingsForm').reset()
|
|
1554
|
-
})
|
|
1555
|
-
</script>
|
|
1556
|
-
`;
|
|
1557
|
-
const templateUser = user ? {
|
|
1558
|
-
name: user.name ?? user.email ?? "Admin",
|
|
1559
|
-
email: user.email ?? "admin@sonicjs.com",
|
|
1560
|
-
role: user.role ?? "admin"
|
|
1561
|
-
} : void 0;
|
|
1562
|
-
return c.html(
|
|
1563
|
-
chunkBZC4FYW7_cjs.renderAdminLayout({
|
|
1564
|
-
title: "Email Settings",
|
|
1565
|
-
content: contentHTML,
|
|
1566
|
-
user: templateUser,
|
|
1567
|
-
currentPath: "/admin/plugins/email/settings"
|
|
1568
|
-
})
|
|
1569
|
-
);
|
|
1570
|
-
});
|
|
1571
1323
|
emailRoutes.post("/settings", async (c) => {
|
|
1572
1324
|
try {
|
|
1573
1325
|
const body = await c.req.json();
|
|
@@ -1588,16 +1340,16 @@ function createEmailPlugin() {
|
|
|
1588
1340
|
try {
|
|
1589
1341
|
const db = c.env.DB;
|
|
1590
1342
|
const body = await c.req.json();
|
|
1591
|
-
const
|
|
1343
|
+
const plugin2 = await db.prepare(`
|
|
1592
1344
|
SELECT settings FROM plugins WHERE id = 'email'
|
|
1593
1345
|
`).first();
|
|
1594
|
-
if (!
|
|
1346
|
+
if (!plugin2?.settings) {
|
|
1595
1347
|
return c.json({
|
|
1596
1348
|
success: false,
|
|
1597
1349
|
error: "Email settings not configured. Please save your settings first."
|
|
1598
1350
|
}, 400);
|
|
1599
1351
|
}
|
|
1600
|
-
const settings = JSON.parse(
|
|
1352
|
+
const settings = JSON.parse(plugin2.settings);
|
|
1601
1353
|
if (!settings.apiKey || !settings.fromEmail || !settings.fromName) {
|
|
1602
1354
|
return c.json({
|
|
1603
1355
|
success: false,
|
|
@@ -1663,7 +1415,7 @@ function createEmailPlugin() {
|
|
|
1663
1415
|
requiresAuth: true,
|
|
1664
1416
|
priority: 80
|
|
1665
1417
|
});
|
|
1666
|
-
builder.addMenuItem("Email", "/admin/plugins/email
|
|
1418
|
+
builder.addMenuItem("Email", "/admin/plugins/email", {
|
|
1667
1419
|
icon: "envelope",
|
|
1668
1420
|
order: 80,
|
|
1669
1421
|
permissions: ["email:manage"]
|
|
@@ -1980,11 +1732,10 @@ var DEFAULT_SETTINGS = {
|
|
|
1980
1732
|
codeExpiryMinutes: 10,
|
|
1981
1733
|
maxAttempts: 3,
|
|
1982
1734
|
rateLimitPerHour: 5,
|
|
1983
|
-
allowNewUserRegistration: false
|
|
1984
|
-
appName: "SonicJS"
|
|
1735
|
+
allowNewUserRegistration: false
|
|
1985
1736
|
};
|
|
1986
1737
|
function createOTPLoginPlugin() {
|
|
1987
|
-
const builder =
|
|
1738
|
+
const builder = chunk6FHNRRJ3_cjs.PluginBuilder.create({
|
|
1988
1739
|
name: "otp-login",
|
|
1989
1740
|
version: "1.0.0-beta.1",
|
|
1990
1741
|
description: "Passwordless authentication via email one-time codes"
|
|
@@ -2012,7 +1763,21 @@ function createOTPLoginPlugin() {
|
|
|
2012
1763
|
const normalizedEmail = email.toLowerCase();
|
|
2013
1764
|
const db = c.env.DB;
|
|
2014
1765
|
const otpService = new OTPService(db);
|
|
2015
|
-
|
|
1766
|
+
let settings = { ...DEFAULT_SETTINGS };
|
|
1767
|
+
const pluginRow = await db.prepare(`
|
|
1768
|
+
SELECT settings FROM plugins WHERE id = 'otp-login'
|
|
1769
|
+
`).first();
|
|
1770
|
+
if (pluginRow?.settings) {
|
|
1771
|
+
try {
|
|
1772
|
+
const savedSettings = JSON.parse(pluginRow.settings);
|
|
1773
|
+
settings = { ...DEFAULT_SETTINGS, ...savedSettings };
|
|
1774
|
+
} catch (e) {
|
|
1775
|
+
console.warn("Failed to parse OTP plugin settings, using defaults");
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
const settingsService = new chunkVNLR35GO_cjs.SettingsService(db);
|
|
1779
|
+
const generalSettings = await settingsService.getGeneralSettings();
|
|
1780
|
+
const siteName = generalSettings.siteName;
|
|
2016
1781
|
const canRequest = await otpService.checkRateLimit(normalizedEmail, settings);
|
|
2017
1782
|
if (!canRequest) {
|
|
2018
1783
|
return c.json({
|
|
@@ -2056,7 +1821,7 @@ function createOTPLoginPlugin() {
|
|
|
2056
1821
|
email: normalizedEmail,
|
|
2057
1822
|
ipAddress,
|
|
2058
1823
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2059
|
-
appName:
|
|
1824
|
+
appName: siteName
|
|
2060
1825
|
});
|
|
2061
1826
|
const emailPlugin2 = await db.prepare(`
|
|
2062
1827
|
SELECT settings FROM plugins WHERE id = 'email'
|
|
@@ -2073,7 +1838,7 @@ function createOTPLoginPlugin() {
|
|
|
2073
1838
|
body: JSON.stringify({
|
|
2074
1839
|
from: `${emailSettings.fromName} <${emailSettings.fromEmail}>`,
|
|
2075
1840
|
to: [normalizedEmail],
|
|
2076
|
-
subject: `Your login code for ${
|
|
1841
|
+
subject: `Your login code for ${siteName}`,
|
|
2077
1842
|
html: emailContent.html,
|
|
2078
1843
|
text: emailContent.text,
|
|
2079
1844
|
reply_to: emailSettings.replyTo || emailSettings.fromEmail
|
|
@@ -2124,7 +1889,18 @@ function createOTPLoginPlugin() {
|
|
|
2124
1889
|
const normalizedEmail = email.toLowerCase();
|
|
2125
1890
|
const db = c.env.DB;
|
|
2126
1891
|
const otpService = new OTPService(db);
|
|
2127
|
-
|
|
1892
|
+
let settings = { ...DEFAULT_SETTINGS };
|
|
1893
|
+
const pluginRow = await db.prepare(`
|
|
1894
|
+
SELECT settings FROM plugins WHERE id = 'otp-login'
|
|
1895
|
+
`).first();
|
|
1896
|
+
if (pluginRow?.settings) {
|
|
1897
|
+
try {
|
|
1898
|
+
const savedSettings = JSON.parse(pluginRow.settings);
|
|
1899
|
+
settings = { ...DEFAULT_SETTINGS, ...savedSettings };
|
|
1900
|
+
} catch (e) {
|
|
1901
|
+
console.warn("Failed to parse OTP plugin settings, using defaults");
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
2128
1904
|
const verification = await otpService.verifyCode(normalizedEmail, code, settings);
|
|
2129
1905
|
if (!verification.valid) {
|
|
2130
1906
|
await otpService.incrementAttempts(normalizedEmail, code);
|
|
@@ -2148,7 +1924,7 @@ function createOTPLoginPlugin() {
|
|
|
2148
1924
|
error: "Account is deactivated"
|
|
2149
1925
|
}, 403);
|
|
2150
1926
|
}
|
|
2151
|
-
const token = await
|
|
1927
|
+
const token = await chunkGPTMGUFN_cjs.AuthManager.generateToken(user.id, user.email, user.role);
|
|
2152
1928
|
cookie.setCookie(c, "auth_token", token, {
|
|
2153
1929
|
httpOnly: true,
|
|
2154
1930
|
secure: true,
|
|
@@ -2203,193 +1979,7 @@ function createOTPLoginPlugin() {
|
|
|
2203
1979
|
requiresAuth: false,
|
|
2204
1980
|
priority: 100
|
|
2205
1981
|
});
|
|
2206
|
-
|
|
2207
|
-
adminRoutes2.get("/settings", async (c) => {
|
|
2208
|
-
const user = c.get("user");
|
|
2209
|
-
const contentHTML = await html.html`
|
|
2210
|
-
<div class="p-8">
|
|
2211
|
-
<div class="mb-8">
|
|
2212
|
-
<h1 class="text-3xl font-bold mb-2">OTP Login Settings</h1>
|
|
2213
|
-
<p class="text-zinc-600 dark:text-zinc-400">Configure passwordless authentication via email codes</p>
|
|
2214
|
-
</div>
|
|
2215
|
-
|
|
2216
|
-
<div class="max-w-3xl">
|
|
2217
|
-
<div class="backdrop-blur-md bg-black/20 border border-white/10 shadow-xl rounded-xl p-6 mb-6">
|
|
2218
|
-
<h2 class="text-xl font-semibold mb-4">Code Settings</h2>
|
|
2219
|
-
|
|
2220
|
-
<form id="otpSettingsForm" class="space-y-6">
|
|
2221
|
-
<div>
|
|
2222
|
-
<label for="codeLength" class="block text-sm font-medium mb-2">
|
|
2223
|
-
Code Length
|
|
2224
|
-
</label>
|
|
2225
|
-
<input
|
|
2226
|
-
type="number"
|
|
2227
|
-
id="codeLength"
|
|
2228
|
-
name="codeLength"
|
|
2229
|
-
min="4"
|
|
2230
|
-
max="8"
|
|
2231
|
-
value="6"
|
|
2232
|
-
class="w-full px-4 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none"
|
|
2233
|
-
/>
|
|
2234
|
-
<p class="text-xs text-zinc-500 mt-1">Number of digits in OTP code (4-8)</p>
|
|
2235
|
-
</div>
|
|
2236
|
-
|
|
2237
|
-
<div>
|
|
2238
|
-
<label for="codeExpiryMinutes" class="block text-sm font-medium mb-2">
|
|
2239
|
-
Code Expiry (minutes)
|
|
2240
|
-
</label>
|
|
2241
|
-
<input
|
|
2242
|
-
type="number"
|
|
2243
|
-
id="codeExpiryMinutes"
|
|
2244
|
-
name="codeExpiryMinutes"
|
|
2245
|
-
min="5"
|
|
2246
|
-
max="60"
|
|
2247
|
-
value="10"
|
|
2248
|
-
class="w-full px-4 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none"
|
|
2249
|
-
/>
|
|
2250
|
-
<p class="text-xs text-zinc-500 mt-1">How long codes remain valid (5-60 minutes)</p>
|
|
2251
|
-
</div>
|
|
2252
|
-
|
|
2253
|
-
<div>
|
|
2254
|
-
<label for="maxAttempts" class="block text-sm font-medium mb-2">
|
|
2255
|
-
Maximum Attempts
|
|
2256
|
-
</label>
|
|
2257
|
-
<input
|
|
2258
|
-
type="number"
|
|
2259
|
-
id="maxAttempts"
|
|
2260
|
-
name="maxAttempts"
|
|
2261
|
-
min="3"
|
|
2262
|
-
max="10"
|
|
2263
|
-
value="3"
|
|
2264
|
-
class="w-full px-4 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none"
|
|
2265
|
-
/>
|
|
2266
|
-
<p class="text-xs text-zinc-500 mt-1">Max verification attempts before invalidation</p>
|
|
2267
|
-
</div>
|
|
2268
|
-
|
|
2269
|
-
<div>
|
|
2270
|
-
<label for="rateLimitPerHour" class="block text-sm font-medium mb-2">
|
|
2271
|
-
Rate Limit (per hour)
|
|
2272
|
-
</label>
|
|
2273
|
-
<input
|
|
2274
|
-
type="number"
|
|
2275
|
-
id="rateLimitPerHour"
|
|
2276
|
-
name="rateLimitPerHour"
|
|
2277
|
-
min="3"
|
|
2278
|
-
max="20"
|
|
2279
|
-
value="5"
|
|
2280
|
-
class="w-full px-4 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none"
|
|
2281
|
-
/>
|
|
2282
|
-
<p class="text-xs text-zinc-500 mt-1">Max code requests per email per hour</p>
|
|
2283
|
-
</div>
|
|
2284
|
-
|
|
2285
|
-
<div class="flex items-center">
|
|
2286
|
-
<input
|
|
2287
|
-
type="checkbox"
|
|
2288
|
-
id="allowNewUserRegistration"
|
|
2289
|
-
name="allowNewUserRegistration"
|
|
2290
|
-
class="w-4 h-4 rounded border-white/10"
|
|
2291
|
-
/>
|
|
2292
|
-
<label for="allowNewUserRegistration" class="ml-2 text-sm">
|
|
2293
|
-
Allow new user registration via OTP
|
|
2294
|
-
</label>
|
|
2295
|
-
</div>
|
|
2296
|
-
|
|
2297
|
-
<div class="flex gap-3 pt-4">
|
|
2298
|
-
<button
|
|
2299
|
-
type="submit"
|
|
2300
|
-
class="px-6 py-2 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg font-medium hover:from-blue-600 hover:to-purple-700 transition-all"
|
|
2301
|
-
>
|
|
2302
|
-
Save Settings
|
|
2303
|
-
</button>
|
|
2304
|
-
<button
|
|
2305
|
-
type="button"
|
|
2306
|
-
id="testOTPBtn"
|
|
2307
|
-
class="px-6 py-2 bg-white/10 hover:bg-white/20 text-white rounded-lg font-medium transition-all"
|
|
2308
|
-
>
|
|
2309
|
-
Send Test Code
|
|
2310
|
-
</button>
|
|
2311
|
-
</div>
|
|
2312
|
-
</form>
|
|
2313
|
-
</div>
|
|
2314
|
-
|
|
2315
|
-
<div id="statusMessage" class="hidden backdrop-blur-md bg-black/20 border border-white/10 rounded-xl p-4 mb-6"></div>
|
|
2316
|
-
|
|
2317
|
-
<div class="backdrop-blur-md bg-blue-500/10 border border-blue-500/20 rounded-xl p-6">
|
|
2318
|
-
<h3 class="font-semibold text-blue-400 mb-3">
|
|
2319
|
-
🔢 Features
|
|
2320
|
-
</h3>
|
|
2321
|
-
<ul class="text-sm text-blue-200 space-y-2">
|
|
2322
|
-
<li>✓ Passwordless authentication</li>
|
|
2323
|
-
<li>✓ Secure random code generation</li>
|
|
2324
|
-
<li>✓ Rate limiting protection</li>
|
|
2325
|
-
<li>✓ Brute force prevention</li>
|
|
2326
|
-
<li>✓ Mobile-friendly UX</li>
|
|
2327
|
-
</ul>
|
|
2328
|
-
</div>
|
|
2329
|
-
</div>
|
|
2330
|
-
</div>
|
|
2331
|
-
|
|
2332
|
-
<script>
|
|
2333
|
-
document.getElementById('otpSettingsForm').addEventListener('submit', async (e) => {
|
|
2334
|
-
e.preventDefault()
|
|
2335
|
-
const statusEl = document.getElementById('statusMessage')
|
|
2336
|
-
statusEl.className = 'backdrop-blur-md bg-green-500/20 border border-green-500/30 rounded-xl p-4 mb-6'
|
|
2337
|
-
statusEl.innerHTML = '✅ Settings saved successfully!'
|
|
2338
|
-
statusEl.classList.remove('hidden')
|
|
2339
|
-
setTimeout(() => statusEl.classList.add('hidden'), 3000)
|
|
2340
|
-
})
|
|
2341
|
-
|
|
2342
|
-
document.getElementById('testOTPBtn').addEventListener('click', async () => {
|
|
2343
|
-
const email = prompt('Enter email address for test:')
|
|
2344
|
-
if (!email) return
|
|
2345
|
-
|
|
2346
|
-
const statusEl = document.getElementById('statusMessage')
|
|
2347
|
-
statusEl.className = 'backdrop-blur-md bg-blue-500/20 border border-blue-500/30 rounded-xl p-4 mb-6'
|
|
2348
|
-
statusEl.innerHTML = '📧 Sending test code...'
|
|
2349
|
-
statusEl.classList.remove('hidden')
|
|
2350
|
-
|
|
2351
|
-
try {
|
|
2352
|
-
const response = await fetch('/auth/otp/request', {
|
|
2353
|
-
method: 'POST',
|
|
2354
|
-
headers: { 'Content-Type': 'application/json' },
|
|
2355
|
-
body: JSON.stringify({ email })
|
|
2356
|
-
})
|
|
2357
|
-
|
|
2358
|
-
const data = await response.json()
|
|
2359
|
-
|
|
2360
|
-
if (response.ok) {
|
|
2361
|
-
statusEl.className = 'backdrop-blur-md bg-green-500/20 border border-green-500/30 rounded-xl p-4 mb-6'
|
|
2362
|
-
statusEl.innerHTML = '✅ Test code sent!' + (data.dev_code ? \` Code: <strong>\${data.dev_code}</strong>\` : '')
|
|
2363
|
-
} else {
|
|
2364
|
-
throw new Error(data.error || 'Failed')
|
|
2365
|
-
}
|
|
2366
|
-
} catch (error) {
|
|
2367
|
-
statusEl.className = 'backdrop-blur-md bg-red-500/20 border border-red-500/30 rounded-xl p-4 mb-6'
|
|
2368
|
-
statusEl.innerHTML = '❌ Failed to send test code'
|
|
2369
|
-
}
|
|
2370
|
-
})
|
|
2371
|
-
</script>
|
|
2372
|
-
`;
|
|
2373
|
-
const templateUser = user ? {
|
|
2374
|
-
name: user.name ?? user.email ?? "Admin",
|
|
2375
|
-
email: user.email ?? "admin@sonicjs.com",
|
|
2376
|
-
role: user.role ?? "admin"
|
|
2377
|
-
} : void 0;
|
|
2378
|
-
return c.html(
|
|
2379
|
-
chunkBZC4FYW7_cjs.adminLayoutV2({
|
|
2380
|
-
title: "OTP Login Settings",
|
|
2381
|
-
content: contentHTML,
|
|
2382
|
-
user: templateUser,
|
|
2383
|
-
currentPath: "/admin/plugins/otp-login/settings"
|
|
2384
|
-
})
|
|
2385
|
-
);
|
|
2386
|
-
});
|
|
2387
|
-
builder.addRoute("/admin/plugins/otp-login", adminRoutes2, {
|
|
2388
|
-
description: "OTP login admin interface",
|
|
2389
|
-
requiresAuth: true,
|
|
2390
|
-
priority: 85
|
|
2391
|
-
});
|
|
2392
|
-
builder.addMenuItem("OTP Login", "/admin/plugins/otp-login/settings", {
|
|
1982
|
+
builder.addMenuItem("OTP Login", "/admin/plugins/otp-login", {
|
|
2393
1983
|
icon: "key",
|
|
2394
1984
|
order: 85,
|
|
2395
1985
|
permissions: ["otp:manage"]
|
|
@@ -2911,11 +2501,11 @@ var AISearchService = class {
|
|
|
2911
2501
|
*/
|
|
2912
2502
|
async getSettings() {
|
|
2913
2503
|
try {
|
|
2914
|
-
const
|
|
2915
|
-
if (!
|
|
2504
|
+
const plugin2 = await this.db.prepare(`SELECT settings FROM plugins WHERE id = ? LIMIT 1`).bind("ai-search").first();
|
|
2505
|
+
if (!plugin2 || !plugin2.settings) {
|
|
2916
2506
|
return this.getDefaultSettings();
|
|
2917
2507
|
}
|
|
2918
|
-
return JSON.parse(
|
|
2508
|
+
return JSON.parse(plugin2.settings);
|
|
2919
2509
|
} catch (error) {
|
|
2920
2510
|
console.error("Error fetching AI Search settings:", error);
|
|
2921
2511
|
return this.getDefaultSettings();
|
|
@@ -3973,7 +3563,7 @@ function renderSettingsPage(data) {
|
|
|
3973
3563
|
}, 30000);
|
|
3974
3564
|
</script>
|
|
3975
3565
|
`;
|
|
3976
|
-
return
|
|
3566
|
+
return chunkSHCYIZAN_cjs.renderAdminLayout({
|
|
3977
3567
|
title: "AI Search Settings",
|
|
3978
3568
|
pageTitle: "AI Search Settings",
|
|
3979
3569
|
currentPath: "/admin/plugins/ai-search/settings",
|
|
@@ -3984,7 +3574,7 @@ function renderSettingsPage(data) {
|
|
|
3984
3574
|
|
|
3985
3575
|
// src/plugins/core-plugins/ai-search-plugin/routes/admin.ts
|
|
3986
3576
|
var adminRoutes = new hono.Hono();
|
|
3987
|
-
adminRoutes.use("*",
|
|
3577
|
+
adminRoutes.use("*", chunkGPTMGUFN_cjs.requireAuth());
|
|
3988
3578
|
adminRoutes.get("/", async (c) => {
|
|
3989
3579
|
try {
|
|
3990
3580
|
const user = c.get("user");
|
|
@@ -4230,7 +3820,7 @@ var manifest_default = {
|
|
|
4230
3820
|
author: "SonicJS"};
|
|
4231
3821
|
|
|
4232
3822
|
// src/plugins/core-plugins/ai-search-plugin/index.ts
|
|
4233
|
-
var aiSearchPlugin = new
|
|
3823
|
+
var aiSearchPlugin = new chunk6FHNRRJ3_cjs.PluginBuilder({
|
|
4234
3824
|
name: manifest_default.name,
|
|
4235
3825
|
version: manifest_default.version,
|
|
4236
3826
|
description: manifest_default.description,
|
|
@@ -4385,12 +3975,12 @@ function createMagicLinkAuthPlugin() {
|
|
|
4385
3975
|
SET used = 1, used_at = ?
|
|
4386
3976
|
WHERE id = ?
|
|
4387
3977
|
`).bind(Date.now(), magicLink.id).run();
|
|
4388
|
-
const jwtToken = await
|
|
3978
|
+
const jwtToken = await chunkGPTMGUFN_cjs.AuthManager.generateToken(
|
|
4389
3979
|
user.id,
|
|
4390
3980
|
user.email,
|
|
4391
3981
|
user.role
|
|
4392
3982
|
);
|
|
4393
|
-
|
|
3983
|
+
chunkGPTMGUFN_cjs.AuthManager.setAuthCookie(c, jwtToken);
|
|
4394
3984
|
await db.prepare(`
|
|
4395
3985
|
UPDATE users SET last_login_at = ? WHERE id = ?
|
|
4396
3986
|
`).bind(Date.now(), user.id).run();
|
|
@@ -4535,100 +4125,1922 @@ function renderMagicLinkEmail(magicLink, expiryMinutes) {
|
|
|
4535
4125
|
}
|
|
4536
4126
|
createMagicLinkAuthPlugin();
|
|
4537
4127
|
|
|
4538
|
-
// src/
|
|
4539
|
-
var
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4128
|
+
// src/plugins/cache/services/cache-config.ts
|
|
4129
|
+
var CACHE_CONFIGS = {
|
|
4130
|
+
// Content (high read, low write)
|
|
4131
|
+
content: {
|
|
4132
|
+
ttl: 3600,
|
|
4133
|
+
// 1 hour
|
|
4134
|
+
kvEnabled: true,
|
|
4135
|
+
memoryEnabled: true,
|
|
4136
|
+
namespace: "content",
|
|
4137
|
+
invalidateOn: ["content.update", "content.delete", "content.publish"],
|
|
4138
|
+
version: "v1"
|
|
4139
|
+
},
|
|
4140
|
+
// User data (medium read, medium write)
|
|
4141
|
+
user: {
|
|
4142
|
+
ttl: 900,
|
|
4143
|
+
// 15 minutes
|
|
4144
|
+
kvEnabled: true,
|
|
4145
|
+
memoryEnabled: true,
|
|
4146
|
+
namespace: "user",
|
|
4147
|
+
invalidateOn: ["user.update", "user.delete", "auth.login"],
|
|
4148
|
+
version: "v1"
|
|
4149
|
+
},
|
|
4150
|
+
// Configuration (high read, very low write)
|
|
4151
|
+
config: {
|
|
4152
|
+
ttl: 7200,
|
|
4153
|
+
// 2 hours
|
|
4154
|
+
kvEnabled: true,
|
|
4155
|
+
memoryEnabled: true,
|
|
4156
|
+
namespace: "config",
|
|
4157
|
+
invalidateOn: ["config.update", "plugin.activate", "plugin.deactivate"],
|
|
4158
|
+
version: "v1"
|
|
4159
|
+
},
|
|
4160
|
+
// Media metadata (high read, low write)
|
|
4161
|
+
media: {
|
|
4162
|
+
ttl: 3600,
|
|
4163
|
+
// 1 hour
|
|
4164
|
+
kvEnabled: true,
|
|
4165
|
+
memoryEnabled: true,
|
|
4166
|
+
namespace: "media",
|
|
4167
|
+
invalidateOn: ["media.upload", "media.delete", "media.update"],
|
|
4168
|
+
version: "v1"
|
|
4169
|
+
},
|
|
4170
|
+
// API responses (very high read, low write)
|
|
4171
|
+
api: {
|
|
4172
|
+
ttl: 300,
|
|
4173
|
+
// 5 minutes
|
|
4174
|
+
kvEnabled: true,
|
|
4175
|
+
memoryEnabled: true,
|
|
4176
|
+
namespace: "api",
|
|
4177
|
+
invalidateOn: ["content.update", "content.publish"],
|
|
4178
|
+
version: "v1"
|
|
4179
|
+
},
|
|
4180
|
+
// Session data (very high read, medium write)
|
|
4181
|
+
session: {
|
|
4182
|
+
ttl: 1800,
|
|
4183
|
+
// 30 minutes
|
|
4184
|
+
kvEnabled: false,
|
|
4185
|
+
// Only in-memory for sessions
|
|
4186
|
+
memoryEnabled: true,
|
|
4187
|
+
namespace: "session",
|
|
4188
|
+
invalidateOn: ["auth.logout"],
|
|
4189
|
+
version: "v1"
|
|
4190
|
+
},
|
|
4191
|
+
// Plugin data
|
|
4192
|
+
plugin: {
|
|
4193
|
+
ttl: 3600,
|
|
4194
|
+
// 1 hour
|
|
4195
|
+
kvEnabled: true,
|
|
4196
|
+
memoryEnabled: true,
|
|
4197
|
+
namespace: "plugin",
|
|
4198
|
+
invalidateOn: ["plugin.activate", "plugin.deactivate", "plugin.update"],
|
|
4199
|
+
version: "v1"
|
|
4200
|
+
},
|
|
4201
|
+
// Collections/schema
|
|
4202
|
+
collection: {
|
|
4203
|
+
ttl: 7200,
|
|
4204
|
+
// 2 hours
|
|
4205
|
+
kvEnabled: true,
|
|
4206
|
+
memoryEnabled: true,
|
|
4207
|
+
namespace: "collection",
|
|
4208
|
+
invalidateOn: ["collection.update", "collection.delete"],
|
|
4209
|
+
version: "v1"
|
|
4210
|
+
}
|
|
4211
|
+
};
|
|
4212
|
+
function getCacheConfig(namespace) {
|
|
4213
|
+
return CACHE_CONFIGS[namespace] || {
|
|
4214
|
+
ttl: 3600,
|
|
4215
|
+
kvEnabled: true,
|
|
4216
|
+
memoryEnabled: true,
|
|
4217
|
+
namespace,
|
|
4218
|
+
invalidateOn: [],
|
|
4219
|
+
version: "v1"
|
|
4220
|
+
};
|
|
4221
|
+
}
|
|
4222
|
+
function generateCacheKey(namespace, type, identifier, version) {
|
|
4223
|
+
const v = version || getCacheConfig(namespace).version || "v1";
|
|
4224
|
+
return `${namespace}:${type}:${identifier}:${v}`;
|
|
4225
|
+
}
|
|
4226
|
+
function parseCacheKey(key) {
|
|
4227
|
+
const parts = key.split(":");
|
|
4228
|
+
if (parts.length !== 4) {
|
|
4229
|
+
return null;
|
|
4230
|
+
}
|
|
4231
|
+
return {
|
|
4232
|
+
namespace: parts[0] || "",
|
|
4233
|
+
type: parts[1] || "",
|
|
4234
|
+
identifier: parts[2] || "",
|
|
4235
|
+
version: parts[3] || ""
|
|
4236
|
+
};
|
|
4237
|
+
}
|
|
4566
4238
|
|
|
4567
|
-
// src/
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4239
|
+
// src/plugins/cache/services/cache.ts
|
|
4240
|
+
var MemoryCache = class {
|
|
4241
|
+
cache = /* @__PURE__ */ new Map();
|
|
4242
|
+
maxSize = 50 * 1024 * 1024;
|
|
4243
|
+
// 50MB
|
|
4244
|
+
currentSize = 0;
|
|
4245
|
+
/**
|
|
4246
|
+
* Get item from memory cache
|
|
4247
|
+
*/
|
|
4248
|
+
get(key) {
|
|
4249
|
+
const entry = this.cache.get(key);
|
|
4250
|
+
if (!entry) {
|
|
4251
|
+
return null;
|
|
4252
|
+
}
|
|
4253
|
+
if (Date.now() > entry.expiresAt) {
|
|
4254
|
+
this.delete(key);
|
|
4255
|
+
return null;
|
|
4581
4256
|
}
|
|
4257
|
+
return entry.data;
|
|
4582
4258
|
}
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
app.route("/admin/settings", chunkN7TDLOUE_cjs.adminSettingsRoutes);
|
|
4601
|
-
app.route("/admin/database-tools", createDatabaseToolsAdminRoutes());
|
|
4602
|
-
app.route("/admin/seed-data", createSeedDataAdminRoutes());
|
|
4603
|
-
app.route("/admin/content", chunkN7TDLOUE_cjs.admin_content_default);
|
|
4604
|
-
app.route("/admin/media", chunkN7TDLOUE_cjs.adminMediaRoutes);
|
|
4605
|
-
if (aiSearchPlugin.routes && aiSearchPlugin.routes.length > 0) {
|
|
4606
|
-
for (const route of aiSearchPlugin.routes) {
|
|
4607
|
-
app.route(route.path, route.handler);
|
|
4259
|
+
/**
|
|
4260
|
+
* Set item in memory cache
|
|
4261
|
+
*/
|
|
4262
|
+
set(key, value, ttl, version = "v1") {
|
|
4263
|
+
const now = Date.now();
|
|
4264
|
+
const entry = {
|
|
4265
|
+
data: value,
|
|
4266
|
+
timestamp: now,
|
|
4267
|
+
expiresAt: now + ttl * 1e3,
|
|
4268
|
+
version
|
|
4269
|
+
};
|
|
4270
|
+
const entrySize = JSON.stringify(entry).length * 2;
|
|
4271
|
+
if (this.currentSize + entrySize > this.maxSize) {
|
|
4272
|
+
this.evictLRU(entrySize);
|
|
4273
|
+
}
|
|
4274
|
+
if (this.cache.has(key)) {
|
|
4275
|
+
this.delete(key);
|
|
4608
4276
|
}
|
|
4277
|
+
this.cache.set(key, entry);
|
|
4278
|
+
this.currentSize += entrySize;
|
|
4609
4279
|
}
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4280
|
+
/**
|
|
4281
|
+
* Delete item from memory cache
|
|
4282
|
+
*/
|
|
4283
|
+
delete(key) {
|
|
4284
|
+
const entry = this.cache.get(key);
|
|
4285
|
+
if (entry) {
|
|
4286
|
+
const entrySize = JSON.stringify(entry).length * 2;
|
|
4287
|
+
this.currentSize -= entrySize;
|
|
4288
|
+
return this.cache.delete(key);
|
|
4618
4289
|
}
|
|
4290
|
+
return false;
|
|
4619
4291
|
}
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4292
|
+
/**
|
|
4293
|
+
* Clear all items from memory cache
|
|
4294
|
+
*/
|
|
4295
|
+
clear() {
|
|
4296
|
+
this.cache.clear();
|
|
4297
|
+
this.currentSize = 0;
|
|
4298
|
+
}
|
|
4299
|
+
/**
|
|
4300
|
+
* Get cache statistics
|
|
4301
|
+
*/
|
|
4302
|
+
getStats() {
|
|
4303
|
+
return {
|
|
4304
|
+
size: this.currentSize,
|
|
4305
|
+
count: this.cache.size
|
|
4306
|
+
};
|
|
4307
|
+
}
|
|
4308
|
+
/**
|
|
4309
|
+
* Evict least recently used items to make space
|
|
4310
|
+
*/
|
|
4311
|
+
evictLRU(neededSpace) {
|
|
4312
|
+
const entries = Array.from(this.cache.entries()).sort(
|
|
4313
|
+
(a, b) => a[1].timestamp - b[1].timestamp
|
|
4314
|
+
);
|
|
4315
|
+
let freedSpace = 0;
|
|
4316
|
+
for (const [key, entry] of entries) {
|
|
4317
|
+
if (freedSpace >= neededSpace) break;
|
|
4318
|
+
const entrySize = JSON.stringify(entry).length * 2;
|
|
4319
|
+
this.delete(key);
|
|
4320
|
+
freedSpace += entrySize;
|
|
4321
|
+
}
|
|
4322
|
+
}
|
|
4323
|
+
/**
|
|
4324
|
+
* Delete items matching a pattern
|
|
4325
|
+
*/
|
|
4326
|
+
invalidatePattern(pattern) {
|
|
4327
|
+
const regex = new RegExp(
|
|
4328
|
+
"^" + pattern.replace(/\*/g, ".*").replace(/\?/g, ".") + "$"
|
|
4329
|
+
);
|
|
4330
|
+
let count = 0;
|
|
4331
|
+
for (const key of this.cache.keys()) {
|
|
4332
|
+
if (regex.test(key)) {
|
|
4333
|
+
this.delete(key);
|
|
4334
|
+
count++;
|
|
4335
|
+
}
|
|
4336
|
+
}
|
|
4337
|
+
return count;
|
|
4338
|
+
}
|
|
4339
|
+
};
|
|
4340
|
+
var CacheService = class {
|
|
4341
|
+
memoryCache;
|
|
4342
|
+
config;
|
|
4343
|
+
stats;
|
|
4344
|
+
kvNamespace;
|
|
4345
|
+
constructor(config, kvNamespace) {
|
|
4346
|
+
this.memoryCache = new MemoryCache();
|
|
4347
|
+
this.config = config;
|
|
4348
|
+
this.kvNamespace = kvNamespace;
|
|
4349
|
+
this.stats = {
|
|
4350
|
+
memoryHits: 0,
|
|
4351
|
+
memoryMisses: 0,
|
|
4352
|
+
kvHits: 0,
|
|
4353
|
+
kvMisses: 0,
|
|
4354
|
+
dbHits: 0,
|
|
4355
|
+
totalRequests: 0,
|
|
4356
|
+
hitRate: 0,
|
|
4357
|
+
memorySize: 0,
|
|
4358
|
+
entryCount: 0
|
|
4359
|
+
};
|
|
4360
|
+
}
|
|
4361
|
+
/**
|
|
4362
|
+
* Get value from cache (tries memory first, then KV)
|
|
4363
|
+
*/
|
|
4364
|
+
async get(key) {
|
|
4365
|
+
this.stats.totalRequests++;
|
|
4366
|
+
if (this.config.memoryEnabled) {
|
|
4367
|
+
const memoryValue = this.memoryCache.get(key);
|
|
4368
|
+
if (memoryValue !== null) {
|
|
4369
|
+
this.stats.memoryHits++;
|
|
4370
|
+
this.updateHitRate();
|
|
4371
|
+
return memoryValue;
|
|
4372
|
+
}
|
|
4373
|
+
this.stats.memoryMisses++;
|
|
4374
|
+
}
|
|
4375
|
+
if (this.config.kvEnabled && this.kvNamespace) {
|
|
4376
|
+
try {
|
|
4377
|
+
const kvValue = await this.kvNamespace.get(key, "json");
|
|
4378
|
+
if (kvValue !== null) {
|
|
4379
|
+
this.stats.kvHits++;
|
|
4380
|
+
if (this.config.memoryEnabled) {
|
|
4381
|
+
this.memoryCache.set(key, kvValue, this.config.ttl, this.config.version);
|
|
4382
|
+
}
|
|
4383
|
+
this.updateHitRate();
|
|
4384
|
+
return kvValue;
|
|
4385
|
+
}
|
|
4386
|
+
this.stats.kvMisses++;
|
|
4387
|
+
} catch (error) {
|
|
4388
|
+
console.error("KV cache read error:", error);
|
|
4389
|
+
this.stats.kvMisses++;
|
|
4390
|
+
}
|
|
4391
|
+
}
|
|
4392
|
+
this.updateHitRate();
|
|
4393
|
+
return null;
|
|
4394
|
+
}
|
|
4395
|
+
/**
|
|
4396
|
+
* Get value from cache with source information
|
|
4397
|
+
*/
|
|
4398
|
+
async getWithSource(key) {
|
|
4399
|
+
this.stats.totalRequests++;
|
|
4400
|
+
if (this.config.memoryEnabled) {
|
|
4401
|
+
const memoryValue = this.memoryCache.get(key);
|
|
4402
|
+
if (memoryValue !== null) {
|
|
4403
|
+
this.stats.memoryHits++;
|
|
4404
|
+
this.updateHitRate();
|
|
4405
|
+
const entry = await this.getEntry(key);
|
|
4406
|
+
return {
|
|
4407
|
+
data: memoryValue,
|
|
4408
|
+
source: "memory",
|
|
4409
|
+
hit: true,
|
|
4410
|
+
timestamp: entry?.timestamp,
|
|
4411
|
+
ttl: entry?.ttl
|
|
4412
|
+
};
|
|
4413
|
+
}
|
|
4414
|
+
this.stats.memoryMisses++;
|
|
4415
|
+
}
|
|
4416
|
+
if (this.config.kvEnabled && this.kvNamespace) {
|
|
4417
|
+
try {
|
|
4418
|
+
const kvValue = await this.kvNamespace.get(key, "json");
|
|
4419
|
+
if (kvValue !== null) {
|
|
4420
|
+
this.stats.kvHits++;
|
|
4421
|
+
if (this.config.memoryEnabled) {
|
|
4422
|
+
this.memoryCache.set(key, kvValue, this.config.ttl, this.config.version);
|
|
4423
|
+
}
|
|
4424
|
+
this.updateHitRate();
|
|
4425
|
+
return {
|
|
4426
|
+
data: kvValue,
|
|
4427
|
+
source: "kv",
|
|
4428
|
+
hit: true
|
|
4429
|
+
};
|
|
4430
|
+
}
|
|
4431
|
+
this.stats.kvMisses++;
|
|
4432
|
+
} catch (error) {
|
|
4433
|
+
console.error("KV cache read error:", error);
|
|
4434
|
+
this.stats.kvMisses++;
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4437
|
+
this.updateHitRate();
|
|
4438
|
+
return {
|
|
4439
|
+
data: null,
|
|
4440
|
+
source: "miss",
|
|
4441
|
+
hit: false
|
|
4442
|
+
};
|
|
4443
|
+
}
|
|
4444
|
+
/**
|
|
4445
|
+
* Set value in cache (stores in both memory and KV)
|
|
4446
|
+
*/
|
|
4447
|
+
async set(key, value, customConfig) {
|
|
4448
|
+
const config = { ...this.config, ...customConfig };
|
|
4449
|
+
if (config.memoryEnabled) {
|
|
4450
|
+
this.memoryCache.set(key, value, config.ttl, config.version);
|
|
4451
|
+
}
|
|
4452
|
+
if (config.kvEnabled && this.kvNamespace) {
|
|
4453
|
+
try {
|
|
4454
|
+
await this.kvNamespace.put(key, JSON.stringify(value), {
|
|
4455
|
+
expirationTtl: config.ttl
|
|
4456
|
+
});
|
|
4457
|
+
} catch (error) {
|
|
4458
|
+
console.error("KV cache write error:", error);
|
|
4459
|
+
}
|
|
4460
|
+
}
|
|
4461
|
+
}
|
|
4462
|
+
/**
|
|
4463
|
+
* Delete value from cache (removes from both memory and KV)
|
|
4464
|
+
*/
|
|
4465
|
+
async delete(key) {
|
|
4466
|
+
if (this.config.memoryEnabled) {
|
|
4467
|
+
this.memoryCache.delete(key);
|
|
4468
|
+
}
|
|
4469
|
+
if (this.config.kvEnabled && this.kvNamespace) {
|
|
4470
|
+
try {
|
|
4471
|
+
await this.kvNamespace.delete(key);
|
|
4472
|
+
} catch (error) {
|
|
4473
|
+
console.error("KV cache delete error:", error);
|
|
4474
|
+
}
|
|
4475
|
+
}
|
|
4476
|
+
}
|
|
4477
|
+
/**
|
|
4478
|
+
* Clear all cache entries for this namespace
|
|
4479
|
+
*/
|
|
4480
|
+
async clear() {
|
|
4481
|
+
if (this.config.memoryEnabled) {
|
|
4482
|
+
this.memoryCache.clear();
|
|
4483
|
+
}
|
|
4484
|
+
this.stats = {
|
|
4485
|
+
memoryHits: 0,
|
|
4486
|
+
memoryMisses: 0,
|
|
4487
|
+
kvHits: 0,
|
|
4488
|
+
kvMisses: 0,
|
|
4489
|
+
dbHits: 0,
|
|
4490
|
+
totalRequests: 0,
|
|
4491
|
+
hitRate: 0,
|
|
4492
|
+
memorySize: 0,
|
|
4493
|
+
entryCount: 0
|
|
4494
|
+
};
|
|
4495
|
+
}
|
|
4496
|
+
/**
|
|
4497
|
+
* Invalidate cache entries matching a pattern
|
|
4498
|
+
*/
|
|
4499
|
+
async invalidate(pattern) {
|
|
4500
|
+
let count = 0;
|
|
4501
|
+
if (this.config.memoryEnabled) {
|
|
4502
|
+
count += this.memoryCache.invalidatePattern(pattern);
|
|
4503
|
+
}
|
|
4504
|
+
if (this.config.kvEnabled && this.kvNamespace) {
|
|
4505
|
+
try {
|
|
4506
|
+
const regex = new RegExp(
|
|
4507
|
+
"^" + pattern.replace(/\*/g, ".*").replace(/\?/g, ".") + "$"
|
|
4508
|
+
);
|
|
4509
|
+
const prefix = this.config.namespace + ":";
|
|
4510
|
+
const list = await this.kvNamespace.list({ prefix });
|
|
4511
|
+
for (const key of list.keys) {
|
|
4512
|
+
if (regex.test(key.name)) {
|
|
4513
|
+
await this.kvNamespace.delete(key.name);
|
|
4514
|
+
count++;
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
} catch (error) {
|
|
4518
|
+
console.error("KV cache invalidation error:", error);
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4521
|
+
return count;
|
|
4522
|
+
}
|
|
4523
|
+
/**
|
|
4524
|
+
* Invalidate cache entries matching a pattern (alias for invalidate)
|
|
4525
|
+
*/
|
|
4526
|
+
async invalidatePattern(pattern) {
|
|
4527
|
+
return this.invalidate(pattern);
|
|
4528
|
+
}
|
|
4529
|
+
/**
|
|
4530
|
+
* Get cache statistics
|
|
4531
|
+
*/
|
|
4532
|
+
getStats() {
|
|
4533
|
+
const memStats = this.memoryCache.getStats();
|
|
4534
|
+
return {
|
|
4535
|
+
...this.stats,
|
|
4536
|
+
memorySize: memStats.size,
|
|
4537
|
+
entryCount: memStats.count
|
|
4538
|
+
};
|
|
4539
|
+
}
|
|
4540
|
+
/**
|
|
4541
|
+
* Update hit rate calculation
|
|
4542
|
+
*/
|
|
4543
|
+
updateHitRate() {
|
|
4544
|
+
const totalHits = this.stats.memoryHits + this.stats.kvHits + this.stats.dbHits;
|
|
4545
|
+
this.stats.hitRate = this.stats.totalRequests > 0 ? totalHits / this.stats.totalRequests * 100 : 0;
|
|
4546
|
+
}
|
|
4547
|
+
/**
|
|
4548
|
+
* Generate a cache key using the configured namespace
|
|
4549
|
+
*/
|
|
4550
|
+
generateKey(type, identifier) {
|
|
4551
|
+
return generateCacheKey(
|
|
4552
|
+
this.config.namespace,
|
|
4553
|
+
type,
|
|
4554
|
+
identifier,
|
|
4555
|
+
this.config.version
|
|
4556
|
+
);
|
|
4557
|
+
}
|
|
4558
|
+
/**
|
|
4559
|
+
* Warm cache with multiple entries
|
|
4560
|
+
*/
|
|
4561
|
+
async warmCache(entries) {
|
|
4562
|
+
for (const entry of entries) {
|
|
4563
|
+
await this.set(entry.key, entry.value);
|
|
4564
|
+
}
|
|
4565
|
+
}
|
|
4566
|
+
/**
|
|
4567
|
+
* Check if a key exists in cache
|
|
4568
|
+
*/
|
|
4569
|
+
async has(key) {
|
|
4570
|
+
const value = await this.get(key);
|
|
4571
|
+
return value !== null;
|
|
4572
|
+
}
|
|
4573
|
+
/**
|
|
4574
|
+
* Get multiple values at once
|
|
4575
|
+
*/
|
|
4576
|
+
async getMany(keys) {
|
|
4577
|
+
const results = /* @__PURE__ */ new Map();
|
|
4578
|
+
for (const key of keys) {
|
|
4579
|
+
const value = await this.get(key);
|
|
4580
|
+
if (value !== null) {
|
|
4581
|
+
results.set(key, value);
|
|
4582
|
+
}
|
|
4583
|
+
}
|
|
4584
|
+
return results;
|
|
4585
|
+
}
|
|
4586
|
+
/**
|
|
4587
|
+
* Set multiple values at once
|
|
4588
|
+
*/
|
|
4589
|
+
async setMany(entries, customConfig) {
|
|
4590
|
+
for (const entry of entries) {
|
|
4591
|
+
await this.set(entry.key, entry.value, customConfig);
|
|
4592
|
+
}
|
|
4593
|
+
}
|
|
4594
|
+
/**
|
|
4595
|
+
* Delete multiple keys at once
|
|
4596
|
+
*/
|
|
4597
|
+
async deleteMany(keys) {
|
|
4598
|
+
for (const key of keys) {
|
|
4599
|
+
await this.delete(key);
|
|
4600
|
+
}
|
|
4601
|
+
}
|
|
4602
|
+
/**
|
|
4603
|
+
* Get or set pattern - fetch from cache or compute if not found
|
|
4604
|
+
*/
|
|
4605
|
+
async getOrSet(key, fetcher, customConfig) {
|
|
4606
|
+
const cached = await this.get(key);
|
|
4607
|
+
if (cached !== null) {
|
|
4608
|
+
return cached;
|
|
4609
|
+
}
|
|
4610
|
+
const value = await fetcher();
|
|
4611
|
+
await this.set(key, value, customConfig);
|
|
4612
|
+
return value;
|
|
4613
|
+
}
|
|
4614
|
+
/**
|
|
4615
|
+
* List all cache keys with metadata
|
|
4616
|
+
*/
|
|
4617
|
+
async listKeys() {
|
|
4618
|
+
const keys = [];
|
|
4619
|
+
if (this.config.memoryEnabled) {
|
|
4620
|
+
const cache = this.memoryCache.cache;
|
|
4621
|
+
for (const [key, entry] of cache.entries()) {
|
|
4622
|
+
const size = JSON.stringify(entry).length * 2;
|
|
4623
|
+
const age = Date.now() - entry.timestamp;
|
|
4624
|
+
keys.push({
|
|
4625
|
+
key,
|
|
4626
|
+
size,
|
|
4627
|
+
expiresAt: entry.expiresAt,
|
|
4628
|
+
age
|
|
4629
|
+
});
|
|
4630
|
+
}
|
|
4631
|
+
}
|
|
4632
|
+
return keys.sort((a, b) => a.age - b.age);
|
|
4633
|
+
}
|
|
4634
|
+
/**
|
|
4635
|
+
* Get cache entry with full metadata
|
|
4636
|
+
*/
|
|
4637
|
+
async getEntry(key) {
|
|
4638
|
+
if (!this.config.memoryEnabled) {
|
|
4639
|
+
return null;
|
|
4640
|
+
}
|
|
4641
|
+
const cache = this.memoryCache.cache;
|
|
4642
|
+
const entry = cache.get(key);
|
|
4643
|
+
if (!entry) {
|
|
4644
|
+
return null;
|
|
4645
|
+
}
|
|
4646
|
+
if (Date.now() > entry.expiresAt) {
|
|
4647
|
+
await this.delete(key);
|
|
4648
|
+
return null;
|
|
4649
|
+
}
|
|
4650
|
+
const size = JSON.stringify(entry).length * 2;
|
|
4651
|
+
const ttl = Math.max(0, entry.expiresAt - Date.now()) / 1e3;
|
|
4652
|
+
return {
|
|
4653
|
+
data: entry.data,
|
|
4654
|
+
timestamp: entry.timestamp,
|
|
4655
|
+
expiresAt: entry.expiresAt,
|
|
4656
|
+
ttl,
|
|
4657
|
+
size
|
|
4658
|
+
};
|
|
4659
|
+
}
|
|
4660
|
+
};
|
|
4661
|
+
var cacheInstances = /* @__PURE__ */ new Map();
|
|
4662
|
+
var globalKVNamespace;
|
|
4663
|
+
function getCacheService(config, kvNamespace) {
|
|
4664
|
+
const key = config.namespace;
|
|
4665
|
+
if (!cacheInstances.has(key)) {
|
|
4666
|
+
const kv = globalKVNamespace;
|
|
4667
|
+
cacheInstances.set(key, new CacheService(config, kv));
|
|
4668
|
+
}
|
|
4669
|
+
return cacheInstances.get(key);
|
|
4670
|
+
}
|
|
4671
|
+
async function clearAllCaches() {
|
|
4672
|
+
for (const cache of cacheInstances.values()) {
|
|
4673
|
+
await cache.clear();
|
|
4674
|
+
}
|
|
4675
|
+
}
|
|
4676
|
+
function getAllCacheStats() {
|
|
4677
|
+
const stats = {};
|
|
4678
|
+
for (const [namespace, cache] of cacheInstances.entries()) {
|
|
4679
|
+
stats[namespace] = cache.getStats();
|
|
4680
|
+
}
|
|
4681
|
+
return stats;
|
|
4682
|
+
}
|
|
4683
|
+
|
|
4684
|
+
// src/plugins/cache/services/event-bus.ts
|
|
4685
|
+
var EventBus = class {
|
|
4686
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
4687
|
+
eventLog = [];
|
|
4688
|
+
maxLogSize = 100;
|
|
4689
|
+
/**
|
|
4690
|
+
* Subscribe to an event
|
|
4691
|
+
*/
|
|
4692
|
+
on(event, handler) {
|
|
4693
|
+
if (!this.subscriptions.has(event)) {
|
|
4694
|
+
this.subscriptions.set(event, []);
|
|
4695
|
+
}
|
|
4696
|
+
this.subscriptions.get(event).push(handler);
|
|
4697
|
+
return () => {
|
|
4698
|
+
const handlers = this.subscriptions.get(event);
|
|
4699
|
+
if (handlers) {
|
|
4700
|
+
const index = handlers.indexOf(handler);
|
|
4701
|
+
if (index > -1) {
|
|
4702
|
+
handlers.splice(index, 1);
|
|
4703
|
+
}
|
|
4704
|
+
}
|
|
4705
|
+
};
|
|
4706
|
+
}
|
|
4707
|
+
/**
|
|
4708
|
+
* Emit an event to all subscribers
|
|
4709
|
+
*/
|
|
4710
|
+
async emit(event, data) {
|
|
4711
|
+
this.logEvent(event, data);
|
|
4712
|
+
const handlers = this.subscriptions.get(event) || [];
|
|
4713
|
+
await Promise.all(
|
|
4714
|
+
handlers.map(async (handler) => {
|
|
4715
|
+
try {
|
|
4716
|
+
await handler(data);
|
|
4717
|
+
} catch (error) {
|
|
4718
|
+
console.error(`Error in event handler for ${event}:`, error);
|
|
4719
|
+
}
|
|
4720
|
+
})
|
|
4721
|
+
);
|
|
4722
|
+
const wildcardHandlers = this.subscriptions.get("*") || [];
|
|
4723
|
+
await Promise.all(
|
|
4724
|
+
wildcardHandlers.map(async (handler) => {
|
|
4725
|
+
try {
|
|
4726
|
+
await handler({ event, data });
|
|
4727
|
+
} catch (error) {
|
|
4728
|
+
console.error(`Error in wildcard event handler for ${event}:`, error);
|
|
4729
|
+
}
|
|
4730
|
+
})
|
|
4731
|
+
);
|
|
4732
|
+
}
|
|
4733
|
+
/**
|
|
4734
|
+
* Remove all subscribers for an event
|
|
4735
|
+
*/
|
|
4736
|
+
off(event) {
|
|
4737
|
+
this.subscriptions.delete(event);
|
|
4738
|
+
}
|
|
4739
|
+
/**
|
|
4740
|
+
* Get all registered events
|
|
4741
|
+
*/
|
|
4742
|
+
getEvents() {
|
|
4743
|
+
return Array.from(this.subscriptions.keys());
|
|
4744
|
+
}
|
|
4745
|
+
/**
|
|
4746
|
+
* Get subscriber count for an event
|
|
4747
|
+
*/
|
|
4748
|
+
getSubscriberCount(event) {
|
|
4749
|
+
return this.subscriptions.get(event)?.length || 0;
|
|
4750
|
+
}
|
|
4751
|
+
/**
|
|
4752
|
+
* Log an event for debugging
|
|
4753
|
+
*/
|
|
4754
|
+
logEvent(event, data) {
|
|
4755
|
+
this.eventLog.push({
|
|
4756
|
+
event,
|
|
4757
|
+
timestamp: Date.now(),
|
|
4758
|
+
data
|
|
4759
|
+
});
|
|
4760
|
+
if (this.eventLog.length > this.maxLogSize) {
|
|
4761
|
+
this.eventLog.shift();
|
|
4762
|
+
}
|
|
4763
|
+
}
|
|
4764
|
+
/**
|
|
4765
|
+
* Get recent event log
|
|
4766
|
+
*/
|
|
4767
|
+
getEventLog(limit = 50) {
|
|
4768
|
+
return this.eventLog.slice(-limit);
|
|
4769
|
+
}
|
|
4770
|
+
/**
|
|
4771
|
+
* Clear event log
|
|
4772
|
+
*/
|
|
4773
|
+
clearEventLog() {
|
|
4774
|
+
this.eventLog = [];
|
|
4775
|
+
}
|
|
4776
|
+
/**
|
|
4777
|
+
* Get statistics
|
|
4778
|
+
*/
|
|
4779
|
+
getStats() {
|
|
4780
|
+
const eventCounts = {};
|
|
4781
|
+
for (const log of this.eventLog) {
|
|
4782
|
+
eventCounts[log.event] = (eventCounts[log.event] || 0) + 1;
|
|
4783
|
+
}
|
|
4784
|
+
return {
|
|
4785
|
+
totalEvents: this.eventLog.length,
|
|
4786
|
+
totalSubscriptions: this.subscriptions.size,
|
|
4787
|
+
eventCounts
|
|
4788
|
+
};
|
|
4789
|
+
}
|
|
4790
|
+
};
|
|
4791
|
+
var globalEventBus = null;
|
|
4792
|
+
function getEventBus() {
|
|
4793
|
+
if (!globalEventBus) {
|
|
4794
|
+
globalEventBus = new EventBus();
|
|
4795
|
+
}
|
|
4796
|
+
return globalEventBus;
|
|
4797
|
+
}
|
|
4798
|
+
function onEvent(event, handler) {
|
|
4799
|
+
const bus = getEventBus();
|
|
4800
|
+
return bus.on(event, handler);
|
|
4801
|
+
}
|
|
4802
|
+
|
|
4803
|
+
// src/plugins/cache/services/cache-invalidation.ts
|
|
4804
|
+
function setupCacheInvalidation() {
|
|
4805
|
+
getEventBus();
|
|
4806
|
+
setupContentInvalidation();
|
|
4807
|
+
setupUserInvalidation();
|
|
4808
|
+
setupConfigInvalidation();
|
|
4809
|
+
setupMediaInvalidation();
|
|
4810
|
+
setupAPIInvalidation();
|
|
4811
|
+
setupCollectionInvalidation();
|
|
4812
|
+
console.log("Cache invalidation listeners registered");
|
|
4813
|
+
}
|
|
4814
|
+
function setupContentInvalidation() {
|
|
4815
|
+
const config = CACHE_CONFIGS.content;
|
|
4816
|
+
if (!config) return;
|
|
4817
|
+
const contentCache = getCacheService(config);
|
|
4818
|
+
onEvent("content.create", async (_data) => {
|
|
4819
|
+
await contentCache.invalidate("content:*");
|
|
4820
|
+
console.log("Cache invalidated: content.create");
|
|
4821
|
+
});
|
|
4822
|
+
onEvent("content.update", async (data) => {
|
|
4823
|
+
if (data?.id) {
|
|
4824
|
+
await contentCache.delete(contentCache.generateKey("item", data.id));
|
|
4825
|
+
}
|
|
4826
|
+
await contentCache.invalidate("content:list:*");
|
|
4827
|
+
console.log("Cache invalidated: content.update", data?.id);
|
|
4828
|
+
});
|
|
4829
|
+
onEvent("content.delete", async (data) => {
|
|
4830
|
+
if (data?.id) {
|
|
4831
|
+
await contentCache.delete(contentCache.generateKey("item", data.id));
|
|
4832
|
+
}
|
|
4833
|
+
await contentCache.invalidate("content:*");
|
|
4834
|
+
console.log("Cache invalidated: content.delete", data?.id);
|
|
4835
|
+
});
|
|
4836
|
+
onEvent("content.publish", async (_data) => {
|
|
4837
|
+
await contentCache.invalidate("content:*");
|
|
4838
|
+
console.log("Cache invalidated: content.publish");
|
|
4839
|
+
});
|
|
4840
|
+
}
|
|
4841
|
+
function setupUserInvalidation() {
|
|
4842
|
+
const config = CACHE_CONFIGS.user;
|
|
4843
|
+
if (!config) return;
|
|
4844
|
+
const userCache = getCacheService(config);
|
|
4845
|
+
onEvent("user.update", async (data) => {
|
|
4846
|
+
if (data?.id) {
|
|
4847
|
+
await userCache.delete(userCache.generateKey("id", data.id));
|
|
4848
|
+
}
|
|
4849
|
+
if (data?.email) {
|
|
4850
|
+
await userCache.delete(userCache.generateKey("email", data.email));
|
|
4851
|
+
}
|
|
4852
|
+
console.log("Cache invalidated: user.update", data?.id);
|
|
4853
|
+
});
|
|
4854
|
+
onEvent("user.delete", async (data) => {
|
|
4855
|
+
if (data?.id) {
|
|
4856
|
+
await userCache.delete(userCache.generateKey("id", data.id));
|
|
4857
|
+
}
|
|
4858
|
+
if (data?.email) {
|
|
4859
|
+
await userCache.delete(userCache.generateKey("email", data.email));
|
|
4860
|
+
}
|
|
4861
|
+
console.log("Cache invalidated: user.delete", data?.id);
|
|
4862
|
+
});
|
|
4863
|
+
onEvent("auth.login", async (data) => {
|
|
4864
|
+
if (data?.userId) {
|
|
4865
|
+
await userCache.delete(userCache.generateKey("id", data.userId));
|
|
4866
|
+
}
|
|
4867
|
+
console.log("Cache invalidated: auth.login", data?.userId);
|
|
4868
|
+
});
|
|
4869
|
+
onEvent("auth.logout", async (data) => {
|
|
4870
|
+
const sessionConfig = CACHE_CONFIGS.session;
|
|
4871
|
+
if (sessionConfig) {
|
|
4872
|
+
const sessionCache = getCacheService(sessionConfig);
|
|
4873
|
+
if (data?.sessionId) {
|
|
4874
|
+
await sessionCache.delete(sessionCache.generateKey("session", data.sessionId));
|
|
4875
|
+
}
|
|
4876
|
+
}
|
|
4877
|
+
console.log("Cache invalidated: auth.logout");
|
|
4878
|
+
});
|
|
4879
|
+
}
|
|
4880
|
+
function setupConfigInvalidation() {
|
|
4881
|
+
const configConfig = CACHE_CONFIGS.config;
|
|
4882
|
+
if (!configConfig) return;
|
|
4883
|
+
const configCache = getCacheService(configConfig);
|
|
4884
|
+
onEvent("config.update", async (_data) => {
|
|
4885
|
+
await configCache.invalidate("config:*");
|
|
4886
|
+
console.log("Cache invalidated: config.update");
|
|
4887
|
+
});
|
|
4888
|
+
onEvent("plugin.activate", async (data) => {
|
|
4889
|
+
await configCache.invalidate("config:*");
|
|
4890
|
+
const pluginConfig = CACHE_CONFIGS.plugin;
|
|
4891
|
+
if (pluginConfig) {
|
|
4892
|
+
const pluginCache = getCacheService(pluginConfig);
|
|
4893
|
+
await pluginCache.invalidate("plugin:*");
|
|
4894
|
+
}
|
|
4895
|
+
console.log("Cache invalidated: plugin.activate", data?.pluginId);
|
|
4896
|
+
});
|
|
4897
|
+
onEvent("plugin.deactivate", async (data) => {
|
|
4898
|
+
await configCache.invalidate("config:*");
|
|
4899
|
+
const pluginConfig = CACHE_CONFIGS.plugin;
|
|
4900
|
+
if (pluginConfig) {
|
|
4901
|
+
const pluginCache = getCacheService(pluginConfig);
|
|
4902
|
+
await pluginCache.invalidate("plugin:*");
|
|
4903
|
+
}
|
|
4904
|
+
console.log("Cache invalidated: plugin.deactivate", data?.pluginId);
|
|
4905
|
+
});
|
|
4906
|
+
onEvent("plugin.update", async (data) => {
|
|
4907
|
+
const pluginConfig = CACHE_CONFIGS.plugin;
|
|
4908
|
+
if (!pluginConfig) return;
|
|
4909
|
+
const pluginCache = getCacheService(pluginConfig);
|
|
4910
|
+
await pluginCache.invalidate("plugin:*");
|
|
4911
|
+
console.log("Cache invalidated: plugin.update", data?.pluginId);
|
|
4912
|
+
});
|
|
4913
|
+
}
|
|
4914
|
+
function setupMediaInvalidation() {
|
|
4915
|
+
const config = CACHE_CONFIGS.media;
|
|
4916
|
+
if (!config) return;
|
|
4917
|
+
const mediaCache = getCacheService(config);
|
|
4918
|
+
onEvent("media.upload", async (_data) => {
|
|
4919
|
+
await mediaCache.invalidate("media:*");
|
|
4920
|
+
console.log("Cache invalidated: media.upload");
|
|
4921
|
+
});
|
|
4922
|
+
onEvent("media.delete", async (data) => {
|
|
4923
|
+
if (data?.id) {
|
|
4924
|
+
await mediaCache.delete(mediaCache.generateKey("item", data.id));
|
|
4925
|
+
}
|
|
4926
|
+
await mediaCache.invalidate("media:list:*");
|
|
4927
|
+
console.log("Cache invalidated: media.delete", data?.id);
|
|
4928
|
+
});
|
|
4929
|
+
onEvent("media.update", async (data) => {
|
|
4930
|
+
if (data?.id) {
|
|
4931
|
+
await mediaCache.delete(mediaCache.generateKey("item", data.id));
|
|
4932
|
+
}
|
|
4933
|
+
await mediaCache.invalidate("media:list:*");
|
|
4934
|
+
console.log("Cache invalidated: media.update", data?.id);
|
|
4935
|
+
});
|
|
4936
|
+
}
|
|
4937
|
+
function setupAPIInvalidation() {
|
|
4938
|
+
const config = CACHE_CONFIGS.api;
|
|
4939
|
+
if (!config) return;
|
|
4940
|
+
const apiCache = getCacheService(config);
|
|
4941
|
+
onEvent("content.update", async (_data) => {
|
|
4942
|
+
await apiCache.invalidate("api:*");
|
|
4943
|
+
console.log("Cache invalidated: api (content.update)");
|
|
4944
|
+
});
|
|
4945
|
+
onEvent("content.publish", async (_data) => {
|
|
4946
|
+
await apiCache.invalidate("api:*");
|
|
4947
|
+
console.log("Cache invalidated: api (content.publish)");
|
|
4948
|
+
});
|
|
4949
|
+
onEvent("content.create", async (_data) => {
|
|
4950
|
+
await apiCache.invalidate("api:*");
|
|
4951
|
+
console.log("Cache invalidated: api (content.create)");
|
|
4952
|
+
});
|
|
4953
|
+
onEvent("content.delete", async (_data) => {
|
|
4954
|
+
await apiCache.invalidate("api:*");
|
|
4955
|
+
console.log("Cache invalidated: api (content.delete)");
|
|
4956
|
+
});
|
|
4957
|
+
onEvent("collection.update", async (_data) => {
|
|
4958
|
+
await apiCache.invalidate("api:*");
|
|
4959
|
+
console.log("Cache invalidated: api (collection.update)");
|
|
4960
|
+
});
|
|
4961
|
+
}
|
|
4962
|
+
function setupCollectionInvalidation() {
|
|
4963
|
+
const config = CACHE_CONFIGS.collection;
|
|
4964
|
+
if (!config) return;
|
|
4965
|
+
const collectionCache = getCacheService(config);
|
|
4966
|
+
onEvent("collection.create", async (_data) => {
|
|
4967
|
+
await collectionCache.invalidate("collection:*");
|
|
4968
|
+
console.log("Cache invalidated: collection.create");
|
|
4969
|
+
});
|
|
4970
|
+
onEvent("collection.update", async (data) => {
|
|
4971
|
+
if (data?.id) {
|
|
4972
|
+
await collectionCache.delete(collectionCache.generateKey("item", data.id));
|
|
4973
|
+
}
|
|
4974
|
+
await collectionCache.invalidate("collection:*");
|
|
4975
|
+
console.log("Cache invalidated: collection.update", data?.id);
|
|
4976
|
+
});
|
|
4977
|
+
onEvent("collection.delete", async (data) => {
|
|
4978
|
+
await collectionCache.invalidate("collection:*");
|
|
4979
|
+
console.log("Cache invalidated: collection.delete", data?.id);
|
|
4980
|
+
});
|
|
4981
|
+
}
|
|
4982
|
+
function getCacheInvalidationStats() {
|
|
4983
|
+
const eventBus = getEventBus();
|
|
4984
|
+
return eventBus.getStats();
|
|
4985
|
+
}
|
|
4986
|
+
function getRecentInvalidations(limit = 50) {
|
|
4987
|
+
const eventBus = getEventBus();
|
|
4988
|
+
return eventBus.getEventLog(limit);
|
|
4989
|
+
}
|
|
4990
|
+
|
|
4991
|
+
// src/plugins/cache/services/cache-warming.ts
|
|
4992
|
+
async function warmCommonCaches(db) {
|
|
4993
|
+
let totalWarmed = 0;
|
|
4994
|
+
let totalErrors = 0;
|
|
4995
|
+
const details = [];
|
|
4996
|
+
try {
|
|
4997
|
+
const collectionCount = await warmCollections(db);
|
|
4998
|
+
totalWarmed += collectionCount;
|
|
4999
|
+
details.push({ namespace: "collection", count: collectionCount });
|
|
5000
|
+
const contentCount = await warmRecentContent(db);
|
|
5001
|
+
totalWarmed += contentCount;
|
|
5002
|
+
details.push({ namespace: "content", count: contentCount });
|
|
5003
|
+
const mediaCount = await warmRecentMedia(db);
|
|
5004
|
+
totalWarmed += mediaCount;
|
|
5005
|
+
details.push({ namespace: "media", count: mediaCount });
|
|
5006
|
+
} catch (error) {
|
|
5007
|
+
console.error("Error warming caches:", error);
|
|
5008
|
+
totalErrors++;
|
|
5009
|
+
}
|
|
5010
|
+
return {
|
|
5011
|
+
warmed: totalWarmed,
|
|
5012
|
+
errors: totalErrors,
|
|
5013
|
+
details
|
|
5014
|
+
};
|
|
5015
|
+
}
|
|
5016
|
+
async function warmCollections(db) {
|
|
5017
|
+
const config = CACHE_CONFIGS.collection;
|
|
5018
|
+
if (!config) return 0;
|
|
5019
|
+
const collectionCache = getCacheService(config);
|
|
5020
|
+
let count = 0;
|
|
5021
|
+
try {
|
|
5022
|
+
const stmt = db.prepare("SELECT * FROM collections WHERE is_active = 1");
|
|
5023
|
+
const { results } = await stmt.all();
|
|
5024
|
+
for (const collection of results) {
|
|
5025
|
+
const key = collectionCache.generateKey("item", collection.id);
|
|
5026
|
+
await collectionCache.set(key, collection);
|
|
5027
|
+
count++;
|
|
5028
|
+
}
|
|
5029
|
+
const listKey = collectionCache.generateKey("list", "all");
|
|
5030
|
+
await collectionCache.set(listKey, results);
|
|
5031
|
+
count++;
|
|
5032
|
+
} catch (error) {
|
|
5033
|
+
console.error("Error warming collections cache:", error);
|
|
5034
|
+
}
|
|
5035
|
+
return count;
|
|
5036
|
+
}
|
|
5037
|
+
async function warmRecentContent(db, limit = 50) {
|
|
5038
|
+
const config = CACHE_CONFIGS.content;
|
|
5039
|
+
if (!config) return 0;
|
|
5040
|
+
const contentCache = getCacheService(config);
|
|
5041
|
+
let count = 0;
|
|
5042
|
+
try {
|
|
5043
|
+
const stmt = db.prepare(`SELECT * FROM content ORDER BY created_at DESC LIMIT ${limit}`);
|
|
5044
|
+
const { results } = await stmt.all();
|
|
5045
|
+
for (const content2 of results) {
|
|
5046
|
+
const key = contentCache.generateKey("item", content2.id);
|
|
5047
|
+
await contentCache.set(key, content2);
|
|
5048
|
+
count++;
|
|
5049
|
+
}
|
|
5050
|
+
const listKey = contentCache.generateKey("list", "recent");
|
|
5051
|
+
await contentCache.set(listKey, results);
|
|
5052
|
+
count++;
|
|
5053
|
+
} catch (error) {
|
|
5054
|
+
console.error("Error warming content cache:", error);
|
|
5055
|
+
}
|
|
5056
|
+
return count;
|
|
5057
|
+
}
|
|
5058
|
+
async function warmRecentMedia(db, limit = 50) {
|
|
5059
|
+
const config = CACHE_CONFIGS.media;
|
|
5060
|
+
if (!config) return 0;
|
|
5061
|
+
const mediaCache = getCacheService(config);
|
|
5062
|
+
let count = 0;
|
|
5063
|
+
try {
|
|
5064
|
+
const stmt = db.prepare(`SELECT * FROM media WHERE deleted_at IS NULL ORDER BY uploaded_at DESC LIMIT ${limit}`);
|
|
5065
|
+
const { results } = await stmt.all();
|
|
5066
|
+
for (const media2 of results) {
|
|
5067
|
+
const key = mediaCache.generateKey("item", media2.id);
|
|
5068
|
+
await mediaCache.set(key, media2);
|
|
5069
|
+
count++;
|
|
5070
|
+
}
|
|
5071
|
+
const listKey = mediaCache.generateKey("list", "recent");
|
|
5072
|
+
await mediaCache.set(listKey, results);
|
|
5073
|
+
count++;
|
|
5074
|
+
} catch (error) {
|
|
5075
|
+
console.error("Error warming media cache:", error);
|
|
5076
|
+
}
|
|
5077
|
+
return count;
|
|
5078
|
+
}
|
|
5079
|
+
async function warmNamespace(namespace, entries) {
|
|
5080
|
+
const config = CACHE_CONFIGS[namespace];
|
|
5081
|
+
if (!config) {
|
|
5082
|
+
throw new Error(`Unknown namespace: ${namespace}`);
|
|
5083
|
+
}
|
|
5084
|
+
const cache = getCacheService(config);
|
|
5085
|
+
await cache.setMany(entries);
|
|
5086
|
+
return entries.length;
|
|
5087
|
+
}
|
|
5088
|
+
|
|
5089
|
+
// src/templates/pages/admin-cache.template.ts
|
|
5090
|
+
chunkSHCYIZAN_cjs.init_admin_layout_catalyst_template();
|
|
5091
|
+
function renderCacheDashboard(data) {
|
|
5092
|
+
const pageContent = `
|
|
5093
|
+
<div class="space-y-6">
|
|
5094
|
+
<!-- Header -->
|
|
5095
|
+
<div class="flex items-center justify-between">
|
|
5096
|
+
<div>
|
|
5097
|
+
<h1 class="text-2xl font-semibold text-zinc-950 dark:text-white">Cache System</h1>
|
|
5098
|
+
<p class="mt-1 text-sm text-zinc-600 dark:text-zinc-400">
|
|
5099
|
+
Monitor and manage cache performance across all namespaces
|
|
5100
|
+
</p>
|
|
5101
|
+
</div>
|
|
5102
|
+
<div class="flex gap-3">
|
|
5103
|
+
<button
|
|
5104
|
+
onclick="refreshStats()"
|
|
5105
|
+
class="inline-flex items-center gap-2 rounded-lg bg-white dark:bg-zinc-900 px-4 py-2 text-sm font-medium text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-800"
|
|
5106
|
+
>
|
|
5107
|
+
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
5108
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
|
|
5109
|
+
</svg>
|
|
5110
|
+
Refresh
|
|
5111
|
+
</button>
|
|
5112
|
+
<button
|
|
5113
|
+
onclick="clearAllCaches()"
|
|
5114
|
+
class="inline-flex items-center gap-2 rounded-lg bg-red-600 dark:bg-red-500 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 dark:hover:bg-red-600"
|
|
5115
|
+
>
|
|
5116
|
+
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
5117
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
|
|
5118
|
+
</svg>
|
|
5119
|
+
Clear All
|
|
5120
|
+
</button>
|
|
5121
|
+
</div>
|
|
5122
|
+
</div>
|
|
5123
|
+
|
|
5124
|
+
<!-- Overall Stats Cards -->
|
|
5125
|
+
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
|
5126
|
+
${renderStatCard("Total Requests", data.totals.requests.toLocaleString(), "lime", `
|
|
5127
|
+
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
5128
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/>
|
|
5129
|
+
</svg>
|
|
5130
|
+
`)}
|
|
5131
|
+
|
|
5132
|
+
${renderStatCard("Hit Rate", data.totals.hitRate + "%", "blue", `
|
|
5133
|
+
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
5134
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
5135
|
+
</svg>
|
|
5136
|
+
`, parseFloat(data.totals.hitRate) > 70 ? "lime" : parseFloat(data.totals.hitRate) > 40 ? "amber" : "red")}
|
|
5137
|
+
|
|
5138
|
+
${renderStatCard("Memory Usage", formatBytes(data.totals.memorySize), "purple", `
|
|
5139
|
+
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
5140
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"/>
|
|
5141
|
+
</svg>
|
|
5142
|
+
`)}
|
|
5143
|
+
|
|
5144
|
+
${renderStatCard("Cached Entries", data.totals.entryCount.toLocaleString(), "sky", `
|
|
5145
|
+
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
5146
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"/>
|
|
5147
|
+
</svg>
|
|
5148
|
+
`)}
|
|
5149
|
+
</div>
|
|
5150
|
+
|
|
5151
|
+
<!-- Namespace Statistics -->
|
|
5152
|
+
<div class="overflow-hidden rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10">
|
|
5153
|
+
<div class="px-6 py-4 border-b border-zinc-950/5 dark:border-white/10">
|
|
5154
|
+
<h2 class="text-lg font-semibold text-zinc-950 dark:text-white">Cache Namespaces</h2>
|
|
5155
|
+
</div>
|
|
5156
|
+
<div class="overflow-x-auto">
|
|
5157
|
+
<table class="min-w-full divide-y divide-zinc-950/5 dark:divide-white/10">
|
|
5158
|
+
<thead class="bg-zinc-50 dark:bg-zinc-800/50">
|
|
5159
|
+
<tr>
|
|
5160
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
|
|
5161
|
+
Namespace
|
|
5162
|
+
</th>
|
|
5163
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
|
|
5164
|
+
Requests
|
|
5165
|
+
</th>
|
|
5166
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
|
|
5167
|
+
Hit Rate
|
|
5168
|
+
</th>
|
|
5169
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
|
|
5170
|
+
Memory Hits
|
|
5171
|
+
</th>
|
|
5172
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
|
|
5173
|
+
KV Hits
|
|
5174
|
+
</th>
|
|
5175
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
|
|
5176
|
+
Entries
|
|
5177
|
+
</th>
|
|
5178
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
|
|
5179
|
+
Size
|
|
5180
|
+
</th>
|
|
5181
|
+
<th class="px-6 py-3 text-right text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">
|
|
5182
|
+
Actions
|
|
5183
|
+
</th>
|
|
5184
|
+
</tr>
|
|
5185
|
+
</thead>
|
|
5186
|
+
<tbody class="divide-y divide-zinc-950/5 dark:divide-white/10">
|
|
5187
|
+
${data.namespaces.map((namespace) => {
|
|
5188
|
+
const stat = data.stats[namespace];
|
|
5189
|
+
if (!stat) return "";
|
|
5190
|
+
return renderNamespaceRow(namespace, stat);
|
|
5191
|
+
}).join("")}
|
|
5192
|
+
</tbody>
|
|
5193
|
+
</table>
|
|
5194
|
+
</div>
|
|
5195
|
+
</div>
|
|
5196
|
+
|
|
5197
|
+
<!-- Performance Chart Placeholder -->
|
|
5198
|
+
<div class="overflow-hidden rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10">
|
|
5199
|
+
<div class="px-6 py-4 border-b border-zinc-950/5 dark:border-white/10">
|
|
5200
|
+
<h2 class="text-lg font-semibold text-zinc-950 dark:text-white">Performance Overview</h2>
|
|
5201
|
+
</div>
|
|
5202
|
+
<div class="p-6">
|
|
5203
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
5204
|
+
${renderPerformanceMetric("Memory Cache", data.totals.hits, data.totals.misses)}
|
|
5205
|
+
${renderHealthStatus(parseFloat(data.totals.hitRate))}
|
|
5206
|
+
</div>
|
|
5207
|
+
</div>
|
|
5208
|
+
</div>
|
|
5209
|
+
</div>
|
|
5210
|
+
|
|
5211
|
+
<script>
|
|
5212
|
+
async function refreshStats() {
|
|
5213
|
+
window.location.reload()
|
|
5214
|
+
}
|
|
5215
|
+
|
|
5216
|
+
async function clearAllCaches() {
|
|
5217
|
+
showConfirmDialog('clear-all-cache-confirm')
|
|
5218
|
+
}
|
|
5219
|
+
|
|
5220
|
+
async function performClearAllCaches() {
|
|
5221
|
+
try {
|
|
5222
|
+
const response = await fetch('/admin/cache/clear', {
|
|
5223
|
+
method: 'POST'
|
|
5224
|
+
})
|
|
5225
|
+
|
|
5226
|
+
const result = await response.json()
|
|
5227
|
+
if (result.success) {
|
|
5228
|
+
alert('All caches cleared successfully')
|
|
5229
|
+
window.location.reload()
|
|
5230
|
+
} else {
|
|
5231
|
+
alert('Error clearing caches: ' + result.error)
|
|
5232
|
+
}
|
|
5233
|
+
} catch (error) {
|
|
5234
|
+
alert('Error clearing caches: ' + error.message)
|
|
5235
|
+
}
|
|
5236
|
+
}
|
|
5237
|
+
|
|
5238
|
+
let namespaceToDelete = null
|
|
5239
|
+
|
|
5240
|
+
async function clearNamespaceCache(namespace) {
|
|
5241
|
+
namespaceToDelete = namespace
|
|
5242
|
+
showConfirmDialog('clear-namespace-cache-confirm')
|
|
5243
|
+
}
|
|
5244
|
+
|
|
5245
|
+
async function performClearNamespaceCache() {
|
|
5246
|
+
if (!namespaceToDelete) return
|
|
5247
|
+
|
|
5248
|
+
try {
|
|
5249
|
+
const response = await fetch(\`/admin/cache/clear/\${namespaceToDelete}\`, {
|
|
5250
|
+
method: 'POST'
|
|
5251
|
+
})
|
|
5252
|
+
|
|
5253
|
+
const result = await response.json()
|
|
5254
|
+
if (result.success) {
|
|
5255
|
+
alert('Cache cleared successfully')
|
|
5256
|
+
window.location.reload()
|
|
5257
|
+
} else {
|
|
5258
|
+
alert('Error clearing cache: ' + result.error)
|
|
5259
|
+
}
|
|
5260
|
+
} catch (error) {
|
|
5261
|
+
alert('Error clearing cache: ' + error.message)
|
|
5262
|
+
} finally {
|
|
5263
|
+
namespaceToDelete = null
|
|
5264
|
+
}
|
|
5265
|
+
}
|
|
5266
|
+
</script>
|
|
5267
|
+
|
|
5268
|
+
<!-- Confirmation Dialogs -->
|
|
5269
|
+
${chunkYE2MU7CN_cjs.renderConfirmationDialog({
|
|
5270
|
+
id: "clear-all-cache-confirm",
|
|
5271
|
+
title: "Clear All Cache",
|
|
5272
|
+
message: "Are you sure you want to clear all cache entries? This cannot be undone.",
|
|
5273
|
+
confirmText: "Clear All",
|
|
5274
|
+
cancelText: "Cancel",
|
|
5275
|
+
iconColor: "yellow",
|
|
5276
|
+
confirmClass: "bg-yellow-500 hover:bg-yellow-400",
|
|
5277
|
+
onConfirm: "performClearAllCaches()"
|
|
5278
|
+
})}
|
|
5279
|
+
|
|
5280
|
+
${chunkYE2MU7CN_cjs.renderConfirmationDialog({
|
|
5281
|
+
id: "clear-namespace-cache-confirm",
|
|
5282
|
+
title: "Clear Namespace Cache",
|
|
5283
|
+
message: "Clear cache for this namespace?",
|
|
5284
|
+
confirmText: "Clear",
|
|
5285
|
+
cancelText: "Cancel",
|
|
5286
|
+
iconColor: "yellow",
|
|
5287
|
+
confirmClass: "bg-yellow-500 hover:bg-yellow-400",
|
|
5288
|
+
onConfirm: "performClearNamespaceCache()"
|
|
5289
|
+
})}
|
|
5290
|
+
|
|
5291
|
+
${chunkYE2MU7CN_cjs.getConfirmationDialogScript()}
|
|
5292
|
+
`;
|
|
5293
|
+
const layoutData = {
|
|
5294
|
+
title: "Cache System",
|
|
5295
|
+
pageTitle: "Cache System",
|
|
5296
|
+
currentPath: "/admin/cache",
|
|
5297
|
+
user: data.user,
|
|
5298
|
+
version: data.version,
|
|
5299
|
+
content: pageContent
|
|
5300
|
+
};
|
|
5301
|
+
return chunkSHCYIZAN_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
5302
|
+
}
|
|
5303
|
+
function renderStatCard(label, value, color, icon, colorOverride) {
|
|
5304
|
+
const finalColor = colorOverride || color;
|
|
5305
|
+
const colorClasses = {
|
|
5306
|
+
lime: "bg-lime-50 dark:bg-lime-500/10 text-lime-600 dark:text-lime-400 ring-lime-600/20 dark:ring-lime-500/20",
|
|
5307
|
+
blue: "bg-blue-50 dark:bg-blue-500/10 text-blue-600 dark:text-blue-400 ring-blue-600/20 dark:ring-blue-500/20",
|
|
5308
|
+
purple: "bg-purple-50 dark:bg-purple-500/10 text-purple-600 dark:text-purple-400 ring-purple-600/20 dark:ring-purple-500/20",
|
|
5309
|
+
sky: "bg-sky-50 dark:bg-sky-500/10 text-sky-600 dark:text-sky-400 ring-sky-600/20 dark:ring-sky-500/20",
|
|
5310
|
+
amber: "bg-amber-50 dark:bg-amber-500/10 text-amber-600 dark:text-amber-400 ring-amber-600/20 dark:ring-amber-500/20",
|
|
5311
|
+
red: "bg-red-50 dark:bg-red-500/10 text-red-600 dark:text-red-400 ring-red-600/20 dark:ring-red-500/20"
|
|
5312
|
+
};
|
|
5313
|
+
return `
|
|
5314
|
+
<div class="overflow-hidden rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10">
|
|
5315
|
+
<div class="p-6">
|
|
5316
|
+
<div class="flex items-center justify-between">
|
|
5317
|
+
<div class="flex items-center gap-3">
|
|
5318
|
+
<div class="rounded-lg p-2 ring-1 ring-inset ${colorClasses[finalColor]}">
|
|
5319
|
+
${icon}
|
|
5320
|
+
</div>
|
|
5321
|
+
<div>
|
|
5322
|
+
<p class="text-sm text-zinc-600 dark:text-zinc-400">${label}</p>
|
|
5323
|
+
<p class="mt-1 text-2xl font-semibold text-zinc-950 dark:text-white">${value}</p>
|
|
5324
|
+
</div>
|
|
5325
|
+
</div>
|
|
5326
|
+
</div>
|
|
5327
|
+
</div>
|
|
5328
|
+
</div>
|
|
5329
|
+
`;
|
|
5330
|
+
}
|
|
5331
|
+
function renderNamespaceRow(namespace, stat) {
|
|
5332
|
+
const hitRate = stat.hitRate.toFixed(1);
|
|
5333
|
+
const hitRateColor = stat.hitRate > 70 ? "text-lime-600 dark:text-lime-400" : stat.hitRate > 40 ? "text-amber-600 dark:text-amber-400" : "text-red-600 dark:text-red-400";
|
|
5334
|
+
return `
|
|
5335
|
+
<tr class="hover:bg-zinc-50 dark:hover:bg-zinc-800/50">
|
|
5336
|
+
<td class="px-6 py-4 whitespace-nowrap">
|
|
5337
|
+
<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 ring-1 ring-inset ring-zinc-200 dark:ring-zinc-700">
|
|
5338
|
+
${namespace}
|
|
5339
|
+
</span>
|
|
5340
|
+
</td>
|
|
5341
|
+
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-900 dark:text-zinc-100">
|
|
5342
|
+
${stat.totalRequests.toLocaleString()}
|
|
5343
|
+
</td>
|
|
5344
|
+
<td class="px-6 py-4 whitespace-nowrap">
|
|
5345
|
+
<span class="text-sm font-medium ${hitRateColor}">
|
|
5346
|
+
${hitRate}%
|
|
5347
|
+
</span>
|
|
5348
|
+
</td>
|
|
5349
|
+
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400">
|
|
5350
|
+
${stat.memoryHits.toLocaleString()}
|
|
5351
|
+
</td>
|
|
5352
|
+
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400">
|
|
5353
|
+
${stat.kvHits.toLocaleString()}
|
|
5354
|
+
</td>
|
|
5355
|
+
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400">
|
|
5356
|
+
${stat.entryCount.toLocaleString()}
|
|
5357
|
+
</td>
|
|
5358
|
+
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400">
|
|
5359
|
+
${formatBytes(stat.memorySize)}
|
|
5360
|
+
</td>
|
|
5361
|
+
<td class="px-6 py-4 whitespace-nowrap text-right text-sm">
|
|
5362
|
+
<button
|
|
5363
|
+
onclick="clearNamespaceCache('${namespace}')"
|
|
5364
|
+
class="text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300"
|
|
5365
|
+
>
|
|
5366
|
+
Clear
|
|
5367
|
+
</button>
|
|
5368
|
+
</td>
|
|
5369
|
+
</tr>
|
|
5370
|
+
`;
|
|
5371
|
+
}
|
|
5372
|
+
function renderPerformanceMetric(label, hits, misses) {
|
|
5373
|
+
const total = hits + misses;
|
|
5374
|
+
const hitPercentage = total > 0 ? hits / total * 100 : 0;
|
|
5375
|
+
return `
|
|
5376
|
+
<div>
|
|
5377
|
+
<h3 class="text-sm font-medium text-zinc-900 dark:text-zinc-100 mb-3">${label}</h3>
|
|
5378
|
+
<div class="space-y-2">
|
|
5379
|
+
<div class="flex items-center justify-between text-sm">
|
|
5380
|
+
<span class="text-zinc-600 dark:text-zinc-400">Hits</span>
|
|
5381
|
+
<span class="font-medium text-zinc-900 dark:text-zinc-100">${hits.toLocaleString()}</span>
|
|
5382
|
+
</div>
|
|
5383
|
+
<div class="flex items-center justify-between text-sm">
|
|
5384
|
+
<span class="text-zinc-600 dark:text-zinc-400">Misses</span>
|
|
5385
|
+
<span class="font-medium text-zinc-900 dark:text-zinc-100">${misses.toLocaleString()}</span>
|
|
5386
|
+
</div>
|
|
5387
|
+
<div class="mt-3">
|
|
5388
|
+
<div class="flex items-center justify-between text-sm mb-1">
|
|
5389
|
+
<span class="text-zinc-600 dark:text-zinc-400">Hit Rate</span>
|
|
5390
|
+
<span class="font-medium text-zinc-900 dark:text-zinc-100">${hitPercentage.toFixed(1)}%</span>
|
|
5391
|
+
</div>
|
|
5392
|
+
<div class="h-2 bg-zinc-200 dark:bg-zinc-700 rounded-full overflow-hidden">
|
|
5393
|
+
<div class="h-full bg-lime-500 dark:bg-lime-400" style="width: ${hitPercentage}%"></div>
|
|
5394
|
+
</div>
|
|
5395
|
+
</div>
|
|
5396
|
+
</div>
|
|
5397
|
+
</div>
|
|
5398
|
+
`;
|
|
5399
|
+
}
|
|
5400
|
+
function renderHealthStatus(hitRate) {
|
|
5401
|
+
const status = hitRate > 70 ? "healthy" : hitRate > 40 ? "warning" : "critical";
|
|
5402
|
+
const statusConfig = {
|
|
5403
|
+
healthy: {
|
|
5404
|
+
label: "Healthy",
|
|
5405
|
+
color: "lime",
|
|
5406
|
+
icon: `<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
5407
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
5408
|
+
</svg>`
|
|
5409
|
+
},
|
|
5410
|
+
warning: {
|
|
5411
|
+
label: "Needs Attention",
|
|
5412
|
+
color: "amber",
|
|
5413
|
+
icon: `<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
5414
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
|
|
5415
|
+
</svg>`
|
|
5416
|
+
},
|
|
5417
|
+
critical: {
|
|
5418
|
+
label: "Critical",
|
|
5419
|
+
color: "red",
|
|
5420
|
+
icon: `<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
5421
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
5422
|
+
</svg>`
|
|
5423
|
+
}
|
|
5424
|
+
};
|
|
5425
|
+
const config = statusConfig[status];
|
|
5426
|
+
const colorClasses = {
|
|
5427
|
+
lime: "bg-lime-50 dark:bg-lime-500/10 text-lime-600 dark:text-lime-400 ring-lime-600/20 dark:ring-lime-500/20",
|
|
5428
|
+
amber: "bg-amber-50 dark:bg-amber-500/10 text-amber-600 dark:text-amber-400 ring-amber-600/20 dark:ring-amber-500/20",
|
|
5429
|
+
red: "bg-red-50 dark:bg-red-500/10 text-red-600 dark:text-red-400 ring-red-600/20 dark:ring-red-500/20"
|
|
5430
|
+
};
|
|
5431
|
+
return `
|
|
5432
|
+
<div>
|
|
5433
|
+
<h3 class="text-sm font-medium text-zinc-900 dark:text-zinc-100 mb-3">System Health</h3>
|
|
5434
|
+
<div class="flex items-center gap-3 p-4 rounded-lg ring-1 ring-inset ${colorClasses[config.color]}">
|
|
5435
|
+
${config.icon}
|
|
5436
|
+
<div>
|
|
5437
|
+
<p class="text-sm font-medium">${config.label}</p>
|
|
5438
|
+
<p class="text-xs mt-0.5 opacity-80">
|
|
5439
|
+
${status === "healthy" ? "Cache is performing well" : status === "warning" ? "Consider increasing cache TTL or capacity" : "Cache hit rate is too low"}
|
|
5440
|
+
</p>
|
|
5441
|
+
</div>
|
|
5442
|
+
</div>
|
|
5443
|
+
</div>
|
|
5444
|
+
`;
|
|
5445
|
+
}
|
|
5446
|
+
function formatBytes(bytes) {
|
|
5447
|
+
if (bytes === 0) return "0 B";
|
|
5448
|
+
const k = 1024;
|
|
5449
|
+
const sizes = ["B", "KB", "MB", "GB"];
|
|
5450
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
5451
|
+
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
|
|
5452
|
+
}
|
|
5453
|
+
|
|
5454
|
+
// src/plugins/cache/routes.ts
|
|
5455
|
+
var app = new hono.Hono();
|
|
5456
|
+
app.get("/", async (c) => {
|
|
5457
|
+
const stats = getAllCacheStats();
|
|
5458
|
+
const user = c.get("user");
|
|
5459
|
+
let totalHits = 0;
|
|
5460
|
+
let totalMisses = 0;
|
|
5461
|
+
let totalSize = 0;
|
|
5462
|
+
let totalEntries = 0;
|
|
5463
|
+
Object.values(stats).forEach((stat) => {
|
|
5464
|
+
totalHits += stat.memoryHits + stat.kvHits;
|
|
5465
|
+
totalMisses += stat.memoryMisses + stat.kvMisses;
|
|
5466
|
+
totalSize += stat.memorySize;
|
|
5467
|
+
totalEntries += stat.entryCount;
|
|
5468
|
+
});
|
|
5469
|
+
const totalRequests = totalHits + totalMisses;
|
|
5470
|
+
const overallHitRate = totalRequests > 0 ? totalHits / totalRequests * 100 : 0;
|
|
5471
|
+
const dashboardData = {
|
|
5472
|
+
stats,
|
|
5473
|
+
totals: {
|
|
5474
|
+
hits: totalHits,
|
|
5475
|
+
misses: totalMisses,
|
|
5476
|
+
requests: totalRequests,
|
|
5477
|
+
hitRate: overallHitRate.toFixed(2),
|
|
5478
|
+
memorySize: totalSize,
|
|
5479
|
+
entryCount: totalEntries
|
|
5480
|
+
},
|
|
5481
|
+
namespaces: Object.keys(stats),
|
|
5482
|
+
user: user ? {
|
|
5483
|
+
name: user.email,
|
|
5484
|
+
email: user.email,
|
|
5485
|
+
role: user.role
|
|
5486
|
+
} : void 0,
|
|
5487
|
+
version: c.get("appVersion")
|
|
5488
|
+
};
|
|
5489
|
+
return c.html(renderCacheDashboard(dashboardData));
|
|
5490
|
+
});
|
|
5491
|
+
app.get("/stats", async (c) => {
|
|
5492
|
+
const stats = getAllCacheStats();
|
|
5493
|
+
return c.json({
|
|
5494
|
+
success: true,
|
|
5495
|
+
data: stats,
|
|
5496
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5497
|
+
});
|
|
5498
|
+
});
|
|
5499
|
+
app.get("/stats/:namespace", async (c) => {
|
|
5500
|
+
const namespace = c.req.param("namespace");
|
|
5501
|
+
const config = CACHE_CONFIGS[namespace];
|
|
5502
|
+
if (!config) {
|
|
5503
|
+
return c.json({
|
|
5504
|
+
success: false,
|
|
5505
|
+
error: `Unknown namespace: ${namespace}`
|
|
5506
|
+
}, 404);
|
|
5507
|
+
}
|
|
5508
|
+
const cache = getCacheService(config);
|
|
5509
|
+
const stats = cache.getStats();
|
|
5510
|
+
return c.json({
|
|
5511
|
+
success: true,
|
|
5512
|
+
data: {
|
|
5513
|
+
namespace,
|
|
5514
|
+
config,
|
|
5515
|
+
stats
|
|
5516
|
+
},
|
|
5517
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5518
|
+
});
|
|
5519
|
+
});
|
|
5520
|
+
app.post("/clear", async (c) => {
|
|
5521
|
+
await clearAllCaches();
|
|
5522
|
+
return c.json({
|
|
5523
|
+
success: true,
|
|
5524
|
+
message: "All cache entries cleared",
|
|
5525
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5526
|
+
});
|
|
5527
|
+
});
|
|
5528
|
+
app.post("/clear/:namespace", async (c) => {
|
|
5529
|
+
const namespace = c.req.param("namespace");
|
|
5530
|
+
const config = CACHE_CONFIGS[namespace];
|
|
5531
|
+
if (!config) {
|
|
5532
|
+
return c.json({
|
|
5533
|
+
success: false,
|
|
5534
|
+
error: `Unknown namespace: ${namespace}`
|
|
5535
|
+
}, 404);
|
|
5536
|
+
}
|
|
5537
|
+
const cache = getCacheService(config);
|
|
5538
|
+
await cache.clear();
|
|
5539
|
+
return c.json({
|
|
5540
|
+
success: true,
|
|
5541
|
+
message: `Cache cleared for namespace: ${namespace}`,
|
|
5542
|
+
namespace,
|
|
5543
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5544
|
+
});
|
|
5545
|
+
});
|
|
5546
|
+
app.post("/invalidate", async (c) => {
|
|
5547
|
+
const body = await c.req.json();
|
|
5548
|
+
const { pattern, namespace } = body;
|
|
5549
|
+
if (!pattern) {
|
|
5550
|
+
return c.json({
|
|
5551
|
+
success: false,
|
|
5552
|
+
error: "Pattern is required"
|
|
5553
|
+
}, 400);
|
|
5554
|
+
}
|
|
5555
|
+
let totalInvalidated = 0;
|
|
5556
|
+
if (namespace) {
|
|
5557
|
+
const config = CACHE_CONFIGS[namespace];
|
|
5558
|
+
if (!config) {
|
|
5559
|
+
return c.json({
|
|
5560
|
+
success: false,
|
|
5561
|
+
error: `Unknown namespace: ${namespace}`
|
|
5562
|
+
}, 404);
|
|
5563
|
+
}
|
|
5564
|
+
const cache = getCacheService(config);
|
|
5565
|
+
totalInvalidated = await cache.invalidate(pattern);
|
|
5566
|
+
} else {
|
|
5567
|
+
for (const config of Object.values(CACHE_CONFIGS)) {
|
|
5568
|
+
const cache = getCacheService(config);
|
|
5569
|
+
totalInvalidated += await cache.invalidate(pattern);
|
|
5570
|
+
}
|
|
5571
|
+
}
|
|
5572
|
+
return c.json({
|
|
5573
|
+
success: true,
|
|
5574
|
+
invalidated: totalInvalidated,
|
|
5575
|
+
pattern,
|
|
5576
|
+
namespace: namespace || "all",
|
|
5577
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5578
|
+
});
|
|
5579
|
+
});
|
|
5580
|
+
app.get("/health", async (c) => {
|
|
5581
|
+
const stats = getAllCacheStats();
|
|
5582
|
+
const namespaces = Object.entries(stats);
|
|
5583
|
+
const healthChecks = namespaces.map(([name, stat]) => {
|
|
5584
|
+
const hitRate = stat.hitRate;
|
|
5585
|
+
const memoryUsage = stat.memorySize / (50 * 1024 * 1024);
|
|
5586
|
+
return {
|
|
5587
|
+
namespace: name,
|
|
5588
|
+
status: hitRate > 70 ? "healthy" : hitRate > 40 ? "warning" : "unhealthy",
|
|
5589
|
+
hitRate,
|
|
5590
|
+
memoryUsage: (memoryUsage * 100).toFixed(2) + "%",
|
|
5591
|
+
entryCount: stat.entryCount
|
|
5592
|
+
};
|
|
5593
|
+
});
|
|
5594
|
+
const overallStatus = healthChecks.every((h) => h.status === "healthy") ? "healthy" : healthChecks.some((h) => h.status === "unhealthy") ? "unhealthy" : "warning";
|
|
5595
|
+
return c.json({
|
|
5596
|
+
success: true,
|
|
5597
|
+
data: {
|
|
5598
|
+
status: overallStatus,
|
|
5599
|
+
namespaces: healthChecks,
|
|
5600
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5601
|
+
}
|
|
5602
|
+
});
|
|
5603
|
+
});
|
|
5604
|
+
app.get("/browser", async (c) => {
|
|
5605
|
+
const namespace = c.req.query("namespace") || "all";
|
|
5606
|
+
const search = c.req.query("search") || "";
|
|
5607
|
+
const sortBy = c.req.query("sort") || "age";
|
|
5608
|
+
const limit = parseInt(c.req.query("limit") || "100");
|
|
5609
|
+
const entries = [];
|
|
5610
|
+
const namespaces = namespace === "all" ? Object.keys(CACHE_CONFIGS) : [namespace];
|
|
5611
|
+
for (const ns of namespaces) {
|
|
5612
|
+
const config = CACHE_CONFIGS[ns];
|
|
5613
|
+
if (!config) continue;
|
|
5614
|
+
const cache = getCacheService(config);
|
|
5615
|
+
const keys = await cache.listKeys();
|
|
5616
|
+
for (const keyInfo of keys) {
|
|
5617
|
+
if (search && !keyInfo.key.toLowerCase().includes(search.toLowerCase())) {
|
|
5618
|
+
continue;
|
|
5619
|
+
}
|
|
5620
|
+
const parsed = parseCacheKey(keyInfo.key);
|
|
5621
|
+
const ttl = Math.max(0, keyInfo.expiresAt - Date.now()) / 1e3;
|
|
5622
|
+
entries.push({
|
|
5623
|
+
namespace: ns,
|
|
5624
|
+
key: keyInfo.key,
|
|
5625
|
+
size: keyInfo.size,
|
|
5626
|
+
age: keyInfo.age,
|
|
5627
|
+
ttl,
|
|
5628
|
+
expiresAt: keyInfo.expiresAt,
|
|
5629
|
+
parsed
|
|
5630
|
+
});
|
|
5631
|
+
}
|
|
5632
|
+
}
|
|
5633
|
+
if (sortBy === "size") {
|
|
5634
|
+
entries.sort((a, b) => b.size - a.size);
|
|
5635
|
+
} else if (sortBy === "age") {
|
|
5636
|
+
entries.sort((a, b) => a.age - b.age);
|
|
5637
|
+
} else if (sortBy === "key") {
|
|
5638
|
+
entries.sort((a, b) => a.key.localeCompare(b.key));
|
|
5639
|
+
}
|
|
5640
|
+
const limitedEntries = entries.slice(0, limit);
|
|
5641
|
+
return c.json({
|
|
5642
|
+
success: true,
|
|
5643
|
+
data: {
|
|
5644
|
+
entries: limitedEntries,
|
|
5645
|
+
total: entries.length,
|
|
5646
|
+
showing: limitedEntries.length,
|
|
5647
|
+
namespace,
|
|
5648
|
+
search,
|
|
5649
|
+
sortBy
|
|
5650
|
+
},
|
|
5651
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5652
|
+
});
|
|
5653
|
+
});
|
|
5654
|
+
app.get("/browser/:namespace/:key", async (c) => {
|
|
5655
|
+
const namespace = c.req.param("namespace");
|
|
5656
|
+
const key = decodeURIComponent(c.req.param("key"));
|
|
5657
|
+
const config = CACHE_CONFIGS[namespace];
|
|
5658
|
+
if (!config) {
|
|
5659
|
+
return c.json({
|
|
5660
|
+
success: false,
|
|
5661
|
+
error: `Unknown namespace: ${namespace}`
|
|
5662
|
+
}, 404);
|
|
5663
|
+
}
|
|
5664
|
+
const cache = getCacheService(config);
|
|
5665
|
+
const entry = await cache.getEntry(key);
|
|
5666
|
+
if (!entry) {
|
|
5667
|
+
return c.json({
|
|
5668
|
+
success: false,
|
|
5669
|
+
error: "Cache entry not found or expired"
|
|
5670
|
+
}, 404);
|
|
5671
|
+
}
|
|
5672
|
+
const parsed = parseCacheKey(key);
|
|
5673
|
+
return c.json({
|
|
5674
|
+
success: true,
|
|
5675
|
+
data: {
|
|
5676
|
+
key,
|
|
5677
|
+
namespace,
|
|
5678
|
+
parsed,
|
|
5679
|
+
...entry,
|
|
5680
|
+
createdAt: new Date(entry.timestamp).toISOString(),
|
|
5681
|
+
expiresAt: new Date(entry.expiresAt).toISOString()
|
|
5682
|
+
},
|
|
5683
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5684
|
+
});
|
|
5685
|
+
});
|
|
5686
|
+
app.get("/analytics", async (c) => {
|
|
5687
|
+
const stats = getAllCacheStats();
|
|
5688
|
+
const invalidationStats = getCacheInvalidationStats();
|
|
5689
|
+
const recentInvalidations = getRecentInvalidations(20);
|
|
5690
|
+
let totalHits = 0;
|
|
5691
|
+
let totalMisses = 0;
|
|
5692
|
+
let totalSize = 0;
|
|
5693
|
+
let totalEntries = 0;
|
|
5694
|
+
const namespacesAnalytics = [];
|
|
5695
|
+
for (const [namespace, stat] of Object.entries(stats)) {
|
|
5696
|
+
totalHits += stat.memoryHits + stat.kvHits;
|
|
5697
|
+
totalMisses += stat.memoryMisses + stat.kvMisses;
|
|
5698
|
+
totalSize += stat.memorySize;
|
|
5699
|
+
totalEntries += stat.entryCount;
|
|
5700
|
+
const totalRequests2 = stat.memoryHits + stat.kvHits + stat.memoryMisses + stat.kvMisses;
|
|
5701
|
+
const hitRate = totalRequests2 > 0 ? (stat.memoryHits + stat.kvHits) / totalRequests2 * 100 : 0;
|
|
5702
|
+
const avgEntrySize = stat.entryCount > 0 ? stat.memorySize / stat.entryCount : 0;
|
|
5703
|
+
namespacesAnalytics.push({
|
|
5704
|
+
namespace,
|
|
5705
|
+
hitRate: hitRate.toFixed(2),
|
|
5706
|
+
totalRequests: totalRequests2,
|
|
5707
|
+
memoryHitRate: totalRequests2 > 0 ? (stat.memoryHits / totalRequests2 * 100).toFixed(2) : "0",
|
|
5708
|
+
kvHitRate: totalRequests2 > 0 ? (stat.kvHits / totalRequests2 * 100).toFixed(2) : "0",
|
|
5709
|
+
avgEntrySize: Math.round(avgEntrySize),
|
|
5710
|
+
totalSize: stat.memorySize,
|
|
5711
|
+
entryCount: stat.entryCount,
|
|
5712
|
+
efficiency: totalRequests2 > 0 ? ((stat.memoryHits + stat.kvHits) / (stat.memoryHits + stat.kvHits + stat.dbHits + 1)).toFixed(2) : "0"
|
|
5713
|
+
});
|
|
5714
|
+
}
|
|
5715
|
+
namespacesAnalytics.sort((a, b) => parseFloat(b.hitRate) - parseFloat(a.hitRate));
|
|
5716
|
+
const totalRequests = totalHits + totalMisses;
|
|
5717
|
+
const overallHitRate = totalRequests > 0 ? totalHits / totalRequests * 100 : 0;
|
|
5718
|
+
const dbQueriesAvoided = totalHits;
|
|
5719
|
+
const timeSaved = dbQueriesAvoided * 48;
|
|
5720
|
+
const estimatedCostSavings = dbQueriesAvoided / 1e6 * 0.5;
|
|
5721
|
+
return c.json({
|
|
5722
|
+
success: true,
|
|
5723
|
+
data: {
|
|
5724
|
+
overview: {
|
|
5725
|
+
totalHits,
|
|
5726
|
+
totalMisses,
|
|
5727
|
+
totalRequests,
|
|
5728
|
+
overallHitRate: overallHitRate.toFixed(2),
|
|
5729
|
+
totalSize,
|
|
5730
|
+
totalEntries,
|
|
5731
|
+
avgEntrySize: totalEntries > 0 ? Math.round(totalSize / totalEntries) : 0
|
|
5732
|
+
},
|
|
5733
|
+
performance: {
|
|
5734
|
+
dbQueriesAvoided,
|
|
5735
|
+
timeSavedMs: timeSaved,
|
|
5736
|
+
timeSavedMinutes: (timeSaved / 1e3 / 60).toFixed(2),
|
|
5737
|
+
estimatedCostSavings: estimatedCostSavings.toFixed(4)
|
|
5738
|
+
},
|
|
5739
|
+
namespaces: namespacesAnalytics,
|
|
5740
|
+
invalidation: {
|
|
5741
|
+
...invalidationStats,
|
|
5742
|
+
recent: recentInvalidations
|
|
5743
|
+
}
|
|
5744
|
+
},
|
|
5745
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5746
|
+
});
|
|
5747
|
+
});
|
|
5748
|
+
app.get("/analytics/trends", async (c) => {
|
|
5749
|
+
const stats = getAllCacheStats();
|
|
5750
|
+
const dataPoint = {
|
|
5751
|
+
timestamp: Date.now(),
|
|
5752
|
+
stats: Object.entries(stats).map(([namespace, stat]) => ({
|
|
5753
|
+
namespace,
|
|
5754
|
+
hitRate: stat.hitRate,
|
|
5755
|
+
entryCount: stat.entryCount,
|
|
5756
|
+
memorySize: stat.memorySize,
|
|
5757
|
+
totalRequests: stat.totalRequests
|
|
5758
|
+
}))
|
|
5759
|
+
};
|
|
5760
|
+
return c.json({
|
|
5761
|
+
success: true,
|
|
5762
|
+
data: {
|
|
5763
|
+
trends: [dataPoint],
|
|
5764
|
+
note: "Historical trends require persistent storage. This returns current snapshot only."
|
|
5765
|
+
},
|
|
5766
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5767
|
+
});
|
|
5768
|
+
});
|
|
5769
|
+
app.get("/analytics/top-keys", async (c) => {
|
|
5770
|
+
c.req.query("namespace") || "all";
|
|
5771
|
+
parseInt(c.req.query("limit") || "10");
|
|
5772
|
+
return c.json({
|
|
5773
|
+
success: true,
|
|
5774
|
+
data: {
|
|
5775
|
+
topKeys: [],
|
|
5776
|
+
note: "Top keys tracking requires per-key hit counting. Feature not yet implemented."
|
|
5777
|
+
},
|
|
5778
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5779
|
+
});
|
|
5780
|
+
});
|
|
5781
|
+
app.post("/warm", async (c) => {
|
|
5782
|
+
try {
|
|
5783
|
+
const db = c.env.DB;
|
|
5784
|
+
const result = await warmCommonCaches(db);
|
|
5785
|
+
return c.json({
|
|
5786
|
+
success: true,
|
|
5787
|
+
message: "Cache warming completed",
|
|
5788
|
+
...result,
|
|
5789
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5790
|
+
});
|
|
5791
|
+
} catch (error) {
|
|
5792
|
+
console.error("Cache warming error:", error);
|
|
5793
|
+
return c.json({
|
|
5794
|
+
success: false,
|
|
5795
|
+
error: "Cache warming failed",
|
|
5796
|
+
details: error instanceof Error ? error.message : "Unknown error"
|
|
5797
|
+
}, 500);
|
|
5798
|
+
}
|
|
5799
|
+
});
|
|
5800
|
+
app.post("/warm/:namespace", async (c) => {
|
|
5801
|
+
try {
|
|
5802
|
+
const namespace = c.req.param("namespace");
|
|
5803
|
+
const body = await c.req.json();
|
|
5804
|
+
const { entries } = body;
|
|
5805
|
+
if (!entries || !Array.isArray(entries)) {
|
|
5806
|
+
return c.json({
|
|
5807
|
+
success: false,
|
|
5808
|
+
error: "Entries array is required"
|
|
5809
|
+
}, 400);
|
|
5810
|
+
}
|
|
5811
|
+
const count = await warmNamespace(namespace, entries);
|
|
5812
|
+
return c.json({
|
|
5813
|
+
success: true,
|
|
5814
|
+
message: `Warmed ${count} entries in namespace: ${namespace}`,
|
|
5815
|
+
namespace,
|
|
5816
|
+
count,
|
|
5817
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5818
|
+
});
|
|
5819
|
+
} catch (error) {
|
|
5820
|
+
console.error("Namespace warming error:", error);
|
|
5821
|
+
return c.json({
|
|
5822
|
+
success: false,
|
|
5823
|
+
error: "Namespace warming failed",
|
|
5824
|
+
details: error instanceof Error ? error.message : "Unknown error"
|
|
5825
|
+
}, 500);
|
|
5826
|
+
}
|
|
5827
|
+
});
|
|
5828
|
+
var routes_default = app;
|
|
5829
|
+
|
|
5830
|
+
// src/plugins/cache/index.ts
|
|
5831
|
+
var CachePlugin = class {
|
|
5832
|
+
_context = null;
|
|
5833
|
+
/**
|
|
5834
|
+
* Get plugin routes
|
|
5835
|
+
*/
|
|
5836
|
+
getRoutes() {
|
|
5837
|
+
return routes_default;
|
|
5838
|
+
}
|
|
5839
|
+
/**
|
|
5840
|
+
* Activate the cache plugin
|
|
5841
|
+
*/
|
|
5842
|
+
async activate(context) {
|
|
5843
|
+
this._context = context;
|
|
5844
|
+
const settings = context.config || {};
|
|
5845
|
+
console.log("\u2705 Cache plugin activated", {
|
|
5846
|
+
memoryEnabled: settings.memoryEnabled ?? true,
|
|
5847
|
+
kvEnabled: settings.kvEnabled ?? false,
|
|
5848
|
+
defaultTTL: settings.defaultTTL ?? 3600
|
|
5849
|
+
});
|
|
5850
|
+
for (const [_namespace, config] of Object.entries(CACHE_CONFIGS)) {
|
|
5851
|
+
getCacheService({
|
|
5852
|
+
...config,
|
|
5853
|
+
memoryEnabled: settings.memoryEnabled ?? config.memoryEnabled,
|
|
5854
|
+
kvEnabled: settings.kvEnabled ?? config.kvEnabled,
|
|
5855
|
+
ttl: settings.defaultTTL ?? config.ttl
|
|
5856
|
+
});
|
|
5857
|
+
}
|
|
5858
|
+
setupCacheInvalidation();
|
|
5859
|
+
}
|
|
5860
|
+
/**
|
|
5861
|
+
* Deactivate the cache plugin
|
|
5862
|
+
*/
|
|
5863
|
+
async deactivate() {
|
|
5864
|
+
console.log("\u274C Cache plugin deactivated - clearing all caches");
|
|
5865
|
+
await clearAllCaches();
|
|
5866
|
+
this._context = null;
|
|
5867
|
+
}
|
|
5868
|
+
/**
|
|
5869
|
+
* Configure the cache plugin
|
|
5870
|
+
*/
|
|
5871
|
+
async configure(settings) {
|
|
5872
|
+
console.log("\u2699\uFE0F Cache plugin configured", settings);
|
|
5873
|
+
for (const [_namespace, config] of Object.entries(CACHE_CONFIGS)) {
|
|
5874
|
+
getCacheService({
|
|
5875
|
+
...config,
|
|
5876
|
+
memoryEnabled: settings.memoryEnabled ?? config.memoryEnabled,
|
|
5877
|
+
kvEnabled: settings.kvEnabled ?? config.kvEnabled,
|
|
5878
|
+
ttl: settings.defaultTTL ?? config.ttl
|
|
5879
|
+
});
|
|
5880
|
+
}
|
|
5881
|
+
}
|
|
5882
|
+
/**
|
|
5883
|
+
* Get cache statistics
|
|
5884
|
+
*/
|
|
5885
|
+
async getStats(c) {
|
|
5886
|
+
const stats = getAllCacheStats();
|
|
5887
|
+
return c.json({
|
|
5888
|
+
success: true,
|
|
5889
|
+
data: stats,
|
|
5890
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5891
|
+
});
|
|
5892
|
+
}
|
|
5893
|
+
/**
|
|
5894
|
+
* Clear all cache entries
|
|
5895
|
+
*/
|
|
5896
|
+
async clearCache(c) {
|
|
5897
|
+
await clearAllCaches();
|
|
5898
|
+
return c.json({
|
|
5899
|
+
success: true,
|
|
5900
|
+
message: "All cache entries cleared",
|
|
5901
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5902
|
+
});
|
|
5903
|
+
}
|
|
5904
|
+
/**
|
|
5905
|
+
* Invalidate cache entries matching pattern
|
|
5906
|
+
*/
|
|
5907
|
+
async invalidatePattern(c) {
|
|
5908
|
+
const body = await c.req.json();
|
|
5909
|
+
const { pattern, namespace: _namespace } = body;
|
|
5910
|
+
if (!pattern) {
|
|
5911
|
+
return c.json({
|
|
5912
|
+
success: false,
|
|
5913
|
+
error: "Pattern is required"
|
|
5914
|
+
}, 400);
|
|
5915
|
+
}
|
|
5916
|
+
let totalInvalidated = 0;
|
|
5917
|
+
if (_namespace) {
|
|
5918
|
+
const cache = getCacheService(CACHE_CONFIGS[_namespace] || {
|
|
5919
|
+
ttl: 3600,
|
|
5920
|
+
kvEnabled: false,
|
|
5921
|
+
memoryEnabled: true,
|
|
5922
|
+
namespace: _namespace,
|
|
5923
|
+
invalidateOn: [],
|
|
5924
|
+
version: "v1"
|
|
5925
|
+
});
|
|
5926
|
+
totalInvalidated = await cache.invalidate(pattern);
|
|
5927
|
+
} else {
|
|
5928
|
+
for (const config of Object.values(CACHE_CONFIGS)) {
|
|
5929
|
+
const cache = getCacheService(config);
|
|
5930
|
+
totalInvalidated += await cache.invalidate(pattern);
|
|
5931
|
+
}
|
|
5932
|
+
}
|
|
5933
|
+
return c.json({
|
|
5934
|
+
success: true,
|
|
5935
|
+
invalidated: totalInvalidated,
|
|
5936
|
+
pattern,
|
|
5937
|
+
namespace: _namespace || "all",
|
|
5938
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
5939
|
+
});
|
|
5940
|
+
}
|
|
5941
|
+
};
|
|
5942
|
+
var plugin = new CachePlugin();
|
|
5943
|
+
var cache_default = plugin;
|
|
5944
|
+
|
|
5945
|
+
// src/assets/favicon.ts
|
|
5946
|
+
var faviconSvg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
5947
|
+
<svg
|
|
5948
|
+
version="1.1"
|
|
5949
|
+
id="Layer_1"
|
|
5950
|
+
x="0px"
|
|
5951
|
+
y="0px"
|
|
5952
|
+
viewBox="380 1300 257.89001 278.8855"
|
|
5953
|
+
xml:space="preserve"
|
|
5954
|
+
width="257.89001"
|
|
5955
|
+
height="278.8855"
|
|
5956
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
5957
|
+
<g
|
|
5958
|
+
id="g10"
|
|
5959
|
+
transform="translate(-383.935,-60.555509)">
|
|
5960
|
+
<g
|
|
5961
|
+
id="g9">
|
|
5962
|
+
<path
|
|
5963
|
+
fill="#f1f2f2"
|
|
5964
|
+
d="m 974.78,1398.211 c -5.016,6.574 -10.034,13.146 -15.048,19.721 -1.828,2.398 -3.657,4.796 -5.487,7.194 1.994,1.719 3.958,3.51 5.873,5.424 18.724,18.731 28.089,41.216 28.089,67.459 0,26.251 -9.366,48.658 -28.089,67.237 -18.731,18.579 -41.215,27.868 -67.459,27.868 -9.848,0 -19.156,-1.308 -27.923,-3.923 l -4.185,3.354 c -8.587,6.885 -17.154,13.796 -25.725,20.702 17.52,8.967 36.86,13.487 58.054,13.487 35.533,0 65.91,-12.608 91.124,-37.821 25.214,-25.215 37.821,-55.584 37.821,-91.125 0,-35.534 -12.607,-65.911 -37.821,-91.126 -3,-2.999 -6.078,-5.808 -9.224,-8.451 z"
|
|
5965
|
+
id="path2" />
|
|
5966
|
+
<path
|
|
5967
|
+
fill="#34d399"
|
|
5968
|
+
d="m 854.024,1585.195 20.001,-16.028 c 16.616,-13.507 33.04,-27.265 50.086,-40.251 1.13,-0.861 2.9,-1.686 2.003,-3.516 -0.843,-1.716 -2.481,-2.302 -4.484,-2.123 -8.514,0.765 -17.016,-0.538 -25.537,-0.353 -1.124,0.024 -2.768,0.221 -3.163,-1.25 -0.371,-1.369 1.088,-2.063 1.919,-2.894 6.26,-6.242 12.574,-12.43 18.816,-18.691 9.303,-9.327 18.565,-18.714 27.851,-28.066 1.848,-1.859 3.701,-3.713 5.549,-5.572 2.655,-2.661 5.309,-5.315 7.958,-7.982 0.574,-0.579 1.259,-1.141 1.246,-1.94 -0.004,-0.257 -0.078,-0.538 -0.254,-0.853 -0.556,-0.981 -1.441,-1.1 -2.469,-0.957 -0.658,0.096 -1.315,0.185 -1.973,0.275 -3.844,0.538 -7.689,1.076 -11.533,1.608 -3.641,0.505 -7.281,1.02 -10.922,1.529 -4.162,0.582 -8.324,1.158 -12.486,1.748 -1.142,0.161 -2.409,1.662 -3.354,0.508 -0.419,-0.508 -0.431,-1.028 -0.251,-1.531 0.269,-0.741 0.957,-1.441 1.387,-2.021 3.414,-4.58 6.882,-9.124 10.356,-13.662 1.74,-2.272 3.48,-4.544 5.214,-6.822 4.682,-6.141 9.369,-12.281 14.051,-18.422 0.09,-0.119 0.181,-0.237 0.271,-0.355 6.848,-8.98 13.7,-17.958 20.553,-26.936 0.488,-0.64 0.977,-1.28 1.465,-1.92 2.159,-2.828 4.315,-5.658 6.476,-8.486 4.197,-5.501 8.454,-10.954 12.67,-16.442 0.263,-0.347 0.538,-0.718 0.717,-1.106 0.269,-0.586 0.299,-1.196 -0.335,-1.776 -0.825,-0.753 -1.8,-0.15 -2.595,0.419 -0.67,0.472 -1.333,0.957 -1.955,1.489 -2.206,1.889 -4.401,3.797 -6.595,5.698 -3.958,3.438 -7.922,6.876 -11.976,10.194 -2.443,2.003 -4.865,4.028 -7.301,6.038 -18.689,-10.581 -39.53,-15.906 -62.549,-15.906 -35.54,0 -65.911,12.607 -91.125,37.82 -25.214,25.215 -37.821,55.592 -37.821,91.126 0,35.54 12.607,65.91 37.821,91.125 4.146,4.146 8.445,7.916 12.87,11.381 -9.015,11.14 -18.036,22.277 -27.034,33.429 -1.208,1.489 -3.755,3.151 -2.745,4.891 0.078,0.144 0.173,0.281 0.305,0.425 1.321,1.429 3.492,-1.303 4.933,-2.457 6.673,-5.333 13.333,-10.685 19.982,-16.042 3.707,-2.984 7.417,-5.965 11.124,-8.952 1.474,-1.188 2.951,-2.373 4.425,-3.561 6.41,-5.164 12.816,-10.333 19.238,-15.481 z m -56.472,-87.186 c 0,-26.243 9.29,-48.728 27.868,-67.459 18.579,-18.723 40.987,-28.089 67.238,-28.089 12.273,0 23.712,2.075 34.34,6.171 -3.37,2.905 -6.734,5.816 -10.069,8.762 -6.075,5.351 -12.365,10.469 -18.667,15.564 -4.179,3.378 -8.371,6.744 -12.514,10.164 -7.54,6.23 -15.037,12.52 -22.529,18.804 -7.091,5.955 -14.182,11.904 -21.19,17.949 -1.136,0.974 -3.055,1.907 -2.135,3.94 0.831,1.836 2.774,1.417 4.341,1.578 l 12.145,-0.599 14.151,-0.698 c 1.031,-0.102 2.192,-0.257 2.89,0.632 0.034,0.044 0.073,0.078 0.106,0.127 1.017,1.561 -0.67,2.105 -1.387,2.942 -6.308,7.318 -12.616,14.637 -18.978,21.907 -8.161,9.339 -16.353,18.649 -24.544,27.958 -2.146,2.433 -4.275,4.879 -6.422,7.312 -1.034,1.172 -2.129,2.272 -1.238,3.922 0.933,1.728 2.685,1.752 4.323,1.602 4.134,-0.367 8.263,-0.489 12.396,-0.492 0.242,0 0.485,-0.01 0.728,0 2.711,0.01 5.422,0.068 8.134,0.145 2.582,0.074 5.166,0.165 7.752,0.249 0.275,1.62 -0.879,2.356 -1.62,3.259 -1.333,1.626 -2.667,3.247 -4,4.867 -4.315,5.252 -8.62,10.514 -12.928,15.772 -3.562,-2.725 -7.007,-5.733 -10.324,-9.051 -18.577,-18.576 -27.867,-40.983 -27.867,-67.234 z"
|
|
5969
|
+
id="path9" />
|
|
5970
|
+
</g>
|
|
5971
|
+
</g>
|
|
5972
|
+
</svg>`;
|
|
5973
|
+
|
|
5974
|
+
// src/app.ts
|
|
5975
|
+
function createSonicJSApp(config = {}) {
|
|
5976
|
+
const app2 = new hono.Hono();
|
|
5977
|
+
const appVersion = config.version || chunk5HMR2SJW_cjs.getCoreVersion();
|
|
5978
|
+
const appName = config.name || "SonicJS AI";
|
|
5979
|
+
app2.use("*", async (c, next) => {
|
|
5980
|
+
c.set("appVersion", appVersion);
|
|
5981
|
+
await next();
|
|
5982
|
+
});
|
|
5983
|
+
app2.use("*", chunkGPTMGUFN_cjs.metricsMiddleware());
|
|
5984
|
+
app2.use("*", chunkGPTMGUFN_cjs.bootstrapMiddleware(config));
|
|
5985
|
+
if (config.middleware?.beforeAuth) {
|
|
5986
|
+
for (const middleware of config.middleware.beforeAuth) {
|
|
5987
|
+
app2.use("*", middleware);
|
|
5988
|
+
}
|
|
5989
|
+
}
|
|
5990
|
+
app2.use("*", async (_c, next) => {
|
|
5991
|
+
await next();
|
|
5992
|
+
});
|
|
5993
|
+
app2.use("*", async (_c, next) => {
|
|
5994
|
+
await next();
|
|
5995
|
+
});
|
|
5996
|
+
if (config.middleware?.afterAuth) {
|
|
5997
|
+
for (const middleware of config.middleware.afterAuth) {
|
|
5998
|
+
app2.use("*", middleware);
|
|
5999
|
+
}
|
|
6000
|
+
}
|
|
6001
|
+
app2.route("/api", chunkYE2MU7CN_cjs.api_default);
|
|
6002
|
+
app2.route("/api/media", chunkYE2MU7CN_cjs.api_media_default);
|
|
6003
|
+
app2.route("/api/system", chunkYE2MU7CN_cjs.api_system_default);
|
|
6004
|
+
app2.route("/admin/api", chunkYE2MU7CN_cjs.admin_api_default);
|
|
6005
|
+
app2.route("/admin/dashboard", chunkYE2MU7CN_cjs.router);
|
|
6006
|
+
app2.route("/admin/collections", chunkYE2MU7CN_cjs.adminCollectionsRoutes);
|
|
6007
|
+
app2.route("/admin/forms", chunkYE2MU7CN_cjs.adminFormsRoutes);
|
|
6008
|
+
app2.route("/admin/settings", chunkYE2MU7CN_cjs.adminSettingsRoutes);
|
|
6009
|
+
app2.route("/forms", chunkYE2MU7CN_cjs.public_forms_default);
|
|
6010
|
+
app2.route("/api/forms", chunkYE2MU7CN_cjs.public_forms_default);
|
|
6011
|
+
app2.route("/admin/api-reference", chunkYE2MU7CN_cjs.router2);
|
|
6012
|
+
app2.route("/admin/database-tools", createDatabaseToolsAdminRoutes());
|
|
6013
|
+
app2.route("/admin/seed-data", createSeedDataAdminRoutes());
|
|
6014
|
+
app2.route("/admin/content", chunkYE2MU7CN_cjs.admin_content_default);
|
|
6015
|
+
app2.route("/admin/media", chunkYE2MU7CN_cjs.adminMediaRoutes);
|
|
6016
|
+
if (aiSearchPlugin.routes && aiSearchPlugin.routes.length > 0) {
|
|
6017
|
+
for (const route of aiSearchPlugin.routes) {
|
|
6018
|
+
app2.route(route.path, route.handler);
|
|
6019
|
+
}
|
|
6020
|
+
}
|
|
6021
|
+
app2.route("/admin/cache", cache_default.getRoutes());
|
|
6022
|
+
if (otpLoginPlugin.routes && otpLoginPlugin.routes.length > 0) {
|
|
6023
|
+
for (const route of otpLoginPlugin.routes) {
|
|
6024
|
+
app2.route(route.path, route.handler);
|
|
6025
|
+
}
|
|
6026
|
+
}
|
|
6027
|
+
app2.route("/admin/plugins", chunkYE2MU7CN_cjs.adminPluginRoutes);
|
|
6028
|
+
app2.route("/admin/logs", chunkYE2MU7CN_cjs.adminLogsRoutes);
|
|
6029
|
+
app2.route("/admin", chunkYE2MU7CN_cjs.userRoutes);
|
|
6030
|
+
app2.route("/auth", chunkYE2MU7CN_cjs.auth_default);
|
|
6031
|
+
app2.route("/", chunkYE2MU7CN_cjs.test_cleanup_default);
|
|
6032
|
+
if (emailPlugin.routes && emailPlugin.routes.length > 0) {
|
|
6033
|
+
for (const route of emailPlugin.routes) {
|
|
6034
|
+
app2.route(route.path, route.handler);
|
|
4623
6035
|
}
|
|
4624
6036
|
}
|
|
4625
6037
|
const magicLinkPlugin = createMagicLinkAuthPlugin();
|
|
4626
6038
|
if (magicLinkPlugin.routes && magicLinkPlugin.routes.length > 0) {
|
|
4627
6039
|
for (const route of magicLinkPlugin.routes) {
|
|
4628
|
-
|
|
6040
|
+
app2.route(route.path, route.handler);
|
|
4629
6041
|
}
|
|
4630
6042
|
}
|
|
4631
|
-
|
|
6043
|
+
app2.get("/favicon.svg", (c) => {
|
|
4632
6044
|
return new Response(faviconSvg, {
|
|
4633
6045
|
headers: {
|
|
4634
6046
|
"Content-Type": "image/svg+xml",
|
|
@@ -4636,7 +6048,7 @@ function createSonicJSApp(config = {}) {
|
|
|
4636
6048
|
}
|
|
4637
6049
|
});
|
|
4638
6050
|
});
|
|
4639
|
-
|
|
6051
|
+
app2.get("/files/*", async (c) => {
|
|
4640
6052
|
try {
|
|
4641
6053
|
const url = new URL(c.req.url);
|
|
4642
6054
|
const pathname = url.pathname;
|
|
@@ -4665,13 +6077,13 @@ function createSonicJSApp(config = {}) {
|
|
|
4665
6077
|
});
|
|
4666
6078
|
if (config.routes) {
|
|
4667
6079
|
for (const route of config.routes) {
|
|
4668
|
-
|
|
6080
|
+
app2.route(route.path, route.handler);
|
|
4669
6081
|
}
|
|
4670
6082
|
}
|
|
4671
|
-
|
|
6083
|
+
app2.get("/", (c) => {
|
|
4672
6084
|
return c.redirect("/auth/login");
|
|
4673
6085
|
});
|
|
4674
|
-
|
|
6086
|
+
app2.get("/health", (c) => {
|
|
4675
6087
|
return c.json({
|
|
4676
6088
|
name: appName,
|
|
4677
6089
|
version: appVersion,
|
|
@@ -4679,14 +6091,14 @@ function createSonicJSApp(config = {}) {
|
|
|
4679
6091
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4680
6092
|
});
|
|
4681
6093
|
});
|
|
4682
|
-
|
|
6094
|
+
app2.notFound((c) => {
|
|
4683
6095
|
return c.json({ error: "Not Found", status: 404 }, 404);
|
|
4684
6096
|
});
|
|
4685
|
-
|
|
6097
|
+
app2.onError((err, c) => {
|
|
4686
6098
|
console.error(err);
|
|
4687
6099
|
return c.json({ error: "Internal Server Error", status: 500 }, 500);
|
|
4688
6100
|
});
|
|
4689
|
-
return
|
|
6101
|
+
return app2;
|
|
4690
6102
|
}
|
|
4691
6103
|
function setupCoreMiddleware(_app) {
|
|
4692
6104
|
console.warn("setupCoreMiddleware is deprecated. Use createSonicJSApp() instead.");
|
|
@@ -4695,331 +6107,331 @@ function setupCoreRoutes(_app) {
|
|
|
4695
6107
|
console.warn("setupCoreRoutes is deprecated. Use createSonicJSApp() instead.");
|
|
4696
6108
|
}
|
|
4697
6109
|
function createDb(d1$1) {
|
|
4698
|
-
return d1.drizzle(d1$1, { schema:
|
|
6110
|
+
return d1.drizzle(d1$1, { schema: chunkVNLR35GO_cjs.schema_exports });
|
|
4699
6111
|
}
|
|
4700
6112
|
|
|
4701
6113
|
// src/index.ts
|
|
4702
|
-
var VERSION =
|
|
6114
|
+
var VERSION = chunk5HMR2SJW_cjs.package_default.version;
|
|
4703
6115
|
|
|
4704
6116
|
Object.defineProperty(exports, "ROUTES_INFO", {
|
|
4705
6117
|
enumerable: true,
|
|
4706
|
-
get: function () { return
|
|
6118
|
+
get: function () { return chunkYE2MU7CN_cjs.ROUTES_INFO; }
|
|
4707
6119
|
});
|
|
4708
6120
|
Object.defineProperty(exports, "adminApiRoutes", {
|
|
4709
6121
|
enumerable: true,
|
|
4710
|
-
get: function () { return
|
|
6122
|
+
get: function () { return chunkYE2MU7CN_cjs.admin_api_default; }
|
|
4711
6123
|
});
|
|
4712
6124
|
Object.defineProperty(exports, "adminCheckboxRoutes", {
|
|
4713
6125
|
enumerable: true,
|
|
4714
|
-
get: function () { return
|
|
6126
|
+
get: function () { return chunkYE2MU7CN_cjs.adminCheckboxRoutes; }
|
|
4715
6127
|
});
|
|
4716
6128
|
Object.defineProperty(exports, "adminCodeExamplesRoutes", {
|
|
4717
6129
|
enumerable: true,
|
|
4718
|
-
get: function () { return
|
|
6130
|
+
get: function () { return chunkYE2MU7CN_cjs.admin_code_examples_default; }
|
|
4719
6131
|
});
|
|
4720
6132
|
Object.defineProperty(exports, "adminCollectionsRoutes", {
|
|
4721
6133
|
enumerable: true,
|
|
4722
|
-
get: function () { return
|
|
6134
|
+
get: function () { return chunkYE2MU7CN_cjs.adminCollectionsRoutes; }
|
|
4723
6135
|
});
|
|
4724
6136
|
Object.defineProperty(exports, "adminContentRoutes", {
|
|
4725
6137
|
enumerable: true,
|
|
4726
|
-
get: function () { return
|
|
6138
|
+
get: function () { return chunkYE2MU7CN_cjs.admin_content_default; }
|
|
4727
6139
|
});
|
|
4728
6140
|
Object.defineProperty(exports, "adminDashboardRoutes", {
|
|
4729
6141
|
enumerable: true,
|
|
4730
|
-
get: function () { return
|
|
6142
|
+
get: function () { return chunkYE2MU7CN_cjs.router; }
|
|
4731
6143
|
});
|
|
4732
6144
|
Object.defineProperty(exports, "adminDesignRoutes", {
|
|
4733
6145
|
enumerable: true,
|
|
4734
|
-
get: function () { return
|
|
6146
|
+
get: function () { return chunkYE2MU7CN_cjs.adminDesignRoutes; }
|
|
4735
6147
|
});
|
|
4736
6148
|
Object.defineProperty(exports, "adminLogsRoutes", {
|
|
4737
6149
|
enumerable: true,
|
|
4738
|
-
get: function () { return
|
|
6150
|
+
get: function () { return chunkYE2MU7CN_cjs.adminLogsRoutes; }
|
|
4739
6151
|
});
|
|
4740
6152
|
Object.defineProperty(exports, "adminMediaRoutes", {
|
|
4741
6153
|
enumerable: true,
|
|
4742
|
-
get: function () { return
|
|
6154
|
+
get: function () { return chunkYE2MU7CN_cjs.adminMediaRoutes; }
|
|
4743
6155
|
});
|
|
4744
6156
|
Object.defineProperty(exports, "adminPluginRoutes", {
|
|
4745
6157
|
enumerable: true,
|
|
4746
|
-
get: function () { return
|
|
6158
|
+
get: function () { return chunkYE2MU7CN_cjs.adminPluginRoutes; }
|
|
4747
6159
|
});
|
|
4748
6160
|
Object.defineProperty(exports, "adminSettingsRoutes", {
|
|
4749
6161
|
enumerable: true,
|
|
4750
|
-
get: function () { return
|
|
6162
|
+
get: function () { return chunkYE2MU7CN_cjs.adminSettingsRoutes; }
|
|
4751
6163
|
});
|
|
4752
6164
|
Object.defineProperty(exports, "adminTestimonialsRoutes", {
|
|
4753
6165
|
enumerable: true,
|
|
4754
|
-
get: function () { return
|
|
6166
|
+
get: function () { return chunkYE2MU7CN_cjs.admin_testimonials_default; }
|
|
4755
6167
|
});
|
|
4756
6168
|
Object.defineProperty(exports, "adminUsersRoutes", {
|
|
4757
6169
|
enumerable: true,
|
|
4758
|
-
get: function () { return
|
|
6170
|
+
get: function () { return chunkYE2MU7CN_cjs.userRoutes; }
|
|
4759
6171
|
});
|
|
4760
6172
|
Object.defineProperty(exports, "apiContentCrudRoutes", {
|
|
4761
6173
|
enumerable: true,
|
|
4762
|
-
get: function () { return
|
|
6174
|
+
get: function () { return chunkYE2MU7CN_cjs.api_content_crud_default; }
|
|
4763
6175
|
});
|
|
4764
6176
|
Object.defineProperty(exports, "apiMediaRoutes", {
|
|
4765
6177
|
enumerable: true,
|
|
4766
|
-
get: function () { return
|
|
6178
|
+
get: function () { return chunkYE2MU7CN_cjs.api_media_default; }
|
|
4767
6179
|
});
|
|
4768
6180
|
Object.defineProperty(exports, "apiRoutes", {
|
|
4769
6181
|
enumerable: true,
|
|
4770
|
-
get: function () { return
|
|
6182
|
+
get: function () { return chunkYE2MU7CN_cjs.api_default; }
|
|
4771
6183
|
});
|
|
4772
6184
|
Object.defineProperty(exports, "apiSystemRoutes", {
|
|
4773
6185
|
enumerable: true,
|
|
4774
|
-
get: function () { return
|
|
6186
|
+
get: function () { return chunkYE2MU7CN_cjs.api_system_default; }
|
|
4775
6187
|
});
|
|
4776
6188
|
Object.defineProperty(exports, "authRoutes", {
|
|
4777
6189
|
enumerable: true,
|
|
4778
|
-
get: function () { return
|
|
6190
|
+
get: function () { return chunkYE2MU7CN_cjs.auth_default; }
|
|
4779
6191
|
});
|
|
4780
6192
|
Object.defineProperty(exports, "Logger", {
|
|
4781
6193
|
enumerable: true,
|
|
4782
|
-
get: function () { return
|
|
6194
|
+
get: function () { return chunkVNLR35GO_cjs.Logger; }
|
|
4783
6195
|
});
|
|
4784
6196
|
Object.defineProperty(exports, "apiTokens", {
|
|
4785
6197
|
enumerable: true,
|
|
4786
|
-
get: function () { return
|
|
6198
|
+
get: function () { return chunkVNLR35GO_cjs.apiTokens; }
|
|
4787
6199
|
});
|
|
4788
6200
|
Object.defineProperty(exports, "collections", {
|
|
4789
6201
|
enumerable: true,
|
|
4790
|
-
get: function () { return
|
|
6202
|
+
get: function () { return chunkVNLR35GO_cjs.collections; }
|
|
4791
6203
|
});
|
|
4792
6204
|
Object.defineProperty(exports, "content", {
|
|
4793
6205
|
enumerable: true,
|
|
4794
|
-
get: function () { return
|
|
6206
|
+
get: function () { return chunkVNLR35GO_cjs.content; }
|
|
4795
6207
|
});
|
|
4796
6208
|
Object.defineProperty(exports, "contentVersions", {
|
|
4797
6209
|
enumerable: true,
|
|
4798
|
-
get: function () { return
|
|
6210
|
+
get: function () { return chunkVNLR35GO_cjs.contentVersions; }
|
|
4799
6211
|
});
|
|
4800
6212
|
Object.defineProperty(exports, "getLogger", {
|
|
4801
6213
|
enumerable: true,
|
|
4802
|
-
get: function () { return
|
|
6214
|
+
get: function () { return chunkVNLR35GO_cjs.getLogger; }
|
|
4803
6215
|
});
|
|
4804
6216
|
Object.defineProperty(exports, "initLogger", {
|
|
4805
6217
|
enumerable: true,
|
|
4806
|
-
get: function () { return
|
|
6218
|
+
get: function () { return chunkVNLR35GO_cjs.initLogger; }
|
|
4807
6219
|
});
|
|
4808
6220
|
Object.defineProperty(exports, "insertCollectionSchema", {
|
|
4809
6221
|
enumerable: true,
|
|
4810
|
-
get: function () { return
|
|
6222
|
+
get: function () { return chunkVNLR35GO_cjs.insertCollectionSchema; }
|
|
4811
6223
|
});
|
|
4812
6224
|
Object.defineProperty(exports, "insertContentSchema", {
|
|
4813
6225
|
enumerable: true,
|
|
4814
|
-
get: function () { return
|
|
6226
|
+
get: function () { return chunkVNLR35GO_cjs.insertContentSchema; }
|
|
4815
6227
|
});
|
|
4816
6228
|
Object.defineProperty(exports, "insertLogConfigSchema", {
|
|
4817
6229
|
enumerable: true,
|
|
4818
|
-
get: function () { return
|
|
6230
|
+
get: function () { return chunkVNLR35GO_cjs.insertLogConfigSchema; }
|
|
4819
6231
|
});
|
|
4820
6232
|
Object.defineProperty(exports, "insertMediaSchema", {
|
|
4821
6233
|
enumerable: true,
|
|
4822
|
-
get: function () { return
|
|
6234
|
+
get: function () { return chunkVNLR35GO_cjs.insertMediaSchema; }
|
|
4823
6235
|
});
|
|
4824
6236
|
Object.defineProperty(exports, "insertPluginActivityLogSchema", {
|
|
4825
6237
|
enumerable: true,
|
|
4826
|
-
get: function () { return
|
|
6238
|
+
get: function () { return chunkVNLR35GO_cjs.insertPluginActivityLogSchema; }
|
|
4827
6239
|
});
|
|
4828
6240
|
Object.defineProperty(exports, "insertPluginAssetSchema", {
|
|
4829
6241
|
enumerable: true,
|
|
4830
|
-
get: function () { return
|
|
6242
|
+
get: function () { return chunkVNLR35GO_cjs.insertPluginAssetSchema; }
|
|
4831
6243
|
});
|
|
4832
6244
|
Object.defineProperty(exports, "insertPluginHookSchema", {
|
|
4833
6245
|
enumerable: true,
|
|
4834
|
-
get: function () { return
|
|
6246
|
+
get: function () { return chunkVNLR35GO_cjs.insertPluginHookSchema; }
|
|
4835
6247
|
});
|
|
4836
6248
|
Object.defineProperty(exports, "insertPluginRouteSchema", {
|
|
4837
6249
|
enumerable: true,
|
|
4838
|
-
get: function () { return
|
|
6250
|
+
get: function () { return chunkVNLR35GO_cjs.insertPluginRouteSchema; }
|
|
4839
6251
|
});
|
|
4840
6252
|
Object.defineProperty(exports, "insertPluginSchema", {
|
|
4841
6253
|
enumerable: true,
|
|
4842
|
-
get: function () { return
|
|
6254
|
+
get: function () { return chunkVNLR35GO_cjs.insertPluginSchema; }
|
|
4843
6255
|
});
|
|
4844
6256
|
Object.defineProperty(exports, "insertSystemLogSchema", {
|
|
4845
6257
|
enumerable: true,
|
|
4846
|
-
get: function () { return
|
|
6258
|
+
get: function () { return chunkVNLR35GO_cjs.insertSystemLogSchema; }
|
|
4847
6259
|
});
|
|
4848
6260
|
Object.defineProperty(exports, "insertUserSchema", {
|
|
4849
6261
|
enumerable: true,
|
|
4850
|
-
get: function () { return
|
|
6262
|
+
get: function () { return chunkVNLR35GO_cjs.insertUserSchema; }
|
|
4851
6263
|
});
|
|
4852
6264
|
Object.defineProperty(exports, "insertWorkflowHistorySchema", {
|
|
4853
6265
|
enumerable: true,
|
|
4854
|
-
get: function () { return
|
|
6266
|
+
get: function () { return chunkVNLR35GO_cjs.insertWorkflowHistorySchema; }
|
|
4855
6267
|
});
|
|
4856
6268
|
Object.defineProperty(exports, "logConfig", {
|
|
4857
6269
|
enumerable: true,
|
|
4858
|
-
get: function () { return
|
|
6270
|
+
get: function () { return chunkVNLR35GO_cjs.logConfig; }
|
|
4859
6271
|
});
|
|
4860
6272
|
Object.defineProperty(exports, "media", {
|
|
4861
6273
|
enumerable: true,
|
|
4862
|
-
get: function () { return
|
|
6274
|
+
get: function () { return chunkVNLR35GO_cjs.media; }
|
|
4863
6275
|
});
|
|
4864
6276
|
Object.defineProperty(exports, "pluginActivityLog", {
|
|
4865
6277
|
enumerable: true,
|
|
4866
|
-
get: function () { return
|
|
6278
|
+
get: function () { return chunkVNLR35GO_cjs.pluginActivityLog; }
|
|
4867
6279
|
});
|
|
4868
6280
|
Object.defineProperty(exports, "pluginAssets", {
|
|
4869
6281
|
enumerable: true,
|
|
4870
|
-
get: function () { return
|
|
6282
|
+
get: function () { return chunkVNLR35GO_cjs.pluginAssets; }
|
|
4871
6283
|
});
|
|
4872
6284
|
Object.defineProperty(exports, "pluginHooks", {
|
|
4873
6285
|
enumerable: true,
|
|
4874
|
-
get: function () { return
|
|
6286
|
+
get: function () { return chunkVNLR35GO_cjs.pluginHooks; }
|
|
4875
6287
|
});
|
|
4876
6288
|
Object.defineProperty(exports, "pluginRoutes", {
|
|
4877
6289
|
enumerable: true,
|
|
4878
|
-
get: function () { return
|
|
6290
|
+
get: function () { return chunkVNLR35GO_cjs.pluginRoutes; }
|
|
4879
6291
|
});
|
|
4880
6292
|
Object.defineProperty(exports, "plugins", {
|
|
4881
6293
|
enumerable: true,
|
|
4882
|
-
get: function () { return
|
|
6294
|
+
get: function () { return chunkVNLR35GO_cjs.plugins; }
|
|
4883
6295
|
});
|
|
4884
6296
|
Object.defineProperty(exports, "selectCollectionSchema", {
|
|
4885
6297
|
enumerable: true,
|
|
4886
|
-
get: function () { return
|
|
6298
|
+
get: function () { return chunkVNLR35GO_cjs.selectCollectionSchema; }
|
|
4887
6299
|
});
|
|
4888
6300
|
Object.defineProperty(exports, "selectContentSchema", {
|
|
4889
6301
|
enumerable: true,
|
|
4890
|
-
get: function () { return
|
|
6302
|
+
get: function () { return chunkVNLR35GO_cjs.selectContentSchema; }
|
|
4891
6303
|
});
|
|
4892
6304
|
Object.defineProperty(exports, "selectLogConfigSchema", {
|
|
4893
6305
|
enumerable: true,
|
|
4894
|
-
get: function () { return
|
|
6306
|
+
get: function () { return chunkVNLR35GO_cjs.selectLogConfigSchema; }
|
|
4895
6307
|
});
|
|
4896
6308
|
Object.defineProperty(exports, "selectMediaSchema", {
|
|
4897
6309
|
enumerable: true,
|
|
4898
|
-
get: function () { return
|
|
6310
|
+
get: function () { return chunkVNLR35GO_cjs.selectMediaSchema; }
|
|
4899
6311
|
});
|
|
4900
6312
|
Object.defineProperty(exports, "selectPluginActivityLogSchema", {
|
|
4901
6313
|
enumerable: true,
|
|
4902
|
-
get: function () { return
|
|
6314
|
+
get: function () { return chunkVNLR35GO_cjs.selectPluginActivityLogSchema; }
|
|
4903
6315
|
});
|
|
4904
6316
|
Object.defineProperty(exports, "selectPluginAssetSchema", {
|
|
4905
6317
|
enumerable: true,
|
|
4906
|
-
get: function () { return
|
|
6318
|
+
get: function () { return chunkVNLR35GO_cjs.selectPluginAssetSchema; }
|
|
4907
6319
|
});
|
|
4908
6320
|
Object.defineProperty(exports, "selectPluginHookSchema", {
|
|
4909
6321
|
enumerable: true,
|
|
4910
|
-
get: function () { return
|
|
6322
|
+
get: function () { return chunkVNLR35GO_cjs.selectPluginHookSchema; }
|
|
4911
6323
|
});
|
|
4912
6324
|
Object.defineProperty(exports, "selectPluginRouteSchema", {
|
|
4913
6325
|
enumerable: true,
|
|
4914
|
-
get: function () { return
|
|
6326
|
+
get: function () { return chunkVNLR35GO_cjs.selectPluginRouteSchema; }
|
|
4915
6327
|
});
|
|
4916
6328
|
Object.defineProperty(exports, "selectPluginSchema", {
|
|
4917
6329
|
enumerable: true,
|
|
4918
|
-
get: function () { return
|
|
6330
|
+
get: function () { return chunkVNLR35GO_cjs.selectPluginSchema; }
|
|
4919
6331
|
});
|
|
4920
6332
|
Object.defineProperty(exports, "selectSystemLogSchema", {
|
|
4921
6333
|
enumerable: true,
|
|
4922
|
-
get: function () { return
|
|
6334
|
+
get: function () { return chunkVNLR35GO_cjs.selectSystemLogSchema; }
|
|
4923
6335
|
});
|
|
4924
6336
|
Object.defineProperty(exports, "selectUserSchema", {
|
|
4925
6337
|
enumerable: true,
|
|
4926
|
-
get: function () { return
|
|
6338
|
+
get: function () { return chunkVNLR35GO_cjs.selectUserSchema; }
|
|
4927
6339
|
});
|
|
4928
6340
|
Object.defineProperty(exports, "selectWorkflowHistorySchema", {
|
|
4929
6341
|
enumerable: true,
|
|
4930
|
-
get: function () { return
|
|
6342
|
+
get: function () { return chunkVNLR35GO_cjs.selectWorkflowHistorySchema; }
|
|
4931
6343
|
});
|
|
4932
6344
|
Object.defineProperty(exports, "systemLogs", {
|
|
4933
6345
|
enumerable: true,
|
|
4934
|
-
get: function () { return
|
|
6346
|
+
get: function () { return chunkVNLR35GO_cjs.systemLogs; }
|
|
4935
6347
|
});
|
|
4936
6348
|
Object.defineProperty(exports, "users", {
|
|
4937
6349
|
enumerable: true,
|
|
4938
|
-
get: function () { return
|
|
6350
|
+
get: function () { return chunkVNLR35GO_cjs.users; }
|
|
4939
6351
|
});
|
|
4940
6352
|
Object.defineProperty(exports, "workflowHistory", {
|
|
4941
6353
|
enumerable: true,
|
|
4942
|
-
get: function () { return
|
|
6354
|
+
get: function () { return chunkVNLR35GO_cjs.workflowHistory; }
|
|
4943
6355
|
});
|
|
4944
6356
|
Object.defineProperty(exports, "AuthManager", {
|
|
4945
6357
|
enumerable: true,
|
|
4946
|
-
get: function () { return
|
|
6358
|
+
get: function () { return chunkGPTMGUFN_cjs.AuthManager; }
|
|
4947
6359
|
});
|
|
4948
6360
|
Object.defineProperty(exports, "PermissionManager", {
|
|
4949
6361
|
enumerable: true,
|
|
4950
|
-
get: function () { return
|
|
6362
|
+
get: function () { return chunkGPTMGUFN_cjs.PermissionManager; }
|
|
4951
6363
|
});
|
|
4952
6364
|
Object.defineProperty(exports, "bootstrapMiddleware", {
|
|
4953
6365
|
enumerable: true,
|
|
4954
|
-
get: function () { return
|
|
6366
|
+
get: function () { return chunkGPTMGUFN_cjs.bootstrapMiddleware; }
|
|
4955
6367
|
});
|
|
4956
6368
|
Object.defineProperty(exports, "cacheHeaders", {
|
|
4957
6369
|
enumerable: true,
|
|
4958
|
-
get: function () { return
|
|
6370
|
+
get: function () { return chunkGPTMGUFN_cjs.cacheHeaders; }
|
|
4959
6371
|
});
|
|
4960
6372
|
Object.defineProperty(exports, "compressionMiddleware", {
|
|
4961
6373
|
enumerable: true,
|
|
4962
|
-
get: function () { return
|
|
6374
|
+
get: function () { return chunkGPTMGUFN_cjs.compressionMiddleware; }
|
|
4963
6375
|
});
|
|
4964
6376
|
Object.defineProperty(exports, "detailedLoggingMiddleware", {
|
|
4965
6377
|
enumerable: true,
|
|
4966
|
-
get: function () { return
|
|
6378
|
+
get: function () { return chunkGPTMGUFN_cjs.detailedLoggingMiddleware; }
|
|
4967
6379
|
});
|
|
4968
6380
|
Object.defineProperty(exports, "getActivePlugins", {
|
|
4969
6381
|
enumerable: true,
|
|
4970
|
-
get: function () { return
|
|
6382
|
+
get: function () { return chunkGPTMGUFN_cjs.getActivePlugins; }
|
|
4971
6383
|
});
|
|
4972
6384
|
Object.defineProperty(exports, "isPluginActive", {
|
|
4973
6385
|
enumerable: true,
|
|
4974
|
-
get: function () { return
|
|
6386
|
+
get: function () { return chunkGPTMGUFN_cjs.isPluginActive; }
|
|
4975
6387
|
});
|
|
4976
6388
|
Object.defineProperty(exports, "logActivity", {
|
|
4977
6389
|
enumerable: true,
|
|
4978
|
-
get: function () { return
|
|
6390
|
+
get: function () { return chunkGPTMGUFN_cjs.logActivity; }
|
|
4979
6391
|
});
|
|
4980
6392
|
Object.defineProperty(exports, "loggingMiddleware", {
|
|
4981
6393
|
enumerable: true,
|
|
4982
|
-
get: function () { return
|
|
6394
|
+
get: function () { return chunkGPTMGUFN_cjs.loggingMiddleware; }
|
|
4983
6395
|
});
|
|
4984
6396
|
Object.defineProperty(exports, "optionalAuth", {
|
|
4985
6397
|
enumerable: true,
|
|
4986
|
-
get: function () { return
|
|
6398
|
+
get: function () { return chunkGPTMGUFN_cjs.optionalAuth; }
|
|
4987
6399
|
});
|
|
4988
6400
|
Object.defineProperty(exports, "performanceLoggingMiddleware", {
|
|
4989
6401
|
enumerable: true,
|
|
4990
|
-
get: function () { return
|
|
6402
|
+
get: function () { return chunkGPTMGUFN_cjs.performanceLoggingMiddleware; }
|
|
4991
6403
|
});
|
|
4992
6404
|
Object.defineProperty(exports, "requireActivePlugin", {
|
|
4993
6405
|
enumerable: true,
|
|
4994
|
-
get: function () { return
|
|
6406
|
+
get: function () { return chunkGPTMGUFN_cjs.requireActivePlugin; }
|
|
4995
6407
|
});
|
|
4996
6408
|
Object.defineProperty(exports, "requireActivePlugins", {
|
|
4997
6409
|
enumerable: true,
|
|
4998
|
-
get: function () { return
|
|
6410
|
+
get: function () { return chunkGPTMGUFN_cjs.requireActivePlugins; }
|
|
4999
6411
|
});
|
|
5000
6412
|
Object.defineProperty(exports, "requireAnyPermission", {
|
|
5001
6413
|
enumerable: true,
|
|
5002
|
-
get: function () { return
|
|
6414
|
+
get: function () { return chunkGPTMGUFN_cjs.requireAnyPermission; }
|
|
5003
6415
|
});
|
|
5004
6416
|
Object.defineProperty(exports, "requireAuth", {
|
|
5005
6417
|
enumerable: true,
|
|
5006
|
-
get: function () { return
|
|
6418
|
+
get: function () { return chunkGPTMGUFN_cjs.requireAuth; }
|
|
5007
6419
|
});
|
|
5008
6420
|
Object.defineProperty(exports, "requirePermission", {
|
|
5009
6421
|
enumerable: true,
|
|
5010
|
-
get: function () { return
|
|
6422
|
+
get: function () { return chunkGPTMGUFN_cjs.requirePermission; }
|
|
5011
6423
|
});
|
|
5012
6424
|
Object.defineProperty(exports, "requireRole", {
|
|
5013
6425
|
enumerable: true,
|
|
5014
|
-
get: function () { return
|
|
6426
|
+
get: function () { return chunkGPTMGUFN_cjs.requireRole; }
|
|
5015
6427
|
});
|
|
5016
6428
|
Object.defineProperty(exports, "securityHeaders", {
|
|
5017
6429
|
enumerable: true,
|
|
5018
|
-
get: function () { return
|
|
6430
|
+
get: function () { return chunkGPTMGUFN_cjs.securityHeaders; }
|
|
5019
6431
|
});
|
|
5020
6432
|
Object.defineProperty(exports, "securityLoggingMiddleware", {
|
|
5021
6433
|
enumerable: true,
|
|
5022
|
-
get: function () { return
|
|
6434
|
+
get: function () { return chunkGPTMGUFN_cjs.securityLoggingMiddleware; }
|
|
5023
6435
|
});
|
|
5024
6436
|
Object.defineProperty(exports, "PluginBootstrapService", {
|
|
5025
6437
|
enumerable: true,
|
|
@@ -5075,111 +6487,111 @@ Object.defineProperty(exports, "validateCollectionConfig", {
|
|
|
5075
6487
|
});
|
|
5076
6488
|
Object.defineProperty(exports, "MigrationService", {
|
|
5077
6489
|
enumerable: true,
|
|
5078
|
-
get: function () { return
|
|
6490
|
+
get: function () { return chunk5CENPGR2_cjs.MigrationService; }
|
|
5079
6491
|
});
|
|
5080
6492
|
Object.defineProperty(exports, "renderFilterBar", {
|
|
5081
6493
|
enumerable: true,
|
|
5082
|
-
get: function () { return
|
|
6494
|
+
get: function () { return chunkS6K2H2TS_cjs.renderFilterBar; }
|
|
5083
6495
|
});
|
|
5084
6496
|
Object.defineProperty(exports, "getConfirmationDialogScript", {
|
|
5085
6497
|
enumerable: true,
|
|
5086
|
-
get: function () { return
|
|
6498
|
+
get: function () { return chunkSHCYIZAN_cjs.getConfirmationDialogScript; }
|
|
5087
6499
|
});
|
|
5088
6500
|
Object.defineProperty(exports, "renderAlert", {
|
|
5089
6501
|
enumerable: true,
|
|
5090
|
-
get: function () { return
|
|
6502
|
+
get: function () { return chunkSHCYIZAN_cjs.renderAlert; }
|
|
5091
6503
|
});
|
|
5092
6504
|
Object.defineProperty(exports, "renderConfirmationDialog", {
|
|
5093
6505
|
enumerable: true,
|
|
5094
|
-
get: function () { return
|
|
6506
|
+
get: function () { return chunkSHCYIZAN_cjs.renderConfirmationDialog; }
|
|
5095
6507
|
});
|
|
5096
6508
|
Object.defineProperty(exports, "renderForm", {
|
|
5097
6509
|
enumerable: true,
|
|
5098
|
-
get: function () { return
|
|
6510
|
+
get: function () { return chunkSHCYIZAN_cjs.renderForm; }
|
|
5099
6511
|
});
|
|
5100
6512
|
Object.defineProperty(exports, "renderFormField", {
|
|
5101
6513
|
enumerable: true,
|
|
5102
|
-
get: function () { return
|
|
6514
|
+
get: function () { return chunkSHCYIZAN_cjs.renderFormField; }
|
|
5103
6515
|
});
|
|
5104
6516
|
Object.defineProperty(exports, "renderPagination", {
|
|
5105
6517
|
enumerable: true,
|
|
5106
|
-
get: function () { return
|
|
6518
|
+
get: function () { return chunkSHCYIZAN_cjs.renderPagination; }
|
|
5107
6519
|
});
|
|
5108
6520
|
Object.defineProperty(exports, "renderTable", {
|
|
5109
6521
|
enumerable: true,
|
|
5110
|
-
get: function () { return
|
|
6522
|
+
get: function () { return chunkSHCYIZAN_cjs.renderTable; }
|
|
5111
6523
|
});
|
|
5112
6524
|
Object.defineProperty(exports, "HookSystemImpl", {
|
|
5113
6525
|
enumerable: true,
|
|
5114
|
-
get: function () { return
|
|
6526
|
+
get: function () { return chunkMNFY6DWY_cjs.HookSystemImpl; }
|
|
5115
6527
|
});
|
|
5116
6528
|
Object.defineProperty(exports, "HookUtils", {
|
|
5117
6529
|
enumerable: true,
|
|
5118
|
-
get: function () { return
|
|
6530
|
+
get: function () { return chunkMNFY6DWY_cjs.HookUtils; }
|
|
5119
6531
|
});
|
|
5120
6532
|
Object.defineProperty(exports, "PluginManagerClass", {
|
|
5121
6533
|
enumerable: true,
|
|
5122
|
-
get: function () { return
|
|
6534
|
+
get: function () { return chunkMNFY6DWY_cjs.PluginManager; }
|
|
5123
6535
|
});
|
|
5124
6536
|
Object.defineProperty(exports, "PluginRegistryImpl", {
|
|
5125
6537
|
enumerable: true,
|
|
5126
|
-
get: function () { return
|
|
6538
|
+
get: function () { return chunkMNFY6DWY_cjs.PluginRegistryImpl; }
|
|
5127
6539
|
});
|
|
5128
6540
|
Object.defineProperty(exports, "PluginValidatorClass", {
|
|
5129
6541
|
enumerable: true,
|
|
5130
|
-
get: function () { return
|
|
6542
|
+
get: function () { return chunkMNFY6DWY_cjs.PluginValidator; }
|
|
5131
6543
|
});
|
|
5132
6544
|
Object.defineProperty(exports, "ScopedHookSystemClass", {
|
|
5133
6545
|
enumerable: true,
|
|
5134
|
-
get: function () { return
|
|
6546
|
+
get: function () { return chunkMNFY6DWY_cjs.ScopedHookSystem; }
|
|
5135
6547
|
});
|
|
5136
6548
|
Object.defineProperty(exports, "PluginBuilder", {
|
|
5137
6549
|
enumerable: true,
|
|
5138
|
-
get: function () { return
|
|
6550
|
+
get: function () { return chunk6FHNRRJ3_cjs.PluginBuilder; }
|
|
5139
6551
|
});
|
|
5140
6552
|
Object.defineProperty(exports, "PluginHelpers", {
|
|
5141
6553
|
enumerable: true,
|
|
5142
|
-
get: function () { return
|
|
6554
|
+
get: function () { return chunk6FHNRRJ3_cjs.PluginHelpers; }
|
|
5143
6555
|
});
|
|
5144
6556
|
Object.defineProperty(exports, "QueryFilterBuilder", {
|
|
5145
6557
|
enumerable: true,
|
|
5146
|
-
get: function () { return
|
|
6558
|
+
get: function () { return chunk5HMR2SJW_cjs.QueryFilterBuilder; }
|
|
5147
6559
|
});
|
|
5148
6560
|
Object.defineProperty(exports, "SONICJS_VERSION", {
|
|
5149
6561
|
enumerable: true,
|
|
5150
|
-
get: function () { return
|
|
6562
|
+
get: function () { return chunk5HMR2SJW_cjs.SONICJS_VERSION; }
|
|
5151
6563
|
});
|
|
5152
6564
|
Object.defineProperty(exports, "TemplateRenderer", {
|
|
5153
6565
|
enumerable: true,
|
|
5154
|
-
get: function () { return
|
|
6566
|
+
get: function () { return chunk5HMR2SJW_cjs.TemplateRenderer; }
|
|
5155
6567
|
});
|
|
5156
6568
|
Object.defineProperty(exports, "buildQuery", {
|
|
5157
6569
|
enumerable: true,
|
|
5158
|
-
get: function () { return
|
|
6570
|
+
get: function () { return chunk5HMR2SJW_cjs.buildQuery; }
|
|
5159
6571
|
});
|
|
5160
6572
|
Object.defineProperty(exports, "escapeHtml", {
|
|
5161
6573
|
enumerable: true,
|
|
5162
|
-
get: function () { return
|
|
6574
|
+
get: function () { return chunk5HMR2SJW_cjs.escapeHtml; }
|
|
5163
6575
|
});
|
|
5164
6576
|
Object.defineProperty(exports, "getCoreVersion", {
|
|
5165
6577
|
enumerable: true,
|
|
5166
|
-
get: function () { return
|
|
6578
|
+
get: function () { return chunk5HMR2SJW_cjs.getCoreVersion; }
|
|
5167
6579
|
});
|
|
5168
6580
|
Object.defineProperty(exports, "renderTemplate", {
|
|
5169
6581
|
enumerable: true,
|
|
5170
|
-
get: function () { return
|
|
6582
|
+
get: function () { return chunk5HMR2SJW_cjs.renderTemplate; }
|
|
5171
6583
|
});
|
|
5172
6584
|
Object.defineProperty(exports, "sanitizeInput", {
|
|
5173
6585
|
enumerable: true,
|
|
5174
|
-
get: function () { return
|
|
6586
|
+
get: function () { return chunk5HMR2SJW_cjs.sanitizeInput; }
|
|
5175
6587
|
});
|
|
5176
6588
|
Object.defineProperty(exports, "sanitizeObject", {
|
|
5177
6589
|
enumerable: true,
|
|
5178
|
-
get: function () { return
|
|
6590
|
+
get: function () { return chunk5HMR2SJW_cjs.sanitizeObject; }
|
|
5179
6591
|
});
|
|
5180
6592
|
Object.defineProperty(exports, "templateRenderer", {
|
|
5181
6593
|
enumerable: true,
|
|
5182
|
-
get: function () { return
|
|
6594
|
+
get: function () { return chunk5HMR2SJW_cjs.templateRenderer; }
|
|
5183
6595
|
});
|
|
5184
6596
|
Object.defineProperty(exports, "metricsTracker", {
|
|
5185
6597
|
enumerable: true,
|