@sonicjs-cms/core 2.14.0 → 2.16.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/admin-layout-catalyst.template-HFD37TY5.cjs +17 -0
- package/dist/admin-layout-catalyst.template-HFD37TY5.cjs.map +1 -0
- package/dist/admin-layout-catalyst.template-UMTIN66R.js +7 -0
- package/dist/admin-layout-catalyst.template-UMTIN66R.js.map +1 -0
- package/dist/{chunk-3QCEYJLK.cjs → chunk-4ZSNJDLS.cjs} +9 -9
- package/dist/{chunk-3QCEYJLK.cjs.map → chunk-4ZSNJDLS.cjs.map} +1 -1
- package/dist/chunk-55RDMDOP.js +684 -0
- package/dist/chunk-55RDMDOP.js.map +1 -0
- package/dist/{chunk-6FHNRRJ3.cjs → chunk-635JAMSE.cjs} +76 -17
- package/dist/chunk-635JAMSE.cjs.map +1 -0
- package/dist/{chunk-DRWSHIFG.cjs → chunk-6ENX7QSA.cjs} +228 -658
- package/dist/chunk-6ENX7QSA.cjs.map +1 -0
- package/dist/{chunk-56GUBLJE.cjs → chunk-ABB34XUS.cjs} +13 -13
- package/dist/{chunk-56GUBLJE.cjs.map → chunk-ABB34XUS.cjs.map} +1 -1
- package/dist/{chunk-YYMPHM3I.cjs → chunk-CZ6BVQZX.cjs} +19 -9
- package/dist/chunk-CZ6BVQZX.cjs.map +1 -0
- package/dist/{chunk-J5WGMRSU.js → chunk-EXNEW5US.js} +76 -17
- package/dist/chunk-EXNEW5US.js.map +1 -0
- package/dist/{chunk-H3XXBAMO.js → chunk-INSDRCG3.js} +722 -212
- package/dist/chunk-INSDRCG3.js.map +1 -0
- package/dist/{chunk-GAVTTYMC.js → chunk-MVSCB4E3.js} +3 -3
- package/dist/{chunk-GAVTTYMC.js.map → chunk-MVSCB4E3.js.map} +1 -1
- package/dist/{chunk-KZ2MFGET.cjs → chunk-OCLUXJ7E.cjs} +9 -2
- package/dist/chunk-OCLUXJ7E.cjs.map +1 -0
- package/dist/{chunk-QP3OHHON.cjs → chunk-OHYBNCVL.cjs} +18 -696
- package/dist/chunk-OHYBNCVL.cjs.map +1 -0
- package/dist/{chunk-CB7ONLGB.js → chunk-ON5ZMSU4.js} +3 -3
- package/dist/{chunk-CB7ONLGB.js.map → chunk-ON5ZMSU4.js.map} +1 -1
- package/dist/{chunk-I6FFGQIT.cjs → chunk-Q5VFZUXV.cjs} +723 -211
- package/dist/chunk-Q5VFZUXV.cjs.map +1 -0
- package/dist/{chunk-2MXF4RYZ.js → chunk-TFNTM3OA.js} +3 -3
- package/dist/{chunk-2MXF4RYZ.js.map → chunk-TFNTM3OA.js.map} +1 -1
- package/dist/chunk-UYJ6TJHX.cjs +691 -0
- package/dist/chunk-UYJ6TJHX.cjs.map +1 -0
- package/dist/{chunk-JKNKO6LA.js → chunk-VFQUULAV.js} +9 -2
- package/dist/chunk-VFQUULAV.js.map +1 -0
- package/dist/{chunk-23DP6TO5.js → chunk-WLSIUKNM.js} +44 -474
- package/dist/chunk-WLSIUKNM.js.map +1 -0
- package/dist/{chunk-JTUCC6WZ.js → chunk-XWIA3HVX.js} +9 -683
- package/dist/chunk-XWIA3HVX.js.map +1 -0
- package/dist/{chunk-AFGOH2F6.js → chunk-Y5EH32F5.js} +15 -5
- package/dist/chunk-Y5EH32F5.js.map +1 -0
- package/dist/{chunk-YULUPQZV.cjs → chunk-YQW2GCJ3.cjs} +3 -3
- package/dist/{chunk-YULUPQZV.cjs.map → chunk-YQW2GCJ3.cjs.map} +1 -1
- package/dist/index.cjs +1591 -236
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1464 -109
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +29 -29
- package/dist/middleware.js +3 -3
- package/dist/migrations-7HQ7LYAL.js +4 -0
- package/dist/{migrations-WKONKRN7.js.map → migrations-7HQ7LYAL.js.map} +1 -1
- package/dist/migrations-SVQTT7NV.cjs +13 -0
- package/dist/{migrations-F7KVA74T.cjs.map → migrations-SVQTT7NV.cjs.map} +1 -1
- package/dist/{plugin-bootstrap-BGwBraaN.d.cts → plugin-bootstrap-DfVerYV4.d.cts} +2 -1
- package/dist/{plugin-bootstrap-Drns7X9w.d.ts → plugin-bootstrap-P_ciLp_C.d.ts} +2 -1
- package/dist/plugins.cjs +11 -11
- package/dist/plugins.js +2 -2
- package/dist/routes.cjs +31 -30
- package/dist/routes.js +8 -7
- package/dist/services.cjs +23 -23
- package/dist/services.d.cts +1 -1
- package/dist/services.d.ts +1 -1
- package/dist/services.js +2 -2
- package/dist/templates.cjs +26 -25
- package/dist/templates.js +3 -2
- package/dist/utils.cjs +11 -11
- package/dist/utils.js +1 -1
- package/migrations/036_analytics_events.sql +22 -0
- package/package.json +1 -1
- package/dist/chunk-23DP6TO5.js.map +0 -1
- package/dist/chunk-6FHNRRJ3.cjs.map +0 -1
- package/dist/chunk-AFGOH2F6.js.map +0 -1
- package/dist/chunk-DRWSHIFG.cjs.map +0 -1
- package/dist/chunk-H3XXBAMO.js.map +0 -1
- package/dist/chunk-I6FFGQIT.cjs.map +0 -1
- package/dist/chunk-J5WGMRSU.js.map +0 -1
- package/dist/chunk-JKNKO6LA.js.map +0 -1
- package/dist/chunk-JTUCC6WZ.js.map +0 -1
- package/dist/chunk-KZ2MFGET.cjs.map +0 -1
- package/dist/chunk-QP3OHHON.cjs.map +0 -1
- package/dist/chunk-YYMPHM3I.cjs.map +0 -1
- package/dist/migrations-F7KVA74T.cjs +0 -13
- package/dist/migrations-WKONKRN7.js +0 -4
package/dist/index.cjs
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunk6ENX7QSA_cjs = require('./chunk-6ENX7QSA.cjs');
|
|
4
4
|
var chunkNZWFCUDA_cjs = require('./chunk-NZWFCUDA.cjs');
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
var
|
|
5
|
+
var chunkCZ6BVQZX_cjs = require('./chunk-CZ6BVQZX.cjs');
|
|
6
|
+
var chunkQ5VFZUXV_cjs = require('./chunk-Q5VFZUXV.cjs');
|
|
7
|
+
var chunkOCLUXJ7E_cjs = require('./chunk-OCLUXJ7E.cjs');
|
|
8
|
+
var chunk4ZSNJDLS_cjs = require('./chunk-4ZSNJDLS.cjs');
|
|
9
|
+
var chunkOHYBNCVL_cjs = require('./chunk-OHYBNCVL.cjs');
|
|
10
|
+
var chunkUYJ6TJHX_cjs = require('./chunk-UYJ6TJHX.cjs');
|
|
11
|
+
var chunkABB34XUS_cjs = require('./chunk-ABB34XUS.cjs');
|
|
12
|
+
var chunk635JAMSE_cjs = require('./chunk-635JAMSE.cjs');
|
|
13
|
+
var chunkYQW2GCJ3_cjs = require('./chunk-YQW2GCJ3.cjs');
|
|
13
14
|
require('./chunk-P3XDZL6Q.cjs');
|
|
14
15
|
var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
|
|
15
16
|
var chunkMNWKYY5E_cjs = require('./chunk-MNWKYY5E.cjs');
|
|
@@ -235,7 +236,7 @@ var DatabaseToolsService = class {
|
|
|
235
236
|
};
|
|
236
237
|
|
|
237
238
|
// src/templates/pages/admin-database-table.template.ts
|
|
238
|
-
|
|
239
|
+
chunkUYJ6TJHX_cjs.init_admin_layout_catalyst_template();
|
|
239
240
|
function renderDatabaseTablePage(data) {
|
|
240
241
|
const totalPages = Math.ceil(data.totalRows / data.pageSize);
|
|
241
242
|
const startRow = (data.currentPage - 1) * data.pageSize + 1;
|
|
@@ -484,7 +485,7 @@ function renderDatabaseTablePage(data) {
|
|
|
484
485
|
user: data.user,
|
|
485
486
|
content: pageContent
|
|
486
487
|
};
|
|
487
|
-
return
|
|
488
|
+
return chunkUYJ6TJHX_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
488
489
|
}
|
|
489
490
|
function generatePageNumbers(currentPage, totalPages) {
|
|
490
491
|
const pages = [];
|
|
@@ -559,7 +560,7 @@ function formatCellValue(value) {
|
|
|
559
560
|
// src/plugins/core-plugins/database-tools-plugin/admin-routes.ts
|
|
560
561
|
function createDatabaseToolsAdminRoutes() {
|
|
561
562
|
const router3 = new hono.Hono();
|
|
562
|
-
router3.use("*",
|
|
563
|
+
router3.use("*", chunkCZ6BVQZX_cjs.requireAuth());
|
|
563
564
|
router3.get("/api/stats", async (c) => {
|
|
564
565
|
try {
|
|
565
566
|
const user = c.get("user");
|
|
@@ -1307,7 +1308,7 @@ function createSeedDataAdminRoutes() {
|
|
|
1307
1308
|
return routes;
|
|
1308
1309
|
}
|
|
1309
1310
|
function createEmailPlugin() {
|
|
1310
|
-
const builder =
|
|
1311
|
+
const builder = chunk635JAMSE_cjs.PluginBuilder.create({
|
|
1311
1312
|
name: "email",
|
|
1312
1313
|
version: "1.0.0-beta.1",
|
|
1313
1314
|
description: "Send transactional emails using Resend"
|
|
@@ -1736,7 +1737,7 @@ var DEFAULT_SETTINGS = {
|
|
|
1736
1737
|
allowNewUserRegistration: false
|
|
1737
1738
|
};
|
|
1738
1739
|
function createOTPLoginPlugin() {
|
|
1739
|
-
const builder =
|
|
1740
|
+
const builder = chunk635JAMSE_cjs.PluginBuilder.create({
|
|
1740
1741
|
name: "otp-login",
|
|
1741
1742
|
version: "1.0.0-beta.1",
|
|
1742
1743
|
description: "Passwordless authentication via email one-time codes"
|
|
@@ -1938,7 +1939,7 @@ function createOTPLoginPlugin() {
|
|
|
1938
1939
|
error: "Account is deactivated"
|
|
1939
1940
|
}, 403);
|
|
1940
1941
|
}
|
|
1941
|
-
const token = await
|
|
1942
|
+
const token = await chunkCZ6BVQZX_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET);
|
|
1942
1943
|
cookie.setCookie(c, "auth_token", token, {
|
|
1943
1944
|
httpOnly: true,
|
|
1944
1945
|
secure: true,
|
|
@@ -2272,7 +2273,7 @@ var OAuthService = class {
|
|
|
2272
2273
|
var STATE_COOKIE_NAME = "oauth_state";
|
|
2273
2274
|
var STATE_COOKIE_MAX_AGE = 600;
|
|
2274
2275
|
function createOAuthProvidersPlugin() {
|
|
2275
|
-
const builder =
|
|
2276
|
+
const builder = chunk635JAMSE_cjs.PluginBuilder.create({
|
|
2276
2277
|
name: "oauth-providers",
|
|
2277
2278
|
version: "1.0.0-beta.1",
|
|
2278
2279
|
description: "OAuth2/OIDC social login with GitHub, Google, and more"
|
|
@@ -2408,13 +2409,13 @@ function createOAuthProvidersPlugin() {
|
|
|
2408
2409
|
if (!user || !user.is_active) {
|
|
2409
2410
|
return c.redirect("/auth/login?error=Account is deactivated");
|
|
2410
2411
|
}
|
|
2411
|
-
const jwt2 = await
|
|
2412
|
+
const jwt2 = await chunkCZ6BVQZX_cjs.AuthManager.generateToken(
|
|
2412
2413
|
user.id,
|
|
2413
2414
|
user.email,
|
|
2414
2415
|
user.role,
|
|
2415
2416
|
c.env.JWT_SECRET
|
|
2416
2417
|
);
|
|
2417
|
-
|
|
2418
|
+
chunkCZ6BVQZX_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax" });
|
|
2418
2419
|
return c.redirect("/admin");
|
|
2419
2420
|
}
|
|
2420
2421
|
const existingUser = await oauthService.findUserByEmail(profile.email);
|
|
@@ -2431,13 +2432,13 @@ function createOAuthProvidersPlugin() {
|
|
|
2431
2432
|
tokenExpiresAt: tokenExpiresAt ?? void 0,
|
|
2432
2433
|
profileData: JSON.stringify(profile)
|
|
2433
2434
|
});
|
|
2434
|
-
const jwt2 = await
|
|
2435
|
+
const jwt2 = await chunkCZ6BVQZX_cjs.AuthManager.generateToken(
|
|
2435
2436
|
existingUser.id,
|
|
2436
2437
|
existingUser.email,
|
|
2437
2438
|
existingUser.role,
|
|
2438
2439
|
c.env.JWT_SECRET
|
|
2439
2440
|
);
|
|
2440
|
-
|
|
2441
|
+
chunkCZ6BVQZX_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax" });
|
|
2441
2442
|
return c.redirect("/admin");
|
|
2442
2443
|
}
|
|
2443
2444
|
const newUserId = await oauthService.createUserFromOAuth(profile);
|
|
@@ -2450,13 +2451,13 @@ function createOAuthProvidersPlugin() {
|
|
|
2450
2451
|
tokenExpiresAt: tokenExpiresAt ?? void 0,
|
|
2451
2452
|
profileData: JSON.stringify(profile)
|
|
2452
2453
|
});
|
|
2453
|
-
const jwt = await
|
|
2454
|
+
const jwt = await chunkCZ6BVQZX_cjs.AuthManager.generateToken(
|
|
2454
2455
|
newUserId,
|
|
2455
2456
|
profile.email.toLowerCase(),
|
|
2456
2457
|
"viewer",
|
|
2457
2458
|
c.env.JWT_SECRET
|
|
2458
2459
|
);
|
|
2459
|
-
|
|
2460
|
+
chunkCZ6BVQZX_cjs.AuthManager.setAuthCookie(c, jwt, { sameSite: "Lax" });
|
|
2460
2461
|
return c.redirect("/admin");
|
|
2461
2462
|
} catch (error) {
|
|
2462
2463
|
console.error("OAuth callback error:", error);
|
|
@@ -4138,7 +4139,7 @@ function renderSettingsPage(data) {
|
|
|
4138
4139
|
}, 30000);
|
|
4139
4140
|
</script>
|
|
4140
4141
|
`;
|
|
4141
|
-
return
|
|
4142
|
+
return chunkOHYBNCVL_cjs.renderAdminLayout({
|
|
4142
4143
|
title: "AI Search Settings",
|
|
4143
4144
|
pageTitle: "AI Search Settings",
|
|
4144
4145
|
currentPath: "/admin/plugins/ai-search/settings",
|
|
@@ -4149,7 +4150,7 @@ function renderSettingsPage(data) {
|
|
|
4149
4150
|
|
|
4150
4151
|
// src/plugins/core-plugins/ai-search-plugin/routes/admin.ts
|
|
4151
4152
|
var adminRoutes = new hono.Hono();
|
|
4152
|
-
adminRoutes.use("*",
|
|
4153
|
+
adminRoutes.use("*", chunkCZ6BVQZX_cjs.requireAuth());
|
|
4153
4154
|
adminRoutes.get("/", async (c) => {
|
|
4154
4155
|
try {
|
|
4155
4156
|
const user = c.get("user");
|
|
@@ -4395,7 +4396,7 @@ var manifest_default = {
|
|
|
4395
4396
|
author: "SonicJS"};
|
|
4396
4397
|
|
|
4397
4398
|
// src/plugins/core-plugins/ai-search-plugin/index.ts
|
|
4398
|
-
var aiSearchPlugin = new
|
|
4399
|
+
var aiSearchPlugin = new chunk635JAMSE_cjs.PluginBuilder({
|
|
4399
4400
|
name: manifest_default.name,
|
|
4400
4401
|
version: manifest_default.version,
|
|
4401
4402
|
description: manifest_default.description,
|
|
@@ -4550,13 +4551,13 @@ function createMagicLinkAuthPlugin() {
|
|
|
4550
4551
|
SET used = 1, used_at = ?
|
|
4551
4552
|
WHERE id = ?
|
|
4552
4553
|
`).bind(Date.now(), magicLink.id).run();
|
|
4553
|
-
const jwtToken = await
|
|
4554
|
+
const jwtToken = await chunkCZ6BVQZX_cjs.AuthManager.generateToken(
|
|
4554
4555
|
user.id,
|
|
4555
4556
|
user.email,
|
|
4556
4557
|
user.role,
|
|
4557
4558
|
c.env.JWT_SECRET
|
|
4558
4559
|
);
|
|
4559
|
-
|
|
4560
|
+
chunkCZ6BVQZX_cjs.AuthManager.setAuthCookie(c, jwtToken);
|
|
4560
4561
|
await db.prepare(`
|
|
4561
4562
|
UPDATE users SET last_login_at = ? WHERE id = ?
|
|
4562
4563
|
`).bind(Date.now(), user.id).run();
|
|
@@ -4994,7 +4995,7 @@ var SecurityAuditService = class {
|
|
|
4994
4995
|
};
|
|
4995
4996
|
|
|
4996
4997
|
// src/plugins/core-plugins/security-audit-plugin/components/dashboard-page.ts
|
|
4997
|
-
|
|
4998
|
+
chunkUYJ6TJHX_cjs.init_admin_layout_catalyst_template();
|
|
4998
4999
|
function formatTimestamp(ts) {
|
|
4999
5000
|
const date = new Date(ts);
|
|
5000
5001
|
const now = Date.now();
|
|
@@ -5193,11 +5194,11 @@ function renderSecurityDashboard(data) {
|
|
|
5193
5194
|
version,
|
|
5194
5195
|
dynamicMenuItems
|
|
5195
5196
|
};
|
|
5196
|
-
return
|
|
5197
|
+
return chunkUYJ6TJHX_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
5197
5198
|
}
|
|
5198
5199
|
|
|
5199
5200
|
// src/plugins/core-plugins/security-audit-plugin/components/event-log-page.ts
|
|
5200
|
-
|
|
5201
|
+
chunkUYJ6TJHX_cjs.init_admin_layout_catalyst_template();
|
|
5201
5202
|
function formatTimestamp2(ts) {
|
|
5202
5203
|
const date = new Date(ts);
|
|
5203
5204
|
return date.toLocaleDateString("en-US", {
|
|
@@ -5404,11 +5405,11 @@ function renderEventLogPage(data) {
|
|
|
5404
5405
|
version,
|
|
5405
5406
|
dynamicMenuItems
|
|
5406
5407
|
};
|
|
5407
|
-
return
|
|
5408
|
+
return chunkUYJ6TJHX_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
5408
5409
|
}
|
|
5409
5410
|
|
|
5410
5411
|
// src/plugins/core-plugins/security-audit-plugin/components/settings-page.ts
|
|
5411
|
-
|
|
5412
|
+
chunkUYJ6TJHX_cjs.init_admin_layout_catalyst_template();
|
|
5412
5413
|
function renderSecuritySettingsPage(data) {
|
|
5413
5414
|
const { settings, user, version, message, dynamicMenuItems } = data;
|
|
5414
5415
|
const content2 = `
|
|
@@ -5561,12 +5562,12 @@ function renderSecuritySettingsPage(data) {
|
|
|
5561
5562
|
version,
|
|
5562
5563
|
dynamicMenuItems
|
|
5563
5564
|
};
|
|
5564
|
-
return
|
|
5565
|
+
return chunkUYJ6TJHX_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
5565
5566
|
}
|
|
5566
5567
|
|
|
5567
5568
|
// src/plugins/core-plugins/security-audit-plugin/routes/admin.ts
|
|
5568
5569
|
var adminRoutes2 = new hono.Hono();
|
|
5569
|
-
adminRoutes2.use("*",
|
|
5570
|
+
adminRoutes2.use("*", chunkCZ6BVQZX_cjs.requireAuth());
|
|
5570
5571
|
adminRoutes2.use("*", async (c, next) => {
|
|
5571
5572
|
const user = c.get("user");
|
|
5572
5573
|
if (user?.role !== "admin") {
|
|
@@ -5576,7 +5577,7 @@ adminRoutes2.use("*", async (c, next) => {
|
|
|
5576
5577
|
});
|
|
5577
5578
|
async function getSettings(db) {
|
|
5578
5579
|
try {
|
|
5579
|
-
const pluginService = new
|
|
5580
|
+
const pluginService = new chunkQ5VFZUXV_cjs.PluginService(db);
|
|
5580
5581
|
const plugin2 = await pluginService.getPlugin("security-audit");
|
|
5581
5582
|
if (plugin2?.settings) {
|
|
5582
5583
|
const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
|
|
@@ -5681,7 +5682,7 @@ adminRoutes2.post("/settings", async (c) => {
|
|
|
5681
5682
|
autoPurge: body["retention.autoPurge"] === "true"
|
|
5682
5683
|
}
|
|
5683
5684
|
};
|
|
5684
|
-
const pluginService = new
|
|
5685
|
+
const pluginService = new chunkQ5VFZUXV_cjs.PluginService(db);
|
|
5685
5686
|
await pluginService.updatePluginSettings("security-audit", settings);
|
|
5686
5687
|
if (c.req.header("HX-Request")) {
|
|
5687
5688
|
return c.json({ success: true });
|
|
@@ -5699,7 +5700,7 @@ var BruteForceDetector = class {
|
|
|
5699
5700
|
}
|
|
5700
5701
|
settings;
|
|
5701
5702
|
async recordFailedAttempt(ip, email) {
|
|
5702
|
-
if (!this.settings.enabled) {
|
|
5703
|
+
if (!this.settings.enabled || !this.kv) {
|
|
5703
5704
|
return { ipCount: 0, emailCount: 0, shouldLockIP: false, shouldLockEmail: false, isSuspicious: false };
|
|
5704
5705
|
}
|
|
5705
5706
|
const windowMs = this.settings.windowMinutes * 60 * 1e3;
|
|
@@ -5716,7 +5717,7 @@ var BruteForceDetector = class {
|
|
|
5716
5717
|
return { ipCount, emailCount, shouldLockIP, shouldLockEmail, isSuspicious };
|
|
5717
5718
|
}
|
|
5718
5719
|
async isLocked(ip, email) {
|
|
5719
|
-
if (!this.settings.enabled) {
|
|
5720
|
+
if (!this.settings.enabled || !this.kv) {
|
|
5720
5721
|
return { locked: false };
|
|
5721
5722
|
}
|
|
5722
5723
|
const ipLocked = await this.kv.get(`${LOCK_PREFIX}ip:${ip}`);
|
|
@@ -5730,6 +5731,7 @@ var BruteForceDetector = class {
|
|
|
5730
5731
|
return { locked: false };
|
|
5731
5732
|
}
|
|
5732
5733
|
async lockIP(ip) {
|
|
5734
|
+
if (!this.kv) return;
|
|
5733
5735
|
const ttl = this.settings.lockoutDurationMinutes * 60;
|
|
5734
5736
|
await this.kv.put(`${LOCK_PREFIX}ip:${ip}`, JSON.stringify({
|
|
5735
5737
|
lockedAt: Date.now(),
|
|
@@ -5737,6 +5739,7 @@ var BruteForceDetector = class {
|
|
|
5737
5739
|
}), { expirationTtl: ttl });
|
|
5738
5740
|
}
|
|
5739
5741
|
async lockEmail(email) {
|
|
5742
|
+
if (!this.kv) return;
|
|
5740
5743
|
const ttl = this.settings.lockoutDurationMinutes * 60;
|
|
5741
5744
|
await this.kv.put(`${LOCK_PREFIX}email:${email}`, JSON.stringify({
|
|
5742
5745
|
lockedAt: Date.now(),
|
|
@@ -5744,12 +5747,15 @@ var BruteForceDetector = class {
|
|
|
5744
5747
|
}), { expirationTtl: ttl });
|
|
5745
5748
|
}
|
|
5746
5749
|
async unlockIP(ip) {
|
|
5750
|
+
if (!this.kv) return;
|
|
5747
5751
|
await this.kv.delete(`${LOCK_PREFIX}ip:${ip}`);
|
|
5748
5752
|
}
|
|
5749
5753
|
async unlockEmail(email) {
|
|
5754
|
+
if (!this.kv) return;
|
|
5750
5755
|
await this.kv.delete(`${LOCK_PREFIX}email:${email}`);
|
|
5751
5756
|
}
|
|
5752
5757
|
async getActiveLockouts() {
|
|
5758
|
+
if (!this.kv) return [];
|
|
5753
5759
|
const ipLocks = await this.kv.list({ prefix: `${LOCK_PREFIX}ip:` });
|
|
5754
5760
|
const emailLocks = await this.kv.list({ prefix: `${LOCK_PREFIX}email:` });
|
|
5755
5761
|
const lockouts = [];
|
|
@@ -5780,6 +5786,7 @@ var BruteForceDetector = class {
|
|
|
5780
5786
|
return lockouts;
|
|
5781
5787
|
}
|
|
5782
5788
|
async releaseLockout(key) {
|
|
5789
|
+
if (!this.kv) return;
|
|
5783
5790
|
await this.kv.delete(key);
|
|
5784
5791
|
}
|
|
5785
5792
|
isAboveAlertThreshold(count) {
|
|
@@ -5836,7 +5843,7 @@ var BruteForceDetector = class {
|
|
|
5836
5843
|
|
|
5837
5844
|
// src/plugins/core-plugins/security-audit-plugin/routes/api.ts
|
|
5838
5845
|
var apiRoutes2 = new hono.Hono();
|
|
5839
|
-
apiRoutes2.use("*",
|
|
5846
|
+
apiRoutes2.use("*", chunkCZ6BVQZX_cjs.requireAuth());
|
|
5840
5847
|
apiRoutes2.use("*", async (c, next) => {
|
|
5841
5848
|
const user = c.get("user");
|
|
5842
5849
|
if (user?.role !== "admin") {
|
|
@@ -5846,7 +5853,7 @@ apiRoutes2.use("*", async (c, next) => {
|
|
|
5846
5853
|
});
|
|
5847
5854
|
async function getSettings2(db) {
|
|
5848
5855
|
try {
|
|
5849
|
-
const pluginService = new
|
|
5856
|
+
const pluginService = new chunkQ5VFZUXV_cjs.PluginService(db);
|
|
5850
5857
|
const plugin2 = await pluginService.getPlugin("security-audit");
|
|
5851
5858
|
if (plugin2?.settings) {
|
|
5852
5859
|
const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
|
|
@@ -5994,7 +6001,7 @@ function generateFingerprint(ip, userAgent) {
|
|
|
5994
6001
|
}
|
|
5995
6002
|
async function getPluginSettings(db) {
|
|
5996
6003
|
try {
|
|
5997
|
-
const pluginService = new
|
|
6004
|
+
const pluginService = new chunkQ5VFZUXV_cjs.PluginService(db);
|
|
5998
6005
|
const plugin2 = await pluginService.getPlugin("security-audit");
|
|
5999
6006
|
if (plugin2?.settings) {
|
|
6000
6007
|
const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
|
|
@@ -6225,7 +6232,7 @@ async function logAuthEvent(c, db, settings, ip, userAgent, countryCode, fingerp
|
|
|
6225
6232
|
|
|
6226
6233
|
// src/plugins/core-plugins/security-audit-plugin/index.ts
|
|
6227
6234
|
function createSecurityAuditPlugin() {
|
|
6228
|
-
const builder =
|
|
6235
|
+
const builder = chunk635JAMSE_cjs.PluginBuilder.create({
|
|
6229
6236
|
name: "security-audit",
|
|
6230
6237
|
version: "1.0.0-beta.1",
|
|
6231
6238
|
description: "Security event logging, brute-force detection, and analytics dashboard"
|
|
@@ -6323,6 +6330,33 @@ var SubscriptionService = class {
|
|
|
6323
6330
|
).first();
|
|
6324
6331
|
return this.mapRow(result);
|
|
6325
6332
|
}
|
|
6333
|
+
/**
|
|
6334
|
+
* Upsert a subscription by stripe_subscription_id (INSERT or UPDATE on conflict)
|
|
6335
|
+
*/
|
|
6336
|
+
async upsert(data) {
|
|
6337
|
+
const result = await this.db.prepare(`
|
|
6338
|
+
INSERT INTO subscriptions (user_id, stripe_customer_id, stripe_subscription_id, stripe_price_id, status, current_period_start, current_period_end, cancel_at_period_end)
|
|
6339
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
6340
|
+
ON CONFLICT(stripe_subscription_id) DO UPDATE SET
|
|
6341
|
+
status = excluded.status,
|
|
6342
|
+
stripe_price_id = excluded.stripe_price_id,
|
|
6343
|
+
current_period_start = excluded.current_period_start,
|
|
6344
|
+
current_period_end = excluded.current_period_end,
|
|
6345
|
+
cancel_at_period_end = excluded.cancel_at_period_end,
|
|
6346
|
+
updated_at = unixepoch()
|
|
6347
|
+
RETURNING *
|
|
6348
|
+
`).bind(
|
|
6349
|
+
data.userId,
|
|
6350
|
+
data.stripeCustomerId,
|
|
6351
|
+
data.stripeSubscriptionId,
|
|
6352
|
+
data.stripePriceId,
|
|
6353
|
+
data.status,
|
|
6354
|
+
data.currentPeriodStart,
|
|
6355
|
+
data.currentPeriodEnd,
|
|
6356
|
+
data.cancelAtPeriodEnd ? 1 : 0
|
|
6357
|
+
).first();
|
|
6358
|
+
return this.mapRow(result);
|
|
6359
|
+
}
|
|
6326
6360
|
/**
|
|
6327
6361
|
* Update a subscription by its Stripe subscription ID
|
|
6328
6362
|
*/
|
|
@@ -6477,24 +6511,183 @@ var SubscriptionService = class {
|
|
|
6477
6511
|
}
|
|
6478
6512
|
};
|
|
6479
6513
|
|
|
6514
|
+
// src/plugins/core-plugins/stripe-plugin/services/stripe-event-service.ts
|
|
6515
|
+
var StripeEventService = class {
|
|
6516
|
+
constructor(db) {
|
|
6517
|
+
this.db = db;
|
|
6518
|
+
}
|
|
6519
|
+
async ensureTable() {
|
|
6520
|
+
await this.db.prepare(`
|
|
6521
|
+
CREATE TABLE IF NOT EXISTS stripe_events (
|
|
6522
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
6523
|
+
stripe_event_id TEXT NOT NULL UNIQUE,
|
|
6524
|
+
type TEXT NOT NULL,
|
|
6525
|
+
object_id TEXT NOT NULL DEFAULT '',
|
|
6526
|
+
object_type TEXT NOT NULL DEFAULT '',
|
|
6527
|
+
data TEXT NOT NULL DEFAULT '{}',
|
|
6528
|
+
processed_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
6529
|
+
status TEXT NOT NULL DEFAULT 'processed',
|
|
6530
|
+
error TEXT
|
|
6531
|
+
)
|
|
6532
|
+
`).run();
|
|
6533
|
+
await this.db.prepare(`
|
|
6534
|
+
CREATE INDEX IF NOT EXISTS idx_stripe_events_type ON stripe_events(type)
|
|
6535
|
+
`).run();
|
|
6536
|
+
await this.db.prepare(`
|
|
6537
|
+
CREATE INDEX IF NOT EXISTS idx_stripe_events_status ON stripe_events(status)
|
|
6538
|
+
`).run();
|
|
6539
|
+
await this.db.prepare(`
|
|
6540
|
+
CREATE INDEX IF NOT EXISTS idx_stripe_events_processed_at ON stripe_events(processed_at DESC)
|
|
6541
|
+
`).run();
|
|
6542
|
+
}
|
|
6543
|
+
async log(event) {
|
|
6544
|
+
await this.db.prepare(`
|
|
6545
|
+
INSERT INTO stripe_events (stripe_event_id, type, object_id, object_type, data, status, error)
|
|
6546
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
6547
|
+
ON CONFLICT(stripe_event_id) DO UPDATE SET
|
|
6548
|
+
status = excluded.status,
|
|
6549
|
+
error = excluded.error,
|
|
6550
|
+
processed_at = unixepoch()
|
|
6551
|
+
`).bind(
|
|
6552
|
+
event.stripeEventId,
|
|
6553
|
+
event.type,
|
|
6554
|
+
event.objectId,
|
|
6555
|
+
event.objectType,
|
|
6556
|
+
JSON.stringify(event.data),
|
|
6557
|
+
event.status,
|
|
6558
|
+
event.error || null
|
|
6559
|
+
).run();
|
|
6560
|
+
}
|
|
6561
|
+
async list(filters = {}) {
|
|
6562
|
+
const where = [];
|
|
6563
|
+
const values = [];
|
|
6564
|
+
if (filters.type) {
|
|
6565
|
+
where.push("type = ?");
|
|
6566
|
+
values.push(filters.type);
|
|
6567
|
+
}
|
|
6568
|
+
if (filters.status) {
|
|
6569
|
+
where.push("status = ?");
|
|
6570
|
+
values.push(filters.status);
|
|
6571
|
+
}
|
|
6572
|
+
if (filters.objectId) {
|
|
6573
|
+
where.push("object_id = ?");
|
|
6574
|
+
values.push(filters.objectId);
|
|
6575
|
+
}
|
|
6576
|
+
const whereClause = where.length > 0 ? `WHERE ${where.join(" AND ")}` : "";
|
|
6577
|
+
const limit = Math.min(filters.limit || 50, 100);
|
|
6578
|
+
const page = filters.page || 1;
|
|
6579
|
+
const offset = (page - 1) * limit;
|
|
6580
|
+
const countResult = await this.db.prepare(
|
|
6581
|
+
`SELECT COUNT(*) as count FROM stripe_events ${whereClause}`
|
|
6582
|
+
).bind(...values).first();
|
|
6583
|
+
const results = await this.db.prepare(
|
|
6584
|
+
`SELECT * FROM stripe_events ${whereClause} ORDER BY processed_at DESC LIMIT ? OFFSET ?`
|
|
6585
|
+
).bind(...values, limit, offset).all();
|
|
6586
|
+
return {
|
|
6587
|
+
events: (results.results || []).map((r) => this.mapRow(r)),
|
|
6588
|
+
total: countResult?.count || 0
|
|
6589
|
+
};
|
|
6590
|
+
}
|
|
6591
|
+
async getStats() {
|
|
6592
|
+
const result = await this.db.prepare(`
|
|
6593
|
+
SELECT
|
|
6594
|
+
COUNT(*) as total,
|
|
6595
|
+
SUM(CASE WHEN status = 'processed' THEN 1 ELSE 0 END) as processed,
|
|
6596
|
+
SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed,
|
|
6597
|
+
SUM(CASE WHEN status = 'ignored' THEN 1 ELSE 0 END) as ignored
|
|
6598
|
+
FROM stripe_events
|
|
6599
|
+
`).first();
|
|
6600
|
+
return {
|
|
6601
|
+
total: result?.total || 0,
|
|
6602
|
+
processed: result?.processed || 0,
|
|
6603
|
+
failed: result?.failed || 0,
|
|
6604
|
+
ignored: result?.ignored || 0
|
|
6605
|
+
};
|
|
6606
|
+
}
|
|
6607
|
+
async getDistinctTypes() {
|
|
6608
|
+
const results = await this.db.prepare(
|
|
6609
|
+
"SELECT DISTINCT type FROM stripe_events ORDER BY type"
|
|
6610
|
+
).all();
|
|
6611
|
+
return (results.results || []).map((r) => r.type);
|
|
6612
|
+
}
|
|
6613
|
+
mapRow(row) {
|
|
6614
|
+
return {
|
|
6615
|
+
id: row.id,
|
|
6616
|
+
stripeEventId: row.stripe_event_id,
|
|
6617
|
+
type: row.type,
|
|
6618
|
+
objectId: row.object_id,
|
|
6619
|
+
objectType: row.object_type,
|
|
6620
|
+
data: row.data,
|
|
6621
|
+
processedAt: row.processed_at,
|
|
6622
|
+
status: row.status,
|
|
6623
|
+
error: row.error || void 0
|
|
6624
|
+
};
|
|
6625
|
+
}
|
|
6626
|
+
};
|
|
6627
|
+
|
|
6480
6628
|
// src/plugins/core-plugins/stripe-plugin/components/subscriptions-page.ts
|
|
6481
|
-
|
|
6629
|
+
chunkUYJ6TJHX_cjs.init_admin_layout_catalyst_template();
|
|
6630
|
+
|
|
6631
|
+
// src/plugins/core-plugins/stripe-plugin/components/tab-bar.ts
|
|
6632
|
+
var TABS = [
|
|
6633
|
+
{ label: "Subscriptions", path: "/admin/plugins/stripe" },
|
|
6634
|
+
{ label: "Events", path: "/admin/plugins/stripe/events" },
|
|
6635
|
+
{ label: "Settings", path: "/admin/plugins/stripe/settings" }
|
|
6636
|
+
];
|
|
6637
|
+
function renderStripeTabBar(currentPath) {
|
|
6638
|
+
const tabs = TABS.map((tab) => {
|
|
6639
|
+
const isActive = currentPath === tab.path || tab.path === "/admin/plugins/stripe" && currentPath === "/admin/plugins/stripe/";
|
|
6640
|
+
return `
|
|
6641
|
+
<a href="${tab.path}"
|
|
6642
|
+
class="${isActive ? "border-cyan-500 text-zinc-950 dark:text-white" : "border-transparent text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300 hover:border-zinc-300 dark:hover:border-zinc-600"} whitespace-nowrap border-b-2 px-4 py-3 text-sm font-medium transition-colors">
|
|
6643
|
+
${tab.label}
|
|
6644
|
+
</a>`;
|
|
6645
|
+
}).join("");
|
|
6482
6646
|
return `
|
|
6483
|
-
<div class="
|
|
6647
|
+
<div class="border-b border-zinc-950/5 dark:border-white/10 mb-6">
|
|
6648
|
+
<nav class="-mb-px flex gap-x-2" aria-label="Stripe tabs">
|
|
6649
|
+
${tabs}
|
|
6650
|
+
</nav>
|
|
6651
|
+
</div>
|
|
6652
|
+
`;
|
|
6653
|
+
}
|
|
6654
|
+
|
|
6655
|
+
// src/plugins/core-plugins/stripe-plugin/components/subscriptions-page.ts
|
|
6656
|
+
function renderSubscriptionsPage(data) {
|
|
6657
|
+
const { subscriptions, stats, filters, user, version, dynamicMenuItems } = data;
|
|
6658
|
+
const content2 = `
|
|
6659
|
+
<div>
|
|
6660
|
+
<div class="sm:flex sm:items-center sm:justify-between mb-6">
|
|
6661
|
+
<div class="sm:flex-auto">
|
|
6662
|
+
<h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">Stripe</h1>
|
|
6663
|
+
<p class="mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400">
|
|
6664
|
+
Manage subscriptions, view billing status, and monitor payment events.
|
|
6665
|
+
</p>
|
|
6666
|
+
</div>
|
|
6667
|
+
<div class="mt-4 sm:mt-0 sm:ml-16">
|
|
6668
|
+
<button id="sync-btn" onclick="syncSubscriptions()"
|
|
6669
|
+
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">
|
|
6670
|
+
Sync from Stripe
|
|
6671
|
+
</button>
|
|
6672
|
+
</div>
|
|
6673
|
+
</div>
|
|
6674
|
+
|
|
6675
|
+
${renderStripeTabBar("/admin/plugins/stripe")}
|
|
6676
|
+
|
|
6484
6677
|
<!-- Stats Cards -->
|
|
6485
|
-
<div class="grid grid-cols-1
|
|
6486
|
-
${statsCard("Total", stats.total, "text-
|
|
6487
|
-
${statsCard("Active", stats.active, "text-
|
|
6488
|
-
${statsCard("Trialing", stats.trialing, "text-blue-600")}
|
|
6489
|
-
${statsCard("Past Due", stats.pastDue, "text-
|
|
6490
|
-
${statsCard("Canceled", stats.canceled, "text-red-600")}
|
|
6678
|
+
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-5 mb-6">
|
|
6679
|
+
${statsCard("Total", stats.total, "text-zinc-950 dark:text-white")}
|
|
6680
|
+
${statsCard("Active", stats.active, "text-emerald-600 dark:text-emerald-400")}
|
|
6681
|
+
${statsCard("Trialing", stats.trialing, "text-blue-600 dark:text-blue-400")}
|
|
6682
|
+
${statsCard("Past Due", stats.pastDue, "text-amber-600 dark:text-amber-400")}
|
|
6683
|
+
${statsCard("Canceled", stats.canceled, "text-red-600 dark:text-red-400")}
|
|
6491
6684
|
</div>
|
|
6492
6685
|
|
|
6493
6686
|
<!-- Filters -->
|
|
6494
|
-
<div class="bg-white
|
|
6687
|
+
<div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-4 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm mb-6">
|
|
6495
6688
|
<form method="GET" class="flex items-center gap-4">
|
|
6496
|
-
<label class="text-sm font-medium text-
|
|
6497
|
-
<select name="status" class="border
|
|
6689
|
+
<label class="text-sm font-medium text-zinc-500 dark:text-zinc-400">Status:</label>
|
|
6690
|
+
<select name="status" class="rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-1.5 text-sm text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10" onchange="this.form.submit()">
|
|
6498
6691
|
<option value="">All</option>
|
|
6499
6692
|
${statusOption("active", filters.status)}
|
|
6500
6693
|
${statusOption("trialing", filters.status)}
|
|
@@ -6507,33 +6700,72 @@ function renderSubscriptionsPage(subscriptions, stats, filters) {
|
|
|
6507
6700
|
</div>
|
|
6508
6701
|
|
|
6509
6702
|
<!-- Subscriptions Table -->
|
|
6510
|
-
<div class="bg-white
|
|
6511
|
-
<table class="min-w-full divide-y divide-
|
|
6512
|
-
<thead
|
|
6703
|
+
<div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-hidden">
|
|
6704
|
+
<table class="min-w-full divide-y divide-zinc-950/5 dark:divide-white/5">
|
|
6705
|
+
<thead>
|
|
6513
6706
|
<tr>
|
|
6514
|
-
<th class="px-6 py-3 text-left text-xs font-medium text-
|
|
6515
|
-
<th class="px-6 py-3 text-left text-xs font-medium text-
|
|
6516
|
-
<th class="px-6 py-3 text-left text-xs font-medium text-
|
|
6517
|
-
<th class="px-6 py-3 text-left text-xs font-medium text-
|
|
6518
|
-
<th class="px-6 py-3 text-left text-xs font-medium text-
|
|
6519
|
-
<th class="px-6 py-3 text-left text-xs font-medium text-
|
|
6707
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">User</th>
|
|
6708
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Status</th>
|
|
6709
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Price ID</th>
|
|
6710
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Current Period</th>
|
|
6711
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Cancel at End</th>
|
|
6712
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Stripe</th>
|
|
6520
6713
|
</tr>
|
|
6521
6714
|
</thead>
|
|
6522
|
-
<tbody class="
|
|
6523
|
-
${subscriptions.length === 0 ? '<tr><td colspan="6" class="px-6 py-8 text-center text-
|
|
6715
|
+
<tbody class="divide-y divide-zinc-950/5 dark:divide-white/5">
|
|
6716
|
+
${subscriptions.length === 0 ? '<tr><td colspan="6" class="px-6 py-8 text-center text-zinc-500 dark:text-zinc-400">No subscriptions found</td></tr>' : subscriptions.map(renderRow).join("")}
|
|
6524
6717
|
</tbody>
|
|
6525
6718
|
</table>
|
|
6526
6719
|
|
|
6527
6720
|
${renderPagination2(filters.page, filters.totalPages, filters.status)}
|
|
6528
6721
|
</div>
|
|
6722
|
+
|
|
6723
|
+
<div id="sync-message" class="hidden mt-4 rounded-lg p-4 text-sm"></div>
|
|
6529
6724
|
</div>
|
|
6725
|
+
|
|
6726
|
+
<script>
|
|
6727
|
+
async function syncSubscriptions() {
|
|
6728
|
+
const btn = document.getElementById('sync-btn')
|
|
6729
|
+
const msg = document.getElementById('sync-message')
|
|
6730
|
+
btn.disabled = true
|
|
6731
|
+
btn.textContent = 'Syncing...'
|
|
6732
|
+
msg.className = 'hidden mt-4 rounded-lg p-4 text-sm'
|
|
6733
|
+
try {
|
|
6734
|
+
const res = await fetch('/api/stripe/sync-subscriptions', { method: 'POST' })
|
|
6735
|
+
const result = await res.json()
|
|
6736
|
+
if (result.success) {
|
|
6737
|
+
msg.className = 'mt-4 rounded-lg p-4 text-sm bg-emerald-400/10 text-emerald-500 dark:text-emerald-400 ring-1 ring-inset ring-emerald-400/20'
|
|
6738
|
+
msg.textContent = 'Synced ' + result.synced + ' of ' + result.total + ' subscriptions from Stripe.' + (result.errors > 0 ? ' (' + result.errors + ' errors)' : '')
|
|
6739
|
+
setTimeout(() => location.reload(), 1500)
|
|
6740
|
+
} else {
|
|
6741
|
+
msg.className = 'mt-4 rounded-lg p-4 text-sm bg-red-400/10 text-red-500 dark:text-red-400 ring-1 ring-inset ring-red-400/20'
|
|
6742
|
+
msg.textContent = result.error || 'Sync failed.'
|
|
6743
|
+
}
|
|
6744
|
+
} catch {
|
|
6745
|
+
msg.className = 'mt-4 rounded-lg p-4 text-sm bg-red-400/10 text-red-500 dark:text-red-400 ring-1 ring-inset ring-red-400/20'
|
|
6746
|
+
msg.textContent = 'Network error. Please try again.'
|
|
6747
|
+
}
|
|
6748
|
+
btn.disabled = false
|
|
6749
|
+
btn.textContent = 'Sync from Stripe'
|
|
6750
|
+
}
|
|
6751
|
+
</script>
|
|
6530
6752
|
`;
|
|
6753
|
+
const layoutData = {
|
|
6754
|
+
title: "Stripe Subscriptions",
|
|
6755
|
+
pageTitle: "Stripe Subscriptions",
|
|
6756
|
+
currentPath: "/admin/plugins/stripe",
|
|
6757
|
+
user,
|
|
6758
|
+
content: content2,
|
|
6759
|
+
version,
|
|
6760
|
+
dynamicMenuItems
|
|
6761
|
+
};
|
|
6762
|
+
return chunkUYJ6TJHX_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
6531
6763
|
}
|
|
6532
6764
|
function statsCard(label, value, colorClass) {
|
|
6533
6765
|
return `
|
|
6534
|
-
<div class="bg-white
|
|
6535
|
-
<
|
|
6536
|
-
<
|
|
6766
|
+
<div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm">
|
|
6767
|
+
<p class="text-sm font-medium text-zinc-500 dark:text-zinc-400">${label}</p>
|
|
6768
|
+
<p class="mt-2 text-3xl font-bold ${colorClass}">${value}</p>
|
|
6537
6769
|
</div>
|
|
6538
6770
|
`;
|
|
6539
6771
|
}
|
|
@@ -6544,18 +6776,18 @@ function statusOption(value, current) {
|
|
|
6544
6776
|
}
|
|
6545
6777
|
function statusBadge(status) {
|
|
6546
6778
|
const colors = {
|
|
6547
|
-
active: "bg-
|
|
6548
|
-
trialing: "bg-blue-
|
|
6549
|
-
past_due: "bg-
|
|
6550
|
-
canceled: "bg-red-
|
|
6551
|
-
unpaid: "bg-orange-
|
|
6552
|
-
paused: "bg-
|
|
6553
|
-
incomplete: "bg-
|
|
6554
|
-
incomplete_expired: "bg-red-
|
|
6779
|
+
active: "bg-emerald-400/10 text-emerald-500 dark:text-emerald-400 ring-emerald-400/20",
|
|
6780
|
+
trialing: "bg-blue-400/10 text-blue-500 dark:text-blue-400 ring-blue-400/20",
|
|
6781
|
+
past_due: "bg-amber-400/10 text-amber-500 dark:text-amber-400 ring-amber-400/20",
|
|
6782
|
+
canceled: "bg-red-400/10 text-red-500 dark:text-red-400 ring-red-400/20",
|
|
6783
|
+
unpaid: "bg-orange-400/10 text-orange-500 dark:text-orange-400 ring-orange-400/20",
|
|
6784
|
+
paused: "bg-zinc-400/10 text-zinc-500 dark:text-zinc-400 ring-zinc-400/20",
|
|
6785
|
+
incomplete: "bg-zinc-400/10 text-zinc-500 dark:text-zinc-400 ring-zinc-400/20",
|
|
6786
|
+
incomplete_expired: "bg-red-400/10 text-red-500 dark:text-red-400 ring-red-400/20"
|
|
6555
6787
|
};
|
|
6556
|
-
const color = colors[status] || "bg-
|
|
6788
|
+
const color = colors[status] || "bg-zinc-400/10 text-zinc-500 ring-zinc-400/20";
|
|
6557
6789
|
const label = status.replace("_", " ");
|
|
6558
|
-
return `<span class="inline-flex items-center px-2
|
|
6790
|
+
return `<span class="inline-flex items-center rounded-full px-2 py-1 text-xs font-medium ring-1 ring-inset ${color}">${label}</span>`;
|
|
6559
6791
|
}
|
|
6560
6792
|
function formatDate(timestamp) {
|
|
6561
6793
|
if (!timestamp) return "-";
|
|
@@ -6567,23 +6799,23 @@ function formatDate(timestamp) {
|
|
|
6567
6799
|
}
|
|
6568
6800
|
function renderRow(sub) {
|
|
6569
6801
|
return `
|
|
6570
|
-
<tr>
|
|
6802
|
+
<tr class="hover:bg-zinc-950/[0.025] dark:hover:bg-white/[0.025]">
|
|
6571
6803
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
6572
|
-
<div class="text-sm font-medium text-
|
|
6573
|
-
<div class="text-xs text-
|
|
6804
|
+
<div class="text-sm font-medium text-zinc-950 dark:text-white">${sub.userEmail || sub.userId}</div>
|
|
6805
|
+
<div class="text-xs text-zinc-500 dark:text-zinc-400">${sub.stripeCustomerId}</div>
|
|
6574
6806
|
</td>
|
|
6575
6807
|
<td class="px-6 py-4 whitespace-nowrap">${statusBadge(sub.status)}</td>
|
|
6576
|
-
<td class="px-6 py-4 whitespace-nowrap text-sm text-
|
|
6577
|
-
<td class="px-6 py-4 whitespace-nowrap text-sm text-
|
|
6808
|
+
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-500 dark:text-zinc-400">${sub.stripePriceId}</td>
|
|
6809
|
+
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-500 dark:text-zinc-400">
|
|
6578
6810
|
${formatDate(sub.currentPeriodStart)} - ${formatDate(sub.currentPeriodEnd)}
|
|
6579
6811
|
</td>
|
|
6580
6812
|
<td class="px-6 py-4 whitespace-nowrap text-sm">
|
|
6581
|
-
${sub.cancelAtPeriodEnd ? '<span class="text-
|
|
6813
|
+
${sub.cancelAtPeriodEnd ? '<span class="text-amber-500 dark:text-amber-400 font-medium">Yes</span>' : '<span class="text-zinc-400 dark:text-zinc-500">No</span>'}
|
|
6582
6814
|
</td>
|
|
6583
6815
|
<td class="px-6 py-4 whitespace-nowrap text-sm">
|
|
6584
6816
|
<a href="https://dashboard.stripe.com/subscriptions/${sub.stripeSubscriptionId}"
|
|
6585
6817
|
target="_blank" rel="noopener noreferrer"
|
|
6586
|
-
class="text-
|
|
6818
|
+
class="text-cyan-600 dark:text-cyan-400 hover:text-cyan-500 dark:hover:text-cyan-300">
|
|
6587
6819
|
View in Stripe
|
|
6588
6820
|
</a>
|
|
6589
6821
|
</td>
|
|
@@ -6594,13 +6826,161 @@ function renderPagination2(page, totalPages, status) {
|
|
|
6594
6826
|
if (totalPages <= 1) return "";
|
|
6595
6827
|
const params = status ? `&status=${status}` : "";
|
|
6596
6828
|
return `
|
|
6597
|
-
<div class="
|
|
6598
|
-
<div class="text-sm text-
|
|
6829
|
+
<div class="px-6 py-3 flex items-center justify-between border-t border-zinc-950/5 dark:border-white/5">
|
|
6830
|
+
<div class="text-sm text-zinc-500 dark:text-zinc-400">
|
|
6831
|
+
Page ${page} of ${totalPages}
|
|
6832
|
+
</div>
|
|
6833
|
+
<div class="flex gap-2">
|
|
6834
|
+
${page > 1 ? `<a href="?page=${page - 1}${params}" class="px-3 py-1 rounded-lg text-sm 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">Previous</a>` : ""}
|
|
6835
|
+
${page < totalPages ? `<a href="?page=${page + 1}${params}" class="px-3 py-1 rounded-lg text-sm 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">Next</a>` : ""}
|
|
6836
|
+
</div>
|
|
6837
|
+
</div>
|
|
6838
|
+
`;
|
|
6839
|
+
}
|
|
6840
|
+
|
|
6841
|
+
// src/plugins/core-plugins/stripe-plugin/components/events-page.ts
|
|
6842
|
+
chunkUYJ6TJHX_cjs.init_admin_layout_catalyst_template();
|
|
6843
|
+
function renderEventsPage(data) {
|
|
6844
|
+
const { events, stats, types, filters, user, version, dynamicMenuItems } = data;
|
|
6845
|
+
const content2 = `
|
|
6846
|
+
<div>
|
|
6847
|
+
<div class="sm:flex sm:items-center sm:justify-between mb-6">
|
|
6848
|
+
<div class="sm:flex-auto">
|
|
6849
|
+
<h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">Stripe</h1>
|
|
6850
|
+
<p class="mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400">
|
|
6851
|
+
Webhook event log showing all processed, failed, and ignored Stripe events.
|
|
6852
|
+
</p>
|
|
6853
|
+
</div>
|
|
6854
|
+
</div>
|
|
6855
|
+
|
|
6856
|
+
${renderStripeTabBar("/admin/plugins/stripe/events")}
|
|
6857
|
+
|
|
6858
|
+
<!-- Stats Cards -->
|
|
6859
|
+
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4 mb-6">
|
|
6860
|
+
${eventStatsCard("Total Events", stats.total, "text-zinc-950 dark:text-white")}
|
|
6861
|
+
${eventStatsCard("Processed", stats.processed, "text-emerald-600 dark:text-emerald-400")}
|
|
6862
|
+
${eventStatsCard("Failed", stats.failed, "text-red-600 dark:text-red-400")}
|
|
6863
|
+
${eventStatsCard("Ignored", stats.ignored, "text-zinc-500 dark:text-zinc-400")}
|
|
6864
|
+
</div>
|
|
6865
|
+
|
|
6866
|
+
<!-- Filters -->
|
|
6867
|
+
<div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-4 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm mb-6">
|
|
6868
|
+
<form method="GET" class="flex items-center gap-4 flex-wrap">
|
|
6869
|
+
<label class="text-sm font-medium text-zinc-500 dark:text-zinc-400">Type:</label>
|
|
6870
|
+
<select name="type" class="rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-1.5 text-sm text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10" onchange="this.form.submit()">
|
|
6871
|
+
<option value="">All</option>
|
|
6872
|
+
${types.map((t) => `<option value="${t}" ${t === filters.type ? "selected" : ""}>${t}</option>`).join("")}
|
|
6873
|
+
</select>
|
|
6874
|
+
|
|
6875
|
+
<label class="text-sm font-medium text-zinc-500 dark:text-zinc-400">Status:</label>
|
|
6876
|
+
<select name="status" class="rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-1.5 text-sm text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10" onchange="this.form.submit()">
|
|
6877
|
+
<option value="">All</option>
|
|
6878
|
+
${eventStatusOption("processed", filters.status)}
|
|
6879
|
+
${eventStatusOption("failed", filters.status)}
|
|
6880
|
+
${eventStatusOption("ignored", filters.status)}
|
|
6881
|
+
</select>
|
|
6882
|
+
</form>
|
|
6883
|
+
</div>
|
|
6884
|
+
|
|
6885
|
+
<!-- Events Table -->
|
|
6886
|
+
<div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-hidden">
|
|
6887
|
+
<table class="min-w-full divide-y divide-zinc-950/5 dark:divide-white/5">
|
|
6888
|
+
<thead>
|
|
6889
|
+
<tr>
|
|
6890
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Time</th>
|
|
6891
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Type</th>
|
|
6892
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Object</th>
|
|
6893
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Status</th>
|
|
6894
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Event ID</th>
|
|
6895
|
+
</tr>
|
|
6896
|
+
</thead>
|
|
6897
|
+
<tbody class="divide-y divide-zinc-950/5 dark:divide-white/5">
|
|
6898
|
+
${events.length === 0 ? '<tr><td colspan="5" class="px-6 py-8 text-center text-zinc-500 dark:text-zinc-400">No events recorded yet</td></tr>' : events.map(renderEventRow).join("")}
|
|
6899
|
+
</tbody>
|
|
6900
|
+
</table>
|
|
6901
|
+
|
|
6902
|
+
${renderEventPagination(filters.page, filters.totalPages, filters.type, filters.status)}
|
|
6903
|
+
</div>
|
|
6904
|
+
</div>
|
|
6905
|
+
`;
|
|
6906
|
+
const layoutData = {
|
|
6907
|
+
title: "Stripe Events",
|
|
6908
|
+
pageTitle: "Stripe Events",
|
|
6909
|
+
currentPath: "/admin/plugins/stripe",
|
|
6910
|
+
user,
|
|
6911
|
+
content: content2,
|
|
6912
|
+
version,
|
|
6913
|
+
dynamicMenuItems
|
|
6914
|
+
};
|
|
6915
|
+
return chunkUYJ6TJHX_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
6916
|
+
}
|
|
6917
|
+
function eventStatsCard(label, value, colorClass) {
|
|
6918
|
+
return `
|
|
6919
|
+
<div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm">
|
|
6920
|
+
<p class="text-sm font-medium text-zinc-500 dark:text-zinc-400">${label}</p>
|
|
6921
|
+
<p class="mt-2 text-3xl font-bold ${colorClass}">${value}</p>
|
|
6922
|
+
</div>
|
|
6923
|
+
`;
|
|
6924
|
+
}
|
|
6925
|
+
function eventStatusOption(value, current) {
|
|
6926
|
+
const selected = value === current ? "selected" : "";
|
|
6927
|
+
const label = value.charAt(0).toUpperCase() + value.slice(1);
|
|
6928
|
+
return `<option value="${value}" ${selected}>${label}</option>`;
|
|
6929
|
+
}
|
|
6930
|
+
function eventStatusBadge(status) {
|
|
6931
|
+
const colors = {
|
|
6932
|
+
processed: "bg-emerald-400/10 text-emerald-500 dark:text-emerald-400 ring-emerald-400/20",
|
|
6933
|
+
failed: "bg-red-400/10 text-red-500 dark:text-red-400 ring-red-400/20",
|
|
6934
|
+
ignored: "bg-zinc-400/10 text-zinc-500 dark:text-zinc-400 ring-zinc-400/20"
|
|
6935
|
+
};
|
|
6936
|
+
const color = colors[status] || "bg-zinc-400/10 text-zinc-500 ring-zinc-400/20";
|
|
6937
|
+
return `<span class="inline-flex items-center rounded-full px-2 py-1 text-xs font-medium ring-1 ring-inset ${color}">${status}</span>`;
|
|
6938
|
+
}
|
|
6939
|
+
function formatTimestamp3(timestamp) {
|
|
6940
|
+
if (!timestamp) return "-";
|
|
6941
|
+
const d = new Date(timestamp * 1e3);
|
|
6942
|
+
return d.toLocaleString("en-US", {
|
|
6943
|
+
month: "short",
|
|
6944
|
+
day: "numeric",
|
|
6945
|
+
year: "numeric",
|
|
6946
|
+
hour: "2-digit",
|
|
6947
|
+
minute: "2-digit",
|
|
6948
|
+
second: "2-digit"
|
|
6949
|
+
});
|
|
6950
|
+
}
|
|
6951
|
+
function renderEventRow(event) {
|
|
6952
|
+
const errorTooltip = event.error ? ` title="${event.error.replace(/"/g, """)}"` : "";
|
|
6953
|
+
return `
|
|
6954
|
+
<tr class="hover:bg-zinc-950/[0.025] dark:hover:bg-white/[0.025]"${errorTooltip}>
|
|
6955
|
+
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-500 dark:text-zinc-400">
|
|
6956
|
+
${formatTimestamp3(event.processedAt)}
|
|
6957
|
+
</td>
|
|
6958
|
+
<td class="px-6 py-4 whitespace-nowrap">
|
|
6959
|
+
<span class="text-sm font-mono text-zinc-950 dark:text-white">${event.type}</span>
|
|
6960
|
+
</td>
|
|
6961
|
+
<td class="px-6 py-4 whitespace-nowrap">
|
|
6962
|
+
<div class="text-sm font-mono text-zinc-500 dark:text-zinc-400">${event.objectId || "-"}</div>
|
|
6963
|
+
<div class="text-xs text-zinc-400 dark:text-zinc-500">${event.objectType}</div>
|
|
6964
|
+
</td>
|
|
6965
|
+
<td class="px-6 py-4 whitespace-nowrap">${eventStatusBadge(event.status)}</td>
|
|
6966
|
+
<td class="px-6 py-4 whitespace-nowrap text-xs font-mono text-zinc-400 dark:text-zinc-500">${event.stripeEventId}</td>
|
|
6967
|
+
</tr>
|
|
6968
|
+
`;
|
|
6969
|
+
}
|
|
6970
|
+
function renderEventPagination(page, totalPages, type, status) {
|
|
6971
|
+
if (totalPages <= 1) return "";
|
|
6972
|
+
const params = [];
|
|
6973
|
+
if (type) params.push(`type=${type}`);
|
|
6974
|
+
if (status) params.push(`status=${status}`);
|
|
6975
|
+
const extra = params.length > 0 ? `&${params.join("&")}` : "";
|
|
6976
|
+
return `
|
|
6977
|
+
<div class="px-6 py-3 flex items-center justify-between border-t border-zinc-950/5 dark:border-white/5">
|
|
6978
|
+
<div class="text-sm text-zinc-500 dark:text-zinc-400">
|
|
6599
6979
|
Page ${page} of ${totalPages}
|
|
6600
6980
|
</div>
|
|
6601
6981
|
<div class="flex gap-2">
|
|
6602
|
-
${page > 1 ? `<a href="?page=${page - 1}${
|
|
6603
|
-
${page < totalPages ? `<a href="?page=${page + 1}${
|
|
6982
|
+
${page > 1 ? `<a href="?page=${page - 1}${extra}" class="px-3 py-1 rounded-lg text-sm 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">Previous</a>` : ""}
|
|
6983
|
+
${page < totalPages ? `<a href="?page=${page + 1}${extra}" class="px-3 py-1 rounded-lg text-sm 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">Next</a>` : ""}
|
|
6604
6984
|
</div>
|
|
6605
6985
|
</div>
|
|
6606
6986
|
`;
|
|
@@ -6608,6 +6988,7 @@ function renderPagination2(page, totalPages, status) {
|
|
|
6608
6988
|
|
|
6609
6989
|
// src/plugins/core-plugins/stripe-plugin/types.ts
|
|
6610
6990
|
var DEFAULT_SETTINGS3 = {
|
|
6991
|
+
stripePublishableKey: "",
|
|
6611
6992
|
stripeSecretKey: "",
|
|
6612
6993
|
stripeWebhookSecret: "",
|
|
6613
6994
|
stripePriceId: "",
|
|
@@ -6617,7 +6998,7 @@ var DEFAULT_SETTINGS3 = {
|
|
|
6617
6998
|
|
|
6618
6999
|
// src/plugins/core-plugins/stripe-plugin/routes/admin.ts
|
|
6619
7000
|
var adminRoutes3 = new hono.Hono();
|
|
6620
|
-
adminRoutes3.use("*",
|
|
7001
|
+
adminRoutes3.use("*", chunkCZ6BVQZX_cjs.requireAuth());
|
|
6621
7002
|
adminRoutes3.use("*", async (c, next) => {
|
|
6622
7003
|
const user = c.get("user");
|
|
6623
7004
|
if (user?.role !== "admin") {
|
|
@@ -6625,8 +7006,21 @@ adminRoutes3.use("*", async (c, next) => {
|
|
|
6625
7006
|
}
|
|
6626
7007
|
return next();
|
|
6627
7008
|
});
|
|
7009
|
+
async function getSettings3(db) {
|
|
7010
|
+
try {
|
|
7011
|
+
const pluginService = new chunkQ5VFZUXV_cjs.PluginService(db);
|
|
7012
|
+
const plugin2 = await pluginService.getPlugin("stripe");
|
|
7013
|
+
if (plugin2?.settings) {
|
|
7014
|
+
const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
|
|
7015
|
+
return { ...DEFAULT_SETTINGS3, ...settings };
|
|
7016
|
+
}
|
|
7017
|
+
} catch {
|
|
7018
|
+
}
|
|
7019
|
+
return DEFAULT_SETTINGS3;
|
|
7020
|
+
}
|
|
6628
7021
|
adminRoutes3.get("/", async (c) => {
|
|
6629
7022
|
const db = c.env.DB;
|
|
7023
|
+
const user = c.get("user");
|
|
6630
7024
|
const subscriptionService = new SubscriptionService(db);
|
|
6631
7025
|
await subscriptionService.ensureTable();
|
|
6632
7026
|
const page = parseInt(c.req.query("page") || "1");
|
|
@@ -6637,13 +7031,152 @@ adminRoutes3.get("/", async (c) => {
|
|
|
6637
7031
|
subscriptionService.getStats()
|
|
6638
7032
|
]);
|
|
6639
7033
|
const totalPages = Math.ceil(total / limit);
|
|
6640
|
-
const html = renderSubscriptionsPage(
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
totalPages
|
|
7034
|
+
const html = renderSubscriptionsPage({
|
|
7035
|
+
subscriptions,
|
|
7036
|
+
stats,
|
|
7037
|
+
filters: { status: statusFilter, page, totalPages },
|
|
7038
|
+
user: user ? { name: user.email, email: user.email, role: user.role } : void 0,
|
|
7039
|
+
version: c.get("appVersion"),
|
|
7040
|
+
dynamicMenuItems: c.get("pluginMenuItems")
|
|
6644
7041
|
});
|
|
6645
7042
|
return c.html(html);
|
|
6646
7043
|
});
|
|
7044
|
+
adminRoutes3.get("/events", async (c) => {
|
|
7045
|
+
const db = c.env.DB;
|
|
7046
|
+
const user = c.get("user");
|
|
7047
|
+
const eventService = new StripeEventService(db);
|
|
7048
|
+
await eventService.ensureTable();
|
|
7049
|
+
const page = parseInt(c.req.query("page") || "1");
|
|
7050
|
+
const limit = 50;
|
|
7051
|
+
const typeFilter = c.req.query("type") || void 0;
|
|
7052
|
+
const statusFilter = c.req.query("status");
|
|
7053
|
+
const [{ events, total }, stats, types] = await Promise.all([
|
|
7054
|
+
eventService.list({ type: typeFilter, status: statusFilter, page, limit }),
|
|
7055
|
+
eventService.getStats(),
|
|
7056
|
+
eventService.getDistinctTypes()
|
|
7057
|
+
]);
|
|
7058
|
+
const totalPages = Math.ceil(total / limit);
|
|
7059
|
+
const html = renderEventsPage({
|
|
7060
|
+
events,
|
|
7061
|
+
stats,
|
|
7062
|
+
types,
|
|
7063
|
+
filters: { type: typeFilter, status: statusFilter, page, totalPages },
|
|
7064
|
+
user: user ? { name: user.email, email: user.email, role: user.role } : void 0,
|
|
7065
|
+
version: c.get("appVersion"),
|
|
7066
|
+
dynamicMenuItems: c.get("pluginMenuItems")
|
|
7067
|
+
});
|
|
7068
|
+
return c.html(html);
|
|
7069
|
+
});
|
|
7070
|
+
adminRoutes3.get("/settings", async (c) => {
|
|
7071
|
+
const db = c.env.DB;
|
|
7072
|
+
const user = c.get("user");
|
|
7073
|
+
const settings = await getSettings3(db);
|
|
7074
|
+
const { renderAdminLayoutCatalyst: renderAdminLayoutCatalyst2 } = await import('./admin-layout-catalyst.template-HFD37TY5.cjs');
|
|
7075
|
+
const content2 = `
|
|
7076
|
+
<div>
|
|
7077
|
+
<div class="mb-6">
|
|
7078
|
+
<h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">Stripe</h1>
|
|
7079
|
+
<p class="mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400">
|
|
7080
|
+
Configure your Stripe API keys and checkout options.
|
|
7081
|
+
</p>
|
|
7082
|
+
</div>
|
|
7083
|
+
|
|
7084
|
+
${renderStripeTabBar("/admin/plugins/stripe/settings")}
|
|
7085
|
+
|
|
7086
|
+
<div id="settings-message" class="hidden mb-4 rounded-lg p-4 text-sm"></div>
|
|
7087
|
+
|
|
7088
|
+
<form id="stripe-settings-form" class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm divide-y divide-zinc-950/5 dark:divide-white/5">
|
|
7089
|
+
<div class="p-6 space-y-5">
|
|
7090
|
+
<div>
|
|
7091
|
+
<label class="block text-sm font-medium text-zinc-950 dark:text-white mb-1.5">Publishable Key</label>
|
|
7092
|
+
<input type="text" name="stripePublishableKey" value="${settings.stripePublishableKey}"
|
|
7093
|
+
placeholder="pk_..."
|
|
7094
|
+
class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3.5 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-400 dark:placeholder:text-zinc-500 focus:ring-2 focus:ring-cyan-500" />
|
|
7095
|
+
<p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Your Stripe publishable key (starts with pk_)</p>
|
|
7096
|
+
</div>
|
|
7097
|
+
|
|
7098
|
+
<div>
|
|
7099
|
+
<label class="block text-sm font-medium text-zinc-950 dark:text-white mb-1.5">Secret Key</label>
|
|
7100
|
+
<input type="password" name="stripeSecretKey" value="${settings.stripeSecretKey}"
|
|
7101
|
+
placeholder="sk_..."
|
|
7102
|
+
class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3.5 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-400 dark:placeholder:text-zinc-500 focus:ring-2 focus:ring-cyan-500" />
|
|
7103
|
+
<p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Your Stripe secret API key (starts with sk_)</p>
|
|
7104
|
+
</div>
|
|
7105
|
+
|
|
7106
|
+
<div>
|
|
7107
|
+
<label class="block text-sm font-medium text-zinc-950 dark:text-white mb-1.5">Webhook Signing Secret</label>
|
|
7108
|
+
<input type="password" name="stripeWebhookSecret" value="${settings.stripeWebhookSecret}"
|
|
7109
|
+
placeholder="whsec_..."
|
|
7110
|
+
class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3.5 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-400 dark:placeholder:text-zinc-500 focus:ring-2 focus:ring-cyan-500" />
|
|
7111
|
+
<p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Stripe webhook endpoint signing secret (starts with whsec_)</p>
|
|
7112
|
+
</div>
|
|
7113
|
+
|
|
7114
|
+
<div>
|
|
7115
|
+
<label class="block text-sm font-medium text-zinc-950 dark:text-white mb-1.5">Default Price ID</label>
|
|
7116
|
+
<input type="text" name="stripePriceId" value="${settings.stripePriceId || ""}"
|
|
7117
|
+
placeholder="price_..."
|
|
7118
|
+
class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3.5 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-400 dark:placeholder:text-zinc-500 focus:ring-2 focus:ring-cyan-500" />
|
|
7119
|
+
<p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Default Stripe Price ID for checkout sessions (optional)</p>
|
|
7120
|
+
</div>
|
|
7121
|
+
|
|
7122
|
+
<div>
|
|
7123
|
+
<label class="block text-sm font-medium text-zinc-950 dark:text-white mb-1.5">Checkout Success URL</label>
|
|
7124
|
+
<input type="text" name="successUrl" value="${settings.successUrl}"
|
|
7125
|
+
class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3.5 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-400 dark:placeholder:text-zinc-500 focus:ring-2 focus:ring-cyan-500" />
|
|
7126
|
+
<p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Redirect URL after successful checkout</p>
|
|
7127
|
+
</div>
|
|
7128
|
+
|
|
7129
|
+
<div>
|
|
7130
|
+
<label class="block text-sm font-medium text-zinc-950 dark:text-white mb-1.5">Checkout Cancel URL</label>
|
|
7131
|
+
<input type="text" name="cancelUrl" value="${settings.cancelUrl}"
|
|
7132
|
+
class="w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3.5 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-400 dark:placeholder:text-zinc-500 focus:ring-2 focus:ring-cyan-500" />
|
|
7133
|
+
<p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Redirect URL if checkout is cancelled</p>
|
|
7134
|
+
</div>
|
|
7135
|
+
</div>
|
|
7136
|
+
|
|
7137
|
+
<div class="px-6 py-4 flex justify-end">
|
|
7138
|
+
<button type="submit"
|
|
7139
|
+
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">
|
|
7140
|
+
Save Settings
|
|
7141
|
+
</button>
|
|
7142
|
+
</div>
|
|
7143
|
+
</form>
|
|
7144
|
+
</div>
|
|
7145
|
+
|
|
7146
|
+
<script>
|
|
7147
|
+
document.getElementById('stripe-settings-form').addEventListener('submit', async (e) => {
|
|
7148
|
+
e.preventDefault()
|
|
7149
|
+
const form = e.target
|
|
7150
|
+
const data = Object.fromEntries(new FormData(form))
|
|
7151
|
+
const msg = document.getElementById('settings-message')
|
|
7152
|
+
try {
|
|
7153
|
+
const res = await fetch('/admin/plugins/stripe/settings', {
|
|
7154
|
+
method: 'POST',
|
|
7155
|
+
headers: { 'Content-Type': 'application/json' },
|
|
7156
|
+
body: JSON.stringify(data)
|
|
7157
|
+
})
|
|
7158
|
+
const result = await res.json()
|
|
7159
|
+
msg.className = result.success
|
|
7160
|
+
? 'mb-4 rounded-lg p-4 text-sm bg-emerald-400/10 text-emerald-500 dark:text-emerald-400 ring-1 ring-inset ring-emerald-400/20'
|
|
7161
|
+
: 'mb-4 rounded-lg p-4 text-sm bg-red-400/10 text-red-500 dark:text-red-400 ring-1 ring-inset ring-red-400/20'
|
|
7162
|
+
msg.textContent = result.success ? 'Settings saved successfully.' : (result.error || 'Failed to save settings.')
|
|
7163
|
+
} catch {
|
|
7164
|
+
msg.className = 'mb-4 rounded-lg p-4 text-sm bg-red-400/10 text-red-500 dark:text-red-400 ring-1 ring-inset ring-red-400/20'
|
|
7165
|
+
msg.textContent = 'Network error. Please try again.'
|
|
7166
|
+
}
|
|
7167
|
+
})
|
|
7168
|
+
</script>
|
|
7169
|
+
`;
|
|
7170
|
+
return c.html(renderAdminLayoutCatalyst2({
|
|
7171
|
+
title: "Stripe Settings",
|
|
7172
|
+
pageTitle: "Stripe Settings",
|
|
7173
|
+
currentPath: "/admin/plugins/stripe",
|
|
7174
|
+
user: user ? { name: user.email, email: user.email, role: user.role } : void 0,
|
|
7175
|
+
content: content2,
|
|
7176
|
+
version: c.get("appVersion"),
|
|
7177
|
+
dynamicMenuItems: c.get("pluginMenuItems")
|
|
7178
|
+
}));
|
|
7179
|
+
});
|
|
6647
7180
|
adminRoutes3.post("/settings", async (c) => {
|
|
6648
7181
|
try {
|
|
6649
7182
|
const body = await c.req.json();
|
|
@@ -6731,7 +7264,31 @@ var StripeAPI = class {
|
|
|
6731
7264
|
body.append(`metadata[${key}]`, value);
|
|
6732
7265
|
}
|
|
6733
7266
|
}
|
|
6734
|
-
return this.request("POST", "/customers", body);
|
|
7267
|
+
return this.request("POST", "/customers", body);
|
|
7268
|
+
}
|
|
7269
|
+
/**
|
|
7270
|
+
* List subscriptions with pagination (auto-expands across pages)
|
|
7271
|
+
*/
|
|
7272
|
+
async listSubscriptions(params) {
|
|
7273
|
+
const qs = new URLSearchParams();
|
|
7274
|
+
qs.append("limit", String(params?.limit || 100));
|
|
7275
|
+
if (params?.status) qs.append("status", params.status);
|
|
7276
|
+
if (params?.startingAfter) qs.append("starting_after", params.startingAfter);
|
|
7277
|
+
return this.request("GET", `/subscriptions?${qs.toString()}`);
|
|
7278
|
+
}
|
|
7279
|
+
/**
|
|
7280
|
+
* Fetch ALL subscriptions from Stripe (handles pagination automatically)
|
|
7281
|
+
*/
|
|
7282
|
+
async listAllSubscriptions() {
|
|
7283
|
+
const all = [];
|
|
7284
|
+
let startingAfter;
|
|
7285
|
+
while (true) {
|
|
7286
|
+
const result = await this.listSubscriptions({ limit: 100, startingAfter });
|
|
7287
|
+
all.push(...result.data);
|
|
7288
|
+
if (!result.has_more || result.data.length === 0) break;
|
|
7289
|
+
startingAfter = result.data[result.data.length - 1].id;
|
|
7290
|
+
}
|
|
7291
|
+
return all;
|
|
6735
7292
|
}
|
|
6736
7293
|
/**
|
|
6737
7294
|
* Search for a customer by email
|
|
@@ -6771,9 +7328,9 @@ function timingSafeEqual(a, b) {
|
|
|
6771
7328
|
|
|
6772
7329
|
// src/plugins/core-plugins/stripe-plugin/routes/api.ts
|
|
6773
7330
|
var apiRoutes3 = new hono.Hono();
|
|
6774
|
-
async function
|
|
7331
|
+
async function getSettings4(db) {
|
|
6775
7332
|
try {
|
|
6776
|
-
const pluginService = new
|
|
7333
|
+
const pluginService = new chunkQ5VFZUXV_cjs.PluginService(db);
|
|
6777
7334
|
const plugin2 = await pluginService.getPlugin("stripe");
|
|
6778
7335
|
if (plugin2?.settings) {
|
|
6779
7336
|
const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
|
|
@@ -6798,7 +7355,7 @@ function mapStripeStatus(status) {
|
|
|
6798
7355
|
}
|
|
6799
7356
|
apiRoutes3.post("/webhook", async (c) => {
|
|
6800
7357
|
const db = c.env.DB;
|
|
6801
|
-
const settings = await
|
|
7358
|
+
const settings = await getSettings4(db);
|
|
6802
7359
|
if (!settings.stripeWebhookSecret) {
|
|
6803
7360
|
return c.json({ error: "Webhook secret not configured" }, 500);
|
|
6804
7361
|
}
|
|
@@ -6811,7 +7368,11 @@ apiRoutes3.post("/webhook", async (c) => {
|
|
|
6811
7368
|
}
|
|
6812
7369
|
const event = JSON.parse(rawBody);
|
|
6813
7370
|
const subscriptionService = new SubscriptionService(db);
|
|
6814
|
-
|
|
7371
|
+
const eventService = new StripeEventService(db);
|
|
7372
|
+
await Promise.all([subscriptionService.ensureTable(), eventService.ensureTable()]);
|
|
7373
|
+
const obj = event.data.object;
|
|
7374
|
+
const objectId = obj?.id || "";
|
|
7375
|
+
const objectType = obj?.object || event.type.split(".")[0] || "";
|
|
6815
7376
|
try {
|
|
6816
7377
|
switch (event.type) {
|
|
6817
7378
|
case "customer.subscription.created": {
|
|
@@ -6886,18 +7447,45 @@ apiRoutes3.post("/webhook", async (c) => {
|
|
|
6886
7447
|
}
|
|
6887
7448
|
default:
|
|
6888
7449
|
console.log(`[Stripe] Unhandled event type: ${event.type}`);
|
|
6889
|
-
|
|
7450
|
+
await eventService.log({
|
|
7451
|
+
stripeEventId: event.id,
|
|
7452
|
+
type: event.type,
|
|
7453
|
+
objectId,
|
|
7454
|
+
objectType,
|
|
7455
|
+
data: event.data.object,
|
|
7456
|
+
status: "ignored"
|
|
7457
|
+
});
|
|
7458
|
+
return c.json({ received: true });
|
|
7459
|
+
}
|
|
7460
|
+
await eventService.log({
|
|
7461
|
+
stripeEventId: event.id,
|
|
7462
|
+
type: event.type,
|
|
7463
|
+
objectId,
|
|
7464
|
+
objectType,
|
|
7465
|
+
data: event.data.object,
|
|
7466
|
+
status: "processed"
|
|
7467
|
+
});
|
|
6890
7468
|
} catch (error) {
|
|
7469
|
+
await eventService.log({
|
|
7470
|
+
stripeEventId: event.id,
|
|
7471
|
+
type: event.type,
|
|
7472
|
+
objectId,
|
|
7473
|
+
objectType,
|
|
7474
|
+
data: event.data.object,
|
|
7475
|
+
status: "failed",
|
|
7476
|
+
error: error instanceof Error ? error.message : String(error)
|
|
7477
|
+
}).catch(() => {
|
|
7478
|
+
});
|
|
6891
7479
|
console.error(`[Stripe] Error processing webhook event ${event.type}:`, error);
|
|
6892
7480
|
return c.json({ error: "Webhook processing failed" }, 500);
|
|
6893
7481
|
}
|
|
6894
7482
|
return c.json({ received: true });
|
|
6895
7483
|
});
|
|
6896
|
-
apiRoutes3.post("/create-checkout-session",
|
|
7484
|
+
apiRoutes3.post("/create-checkout-session", chunkCZ6BVQZX_cjs.requireAuth(), async (c) => {
|
|
6897
7485
|
const db = c.env.DB;
|
|
6898
7486
|
const user = c.get("user");
|
|
6899
7487
|
if (!user) return c.json({ error: "Unauthorized" }, 401);
|
|
6900
|
-
const settings = await
|
|
7488
|
+
const settings = await getSettings4(db);
|
|
6901
7489
|
if (!settings.stripeSecretKey) {
|
|
6902
7490
|
return c.json({ error: "Stripe not configured" }, 500);
|
|
6903
7491
|
}
|
|
@@ -6933,7 +7521,7 @@ apiRoutes3.post("/create-checkout-session", chunkYYMPHM3I_cjs.requireAuth(), asy
|
|
|
6933
7521
|
});
|
|
6934
7522
|
return c.json({ sessionId: session.id, url: session.url });
|
|
6935
7523
|
});
|
|
6936
|
-
apiRoutes3.get("/subscription",
|
|
7524
|
+
apiRoutes3.get("/subscription", chunkCZ6BVQZX_cjs.requireAuth(), async (c) => {
|
|
6937
7525
|
const user = c.get("user");
|
|
6938
7526
|
if (!user) return c.json({ error: "Unauthorized" }, 401);
|
|
6939
7527
|
const db = c.env.DB;
|
|
@@ -6945,7 +7533,7 @@ apiRoutes3.get("/subscription", chunkYYMPHM3I_cjs.requireAuth(), async (c) => {
|
|
|
6945
7533
|
}
|
|
6946
7534
|
return c.json({ subscription });
|
|
6947
7535
|
});
|
|
6948
|
-
apiRoutes3.get("/subscriptions",
|
|
7536
|
+
apiRoutes3.get("/subscriptions", chunkCZ6BVQZX_cjs.requireAuth(), async (c) => {
|
|
6949
7537
|
const user = c.get("user");
|
|
6950
7538
|
if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
|
|
6951
7539
|
const db = c.env.DB;
|
|
@@ -6961,7 +7549,7 @@ apiRoutes3.get("/subscriptions", chunkYYMPHM3I_cjs.requireAuth(), async (c) => {
|
|
|
6961
7549
|
const result = await subscriptionService.list(filters);
|
|
6962
7550
|
return c.json(result);
|
|
6963
7551
|
});
|
|
6964
|
-
apiRoutes3.get("/stats",
|
|
7552
|
+
apiRoutes3.get("/stats", chunkCZ6BVQZX_cjs.requireAuth(), async (c) => {
|
|
6965
7553
|
const user = c.get("user");
|
|
6966
7554
|
if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
|
|
6967
7555
|
const db = c.env.DB;
|
|
@@ -6970,10 +7558,78 @@ apiRoutes3.get("/stats", chunkYYMPHM3I_cjs.requireAuth(), async (c) => {
|
|
|
6970
7558
|
const stats = await subscriptionService.getStats();
|
|
6971
7559
|
return c.json(stats);
|
|
6972
7560
|
});
|
|
7561
|
+
apiRoutes3.post("/sync-subscriptions", chunkCZ6BVQZX_cjs.requireAuth(), async (c) => {
|
|
7562
|
+
const user = c.get("user");
|
|
7563
|
+
if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
|
|
7564
|
+
const db = c.env.DB;
|
|
7565
|
+
const settings = await getSettings4(db);
|
|
7566
|
+
if (!settings.stripeSecretKey) {
|
|
7567
|
+
return c.json({ error: "Stripe secret key not configured" }, 400);
|
|
7568
|
+
}
|
|
7569
|
+
const stripeApi = new StripeAPI(settings.stripeSecretKey);
|
|
7570
|
+
const subscriptionService = new SubscriptionService(db);
|
|
7571
|
+
await subscriptionService.ensureTable();
|
|
7572
|
+
try {
|
|
7573
|
+
const allSubs = await stripeApi.listAllSubscriptions();
|
|
7574
|
+
let synced = 0;
|
|
7575
|
+
let errors = 0;
|
|
7576
|
+
for (const sub of allSubs) {
|
|
7577
|
+
try {
|
|
7578
|
+
const userId = sub.metadata?.sonicjs_user_id || await subscriptionService.getUserIdByStripeCustomer(sub.customer) || "";
|
|
7579
|
+
await subscriptionService.upsert({
|
|
7580
|
+
userId,
|
|
7581
|
+
stripeCustomerId: typeof sub.customer === "string" ? sub.customer : sub.customer.id,
|
|
7582
|
+
stripeSubscriptionId: sub.id,
|
|
7583
|
+
stripePriceId: sub.items?.data?.[0]?.price?.id || "",
|
|
7584
|
+
status: mapStripeStatus(sub.status),
|
|
7585
|
+
currentPeriodStart: sub.current_period_start,
|
|
7586
|
+
currentPeriodEnd: sub.current_period_end,
|
|
7587
|
+
cancelAtPeriodEnd: sub.cancel_at_period_end
|
|
7588
|
+
});
|
|
7589
|
+
synced++;
|
|
7590
|
+
} catch (err) {
|
|
7591
|
+
console.error(`[Stripe Sync] Failed to upsert subscription ${sub.id}:`, err);
|
|
7592
|
+
errors++;
|
|
7593
|
+
}
|
|
7594
|
+
}
|
|
7595
|
+
return c.json({
|
|
7596
|
+
success: true,
|
|
7597
|
+
total: allSubs.length,
|
|
7598
|
+
synced,
|
|
7599
|
+
errors
|
|
7600
|
+
});
|
|
7601
|
+
} catch (error) {
|
|
7602
|
+
console.error("[Stripe Sync] Error:", error);
|
|
7603
|
+
return c.json({
|
|
7604
|
+
success: false,
|
|
7605
|
+
error: error instanceof Error ? error.message : "Sync failed"
|
|
7606
|
+
}, 500);
|
|
7607
|
+
}
|
|
7608
|
+
});
|
|
7609
|
+
apiRoutes3.get("/events", chunkCZ6BVQZX_cjs.requireAuth(), async (c) => {
|
|
7610
|
+
const user = c.get("user");
|
|
7611
|
+
if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
|
|
7612
|
+
const db = c.env.DB;
|
|
7613
|
+
const eventService = new StripeEventService(db);
|
|
7614
|
+
await eventService.ensureTable();
|
|
7615
|
+
const filters = {
|
|
7616
|
+
type: c.req.query("type") || void 0,
|
|
7617
|
+
status: c.req.query("status") || void 0,
|
|
7618
|
+
objectId: c.req.query("objectId") || void 0,
|
|
7619
|
+
page: c.req.query("page") ? parseInt(c.req.query("page")) : 1,
|
|
7620
|
+
limit: c.req.query("limit") ? parseInt(c.req.query("limit")) : 50
|
|
7621
|
+
};
|
|
7622
|
+
const [result, stats, types] = await Promise.all([
|
|
7623
|
+
eventService.list(filters),
|
|
7624
|
+
eventService.getStats(),
|
|
7625
|
+
eventService.getDistinctTypes()
|
|
7626
|
+
]);
|
|
7627
|
+
return c.json({ ...result, stats, types });
|
|
7628
|
+
});
|
|
6973
7629
|
|
|
6974
7630
|
// src/plugins/core-plugins/stripe-plugin/index.ts
|
|
6975
7631
|
function createStripePlugin() {
|
|
6976
|
-
const builder =
|
|
7632
|
+
const builder = chunk635JAMSE_cjs.PluginBuilder.create({
|
|
6977
7633
|
name: "stripe",
|
|
6978
7634
|
version: "1.0.0-beta.1",
|
|
6979
7635
|
description: "Stripe subscription management with webhook handling, checkout sessions, and subscription gating"
|
|
@@ -7016,13 +7672,35 @@ function createStripePlugin() {
|
|
|
7016
7672
|
var stripePlugin = createStripePlugin();
|
|
7017
7673
|
|
|
7018
7674
|
// src/middleware/plugin-menu.ts
|
|
7019
|
-
var
|
|
7020
|
-
|
|
7021
|
-
|
|
7675
|
+
var REGISTRY_MENU_PLUGINS = Object.values(chunkQ5VFZUXV_cjs.PLUGIN_REGISTRY).filter((p) => p.adminMenu !== null).map((p) => ({
|
|
7676
|
+
codeName: p.codeName,
|
|
7677
|
+
label: p.adminMenu.label,
|
|
7678
|
+
path: p.adminMenu.path,
|
|
7679
|
+
icon: p.adminMenu.icon,
|
|
7680
|
+
order: p.adminMenu.order
|
|
7681
|
+
}));
|
|
7682
|
+
var ICON_SVG = {
|
|
7683
|
+
"magnifying-glass": '<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"/></svg>',
|
|
7684
|
+
"chart-bar": '<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z"/></svg>',
|
|
7685
|
+
"image": '<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z"/></svg>',
|
|
7686
|
+
"palette": '<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.098 19.902a3.75 3.75 0 0 0 5.304 0l6.401-6.402M6.75 21A3.75 3.75 0 0 1 3 17.25V4.125C3 3.504 3.504 3 4.125 3h5.25c.621 0 1.125.504 1.125 1.125v4.072M6.75 21a3.75 3.75 0 0 0 3.75-3.75V8.197M6.75 21h13.125c.621 0 1.125-.504 1.125-1.125v-5.25c0-.621-.504-1.125-1.125-1.125h-4.072M10.5 8.197l2.88-2.88c.438-.439 1.15-.439 1.59 0l3.712 3.713c.44.44.44 1.152 0 1.59l-2.879 2.88M6.75 17.25h.008v.008H6.75v-.008Z"/></svg>',
|
|
7687
|
+
"envelope": '<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75"/></svg>',
|
|
7688
|
+
"hand-raised": '<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.05 4.575a1.575 1.575 0 1 0-3.15 0v3m3.15-3v-1.5a1.575 1.575 0 0 1 3.15 0v1.5m-3.15 0 .075 5.925m3.075-5.925v2.925m0-2.925a1.575 1.575 0 0 1 3.15 0V9.9m-3.15-2.4v5.325M16.5 9.9a1.575 1.575 0 0 1 3.15 0V15a6.15 6.15 0 0 1-6.15 6.15H12A6.15 6.15 0 0 1 5.85 15V9.525"/></svg>',
|
|
7689
|
+
"key": '<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.75 5.25a3 3 0 0 1 3 3m3 0a6 6 0 0 1-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1 1 21.75 8.25Z"/></svg>',
|
|
7690
|
+
"arrow-right": '<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3"/></svg>',
|
|
7691
|
+
"shield-check": '<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/></svg>',
|
|
7692
|
+
"credit-card": '<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.25 8.25h19.5M2.25 9h19.5m-16.5 5.25h6m-6 2.25h3m-3.75 3h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Z"/></svg>'
|
|
7693
|
+
};
|
|
7694
|
+
function resolveIcon(iconName) {
|
|
7695
|
+
if (!iconName) return "";
|
|
7696
|
+
if (iconName.startsWith("<svg") || iconName.startsWith("<")) return iconName;
|
|
7697
|
+
return ICON_SVG[iconName] || "";
|
|
7698
|
+
}
|
|
7022
7699
|
var MARKER = "<!-- DYNAMIC_PLUGIN_MENU -->";
|
|
7023
7700
|
function renderMenuItem(item, currentPath) {
|
|
7024
7701
|
const isActive = currentPath === item.path || currentPath.startsWith(item.path);
|
|
7025
7702
|
const fallbackIcon = `<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>`;
|
|
7703
|
+
const resolvedIcon = resolveIcon(item.icon) || fallbackIcon;
|
|
7026
7704
|
return `
|
|
7027
7705
|
<span class="relative">
|
|
7028
7706
|
${isActive ? '<span class="absolute inset-y-2 -left-4 w-0.5 rounded-full bg-cyan-500 dark:bg-cyan-400"></span>' : ""}
|
|
@@ -7032,7 +7710,7 @@ function renderMenuItem(item, currentPath) {
|
|
|
7032
7710
|
${isActive ? 'data-current="true"' : ""}
|
|
7033
7711
|
>
|
|
7034
7712
|
<span class="shrink-0 ${isActive ? "fill-zinc-950 dark:fill-white" : "fill-zinc-500 dark:fill-zinc-400"}">
|
|
7035
|
-
${
|
|
7713
|
+
${resolvedIcon}
|
|
7036
7714
|
</span>
|
|
7037
7715
|
<span class="truncate">${item.label}</span>
|
|
7038
7716
|
</a>
|
|
@@ -7047,23 +7725,28 @@ function pluginMenuMiddleware() {
|
|
|
7047
7725
|
let activeMenuItems = [];
|
|
7048
7726
|
try {
|
|
7049
7727
|
const db = c.env.DB;
|
|
7050
|
-
const
|
|
7051
|
-
if (
|
|
7052
|
-
const placeholders =
|
|
7728
|
+
const pluginCodeNames = REGISTRY_MENU_PLUGINS.map((p) => p.codeName);
|
|
7729
|
+
if (pluginCodeNames.length > 0) {
|
|
7730
|
+
const placeholders = pluginCodeNames.map(() => "?").join(",");
|
|
7053
7731
|
const result = await db.prepare(
|
|
7054
7732
|
`SELECT name FROM plugins WHERE name IN (${placeholders}) AND status = 'active'`
|
|
7055
|
-
).bind(...
|
|
7733
|
+
).bind(...pluginCodeNames).all();
|
|
7056
7734
|
const activeNames = new Set((result.results || []).map((r) => r.name));
|
|
7057
|
-
for (const plugin2 of
|
|
7058
|
-
if (activeNames.has(plugin2.
|
|
7059
|
-
activeMenuItems.push(
|
|
7735
|
+
for (const plugin2 of REGISTRY_MENU_PLUGINS) {
|
|
7736
|
+
if (activeNames.has(plugin2.codeName)) {
|
|
7737
|
+
activeMenuItems.push({
|
|
7738
|
+
label: plugin2.label,
|
|
7739
|
+
path: plugin2.path,
|
|
7740
|
+
icon: plugin2.icon,
|
|
7741
|
+
order: plugin2.order
|
|
7742
|
+
});
|
|
7060
7743
|
}
|
|
7061
7744
|
}
|
|
7062
|
-
activeMenuItems.sort((a, b) =>
|
|
7745
|
+
activeMenuItems.sort((a, b) => a.order - b.order);
|
|
7063
7746
|
}
|
|
7064
7747
|
} catch {
|
|
7065
7748
|
}
|
|
7066
|
-
c.set("pluginMenuItems", activeMenuItems.map((m) => ({ label: m.label, path: m.path, icon: m.icon || "" })));
|
|
7749
|
+
c.set("pluginMenuItems", activeMenuItems.map((m) => ({ label: m.label, path: m.path, icon: resolveIcon(m.icon) || "" })));
|
|
7067
7750
|
await next();
|
|
7068
7751
|
if (activeMenuItems.length > 0 && c.res.headers.get("content-type")?.includes("text/html")) {
|
|
7069
7752
|
const status = c.res.status;
|
|
@@ -7080,6 +7763,672 @@ function pluginMenuMiddleware() {
|
|
|
7080
7763
|
};
|
|
7081
7764
|
}
|
|
7082
7765
|
|
|
7766
|
+
// src/plugins/types.ts
|
|
7767
|
+
var HOOKS2 = {
|
|
7768
|
+
// Request lifecycle
|
|
7769
|
+
REQUEST_START: "request:start",
|
|
7770
|
+
REQUEST_END: "request:end",
|
|
7771
|
+
USER_LOGIN: "user:login"};
|
|
7772
|
+
chunkUYJ6TJHX_cjs.init_admin_layout_catalyst_template();
|
|
7773
|
+
var adminRoutes4 = new hono.Hono();
|
|
7774
|
+
adminRoutes4.use("*", chunkCZ6BVQZX_cjs.requireAuth());
|
|
7775
|
+
adminRoutes4.use("*", async (c, next) => {
|
|
7776
|
+
const user = c.get("user");
|
|
7777
|
+
if (user?.role !== "admin") {
|
|
7778
|
+
return c.text("Access denied", 403);
|
|
7779
|
+
}
|
|
7780
|
+
return next();
|
|
7781
|
+
});
|
|
7782
|
+
adminRoutes4.get("/", async (c) => {
|
|
7783
|
+
const user = c.get("user");
|
|
7784
|
+
const db = c.env.DB;
|
|
7785
|
+
let totalRequests = 0;
|
|
7786
|
+
let uniqueIPs = 0;
|
|
7787
|
+
let avgDuration = 0;
|
|
7788
|
+
let errorCount = 0;
|
|
7789
|
+
let topPages = [];
|
|
7790
|
+
let recentActivity = [];
|
|
7791
|
+
try {
|
|
7792
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
7793
|
+
const dayAgo = now - 86400;
|
|
7794
|
+
const [requestsResult, ipsResult, durationResult, errorsResult, pagesResult, activityResult] = await Promise.all([
|
|
7795
|
+
db.prepare("SELECT COUNT(*) as count FROM system_logs WHERE category = ? AND created_at > ?").bind("api", dayAgo).first(),
|
|
7796
|
+
db.prepare("SELECT COUNT(DISTINCT ip_address) as count FROM system_logs WHERE category = ? AND created_at > ?").bind("api", dayAgo).first(),
|
|
7797
|
+
db.prepare("SELECT AVG(duration) as avg FROM system_logs WHERE category = ? AND created_at > ? AND duration IS NOT NULL").bind("api", dayAgo).first(),
|
|
7798
|
+
db.prepare("SELECT COUNT(*) as count FROM system_logs WHERE level IN (?, ?) AND created_at > ?").bind("error", "fatal", dayAgo).first(),
|
|
7799
|
+
db.prepare("SELECT url, COUNT(*) as views FROM system_logs WHERE category = ? AND created_at > ? AND url IS NOT NULL GROUP BY url ORDER BY views DESC LIMIT 10").bind("api", dayAgo).all(),
|
|
7800
|
+
db.prepare("SELECT url, method, status_code, duration, created_at FROM system_logs WHERE category = ? ORDER BY created_at DESC LIMIT 20").bind("api").all()
|
|
7801
|
+
]);
|
|
7802
|
+
totalRequests = requestsResult?.count || 0;
|
|
7803
|
+
uniqueIPs = ipsResult?.count || 0;
|
|
7804
|
+
avgDuration = Math.round(durationResult?.avg || 0);
|
|
7805
|
+
errorCount = errorsResult?.count || 0;
|
|
7806
|
+
topPages = (pagesResult.results || []).map((r) => ({ path: r.url, views: r.views }));
|
|
7807
|
+
recentActivity = activityResult.results || [];
|
|
7808
|
+
} catch {
|
|
7809
|
+
}
|
|
7810
|
+
const content2 = `
|
|
7811
|
+
<div class="space-y-8">
|
|
7812
|
+
<div>
|
|
7813
|
+
<h1 class="text-2xl font-semibold text-zinc-950 dark:text-white">Analytics Dashboard</h1>
|
|
7814
|
+
<p class="mt-1 text-sm text-zinc-500 dark:text-zinc-400">Last 24 hours overview from system logs</p>
|
|
7815
|
+
</div>
|
|
7816
|
+
|
|
7817
|
+
<!-- Stats Cards -->
|
|
7818
|
+
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
|
7819
|
+
<div class="rounded-lg bg-white dark:bg-zinc-800 p-6 ring-1 ring-zinc-950/5 dark:ring-white/10">
|
|
7820
|
+
<p class="text-sm font-medium text-zinc-500 dark:text-zinc-400">Total Requests</p>
|
|
7821
|
+
<p class="mt-2 text-3xl font-semibold text-zinc-950 dark:text-white">${totalRequests.toLocaleString()}</p>
|
|
7822
|
+
</div>
|
|
7823
|
+
<div class="rounded-lg bg-white dark:bg-zinc-800 p-6 ring-1 ring-zinc-950/5 dark:ring-white/10">
|
|
7824
|
+
<p class="text-sm font-medium text-zinc-500 dark:text-zinc-400">Unique Visitors</p>
|
|
7825
|
+
<p class="mt-2 text-3xl font-semibold text-zinc-950 dark:text-white">${uniqueIPs.toLocaleString()}</p>
|
|
7826
|
+
</div>
|
|
7827
|
+
<div class="rounded-lg bg-white dark:bg-zinc-800 p-6 ring-1 ring-zinc-950/5 dark:ring-white/10">
|
|
7828
|
+
<p class="text-sm font-medium text-zinc-500 dark:text-zinc-400">Avg Response Time</p>
|
|
7829
|
+
<p class="mt-2 text-3xl font-semibold text-zinc-950 dark:text-white">${avgDuration}ms</p>
|
|
7830
|
+
</div>
|
|
7831
|
+
<div class="rounded-lg bg-white dark:bg-zinc-800 p-6 ring-1 ring-zinc-950/5 dark:ring-white/10">
|
|
7832
|
+
<p class="text-sm font-medium text-zinc-500 dark:text-zinc-400">Errors</p>
|
|
7833
|
+
<p class="mt-2 text-3xl font-semibold ${errorCount > 0 ? "text-red-600 dark:text-red-400" : "text-zinc-950 dark:text-white"}">${errorCount.toLocaleString()}</p>
|
|
7834
|
+
</div>
|
|
7835
|
+
</div>
|
|
7836
|
+
|
|
7837
|
+
<!-- Top Pages -->
|
|
7838
|
+
<div class="rounded-lg bg-white dark:bg-zinc-800 ring-1 ring-zinc-950/5 dark:ring-white/10">
|
|
7839
|
+
<div class="px-6 py-4 border-b border-zinc-950/5 dark:border-white/10">
|
|
7840
|
+
<h2 class="text-lg font-semibold text-zinc-950 dark:text-white">Top Pages</h2>
|
|
7841
|
+
</div>
|
|
7842
|
+
<div class="divide-y divide-zinc-950/5 dark:divide-white/10">
|
|
7843
|
+
${topPages.length > 0 ? topPages.map((p) => `
|
|
7844
|
+
<div class="flex items-center justify-between px-6 py-3">
|
|
7845
|
+
<span class="text-sm text-zinc-700 dark:text-zinc-300 font-mono truncate">${escapeHtml3(p.path)}</span>
|
|
7846
|
+
<span class="text-sm font-medium text-zinc-500 dark:text-zinc-400">${p.views}</span>
|
|
7847
|
+
</div>
|
|
7848
|
+
`).join("") : `
|
|
7849
|
+
<div class="px-6 py-8 text-center text-sm text-zinc-500 dark:text-zinc-400">
|
|
7850
|
+
No page views recorded yet. Analytics data will appear once requests are logged.
|
|
7851
|
+
</div>
|
|
7852
|
+
`}
|
|
7853
|
+
</div>
|
|
7854
|
+
</div>
|
|
7855
|
+
|
|
7856
|
+
<!-- Recent Activity -->
|
|
7857
|
+
<div class="rounded-lg bg-white dark:bg-zinc-800 ring-1 ring-zinc-950/5 dark:ring-white/10">
|
|
7858
|
+
<div class="px-6 py-4 border-b border-zinc-950/5 dark:border-white/10">
|
|
7859
|
+
<h2 class="text-lg font-semibold text-zinc-950 dark:text-white">Recent Activity</h2>
|
|
7860
|
+
</div>
|
|
7861
|
+
<div class="overflow-x-auto">
|
|
7862
|
+
<table class="w-full text-sm">
|
|
7863
|
+
<thead class="bg-zinc-50 dark:bg-zinc-800/50">
|
|
7864
|
+
<tr>
|
|
7865
|
+
<th class="px-6 py-2 text-left font-medium text-zinc-500 dark:text-zinc-400">Path</th>
|
|
7866
|
+
<th class="px-6 py-2 text-left font-medium text-zinc-500 dark:text-zinc-400">Method</th>
|
|
7867
|
+
<th class="px-6 py-2 text-left font-medium text-zinc-500 dark:text-zinc-400">Status</th>
|
|
7868
|
+
<th class="px-6 py-2 text-left font-medium text-zinc-500 dark:text-zinc-400">Duration</th>
|
|
7869
|
+
</tr>
|
|
7870
|
+
</thead>
|
|
7871
|
+
<tbody class="divide-y divide-zinc-950/5 dark:divide-white/10">
|
|
7872
|
+
${recentActivity.length > 0 ? recentActivity.map((a) => `
|
|
7873
|
+
<tr>
|
|
7874
|
+
<td class="px-6 py-2 font-mono text-zinc-700 dark:text-zinc-300 truncate max-w-xs">${escapeHtml3(a.url || "")}</td>
|
|
7875
|
+
<td class="px-6 py-2"><span class="inline-flex items-center rounded px-1.5 py-0.5 text-xs font-medium ${a.method === "GET" ? "bg-green-50 text-green-700 dark:bg-green-900/30 dark:text-green-400" : "bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400"}">${a.method || ""}</span></td>
|
|
7876
|
+
<td class="px-6 py-2"><span class="inline-flex items-center rounded px-1.5 py-0.5 text-xs font-medium ${(a.status_code || 0) >= 400 ? "bg-red-50 text-red-700 dark:bg-red-900/30 dark:text-red-400" : "bg-green-50 text-green-700 dark:bg-green-900/30 dark:text-green-400"}">${a.status_code || ""}</span></td>
|
|
7877
|
+
<td class="px-6 py-2 text-zinc-500 dark:text-zinc-400">${a.duration || 0}ms</td>
|
|
7878
|
+
</tr>
|
|
7879
|
+
`).join("") : `
|
|
7880
|
+
<tr>
|
|
7881
|
+
<td colspan="4" class="px-6 py-8 text-center text-zinc-500 dark:text-zinc-400">No activity recorded yet.</td>
|
|
7882
|
+
</tr>
|
|
7883
|
+
`}
|
|
7884
|
+
</tbody>
|
|
7885
|
+
</table>
|
|
7886
|
+
</div>
|
|
7887
|
+
</div>
|
|
7888
|
+
</div>
|
|
7889
|
+
`;
|
|
7890
|
+
return c.html(chunkUYJ6TJHX_cjs.renderAdminLayoutCatalyst({
|
|
7891
|
+
title: "Analytics",
|
|
7892
|
+
pageTitle: "Analytics Dashboard",
|
|
7893
|
+
currentPath: "/admin/analytics",
|
|
7894
|
+
version: c.get("appVersion"),
|
|
7895
|
+
user: user ? {
|
|
7896
|
+
name: user.email.split("@")[0] || "Admin",
|
|
7897
|
+
email: user.email,
|
|
7898
|
+
role: user.role
|
|
7899
|
+
} : void 0,
|
|
7900
|
+
content: content2,
|
|
7901
|
+
dynamicMenuItems: c.get("pluginMenuItems")
|
|
7902
|
+
}));
|
|
7903
|
+
});
|
|
7904
|
+
function escapeHtml3(str) {
|
|
7905
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
7906
|
+
}
|
|
7907
|
+
|
|
7908
|
+
// src/plugins/core-plugins/analytics/index.ts
|
|
7909
|
+
function createAnalyticsPlugin() {
|
|
7910
|
+
const builder = chunk635JAMSE_cjs.PluginBuilder.create({
|
|
7911
|
+
name: "core-analytics",
|
|
7912
|
+
version: "1.0.0-beta.1",
|
|
7913
|
+
description: "Core analytics tracking and reporting plugin"
|
|
7914
|
+
});
|
|
7915
|
+
builder.metadata({
|
|
7916
|
+
author: {
|
|
7917
|
+
name: "SonicJS Team",
|
|
7918
|
+
email: "team@sonicjs.com"
|
|
7919
|
+
},
|
|
7920
|
+
license: "MIT",
|
|
7921
|
+
compatibility: "^0.1.0",
|
|
7922
|
+
dependencies: ["core-auth"]
|
|
7923
|
+
// Requires auth for admin access
|
|
7924
|
+
});
|
|
7925
|
+
const analyticsAPI = new hono.Hono();
|
|
7926
|
+
analyticsAPI.get("/stats", async (c) => {
|
|
7927
|
+
const timeRange = c.req.query("range") || "7d";
|
|
7928
|
+
c.req.query("metric") || "all";
|
|
7929
|
+
return c.json({
|
|
7930
|
+
message: "Analytics stats",
|
|
7931
|
+
data: {
|
|
7932
|
+
pageviews: 12500,
|
|
7933
|
+
uniqueVisitors: 3200,
|
|
7934
|
+
sessions: 4800,
|
|
7935
|
+
avgSessionDuration: 245,
|
|
7936
|
+
bounceRate: 0.35,
|
|
7937
|
+
topPages: [
|
|
7938
|
+
{ path: "/", views: 3200 },
|
|
7939
|
+
{ path: "/about", views: 1800 },
|
|
7940
|
+
{ path: "/contact", views: 950 }
|
|
7941
|
+
],
|
|
7942
|
+
timeRange
|
|
7943
|
+
}
|
|
7944
|
+
});
|
|
7945
|
+
});
|
|
7946
|
+
analyticsAPI.post("/track", async (c) => {
|
|
7947
|
+
const event = await c.req.json();
|
|
7948
|
+
console.info("Analytics event tracked:", event);
|
|
7949
|
+
return c.json({
|
|
7950
|
+
message: "Event tracked successfully",
|
|
7951
|
+
eventId: `event-${Date.now()}`
|
|
7952
|
+
});
|
|
7953
|
+
});
|
|
7954
|
+
analyticsAPI.get("/reports", async (c) => {
|
|
7955
|
+
const reportType = c.req.query("type") || "traffic";
|
|
7956
|
+
const startDate = c.req.query("start");
|
|
7957
|
+
const endDate = c.req.query("end");
|
|
7958
|
+
return c.json({
|
|
7959
|
+
message: "Analytics report",
|
|
7960
|
+
data: {
|
|
7961
|
+
reportType,
|
|
7962
|
+
dateRange: { start: startDate, end: endDate },
|
|
7963
|
+
data: []
|
|
7964
|
+
}
|
|
7965
|
+
});
|
|
7966
|
+
});
|
|
7967
|
+
analyticsAPI.get("/realtime", async (c) => {
|
|
7968
|
+
return c.json({
|
|
7969
|
+
message: "Real-time analytics",
|
|
7970
|
+
data: {
|
|
7971
|
+
activeUsers: 23,
|
|
7972
|
+
activePages: [
|
|
7973
|
+
{ path: "/", users: 8 },
|
|
7974
|
+
{ path: "/blog", users: 5 },
|
|
7975
|
+
{ path: "/products", users: 4 }
|
|
7976
|
+
],
|
|
7977
|
+
recentEvents: []
|
|
7978
|
+
}
|
|
7979
|
+
});
|
|
7980
|
+
});
|
|
7981
|
+
builder.addRoute("/api/analytics", analyticsAPI, {
|
|
7982
|
+
description: "Analytics tracking and reporting API",
|
|
7983
|
+
requiresAuth: true,
|
|
7984
|
+
roles: ["admin", "analytics:read"],
|
|
7985
|
+
priority: 3
|
|
7986
|
+
});
|
|
7987
|
+
builder.addRoute("/admin/analytics", adminRoutes4, {
|
|
7988
|
+
description: "Analytics admin dashboard",
|
|
7989
|
+
requiresAuth: true,
|
|
7990
|
+
priority: 50
|
|
7991
|
+
});
|
|
7992
|
+
builder.addSingleMiddleware("analytics-tracker", async (c, next) => {
|
|
7993
|
+
const start = Date.now();
|
|
7994
|
+
const path = c.req.path;
|
|
7995
|
+
const method = c.req.method;
|
|
7996
|
+
const userAgent = c.req.header("user-agent");
|
|
7997
|
+
const referer = c.req.header("referer");
|
|
7998
|
+
const ip = c.req.header("CF-Connecting-IP") || c.req.header("x-forwarded-for");
|
|
7999
|
+
await next();
|
|
8000
|
+
const duration = Date.now() - start;
|
|
8001
|
+
const status = c.res.status;
|
|
8002
|
+
const analyticsData = {
|
|
8003
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8004
|
+
path,
|
|
8005
|
+
method,
|
|
8006
|
+
status,
|
|
8007
|
+
duration,
|
|
8008
|
+
userAgent,
|
|
8009
|
+
referer,
|
|
8010
|
+
ip,
|
|
8011
|
+
responseSize: c.res.headers.get("content-length") || 0
|
|
8012
|
+
};
|
|
8013
|
+
console.debug("Analytics tracking:", analyticsData);
|
|
8014
|
+
}, {
|
|
8015
|
+
description: "Track page views and request analytics",
|
|
8016
|
+
global: true,
|
|
8017
|
+
priority: 99
|
|
8018
|
+
// Run last to capture response data
|
|
8019
|
+
});
|
|
8020
|
+
builder.addService("analyticsService", {
|
|
8021
|
+
trackEvent: async (event) => {
|
|
8022
|
+
console.info("Tracking event:", event);
|
|
8023
|
+
return { eventId: `event-${Date.now()}` };
|
|
8024
|
+
},
|
|
8025
|
+
trackPageView: async (data) => {
|
|
8026
|
+
console.info("Tracking pageview:", data.path);
|
|
8027
|
+
return { viewId: `view-${Date.now()}` };
|
|
8028
|
+
},
|
|
8029
|
+
getStats: async (_timeRange) => {
|
|
8030
|
+
return {
|
|
8031
|
+
pageviews: 12500,
|
|
8032
|
+
sessions: 4800,
|
|
8033
|
+
uniqueVisitors: 3200
|
|
8034
|
+
};
|
|
8035
|
+
},
|
|
8036
|
+
generateReport: async (type, options) => {
|
|
8037
|
+
console.info(`Generating ${type} report with options:`, options);
|
|
8038
|
+
return { reportId: `report-${Date.now()}` };
|
|
8039
|
+
}
|
|
8040
|
+
}, {
|
|
8041
|
+
description: "Core analytics tracking service",
|
|
8042
|
+
singleton: true
|
|
8043
|
+
});
|
|
8044
|
+
const pageViewSchema = chunk635JAMSE_cjs.PluginHelpers.createSchema([
|
|
8045
|
+
{ name: "path", type: "string", optional: false },
|
|
8046
|
+
{ name: "title", type: "string", optional: true },
|
|
8047
|
+
{ name: "referrer", type: "string", optional: true },
|
|
8048
|
+
{ name: "userAgent", type: "string", optional: true },
|
|
8049
|
+
{ name: "ipAddress", type: "string", optional: true },
|
|
8050
|
+
{ name: "sessionId", type: "string", optional: true },
|
|
8051
|
+
{ name: "userId", type: "number", optional: true },
|
|
8052
|
+
{ name: "duration", type: "number", optional: true }
|
|
8053
|
+
]);
|
|
8054
|
+
const eventSchema = chunk635JAMSE_cjs.PluginHelpers.createSchema([
|
|
8055
|
+
{ name: "eventType", type: "string", optional: false },
|
|
8056
|
+
{ name: "eventName", type: "string", optional: false },
|
|
8057
|
+
{ name: "eventData", type: "object", optional: true },
|
|
8058
|
+
{ name: "path", type: "string", optional: true },
|
|
8059
|
+
{ name: "sessionId", type: "string", optional: true },
|
|
8060
|
+
{ name: "userId", type: "number", optional: true }
|
|
8061
|
+
]);
|
|
8062
|
+
const pageViewMigration = chunk635JAMSE_cjs.PluginHelpers.createMigration("analytics_pageviews", [
|
|
8063
|
+
{ name: "id", type: "INTEGER", primaryKey: true },
|
|
8064
|
+
{ name: "path", type: "TEXT", nullable: false },
|
|
8065
|
+
{ name: "title", type: "TEXT", nullable: true },
|
|
8066
|
+
{ name: "referrer", type: "TEXT", nullable: true },
|
|
8067
|
+
{ name: "user_agent", type: "TEXT", nullable: true },
|
|
8068
|
+
{ name: "ip_address", type: "TEXT", nullable: true },
|
|
8069
|
+
{ name: "session_id", type: "TEXT", nullable: true },
|
|
8070
|
+
{ name: "user_id", type: "INTEGER", nullable: true },
|
|
8071
|
+
{ name: "duration", type: "INTEGER", nullable: true }
|
|
8072
|
+
]);
|
|
8073
|
+
const eventMigration = chunk635JAMSE_cjs.PluginHelpers.createMigration("analytics_events", [
|
|
8074
|
+
{ name: "id", type: "INTEGER", primaryKey: true },
|
|
8075
|
+
{ name: "event_type", type: "TEXT", nullable: false },
|
|
8076
|
+
{ name: "event_name", type: "TEXT", nullable: false },
|
|
8077
|
+
{ name: "event_data", type: "TEXT", nullable: true },
|
|
8078
|
+
{ name: "path", type: "TEXT", nullable: true },
|
|
8079
|
+
{ name: "session_id", type: "TEXT", nullable: true },
|
|
8080
|
+
{ name: "user_id", type: "INTEGER", nullable: true }
|
|
8081
|
+
]);
|
|
8082
|
+
builder.addModel("PageView", {
|
|
8083
|
+
tableName: "analytics_pageviews",
|
|
8084
|
+
schema: pageViewSchema,
|
|
8085
|
+
migrations: [pageViewMigration]
|
|
8086
|
+
});
|
|
8087
|
+
builder.addModel("AnalyticsEvent", {
|
|
8088
|
+
tableName: "analytics_events",
|
|
8089
|
+
schema: eventSchema,
|
|
8090
|
+
migrations: [eventMigration]
|
|
8091
|
+
});
|
|
8092
|
+
builder.addHook(HOOKS2.REQUEST_START, async (data, _context) => {
|
|
8093
|
+
data.analytics = {
|
|
8094
|
+
startTime: Date.now(),
|
|
8095
|
+
sessionId: `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
|
8096
|
+
};
|
|
8097
|
+
return data;
|
|
8098
|
+
}, {
|
|
8099
|
+
priority: 1,
|
|
8100
|
+
description: "Initialize analytics tracking for requests"
|
|
8101
|
+
});
|
|
8102
|
+
builder.addHook(HOOKS2.REQUEST_END, async (data, _context) => {
|
|
8103
|
+
if (data.analytics) {
|
|
8104
|
+
const duration = Date.now() - data.analytics.startTime;
|
|
8105
|
+
console.debug(`Request completed in ${duration}ms`);
|
|
8106
|
+
}
|
|
8107
|
+
return data;
|
|
8108
|
+
}, {
|
|
8109
|
+
priority: 1,
|
|
8110
|
+
description: "Complete analytics tracking for requests"
|
|
8111
|
+
});
|
|
8112
|
+
builder.addHook(HOOKS2.USER_LOGIN, async (data, context) => {
|
|
8113
|
+
await context.services?.analyticsService?.trackEvent({
|
|
8114
|
+
eventType: "auth",
|
|
8115
|
+
eventName: "user_login",
|
|
8116
|
+
userId: data.userId,
|
|
8117
|
+
eventData: { loginMethod: data.method }
|
|
8118
|
+
});
|
|
8119
|
+
return data;
|
|
8120
|
+
}, {
|
|
8121
|
+
priority: 8,
|
|
8122
|
+
description: "Track user login events"
|
|
8123
|
+
});
|
|
8124
|
+
builder.addHook("content:view", async (data, context) => {
|
|
8125
|
+
await context.services?.analyticsService?.trackEvent({
|
|
8126
|
+
eventType: "content",
|
|
8127
|
+
eventName: "content_view",
|
|
8128
|
+
eventData: {
|
|
8129
|
+
contentId: data.id,
|
|
8130
|
+
contentType: data.type,
|
|
8131
|
+
title: data.title
|
|
8132
|
+
}
|
|
8133
|
+
});
|
|
8134
|
+
return data;
|
|
8135
|
+
}, {
|
|
8136
|
+
priority: 8,
|
|
8137
|
+
description: "Track content view events"
|
|
8138
|
+
});
|
|
8139
|
+
builder.addAdminPage(
|
|
8140
|
+
"/analytics",
|
|
8141
|
+
"Analytics Dashboard",
|
|
8142
|
+
"AnalyticsDashboardView",
|
|
8143
|
+
{
|
|
8144
|
+
description: "View analytics overview and key metrics",
|
|
8145
|
+
permissions: ["admin", "analytics:read"],
|
|
8146
|
+
icon: "chart-bar"
|
|
8147
|
+
}
|
|
8148
|
+
);
|
|
8149
|
+
builder.addAdminPage(
|
|
8150
|
+
"/analytics/reports",
|
|
8151
|
+
"Analytics Reports",
|
|
8152
|
+
"AnalyticsReportsView",
|
|
8153
|
+
{
|
|
8154
|
+
description: "Generate and view detailed analytics reports",
|
|
8155
|
+
permissions: ["admin", "analytics:read"],
|
|
8156
|
+
icon: "document-report"
|
|
8157
|
+
}
|
|
8158
|
+
);
|
|
8159
|
+
builder.addAdminPage(
|
|
8160
|
+
"/analytics/realtime",
|
|
8161
|
+
"Real-time Analytics",
|
|
8162
|
+
"AnalyticsRealtimeView",
|
|
8163
|
+
{
|
|
8164
|
+
description: "View real-time visitor activity",
|
|
8165
|
+
permissions: ["admin", "analytics:read"],
|
|
8166
|
+
icon: "lightning-bolt"
|
|
8167
|
+
}
|
|
8168
|
+
);
|
|
8169
|
+
builder.addAdminPage(
|
|
8170
|
+
"/analytics/settings",
|
|
8171
|
+
"Analytics Settings",
|
|
8172
|
+
"AnalyticsSettingsView",
|
|
8173
|
+
{
|
|
8174
|
+
description: "Configure analytics tracking and data collection",
|
|
8175
|
+
permissions: ["admin", "analytics:configure"],
|
|
8176
|
+
icon: "cog"
|
|
8177
|
+
}
|
|
8178
|
+
);
|
|
8179
|
+
builder.addMenuItem("Analytics", "/admin/analytics", {
|
|
8180
|
+
icon: "chart-bar",
|
|
8181
|
+
order: 40,
|
|
8182
|
+
permissions: ["admin", "analytics:read"]
|
|
8183
|
+
});
|
|
8184
|
+
builder.addMenuItem("Dashboard", "/admin/analytics", {
|
|
8185
|
+
icon: "chart-bar",
|
|
8186
|
+
parent: "Analytics",
|
|
8187
|
+
order: 1,
|
|
8188
|
+
permissions: ["admin", "analytics:read"]
|
|
8189
|
+
});
|
|
8190
|
+
builder.addMenuItem("Reports", "/admin/analytics/reports", {
|
|
8191
|
+
icon: "document-report",
|
|
8192
|
+
parent: "Analytics",
|
|
8193
|
+
order: 2,
|
|
8194
|
+
permissions: ["admin", "analytics:read"]
|
|
8195
|
+
});
|
|
8196
|
+
builder.addMenuItem("Real-time", "/admin/analytics/realtime", {
|
|
8197
|
+
icon: "lightning-bolt",
|
|
8198
|
+
parent: "Analytics",
|
|
8199
|
+
order: 3,
|
|
8200
|
+
permissions: ["admin", "analytics:read"]
|
|
8201
|
+
});
|
|
8202
|
+
builder.addMenuItem("Settings", "/admin/analytics/settings", {
|
|
8203
|
+
icon: "cog",
|
|
8204
|
+
parent: "Analytics",
|
|
8205
|
+
order: 4,
|
|
8206
|
+
permissions: ["admin", "analytics:configure"]
|
|
8207
|
+
});
|
|
8208
|
+
builder.lifecycle({
|
|
8209
|
+
install: async () => {
|
|
8210
|
+
console.info("Installing analytics plugin...");
|
|
8211
|
+
},
|
|
8212
|
+
activate: async () => {
|
|
8213
|
+
console.info("Activating analytics plugin...");
|
|
8214
|
+
},
|
|
8215
|
+
deactivate: async () => {
|
|
8216
|
+
console.info("Deactivating analytics plugin...");
|
|
8217
|
+
},
|
|
8218
|
+
configure: async (config) => {
|
|
8219
|
+
console.info("Configuring analytics plugin...", config);
|
|
8220
|
+
}
|
|
8221
|
+
});
|
|
8222
|
+
return builder.build();
|
|
8223
|
+
}
|
|
8224
|
+
var analyticsPlugin = createAnalyticsPlugin();
|
|
8225
|
+
|
|
8226
|
+
// src/plugins/core-plugins/analytics/services/event-tracking-service.ts
|
|
8227
|
+
var EventTrackingService = class {
|
|
8228
|
+
constructor(db) {
|
|
8229
|
+
this.db = db;
|
|
8230
|
+
}
|
|
8231
|
+
async trackEvent(input) {
|
|
8232
|
+
const id = crypto.randomUUID();
|
|
8233
|
+
const category = input.category || "user-activity";
|
|
8234
|
+
await this.db.prepare(`
|
|
8235
|
+
INSERT INTO analytics_events (id, event, category, properties, user_id, session_id, ip_address, user_agent, path)
|
|
8236
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
8237
|
+
`).bind(
|
|
8238
|
+
id,
|
|
8239
|
+
input.event,
|
|
8240
|
+
category,
|
|
8241
|
+
input.properties ? JSON.stringify(input.properties) : null,
|
|
8242
|
+
input.userId || null,
|
|
8243
|
+
input.sessionId || null,
|
|
8244
|
+
input.ipAddress || null,
|
|
8245
|
+
input.userAgent || null,
|
|
8246
|
+
input.path || null
|
|
8247
|
+
).run();
|
|
8248
|
+
return id;
|
|
8249
|
+
}
|
|
8250
|
+
async trackBatch(events) {
|
|
8251
|
+
const ids = [];
|
|
8252
|
+
const stmts = events.map((input) => {
|
|
8253
|
+
const id = crypto.randomUUID();
|
|
8254
|
+
ids.push(id);
|
|
8255
|
+
const category = input.category || "user-activity";
|
|
8256
|
+
return this.db.prepare(`
|
|
8257
|
+
INSERT INTO analytics_events (id, event, category, properties, user_id, session_id, ip_address, user_agent, path)
|
|
8258
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
8259
|
+
`).bind(
|
|
8260
|
+
id,
|
|
8261
|
+
input.event,
|
|
8262
|
+
category,
|
|
8263
|
+
input.properties ? JSON.stringify(input.properties) : null,
|
|
8264
|
+
input.userId || null,
|
|
8265
|
+
input.sessionId || null,
|
|
8266
|
+
input.ipAddress || null,
|
|
8267
|
+
input.userAgent || null,
|
|
8268
|
+
input.path || null
|
|
8269
|
+
);
|
|
8270
|
+
});
|
|
8271
|
+
await this.db.batch(stmts);
|
|
8272
|
+
return ids;
|
|
8273
|
+
}
|
|
8274
|
+
async queryEvents(filters = {}) {
|
|
8275
|
+
const conditions = [];
|
|
8276
|
+
const params = [];
|
|
8277
|
+
if (filters.event) {
|
|
8278
|
+
conditions.push("event = ?");
|
|
8279
|
+
params.push(filters.event);
|
|
8280
|
+
}
|
|
8281
|
+
if (filters.category) {
|
|
8282
|
+
conditions.push("category = ?");
|
|
8283
|
+
params.push(filters.category);
|
|
8284
|
+
}
|
|
8285
|
+
if (filters.userId) {
|
|
8286
|
+
conditions.push("user_id = ?");
|
|
8287
|
+
params.push(filters.userId);
|
|
8288
|
+
}
|
|
8289
|
+
if (filters.sessionId) {
|
|
8290
|
+
conditions.push("session_id = ?");
|
|
8291
|
+
params.push(filters.sessionId);
|
|
8292
|
+
}
|
|
8293
|
+
if (filters.startDate) {
|
|
8294
|
+
conditions.push("created_at >= ?");
|
|
8295
|
+
params.push(filters.startDate);
|
|
8296
|
+
}
|
|
8297
|
+
if (filters.endDate) {
|
|
8298
|
+
conditions.push("created_at <= ?");
|
|
8299
|
+
params.push(filters.endDate);
|
|
8300
|
+
}
|
|
8301
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
8302
|
+
const limit = filters.limit || 50;
|
|
8303
|
+
const offset = filters.offset || 0;
|
|
8304
|
+
const [countResult, eventsResult] = await Promise.all([
|
|
8305
|
+
this.db.prepare(`SELECT COUNT(*) as total FROM analytics_events ${where}`).bind(...params).first(),
|
|
8306
|
+
this.db.prepare(`SELECT * FROM analytics_events ${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`).bind(...params, limit, offset).all()
|
|
8307
|
+
]);
|
|
8308
|
+
const events = (eventsResult.results || []).map((e) => ({
|
|
8309
|
+
...e,
|
|
8310
|
+
properties: e.properties ? JSON.parse(e.properties) : null
|
|
8311
|
+
}));
|
|
8312
|
+
return { events, total: countResult?.total || 0 };
|
|
8313
|
+
}
|
|
8314
|
+
async getStats(startDate, endDate) {
|
|
8315
|
+
const conditions = [];
|
|
8316
|
+
const params = [];
|
|
8317
|
+
if (startDate) {
|
|
8318
|
+
conditions.push("created_at >= ?");
|
|
8319
|
+
params.push(startDate);
|
|
8320
|
+
}
|
|
8321
|
+
if (endDate) {
|
|
8322
|
+
conditions.push("created_at <= ?");
|
|
8323
|
+
params.push(endDate);
|
|
8324
|
+
}
|
|
8325
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
8326
|
+
const [totals, topEvents] = await Promise.all([
|
|
8327
|
+
this.db.prepare(`
|
|
8328
|
+
SELECT
|
|
8329
|
+
COUNT(*) as total_events,
|
|
8330
|
+
COUNT(DISTINCT user_id) as unique_users,
|
|
8331
|
+
COUNT(DISTINCT session_id) as unique_sessions
|
|
8332
|
+
FROM analytics_events ${where}
|
|
8333
|
+
`).bind(...params).first(),
|
|
8334
|
+
this.db.prepare(`
|
|
8335
|
+
SELECT event, COUNT(*) as count
|
|
8336
|
+
FROM analytics_events ${where}
|
|
8337
|
+
GROUP BY event ORDER BY count DESC LIMIT 20
|
|
8338
|
+
`).bind(...params).all()
|
|
8339
|
+
]);
|
|
8340
|
+
return {
|
|
8341
|
+
totalEvents: totals?.total_events || 0,
|
|
8342
|
+
uniqueUsers: totals?.unique_users || 0,
|
|
8343
|
+
uniqueSessions: totals?.unique_sessions || 0,
|
|
8344
|
+
topEvents: (topEvents.results || []).map((r) => ({ event: r.event, count: r.count }))
|
|
8345
|
+
};
|
|
8346
|
+
}
|
|
8347
|
+
};
|
|
8348
|
+
|
|
8349
|
+
// src/plugins/core-plugins/analytics/routes/api.ts
|
|
8350
|
+
var apiRoutes4 = new hono.Hono();
|
|
8351
|
+
apiRoutes4.post("/", async (c) => {
|
|
8352
|
+
const db = c.env.DB;
|
|
8353
|
+
const service = new EventTrackingService(db);
|
|
8354
|
+
const ip = c.req.header("cf-connecting-ip") || c.req.header("x-forwarded-for")?.split(",")[0]?.trim() || "unknown";
|
|
8355
|
+
const userAgent = c.req.header("user-agent") || "";
|
|
8356
|
+
const user = c.get("user");
|
|
8357
|
+
let body;
|
|
8358
|
+
try {
|
|
8359
|
+
body = await c.req.json();
|
|
8360
|
+
} catch {
|
|
8361
|
+
return c.json({ error: "Invalid JSON body" }, 400);
|
|
8362
|
+
}
|
|
8363
|
+
if (Array.isArray(body)) {
|
|
8364
|
+
if (body.length > 100) {
|
|
8365
|
+
return c.json({ error: "Batch size limit is 100 events" }, 400);
|
|
8366
|
+
}
|
|
8367
|
+
const events = body.map((e) => ({
|
|
8368
|
+
event: e.event,
|
|
8369
|
+
category: e.category || "user-activity",
|
|
8370
|
+
properties: e.properties,
|
|
8371
|
+
userId: user?.userId || e.userId,
|
|
8372
|
+
sessionId: e.sessionId,
|
|
8373
|
+
ipAddress: ip,
|
|
8374
|
+
userAgent,
|
|
8375
|
+
path: e.path
|
|
8376
|
+
}));
|
|
8377
|
+
const invalid = events.find((e) => !e.event || typeof e.event !== "string");
|
|
8378
|
+
if (invalid) {
|
|
8379
|
+
return c.json({ error: 'Each event must have an "event" string field' }, 400);
|
|
8380
|
+
}
|
|
8381
|
+
const ids = await service.trackBatch(events);
|
|
8382
|
+
return c.json({ success: true, eventIds: ids, count: ids.length });
|
|
8383
|
+
}
|
|
8384
|
+
if (!body.event || typeof body.event !== "string") {
|
|
8385
|
+
return c.json({ error: '"event" field is required and must be a string' }, 400);
|
|
8386
|
+
}
|
|
8387
|
+
const eventId = await service.trackEvent({
|
|
8388
|
+
event: body.event,
|
|
8389
|
+
category: body.category || "user-activity",
|
|
8390
|
+
properties: body.properties,
|
|
8391
|
+
userId: user?.userId || body.userId,
|
|
8392
|
+
sessionId: body.sessionId,
|
|
8393
|
+
ipAddress: ip,
|
|
8394
|
+
userAgent,
|
|
8395
|
+
path: body.path
|
|
8396
|
+
});
|
|
8397
|
+
return c.json({ success: true, eventId });
|
|
8398
|
+
});
|
|
8399
|
+
apiRoutes4.get("/", async (c) => {
|
|
8400
|
+
const user = c.get("user");
|
|
8401
|
+
if (!user || user.role !== "admin") {
|
|
8402
|
+
return c.json({ error: "Admin access required" }, 403);
|
|
8403
|
+
}
|
|
8404
|
+
const db = c.env.DB;
|
|
8405
|
+
const service = new EventTrackingService(db);
|
|
8406
|
+
const filters = {
|
|
8407
|
+
event: c.req.query("event") || void 0,
|
|
8408
|
+
category: c.req.query("category") || void 0,
|
|
8409
|
+
userId: c.req.query("userId") || void 0,
|
|
8410
|
+
sessionId: c.req.query("sessionId") || void 0,
|
|
8411
|
+
startDate: c.req.query("startDate") ? parseInt(c.req.query("startDate")) : void 0,
|
|
8412
|
+
endDate: c.req.query("endDate") ? parseInt(c.req.query("endDate")) : void 0,
|
|
8413
|
+
limit: c.req.query("limit") ? parseInt(c.req.query("limit")) : 50,
|
|
8414
|
+
offset: c.req.query("offset") ? parseInt(c.req.query("offset")) : 0
|
|
8415
|
+
};
|
|
8416
|
+
const result = await service.queryEvents(filters);
|
|
8417
|
+
return c.json(result);
|
|
8418
|
+
});
|
|
8419
|
+
apiRoutes4.get("/stats", async (c) => {
|
|
8420
|
+
const user = c.get("user");
|
|
8421
|
+
if (!user || user.role !== "admin") {
|
|
8422
|
+
return c.json({ error: "Admin access required" }, 403);
|
|
8423
|
+
}
|
|
8424
|
+
const db = c.env.DB;
|
|
8425
|
+
const service = new EventTrackingService(db);
|
|
8426
|
+
const startDate = c.req.query("startDate") ? parseInt(c.req.query("startDate")) : void 0;
|
|
8427
|
+
const endDate = c.req.query("endDate") ? parseInt(c.req.query("endDate")) : void 0;
|
|
8428
|
+
const stats = await service.getStats(startDate, endDate);
|
|
8429
|
+
return c.json(stats);
|
|
8430
|
+
});
|
|
8431
|
+
|
|
7083
8432
|
// src/plugins/cache/services/cache-config.ts
|
|
7084
8433
|
var CACHE_CONFIGS = {
|
|
7085
8434
|
// Content (high read, low write)
|
|
@@ -8042,7 +9391,7 @@ async function warmNamespace(namespace, entries) {
|
|
|
8042
9391
|
}
|
|
8043
9392
|
|
|
8044
9393
|
// src/templates/pages/admin-cache.template.ts
|
|
8045
|
-
|
|
9394
|
+
chunkUYJ6TJHX_cjs.init_admin_layout_catalyst_template();
|
|
8046
9395
|
function renderCacheDashboard(data) {
|
|
8047
9396
|
const pageContent = `
|
|
8048
9397
|
<div class="space-y-6">
|
|
@@ -8221,7 +9570,7 @@ function renderCacheDashboard(data) {
|
|
|
8221
9570
|
</script>
|
|
8222
9571
|
|
|
8223
9572
|
<!-- Confirmation Dialogs -->
|
|
8224
|
-
${
|
|
9573
|
+
${chunk6ENX7QSA_cjs.renderConfirmationDialog({
|
|
8225
9574
|
id: "clear-all-cache-confirm",
|
|
8226
9575
|
title: "Clear All Cache",
|
|
8227
9576
|
message: "Are you sure you want to clear all cache entries? This cannot be undone.",
|
|
@@ -8232,7 +9581,7 @@ function renderCacheDashboard(data) {
|
|
|
8232
9581
|
onConfirm: "performClearAllCaches()"
|
|
8233
9582
|
})}
|
|
8234
9583
|
|
|
8235
|
-
${
|
|
9584
|
+
${chunk6ENX7QSA_cjs.renderConfirmationDialog({
|
|
8236
9585
|
id: "clear-namespace-cache-confirm",
|
|
8237
9586
|
title: "Clear Namespace Cache",
|
|
8238
9587
|
message: "Clear cache for this namespace?",
|
|
@@ -8243,7 +9592,7 @@ function renderCacheDashboard(data) {
|
|
|
8243
9592
|
onConfirm: "performClearNamespaceCache()"
|
|
8244
9593
|
})}
|
|
8245
9594
|
|
|
8246
|
-
${
|
|
9595
|
+
${chunk6ENX7QSA_cjs.getConfirmationDialogScript()}
|
|
8247
9596
|
`;
|
|
8248
9597
|
const layoutData = {
|
|
8249
9598
|
title: "Cache System",
|
|
@@ -8253,7 +9602,7 @@ function renderCacheDashboard(data) {
|
|
|
8253
9602
|
version: data.version,
|
|
8254
9603
|
content: pageContent
|
|
8255
9604
|
};
|
|
8256
|
-
return
|
|
9605
|
+
return chunkUYJ6TJHX_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
8257
9606
|
}
|
|
8258
9607
|
function renderStatCard(label, value, color, icon, colorOverride) {
|
|
8259
9608
|
const finalColor = colorOverride || color;
|
|
@@ -8929,14 +10278,14 @@ var faviconSvg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
|
8929
10278
|
// src/app.ts
|
|
8930
10279
|
function createSonicJSApp(config = {}) {
|
|
8931
10280
|
const app2 = new hono.Hono();
|
|
8932
|
-
const appVersion = config.version ||
|
|
10281
|
+
const appVersion = config.version || chunkYQW2GCJ3_cjs.getCoreVersion();
|
|
8933
10282
|
const appName = config.name || "SonicJS AI";
|
|
8934
10283
|
app2.use("*", async (c, next) => {
|
|
8935
10284
|
c.set("appVersion", appVersion);
|
|
8936
10285
|
await next();
|
|
8937
10286
|
});
|
|
8938
|
-
app2.use("*",
|
|
8939
|
-
app2.use("*",
|
|
10287
|
+
app2.use("*", chunkCZ6BVQZX_cjs.metricsMiddleware());
|
|
10288
|
+
app2.use("*", chunkCZ6BVQZX_cjs.bootstrapMiddleware(config));
|
|
8940
10289
|
if (config.middleware?.beforeAuth) {
|
|
8941
10290
|
for (const middleware of config.middleware.beforeAuth) {
|
|
8942
10291
|
app2.use("*", middleware);
|
|
@@ -8945,29 +10294,29 @@ function createSonicJSApp(config = {}) {
|
|
|
8945
10294
|
app2.use("*", async (_c, next) => {
|
|
8946
10295
|
await next();
|
|
8947
10296
|
});
|
|
8948
|
-
app2.use("*",
|
|
8949
|
-
app2.use("*",
|
|
10297
|
+
app2.use("*", chunkCZ6BVQZX_cjs.securityHeadersMiddleware());
|
|
10298
|
+
app2.use("*", chunkCZ6BVQZX_cjs.csrfProtection());
|
|
8950
10299
|
if (config.middleware?.afterAuth) {
|
|
8951
10300
|
for (const middleware of config.middleware.afterAuth) {
|
|
8952
10301
|
app2.use("*", middleware);
|
|
8953
10302
|
}
|
|
8954
10303
|
}
|
|
8955
10304
|
app2.use("/admin/*", pluginMenuMiddleware());
|
|
8956
|
-
app2.route("/api",
|
|
8957
|
-
app2.route("/api/media",
|
|
8958
|
-
app2.route("/api/system",
|
|
8959
|
-
app2.route("/admin/api",
|
|
8960
|
-
app2.route("/admin/dashboard",
|
|
8961
|
-
app2.route("/admin/collections",
|
|
8962
|
-
app2.route("/admin/forms",
|
|
8963
|
-
app2.route("/admin/settings",
|
|
8964
|
-
app2.route("/forms",
|
|
8965
|
-
app2.route("/api/forms",
|
|
8966
|
-
app2.route("/admin/api-reference",
|
|
10305
|
+
app2.route("/api", chunk6ENX7QSA_cjs.api_default);
|
|
10306
|
+
app2.route("/api/media", chunk6ENX7QSA_cjs.api_media_default);
|
|
10307
|
+
app2.route("/api/system", chunk6ENX7QSA_cjs.api_system_default);
|
|
10308
|
+
app2.route("/admin/api", chunk6ENX7QSA_cjs.admin_api_default);
|
|
10309
|
+
app2.route("/admin/dashboard", chunk6ENX7QSA_cjs.router);
|
|
10310
|
+
app2.route("/admin/collections", chunk6ENX7QSA_cjs.adminCollectionsRoutes);
|
|
10311
|
+
app2.route("/admin/forms", chunk6ENX7QSA_cjs.adminFormsRoutes);
|
|
10312
|
+
app2.route("/admin/settings", chunk6ENX7QSA_cjs.adminSettingsRoutes);
|
|
10313
|
+
app2.route("/forms", chunk6ENX7QSA_cjs.public_forms_default);
|
|
10314
|
+
app2.route("/api/forms", chunk6ENX7QSA_cjs.public_forms_default);
|
|
10315
|
+
app2.route("/admin/api-reference", chunk6ENX7QSA_cjs.router2);
|
|
8967
10316
|
app2.route("/admin/database-tools", createDatabaseToolsAdminRoutes());
|
|
8968
10317
|
app2.route("/admin/seed-data", createSeedDataAdminRoutes());
|
|
8969
|
-
app2.route("/admin/content",
|
|
8970
|
-
app2.route("/admin/media",
|
|
10318
|
+
app2.route("/admin/content", chunk6ENX7QSA_cjs.admin_content_default);
|
|
10319
|
+
app2.route("/admin/media", chunk6ENX7QSA_cjs.adminMediaRoutes);
|
|
8971
10320
|
app2.use("/auth/*", securityAuditMiddleware());
|
|
8972
10321
|
if (securityAuditPlugin.routes && securityAuditPlugin.routes.length > 0) {
|
|
8973
10322
|
for (const route of securityAuditPlugin.routes) {
|
|
@@ -8985,8 +10334,8 @@ function createSonicJSApp(config = {}) {
|
|
|
8985
10334
|
app2.route(route.path, route.handler);
|
|
8986
10335
|
}
|
|
8987
10336
|
}
|
|
8988
|
-
if (
|
|
8989
|
-
for (const route of
|
|
10337
|
+
if (chunk6ENX7QSA_cjs.userProfilesPlugin.routes && chunk6ENX7QSA_cjs.userProfilesPlugin.routes.length > 0) {
|
|
10338
|
+
for (const route of chunk6ENX7QSA_cjs.userProfilesPlugin.routes) {
|
|
8990
10339
|
app2.route(route.path, route.handler);
|
|
8991
10340
|
}
|
|
8992
10341
|
}
|
|
@@ -8995,16 +10344,22 @@ function createSonicJSApp(config = {}) {
|
|
|
8995
10344
|
app2.route(route.path, route.handler);
|
|
8996
10345
|
}
|
|
8997
10346
|
}
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
|
|
10347
|
+
if (analyticsPlugin.routes && analyticsPlugin.routes.length > 0) {
|
|
10348
|
+
for (const route of analyticsPlugin.routes) {
|
|
10349
|
+
app2.route(route.path, route.handler);
|
|
10350
|
+
}
|
|
10351
|
+
}
|
|
10352
|
+
app2.route("/api/events", apiRoutes4);
|
|
9003
10353
|
if (stripePlugin.routes && stripePlugin.routes.length > 0) {
|
|
9004
10354
|
for (const route of stripePlugin.routes) {
|
|
9005
10355
|
app2.route(route.path, route.handler);
|
|
9006
10356
|
}
|
|
9007
10357
|
}
|
|
10358
|
+
app2.route("/admin/plugins", chunk6ENX7QSA_cjs.adminPluginRoutes);
|
|
10359
|
+
app2.route("/admin/logs", chunk6ENX7QSA_cjs.adminLogsRoutes);
|
|
10360
|
+
app2.route("/admin", chunk6ENX7QSA_cjs.userRoutes);
|
|
10361
|
+
app2.route("/auth", chunk6ENX7QSA_cjs.auth_default);
|
|
10362
|
+
app2.route("/", chunk6ENX7QSA_cjs.test_cleanup_default);
|
|
9008
10363
|
if (emailPlugin.routes && emailPlugin.routes.length > 0) {
|
|
9009
10364
|
for (const route of emailPlugin.routes) {
|
|
9010
10365
|
app2.route(route.path, route.handler);
|
|
@@ -9088,99 +10443,99 @@ function createDb(d1$1) {
|
|
|
9088
10443
|
}
|
|
9089
10444
|
|
|
9090
10445
|
// src/index.ts
|
|
9091
|
-
var VERSION =
|
|
10446
|
+
var VERSION = chunkYQW2GCJ3_cjs.package_default.version;
|
|
9092
10447
|
|
|
9093
10448
|
Object.defineProperty(exports, "ROUTES_INFO", {
|
|
9094
10449
|
enumerable: true,
|
|
9095
|
-
get: function () { return
|
|
10450
|
+
get: function () { return chunk6ENX7QSA_cjs.ROUTES_INFO; }
|
|
9096
10451
|
});
|
|
9097
10452
|
Object.defineProperty(exports, "adminApiRoutes", {
|
|
9098
10453
|
enumerable: true,
|
|
9099
|
-
get: function () { return
|
|
10454
|
+
get: function () { return chunk6ENX7QSA_cjs.admin_api_default; }
|
|
9100
10455
|
});
|
|
9101
10456
|
Object.defineProperty(exports, "adminCheckboxRoutes", {
|
|
9102
10457
|
enumerable: true,
|
|
9103
|
-
get: function () { return
|
|
10458
|
+
get: function () { return chunk6ENX7QSA_cjs.adminCheckboxRoutes; }
|
|
9104
10459
|
});
|
|
9105
10460
|
Object.defineProperty(exports, "adminCodeExamplesRoutes", {
|
|
9106
10461
|
enumerable: true,
|
|
9107
|
-
get: function () { return
|
|
10462
|
+
get: function () { return chunk6ENX7QSA_cjs.admin_code_examples_default; }
|
|
9108
10463
|
});
|
|
9109
10464
|
Object.defineProperty(exports, "adminCollectionsRoutes", {
|
|
9110
10465
|
enumerable: true,
|
|
9111
|
-
get: function () { return
|
|
10466
|
+
get: function () { return chunk6ENX7QSA_cjs.adminCollectionsRoutes; }
|
|
9112
10467
|
});
|
|
9113
10468
|
Object.defineProperty(exports, "adminContentRoutes", {
|
|
9114
10469
|
enumerable: true,
|
|
9115
|
-
get: function () { return
|
|
10470
|
+
get: function () { return chunk6ENX7QSA_cjs.admin_content_default; }
|
|
9116
10471
|
});
|
|
9117
10472
|
Object.defineProperty(exports, "adminDashboardRoutes", {
|
|
9118
10473
|
enumerable: true,
|
|
9119
|
-
get: function () { return
|
|
10474
|
+
get: function () { return chunk6ENX7QSA_cjs.router; }
|
|
9120
10475
|
});
|
|
9121
10476
|
Object.defineProperty(exports, "adminDesignRoutes", {
|
|
9122
10477
|
enumerable: true,
|
|
9123
|
-
get: function () { return
|
|
10478
|
+
get: function () { return chunk6ENX7QSA_cjs.adminDesignRoutes; }
|
|
9124
10479
|
});
|
|
9125
10480
|
Object.defineProperty(exports, "adminLogsRoutes", {
|
|
9126
10481
|
enumerable: true,
|
|
9127
|
-
get: function () { return
|
|
10482
|
+
get: function () { return chunk6ENX7QSA_cjs.adminLogsRoutes; }
|
|
9128
10483
|
});
|
|
9129
10484
|
Object.defineProperty(exports, "adminMediaRoutes", {
|
|
9130
10485
|
enumerable: true,
|
|
9131
|
-
get: function () { return
|
|
10486
|
+
get: function () { return chunk6ENX7QSA_cjs.adminMediaRoutes; }
|
|
9132
10487
|
});
|
|
9133
10488
|
Object.defineProperty(exports, "adminPluginRoutes", {
|
|
9134
10489
|
enumerable: true,
|
|
9135
|
-
get: function () { return
|
|
10490
|
+
get: function () { return chunk6ENX7QSA_cjs.adminPluginRoutes; }
|
|
9136
10491
|
});
|
|
9137
10492
|
Object.defineProperty(exports, "adminSettingsRoutes", {
|
|
9138
10493
|
enumerable: true,
|
|
9139
|
-
get: function () { return
|
|
10494
|
+
get: function () { return chunk6ENX7QSA_cjs.adminSettingsRoutes; }
|
|
9140
10495
|
});
|
|
9141
10496
|
Object.defineProperty(exports, "adminTestimonialsRoutes", {
|
|
9142
10497
|
enumerable: true,
|
|
9143
|
-
get: function () { return
|
|
10498
|
+
get: function () { return chunk6ENX7QSA_cjs.admin_testimonials_default; }
|
|
9144
10499
|
});
|
|
9145
10500
|
Object.defineProperty(exports, "adminUsersRoutes", {
|
|
9146
10501
|
enumerable: true,
|
|
9147
|
-
get: function () { return
|
|
10502
|
+
get: function () { return chunk6ENX7QSA_cjs.userRoutes; }
|
|
9148
10503
|
});
|
|
9149
10504
|
Object.defineProperty(exports, "apiContentCrudRoutes", {
|
|
9150
10505
|
enumerable: true,
|
|
9151
|
-
get: function () { return
|
|
10506
|
+
get: function () { return chunk6ENX7QSA_cjs.api_content_crud_default; }
|
|
9152
10507
|
});
|
|
9153
10508
|
Object.defineProperty(exports, "apiMediaRoutes", {
|
|
9154
10509
|
enumerable: true,
|
|
9155
|
-
get: function () { return
|
|
10510
|
+
get: function () { return chunk6ENX7QSA_cjs.api_media_default; }
|
|
9156
10511
|
});
|
|
9157
10512
|
Object.defineProperty(exports, "apiRoutes", {
|
|
9158
10513
|
enumerable: true,
|
|
9159
|
-
get: function () { return
|
|
10514
|
+
get: function () { return chunk6ENX7QSA_cjs.api_default; }
|
|
9160
10515
|
});
|
|
9161
10516
|
Object.defineProperty(exports, "apiSystemRoutes", {
|
|
9162
10517
|
enumerable: true,
|
|
9163
|
-
get: function () { return
|
|
10518
|
+
get: function () { return chunk6ENX7QSA_cjs.api_system_default; }
|
|
9164
10519
|
});
|
|
9165
10520
|
Object.defineProperty(exports, "authRoutes", {
|
|
9166
10521
|
enumerable: true,
|
|
9167
|
-
get: function () { return
|
|
10522
|
+
get: function () { return chunk6ENX7QSA_cjs.auth_default; }
|
|
9168
10523
|
});
|
|
9169
10524
|
Object.defineProperty(exports, "createUserProfilesPlugin", {
|
|
9170
10525
|
enumerable: true,
|
|
9171
|
-
get: function () { return
|
|
10526
|
+
get: function () { return chunk6ENX7QSA_cjs.createUserProfilesPlugin; }
|
|
9172
10527
|
});
|
|
9173
10528
|
Object.defineProperty(exports, "defineUserProfile", {
|
|
9174
10529
|
enumerable: true,
|
|
9175
|
-
get: function () { return
|
|
10530
|
+
get: function () { return chunk6ENX7QSA_cjs.defineUserProfile; }
|
|
9176
10531
|
});
|
|
9177
10532
|
Object.defineProperty(exports, "getUserProfileConfig", {
|
|
9178
10533
|
enumerable: true,
|
|
9179
|
-
get: function () { return
|
|
10534
|
+
get: function () { return chunk6ENX7QSA_cjs.getUserProfileConfig; }
|
|
9180
10535
|
});
|
|
9181
10536
|
Object.defineProperty(exports, "userProfilesPlugin", {
|
|
9182
10537
|
enumerable: true,
|
|
9183
|
-
get: function () { return
|
|
10538
|
+
get: function () { return chunk6ENX7QSA_cjs.userProfilesPlugin; }
|
|
9184
10539
|
});
|
|
9185
10540
|
Object.defineProperty(exports, "Logger", {
|
|
9186
10541
|
enumerable: true,
|
|
@@ -9348,259 +10703,259 @@ Object.defineProperty(exports, "workflowHistory", {
|
|
|
9348
10703
|
});
|
|
9349
10704
|
Object.defineProperty(exports, "AuthManager", {
|
|
9350
10705
|
enumerable: true,
|
|
9351
|
-
get: function () { return
|
|
10706
|
+
get: function () { return chunkCZ6BVQZX_cjs.AuthManager; }
|
|
9352
10707
|
});
|
|
9353
10708
|
Object.defineProperty(exports, "PermissionManager", {
|
|
9354
10709
|
enumerable: true,
|
|
9355
|
-
get: function () { return
|
|
10710
|
+
get: function () { return chunkCZ6BVQZX_cjs.PermissionManager; }
|
|
9356
10711
|
});
|
|
9357
10712
|
Object.defineProperty(exports, "bootstrapMiddleware", {
|
|
9358
10713
|
enumerable: true,
|
|
9359
|
-
get: function () { return
|
|
10714
|
+
get: function () { return chunkCZ6BVQZX_cjs.bootstrapMiddleware; }
|
|
9360
10715
|
});
|
|
9361
10716
|
Object.defineProperty(exports, "cacheHeaders", {
|
|
9362
10717
|
enumerable: true,
|
|
9363
|
-
get: function () { return
|
|
10718
|
+
get: function () { return chunkCZ6BVQZX_cjs.cacheHeaders; }
|
|
9364
10719
|
});
|
|
9365
10720
|
Object.defineProperty(exports, "compressionMiddleware", {
|
|
9366
10721
|
enumerable: true,
|
|
9367
|
-
get: function () { return
|
|
10722
|
+
get: function () { return chunkCZ6BVQZX_cjs.compressionMiddleware; }
|
|
9368
10723
|
});
|
|
9369
10724
|
Object.defineProperty(exports, "detailedLoggingMiddleware", {
|
|
9370
10725
|
enumerable: true,
|
|
9371
|
-
get: function () { return
|
|
10726
|
+
get: function () { return chunkCZ6BVQZX_cjs.detailedLoggingMiddleware; }
|
|
9372
10727
|
});
|
|
9373
10728
|
Object.defineProperty(exports, "getActivePlugins", {
|
|
9374
10729
|
enumerable: true,
|
|
9375
|
-
get: function () { return
|
|
10730
|
+
get: function () { return chunkCZ6BVQZX_cjs.getActivePlugins; }
|
|
9376
10731
|
});
|
|
9377
10732
|
Object.defineProperty(exports, "isPluginActive", {
|
|
9378
10733
|
enumerable: true,
|
|
9379
|
-
get: function () { return
|
|
10734
|
+
get: function () { return chunkCZ6BVQZX_cjs.isPluginActive; }
|
|
9380
10735
|
});
|
|
9381
10736
|
Object.defineProperty(exports, "logActivity", {
|
|
9382
10737
|
enumerable: true,
|
|
9383
|
-
get: function () { return
|
|
10738
|
+
get: function () { return chunkCZ6BVQZX_cjs.logActivity; }
|
|
9384
10739
|
});
|
|
9385
10740
|
Object.defineProperty(exports, "loggingMiddleware", {
|
|
9386
10741
|
enumerable: true,
|
|
9387
|
-
get: function () { return
|
|
10742
|
+
get: function () { return chunkCZ6BVQZX_cjs.loggingMiddleware; }
|
|
9388
10743
|
});
|
|
9389
10744
|
Object.defineProperty(exports, "optionalAuth", {
|
|
9390
10745
|
enumerable: true,
|
|
9391
|
-
get: function () { return
|
|
10746
|
+
get: function () { return chunkCZ6BVQZX_cjs.optionalAuth; }
|
|
9392
10747
|
});
|
|
9393
10748
|
Object.defineProperty(exports, "performanceLoggingMiddleware", {
|
|
9394
10749
|
enumerable: true,
|
|
9395
|
-
get: function () { return
|
|
10750
|
+
get: function () { return chunkCZ6BVQZX_cjs.performanceLoggingMiddleware; }
|
|
9396
10751
|
});
|
|
9397
10752
|
Object.defineProperty(exports, "requireActivePlugin", {
|
|
9398
10753
|
enumerable: true,
|
|
9399
|
-
get: function () { return
|
|
10754
|
+
get: function () { return chunkCZ6BVQZX_cjs.requireActivePlugin; }
|
|
9400
10755
|
});
|
|
9401
10756
|
Object.defineProperty(exports, "requireActivePlugins", {
|
|
9402
10757
|
enumerable: true,
|
|
9403
|
-
get: function () { return
|
|
10758
|
+
get: function () { return chunkCZ6BVQZX_cjs.requireActivePlugins; }
|
|
9404
10759
|
});
|
|
9405
10760
|
Object.defineProperty(exports, "requireAnyPermission", {
|
|
9406
10761
|
enumerable: true,
|
|
9407
|
-
get: function () { return
|
|
10762
|
+
get: function () { return chunkCZ6BVQZX_cjs.requireAnyPermission; }
|
|
9408
10763
|
});
|
|
9409
10764
|
Object.defineProperty(exports, "requireAuth", {
|
|
9410
10765
|
enumerable: true,
|
|
9411
|
-
get: function () { return
|
|
10766
|
+
get: function () { return chunkCZ6BVQZX_cjs.requireAuth; }
|
|
9412
10767
|
});
|
|
9413
10768
|
Object.defineProperty(exports, "requirePermission", {
|
|
9414
10769
|
enumerable: true,
|
|
9415
|
-
get: function () { return
|
|
10770
|
+
get: function () { return chunkCZ6BVQZX_cjs.requirePermission; }
|
|
9416
10771
|
});
|
|
9417
10772
|
Object.defineProperty(exports, "requireRole", {
|
|
9418
10773
|
enumerable: true,
|
|
9419
|
-
get: function () { return
|
|
10774
|
+
get: function () { return chunkCZ6BVQZX_cjs.requireRole; }
|
|
9420
10775
|
});
|
|
9421
10776
|
Object.defineProperty(exports, "securityHeaders", {
|
|
9422
10777
|
enumerable: true,
|
|
9423
|
-
get: function () { return
|
|
10778
|
+
get: function () { return chunkCZ6BVQZX_cjs.securityHeadersMiddleware; }
|
|
9424
10779
|
});
|
|
9425
10780
|
Object.defineProperty(exports, "securityLoggingMiddleware", {
|
|
9426
10781
|
enumerable: true,
|
|
9427
|
-
get: function () { return
|
|
10782
|
+
get: function () { return chunkCZ6BVQZX_cjs.securityLoggingMiddleware; }
|
|
9428
10783
|
});
|
|
9429
10784
|
Object.defineProperty(exports, "PluginBootstrapService", {
|
|
9430
10785
|
enumerable: true,
|
|
9431
|
-
get: function () { return
|
|
10786
|
+
get: function () { return chunkQ5VFZUXV_cjs.PluginBootstrapService; }
|
|
9432
10787
|
});
|
|
9433
10788
|
Object.defineProperty(exports, "PluginServiceClass", {
|
|
9434
10789
|
enumerable: true,
|
|
9435
|
-
get: function () { return
|
|
10790
|
+
get: function () { return chunkQ5VFZUXV_cjs.PluginService; }
|
|
9436
10791
|
});
|
|
9437
10792
|
Object.defineProperty(exports, "backfillFormSubmissions", {
|
|
9438
10793
|
enumerable: true,
|
|
9439
|
-
get: function () { return
|
|
10794
|
+
get: function () { return chunkQ5VFZUXV_cjs.backfillFormSubmissions; }
|
|
9440
10795
|
});
|
|
9441
10796
|
Object.defineProperty(exports, "cleanupRemovedCollections", {
|
|
9442
10797
|
enumerable: true,
|
|
9443
|
-
get: function () { return
|
|
10798
|
+
get: function () { return chunkQ5VFZUXV_cjs.cleanupRemovedCollections; }
|
|
9444
10799
|
});
|
|
9445
10800
|
Object.defineProperty(exports, "createContentFromSubmission", {
|
|
9446
10801
|
enumerable: true,
|
|
9447
|
-
get: function () { return
|
|
10802
|
+
get: function () { return chunkQ5VFZUXV_cjs.createContentFromSubmission; }
|
|
9448
10803
|
});
|
|
9449
10804
|
Object.defineProperty(exports, "deriveCollectionSchemaFromFormio", {
|
|
9450
10805
|
enumerable: true,
|
|
9451
|
-
get: function () { return
|
|
10806
|
+
get: function () { return chunkQ5VFZUXV_cjs.deriveCollectionSchemaFromFormio; }
|
|
9452
10807
|
});
|
|
9453
10808
|
Object.defineProperty(exports, "deriveSubmissionTitle", {
|
|
9454
10809
|
enumerable: true,
|
|
9455
|
-
get: function () { return
|
|
10810
|
+
get: function () { return chunkQ5VFZUXV_cjs.deriveSubmissionTitle; }
|
|
9456
10811
|
});
|
|
9457
10812
|
Object.defineProperty(exports, "fullCollectionSync", {
|
|
9458
10813
|
enumerable: true,
|
|
9459
|
-
get: function () { return
|
|
10814
|
+
get: function () { return chunkQ5VFZUXV_cjs.fullCollectionSync; }
|
|
9460
10815
|
});
|
|
9461
10816
|
Object.defineProperty(exports, "getAvailableCollectionNames", {
|
|
9462
10817
|
enumerable: true,
|
|
9463
|
-
get: function () { return
|
|
10818
|
+
get: function () { return chunkQ5VFZUXV_cjs.getAvailableCollectionNames; }
|
|
9464
10819
|
});
|
|
9465
10820
|
Object.defineProperty(exports, "getManagedCollections", {
|
|
9466
10821
|
enumerable: true,
|
|
9467
|
-
get: function () { return
|
|
10822
|
+
get: function () { return chunkQ5VFZUXV_cjs.getManagedCollections; }
|
|
9468
10823
|
});
|
|
9469
10824
|
Object.defineProperty(exports, "isCollectionManaged", {
|
|
9470
10825
|
enumerable: true,
|
|
9471
|
-
get: function () { return
|
|
10826
|
+
get: function () { return chunkQ5VFZUXV_cjs.isCollectionManaged; }
|
|
9472
10827
|
});
|
|
9473
10828
|
Object.defineProperty(exports, "loadCollectionConfig", {
|
|
9474
10829
|
enumerable: true,
|
|
9475
|
-
get: function () { return
|
|
10830
|
+
get: function () { return chunkQ5VFZUXV_cjs.loadCollectionConfig; }
|
|
9476
10831
|
});
|
|
9477
10832
|
Object.defineProperty(exports, "loadCollectionConfigs", {
|
|
9478
10833
|
enumerable: true,
|
|
9479
|
-
get: function () { return
|
|
10834
|
+
get: function () { return chunkQ5VFZUXV_cjs.loadCollectionConfigs; }
|
|
9480
10835
|
});
|
|
9481
10836
|
Object.defineProperty(exports, "mapFormStatusToContentStatus", {
|
|
9482
10837
|
enumerable: true,
|
|
9483
|
-
get: function () { return
|
|
10838
|
+
get: function () { return chunkQ5VFZUXV_cjs.mapFormStatusToContentStatus; }
|
|
9484
10839
|
});
|
|
9485
10840
|
Object.defineProperty(exports, "registerCollections", {
|
|
9486
10841
|
enumerable: true,
|
|
9487
|
-
get: function () { return
|
|
10842
|
+
get: function () { return chunkQ5VFZUXV_cjs.registerCollections; }
|
|
9488
10843
|
});
|
|
9489
10844
|
Object.defineProperty(exports, "syncAllFormCollections", {
|
|
9490
10845
|
enumerable: true,
|
|
9491
|
-
get: function () { return
|
|
10846
|
+
get: function () { return chunkQ5VFZUXV_cjs.syncAllFormCollections; }
|
|
9492
10847
|
});
|
|
9493
10848
|
Object.defineProperty(exports, "syncCollection", {
|
|
9494
10849
|
enumerable: true,
|
|
9495
|
-
get: function () { return
|
|
10850
|
+
get: function () { return chunkQ5VFZUXV_cjs.syncCollection; }
|
|
9496
10851
|
});
|
|
9497
10852
|
Object.defineProperty(exports, "syncCollections", {
|
|
9498
10853
|
enumerable: true,
|
|
9499
|
-
get: function () { return
|
|
10854
|
+
get: function () { return chunkQ5VFZUXV_cjs.syncCollections; }
|
|
9500
10855
|
});
|
|
9501
10856
|
Object.defineProperty(exports, "syncFormCollection", {
|
|
9502
10857
|
enumerable: true,
|
|
9503
|
-
get: function () { return
|
|
10858
|
+
get: function () { return chunkQ5VFZUXV_cjs.syncFormCollection; }
|
|
9504
10859
|
});
|
|
9505
10860
|
Object.defineProperty(exports, "validateCollectionConfig", {
|
|
9506
10861
|
enumerable: true,
|
|
9507
|
-
get: function () { return
|
|
10862
|
+
get: function () { return chunkQ5VFZUXV_cjs.validateCollectionConfig; }
|
|
9508
10863
|
});
|
|
9509
10864
|
Object.defineProperty(exports, "MigrationService", {
|
|
9510
10865
|
enumerable: true,
|
|
9511
|
-
get: function () { return
|
|
10866
|
+
get: function () { return chunkOCLUXJ7E_cjs.MigrationService; }
|
|
9512
10867
|
});
|
|
9513
10868
|
Object.defineProperty(exports, "renderFilterBar", {
|
|
9514
10869
|
enumerable: true,
|
|
9515
|
-
get: function () { return
|
|
10870
|
+
get: function () { return chunk4ZSNJDLS_cjs.renderFilterBar; }
|
|
9516
10871
|
});
|
|
9517
10872
|
Object.defineProperty(exports, "getConfirmationDialogScript", {
|
|
9518
10873
|
enumerable: true,
|
|
9519
|
-
get: function () { return
|
|
10874
|
+
get: function () { return chunkOHYBNCVL_cjs.getConfirmationDialogScript; }
|
|
9520
10875
|
});
|
|
9521
10876
|
Object.defineProperty(exports, "renderAlert", {
|
|
9522
10877
|
enumerable: true,
|
|
9523
|
-
get: function () { return
|
|
10878
|
+
get: function () { return chunkOHYBNCVL_cjs.renderAlert; }
|
|
9524
10879
|
});
|
|
9525
10880
|
Object.defineProperty(exports, "renderConfirmationDialog", {
|
|
9526
10881
|
enumerable: true,
|
|
9527
|
-
get: function () { return
|
|
10882
|
+
get: function () { return chunkOHYBNCVL_cjs.renderConfirmationDialog; }
|
|
9528
10883
|
});
|
|
9529
10884
|
Object.defineProperty(exports, "renderForm", {
|
|
9530
10885
|
enumerable: true,
|
|
9531
|
-
get: function () { return
|
|
10886
|
+
get: function () { return chunkOHYBNCVL_cjs.renderForm; }
|
|
9532
10887
|
});
|
|
9533
10888
|
Object.defineProperty(exports, "renderFormField", {
|
|
9534
10889
|
enumerable: true,
|
|
9535
|
-
get: function () { return
|
|
10890
|
+
get: function () { return chunkOHYBNCVL_cjs.renderFormField; }
|
|
9536
10891
|
});
|
|
9537
10892
|
Object.defineProperty(exports, "renderPagination", {
|
|
9538
10893
|
enumerable: true,
|
|
9539
|
-
get: function () { return
|
|
10894
|
+
get: function () { return chunkOHYBNCVL_cjs.renderPagination; }
|
|
9540
10895
|
});
|
|
9541
10896
|
Object.defineProperty(exports, "renderTable", {
|
|
9542
10897
|
enumerable: true,
|
|
9543
|
-
get: function () { return
|
|
10898
|
+
get: function () { return chunkOHYBNCVL_cjs.renderTable; }
|
|
9544
10899
|
});
|
|
9545
10900
|
Object.defineProperty(exports, "HookSystemImpl", {
|
|
9546
10901
|
enumerable: true,
|
|
9547
|
-
get: function () { return
|
|
10902
|
+
get: function () { return chunkABB34XUS_cjs.HookSystemImpl; }
|
|
9548
10903
|
});
|
|
9549
10904
|
Object.defineProperty(exports, "HookUtils", {
|
|
9550
10905
|
enumerable: true,
|
|
9551
|
-
get: function () { return
|
|
10906
|
+
get: function () { return chunkABB34XUS_cjs.HookUtils; }
|
|
9552
10907
|
});
|
|
9553
10908
|
Object.defineProperty(exports, "PluginManagerClass", {
|
|
9554
10909
|
enumerable: true,
|
|
9555
|
-
get: function () { return
|
|
10910
|
+
get: function () { return chunkABB34XUS_cjs.PluginManager; }
|
|
9556
10911
|
});
|
|
9557
10912
|
Object.defineProperty(exports, "PluginRegistryImpl", {
|
|
9558
10913
|
enumerable: true,
|
|
9559
|
-
get: function () { return
|
|
10914
|
+
get: function () { return chunkABB34XUS_cjs.PluginRegistryImpl; }
|
|
9560
10915
|
});
|
|
9561
10916
|
Object.defineProperty(exports, "PluginValidatorClass", {
|
|
9562
10917
|
enumerable: true,
|
|
9563
|
-
get: function () { return
|
|
10918
|
+
get: function () { return chunkABB34XUS_cjs.PluginValidator; }
|
|
9564
10919
|
});
|
|
9565
10920
|
Object.defineProperty(exports, "ScopedHookSystemClass", {
|
|
9566
10921
|
enumerable: true,
|
|
9567
|
-
get: function () { return
|
|
10922
|
+
get: function () { return chunkABB34XUS_cjs.ScopedHookSystem; }
|
|
9568
10923
|
});
|
|
9569
10924
|
Object.defineProperty(exports, "PluginBuilder", {
|
|
9570
10925
|
enumerable: true,
|
|
9571
|
-
get: function () { return
|
|
10926
|
+
get: function () { return chunk635JAMSE_cjs.PluginBuilder; }
|
|
9572
10927
|
});
|
|
9573
10928
|
Object.defineProperty(exports, "PluginHelpers", {
|
|
9574
10929
|
enumerable: true,
|
|
9575
|
-
get: function () { return
|
|
10930
|
+
get: function () { return chunk635JAMSE_cjs.PluginHelpers; }
|
|
9576
10931
|
});
|
|
9577
10932
|
Object.defineProperty(exports, "QueryFilterBuilder", {
|
|
9578
10933
|
enumerable: true,
|
|
9579
|
-
get: function () { return
|
|
10934
|
+
get: function () { return chunkYQW2GCJ3_cjs.QueryFilterBuilder; }
|
|
9580
10935
|
});
|
|
9581
10936
|
Object.defineProperty(exports, "SONICJS_VERSION", {
|
|
9582
10937
|
enumerable: true,
|
|
9583
|
-
get: function () { return
|
|
10938
|
+
get: function () { return chunkYQW2GCJ3_cjs.SONICJS_VERSION; }
|
|
9584
10939
|
});
|
|
9585
10940
|
Object.defineProperty(exports, "TemplateRenderer", {
|
|
9586
10941
|
enumerable: true,
|
|
9587
|
-
get: function () { return
|
|
10942
|
+
get: function () { return chunkYQW2GCJ3_cjs.TemplateRenderer; }
|
|
9588
10943
|
});
|
|
9589
10944
|
Object.defineProperty(exports, "buildQuery", {
|
|
9590
10945
|
enumerable: true,
|
|
9591
|
-
get: function () { return
|
|
10946
|
+
get: function () { return chunkYQW2GCJ3_cjs.buildQuery; }
|
|
9592
10947
|
});
|
|
9593
10948
|
Object.defineProperty(exports, "getCoreVersion", {
|
|
9594
10949
|
enumerable: true,
|
|
9595
|
-
get: function () { return
|
|
10950
|
+
get: function () { return chunkYQW2GCJ3_cjs.getCoreVersion; }
|
|
9596
10951
|
});
|
|
9597
10952
|
Object.defineProperty(exports, "renderTemplate", {
|
|
9598
10953
|
enumerable: true,
|
|
9599
|
-
get: function () { return
|
|
10954
|
+
get: function () { return chunkYQW2GCJ3_cjs.renderTemplate; }
|
|
9600
10955
|
});
|
|
9601
10956
|
Object.defineProperty(exports, "templateRenderer", {
|
|
9602
10957
|
enumerable: true,
|
|
9603
|
-
get: function () { return
|
|
10958
|
+
get: function () { return chunkYQW2GCJ3_cjs.templateRenderer; }
|
|
9604
10959
|
});
|
|
9605
10960
|
Object.defineProperty(exports, "metricsTracker", {
|
|
9606
10961
|
enumerable: true,
|