@sonicjs-cms/core 3.0.0-beta.22 → 3.0.0-beta.24
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/adapters.cjs +512 -0
- package/dist/adapters.cjs.map +1 -0
- package/dist/adapters.d.cts +342 -0
- package/dist/adapters.d.ts +342 -0
- package/dist/adapters.js +501 -0
- package/dist/adapters.js.map +1 -0
- package/dist/admin-documents-form.template-55V2ZGWT.js +6 -0
- package/dist/{admin-documents-form.template-DDSH6ROU.js.map → admin-documents-form.template-55V2ZGWT.js.map} +1 -1
- package/dist/admin-documents-form.template-YNAVMJCV.cjs +19 -0
- package/dist/{admin-layout-catalyst.template-YQ4EMF2J.js.map → admin-documents-form.template-YNAVMJCV.cjs.map} +1 -1
- package/dist/admin-layout-catalyst.template-3XZXDGF7.cjs +21 -0
- package/dist/{admin-layout-catalyst.template-KDHKVLXR.cjs.map → admin-layout-catalyst.template-3XZXDGF7.cjs.map} +1 -1
- package/dist/admin-layout-catalyst.template-6UQGLCKI.js +7 -0
- package/dist/{admin-documents-form.template-LSZKGA5J.cjs.map → admin-layout-catalyst.template-6UQGLCKI.js.map} +1 -1
- package/dist/{chunk-FTXGZ3BF.cjs → chunk-37V3RET3.cjs} +21 -37
- package/dist/chunk-37V3RET3.cjs.map +1 -0
- package/dist/{chunk-3CT3SUR4.cjs → chunk-A2SN3RVL.cjs} +3 -3
- package/dist/chunk-A2SN3RVL.cjs.map +1 -0
- package/dist/{chunk-CRGUD4KC.cjs → chunk-BBEKHLTW.cjs} +9 -9
- package/dist/{chunk-CRGUD4KC.cjs.map → chunk-BBEKHLTW.cjs.map} +1 -1
- package/dist/{chunk-RMRJGMDE.js → chunk-BHND5PEV.js} +3 -3
- package/dist/{chunk-RMRJGMDE.js.map → chunk-BHND5PEV.js.map} +1 -1
- package/dist/{chunk-OBA2RYZN.js → chunk-BJROXF4N.js} +3 -3
- package/dist/{chunk-OBA2RYZN.js.map → chunk-BJROXF4N.js.map} +1 -1
- package/dist/{chunk-EUJAEB6W.cjs → chunk-BP52BFIV.cjs} +53 -4
- package/dist/chunk-BP52BFIV.cjs.map +1 -0
- package/dist/{chunk-PXNTCCPE.cjs → chunk-E66UVONV.cjs} +8 -8
- package/dist/{chunk-PXNTCCPE.cjs.map → chunk-E66UVONV.cjs.map} +1 -1
- package/dist/{chunk-CHWT5KBK.js → chunk-FHPEM77Y.js} +9 -25
- package/dist/chunk-FHPEM77Y.js.map +1 -0
- package/dist/{chunk-JFLZHOQP.cjs → chunk-I767LVN7.cjs} +531 -419
- package/dist/chunk-I767LVN7.cjs.map +1 -0
- package/dist/{chunk-N32OWET6.cjs → chunk-JMJM7DMM.cjs} +5 -5
- package/dist/{chunk-N32OWET6.cjs.map → chunk-JMJM7DMM.cjs.map} +1 -1
- package/dist/{chunk-QWSR4THH.cjs → chunk-KKNEYIZJ.cjs} +12 -5
- package/dist/chunk-KKNEYIZJ.cjs.map +1 -0
- package/dist/{chunk-73O4GPJ6.js → chunk-LNI3FYSI.js} +12 -5
- package/dist/chunk-LNI3FYSI.js.map +1 -0
- package/dist/{chunk-PYZYU7EK.cjs → chunk-QCJHCSOK.cjs} +36 -2
- package/dist/chunk-QCJHCSOK.cjs.map +1 -0
- package/dist/{chunk-MGHHPNJN.cjs → chunk-QJUJNTIU.cjs} +11 -59
- package/dist/chunk-QJUJNTIU.cjs.map +1 -0
- package/dist/{chunk-DOMXI5PM.js → chunk-RJ2O5IIE.js} +36 -2
- package/dist/chunk-RJ2O5IIE.js.map +1 -0
- package/dist/{chunk-5V62WT6M.js → chunk-THFZSDIU.js} +4 -2
- package/dist/chunk-THFZSDIU.js.map +1 -0
- package/dist/{chunk-2FCKKOA5.js → chunk-UIHIXTIS.js} +3 -3
- package/dist/chunk-UIHIXTIS.js.map +1 -0
- package/dist/{chunk-JQISFW6U.js → chunk-URIBTX27.js} +3 -3
- package/dist/{chunk-JQISFW6U.js.map → chunk-URIBTX27.js.map} +1 -1
- package/dist/{chunk-K623Q6WD.cjs → chunk-UYJQDDEE.cjs} +4 -2
- package/dist/chunk-UYJQDDEE.cjs.map +1 -0
- package/dist/{chunk-6KNTZ67K.js → chunk-VC5XVPLM.js} +234 -126
- package/dist/chunk-VC5XVPLM.js.map +1 -0
- package/dist/{chunk-I2DM27HP.js → chunk-VGEZNFWH.js} +49 -4
- package/dist/chunk-VGEZNFWH.js.map +1 -0
- package/dist/{chunk-GB2Q2DNK.js → chunk-VYQVDL2M.js} +5 -49
- package/dist/chunk-VYQVDL2M.js.map +1 -0
- package/dist/{define-plugin-DsKiGu1q.d.cts → define-plugin-DMcvEy_C.d.cts} +33 -0
- package/dist/{define-plugin-BYIey6sp.d.ts → define-plugin-D_6D9vVZ.d.ts} +33 -0
- package/dist/index.cjs +2587 -326
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -3
- package/dist/index.d.ts +30 -3
- package/dist/index.js +2281 -22
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +34 -34
- package/dist/middleware.js +5 -5
- package/dist/migrations-FGXZPKDC.cjs +13 -0
- package/dist/{migrations-UIMA6ZL6.cjs.map → migrations-FGXZPKDC.cjs.map} +1 -1
- package/dist/migrations-Z6D27NAW.js +4 -0
- package/dist/{migrations-HLK2QF4T.js.map → migrations-Z6D27NAW.js.map} +1 -1
- package/dist/plugins.cjs +40 -40
- package/dist/plugins.d.cts +1 -1
- package/dist/plugins.d.ts +1 -1
- package/dist/plugins.js +3 -3
- package/dist/routes.cjs +29 -29
- package/dist/routes.js +9 -9
- package/dist/services.cjs +18 -18
- package/dist/services.js +2 -2
- package/dist/templates.cjs +17 -17
- package/dist/templates.js +3 -3
- package/dist/utils.cjs +3 -3
- package/dist/utils.js +1 -1
- package/migrations/0001_core.sql +7 -1
- package/package.json +10 -3
- package/dist/admin-documents-form.template-DDSH6ROU.js +0 -6
- package/dist/admin-documents-form.template-LSZKGA5J.cjs +0 -19
- package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs +0 -21
- package/dist/admin-layout-catalyst.template-YQ4EMF2J.js +0 -7
- package/dist/chunk-2FCKKOA5.js.map +0 -1
- package/dist/chunk-3CT3SUR4.cjs.map +0 -1
- package/dist/chunk-5V62WT6M.js.map +0 -1
- package/dist/chunk-6KNTZ67K.js.map +0 -1
- package/dist/chunk-73O4GPJ6.js.map +0 -1
- package/dist/chunk-CHWT5KBK.js.map +0 -1
- package/dist/chunk-DOMXI5PM.js.map +0 -1
- package/dist/chunk-EUJAEB6W.cjs.map +0 -1
- package/dist/chunk-FTXGZ3BF.cjs.map +0 -1
- package/dist/chunk-GB2Q2DNK.js.map +0 -1
- package/dist/chunk-I2DM27HP.js.map +0 -1
- package/dist/chunk-JFLZHOQP.cjs.map +0 -1
- package/dist/chunk-K623Q6WD.cjs.map +0 -1
- package/dist/chunk-MGHHPNJN.cjs.map +0 -1
- package/dist/chunk-PYZYU7EK.cjs.map +0 -1
- package/dist/chunk-QWSR4THH.cjs.map +0 -1
- package/dist/migrations-HLK2QF4T.js +0 -4
- package/dist/migrations-UIMA6ZL6.cjs +0 -13
package/dist/index.cjs
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkGMMCCIQO_cjs = require('./chunk-GMMCCIQO.cjs');
|
|
4
|
-
var
|
|
4
|
+
var chunkI767LVN7_cjs = require('./chunk-I767LVN7.cjs');
|
|
5
5
|
require('./chunk-XWVDSM2L.cjs');
|
|
6
|
-
require('./chunk-
|
|
6
|
+
require('./chunk-JMJM7DMM.cjs');
|
|
7
7
|
var chunk36Z3AKX3_cjs = require('./chunk-36Z3AKX3.cjs');
|
|
8
8
|
var chunkYA3TJ65D_cjs = require('./chunk-YA3TJ65D.cjs');
|
|
9
9
|
var chunkYP7GW2G5_cjs = require('./chunk-YP7GW2G5.cjs');
|
|
10
|
-
var
|
|
10
|
+
var chunk37V3RET3_cjs = require('./chunk-37V3RET3.cjs');
|
|
11
11
|
var chunkLTZ5WYOK_cjs = require('./chunk-LTZ5WYOK.cjs');
|
|
12
12
|
var chunkKIGVVO6N_cjs = require('./chunk-KIGVVO6N.cjs');
|
|
13
|
-
var
|
|
14
|
-
var
|
|
15
|
-
var
|
|
16
|
-
var
|
|
17
|
-
var
|
|
18
|
-
var
|
|
19
|
-
var
|
|
13
|
+
var chunkQCJHCSOK_cjs = require('./chunk-QCJHCSOK.cjs');
|
|
14
|
+
var chunkA2SN3RVL_cjs = require('./chunk-A2SN3RVL.cjs');
|
|
15
|
+
var chunkBBEKHLTW_cjs = require('./chunk-BBEKHLTW.cjs');
|
|
16
|
+
var chunkE66UVONV_cjs = require('./chunk-E66UVONV.cjs');
|
|
17
|
+
var chunkUYJQDDEE_cjs = require('./chunk-UYJQDDEE.cjs');
|
|
18
|
+
var chunkQJUJNTIU_cjs = require('./chunk-QJUJNTIU.cjs');
|
|
19
|
+
var chunkBP52BFIV_cjs = require('./chunk-BP52BFIV.cjs');
|
|
20
20
|
var chunkJ6JTWD2A_cjs = require('./chunk-J6JTWD2A.cjs');
|
|
21
21
|
var chunkIXUHXTHW_cjs = require('./chunk-IXUHXTHW.cjs');
|
|
22
22
|
var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
|
|
23
23
|
require('./chunk-P3XDZL6Q.cjs');
|
|
24
|
-
var
|
|
24
|
+
var chunkKKNEYIZJ_cjs = require('./chunk-KKNEYIZJ.cjs');
|
|
25
25
|
var chunkMNWKYY5E_cjs = require('./chunk-MNWKYY5E.cjs');
|
|
26
26
|
var chunkQTFKZBLC_cjs = require('./chunk-QTFKZBLC.cjs');
|
|
27
27
|
require('./chunk-IGJUBJBW.cjs');
|
|
@@ -263,7 +263,7 @@ var DatabaseToolsService = class {
|
|
|
263
263
|
};
|
|
264
264
|
|
|
265
265
|
// src/templates/pages/admin-database-table.template.ts
|
|
266
|
-
|
|
266
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
267
267
|
function renderDatabaseTablePage(data) {
|
|
268
268
|
const totalPages = Math.ceil(data.totalRows / data.pageSize);
|
|
269
269
|
const startRow = (data.currentPage - 1) * data.pageSize + 1;
|
|
@@ -613,7 +613,7 @@ function renderDatabaseTablePage(data) {
|
|
|
613
613
|
user: data.user,
|
|
614
614
|
content: pageContent
|
|
615
615
|
};
|
|
616
|
-
return
|
|
616
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
617
617
|
}
|
|
618
618
|
function generatePageNumbers(currentPage, totalPages) {
|
|
619
619
|
const pages = [];
|
|
@@ -701,7 +701,7 @@ function formatCellValue(value, colName) {
|
|
|
701
701
|
// src/plugins/core-plugins/database-tools-plugin/admin-routes.ts
|
|
702
702
|
function createDatabaseToolsAdminRoutes() {
|
|
703
703
|
const router3 = new hono.Hono();
|
|
704
|
-
router3.use("*",
|
|
704
|
+
router3.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
705
705
|
router3.get("/api/stats", async (c) => {
|
|
706
706
|
try {
|
|
707
707
|
const user = c.get("user");
|
|
@@ -1110,7 +1110,7 @@ var SiteConfigService = class {
|
|
|
1110
1110
|
|
|
1111
1111
|
// src/plugins/core-plugins/email-plugin/routes/admin.ts
|
|
1112
1112
|
var adminRoutes = new hono.Hono();
|
|
1113
|
-
adminRoutes.use("*",
|
|
1113
|
+
adminRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
1114
1114
|
adminRoutes.post("/settings", async (c) => {
|
|
1115
1115
|
if (c.get("user")?.role !== "admin") {
|
|
1116
1116
|
return c.json({ error: "admin role required" }, 403);
|
|
@@ -1148,7 +1148,7 @@ adminRoutes.post("/test", async (c) => {
|
|
|
1148
1148
|
const { subject, html: html4, text } = renderTestEmail({ siteName });
|
|
1149
1149
|
try {
|
|
1150
1150
|
const settingsLoaded = await settings.load();
|
|
1151
|
-
const result = await
|
|
1151
|
+
const result = await chunkI767LVN7_cjs.getEmailService().send({
|
|
1152
1152
|
to,
|
|
1153
1153
|
subject,
|
|
1154
1154
|
html: html4,
|
|
@@ -1230,7 +1230,7 @@ function makeOnRegistrationCompleted(env) {
|
|
|
1230
1230
|
siteName,
|
|
1231
1231
|
loginUrl: siteConfig.buildLoginUrl(siteUrl)
|
|
1232
1232
|
});
|
|
1233
|
-
const result = await
|
|
1233
|
+
const result = await chunkI767LVN7_cjs.getEmailService().send({
|
|
1234
1234
|
to: user.email,
|
|
1235
1235
|
subject,
|
|
1236
1236
|
html: html4,
|
|
@@ -1304,7 +1304,7 @@ function makeOnPasswordResetRequested(env) {
|
|
|
1304
1304
|
expiresAt: Date.now() + DEFAULT_EXPIRY_MS,
|
|
1305
1305
|
siteName
|
|
1306
1306
|
});
|
|
1307
|
-
const result = await
|
|
1307
|
+
const result = await chunkI767LVN7_cjs.getEmailService().send({
|
|
1308
1308
|
to: user.email,
|
|
1309
1309
|
subject,
|
|
1310
1310
|
html: html4,
|
|
@@ -1372,7 +1372,7 @@ function makeOnPasswordResetCompleted(env) {
|
|
|
1372
1372
|
supportEmail,
|
|
1373
1373
|
when: Date.now()
|
|
1374
1374
|
});
|
|
1375
|
-
const result = await
|
|
1375
|
+
const result = await chunkI767LVN7_cjs.getEmailService().send({
|
|
1376
1376
|
to: user.email,
|
|
1377
1377
|
subject,
|
|
1378
1378
|
html: html4,
|
|
@@ -2113,7 +2113,7 @@ var CloudflareEmailProvider = class {
|
|
|
2113
2113
|
}
|
|
2114
2114
|
}
|
|
2115
2115
|
};
|
|
2116
|
-
var emailPluginV3 =
|
|
2116
|
+
var emailPluginV3 = chunkBP52BFIV_cjs.definePlugin({
|
|
2117
2117
|
id: "email",
|
|
2118
2118
|
version: "1.0.0",
|
|
2119
2119
|
name: "Email",
|
|
@@ -2127,7 +2127,7 @@ var emailPluginV3 = chunkEUJAEB6W_cjs.definePlugin({
|
|
|
2127
2127
|
const db = env.DB;
|
|
2128
2128
|
if (db) {
|
|
2129
2129
|
try {
|
|
2130
|
-
const typeRegistry = new
|
|
2130
|
+
const typeRegistry = new chunk37V3RET3_cjs.DocumentTypeRegistry(db);
|
|
2131
2131
|
await typeRegistry.register({
|
|
2132
2132
|
id: "email_log",
|
|
2133
2133
|
name: "email_log",
|
|
@@ -2142,7 +2142,7 @@ var emailPluginV3 = chunkEUJAEB6W_cjs.definePlugin({
|
|
|
2142
2142
|
} catch {
|
|
2143
2143
|
}
|
|
2144
2144
|
}
|
|
2145
|
-
if (!
|
|
2145
|
+
if (!chunkI767LVN7_cjs.hasEmailService()) {
|
|
2146
2146
|
const settings = db ? await new EmailSettingsService(db).load() : {};
|
|
2147
2147
|
const envResendKey = typeof env.RESEND_API_KEY === "string" && env.RESEND_API_KEY ? env.RESEND_API_KEY : void 0;
|
|
2148
2148
|
const cfEmailBinding = env.EMAIL;
|
|
@@ -2160,7 +2160,7 @@ var emailPluginV3 = chunkEUJAEB6W_cjs.definePlugin({
|
|
|
2160
2160
|
} else {
|
|
2161
2161
|
provider = resolveEmailProvider({ env });
|
|
2162
2162
|
}
|
|
2163
|
-
|
|
2163
|
+
chunkI767LVN7_cjs.setEmailService(new EmailService({ ...serviceOpts, provider }));
|
|
2164
2164
|
}
|
|
2165
2165
|
ctx.hooks.on("auth:registration:completed", makeOnRegistrationCompleted(env));
|
|
2166
2166
|
ctx.hooks.on("auth:password-reset:requested", makeOnPasswordResetRequested(env));
|
|
@@ -2171,7 +2171,7 @@ var emailPluginV3 = chunkEUJAEB6W_cjs.definePlugin({
|
|
|
2171
2171
|
var BATCH_SIZE = 100;
|
|
2172
2172
|
({
|
|
2173
2173
|
schema: zod.z.record(zod.z.string(), zod.z.unknown())});
|
|
2174
|
-
var emailReconciliationPlugin =
|
|
2174
|
+
var emailReconciliationPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
2175
2175
|
id: "email-reconciliation",
|
|
2176
2176
|
version: "1.0.0",
|
|
2177
2177
|
description: "Hourly cron that backfills email delivery state from provider status APIs. Only active for providers that implement EmailProvider.reconcile().",
|
|
@@ -2192,11 +2192,11 @@ var emailReconciliationPlugin = chunkEUJAEB6W_cjs.definePlugin({
|
|
|
2192
2192
|
console.warn("[email-reconciliation] No DB binding in cron env \u2014 skipping.");
|
|
2193
2193
|
return;
|
|
2194
2194
|
}
|
|
2195
|
-
if (!
|
|
2195
|
+
if (!chunkI767LVN7_cjs.hasEmailService()) {
|
|
2196
2196
|
console.warn("[email-reconciliation] EmailService not initialized \u2014 skipping.");
|
|
2197
2197
|
return;
|
|
2198
2198
|
}
|
|
2199
|
-
const emailService =
|
|
2199
|
+
const emailService = chunkI767LVN7_cjs.getEmailService();
|
|
2200
2200
|
let rows = [];
|
|
2201
2201
|
try {
|
|
2202
2202
|
const result = await db.prepare(
|
|
@@ -2683,8 +2683,8 @@ function buildOtpApi() {
|
|
|
2683
2683
|
loginUrl: settings.loginUrl || "",
|
|
2684
2684
|
loginButtonText: settings.loginButtonText || ""
|
|
2685
2685
|
});
|
|
2686
|
-
if (
|
|
2687
|
-
const sent = await
|
|
2686
|
+
if (chunkI767LVN7_cjs.hasEmailService()) {
|
|
2687
|
+
const sent = await chunkI767LVN7_cjs.getEmailService().send({
|
|
2688
2688
|
to: normalizedEmail,
|
|
2689
2689
|
subject: `Your login code for ${siteName}`,
|
|
2690
2690
|
flow: "otp",
|
|
@@ -2786,21 +2786,21 @@ function buildOtpApi() {
|
|
|
2786
2786
|
error: "Account is deactivated"
|
|
2787
2787
|
}, 403);
|
|
2788
2788
|
}
|
|
2789
|
-
const tokenTtl = await
|
|
2790
|
-
const token = await
|
|
2789
|
+
const tokenTtl = await chunk37V3RET3_cjs.getJwtExpirySecondsFromDb(db, c.env);
|
|
2790
|
+
const token = await chunk37V3RET3_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET, tokenTtl);
|
|
2791
2791
|
cookie.setCookie(c, "auth_token", token, {
|
|
2792
2792
|
httpOnly: true,
|
|
2793
2793
|
secure: true,
|
|
2794
2794
|
sameSite: "Strict",
|
|
2795
2795
|
maxAge: tokenTtl
|
|
2796
2796
|
});
|
|
2797
|
-
|
|
2797
|
+
chunkI767LVN7_cjs.dispatchHookEvent(
|
|
2798
2798
|
c,
|
|
2799
2799
|
"auth:otp:verified",
|
|
2800
2800
|
{ user: { id: user.id, email: user.email, role: user.role } },
|
|
2801
2801
|
"fire-and-forget"
|
|
2802
2802
|
);
|
|
2803
|
-
const customData = await
|
|
2803
|
+
const customData = await chunkI767LVN7_cjs.getCustomData(db, user.id);
|
|
2804
2804
|
const { is_active: _isActive, ...publicUser } = user;
|
|
2805
2805
|
return c.json({
|
|
2806
2806
|
success: true,
|
|
@@ -2845,7 +2845,7 @@ function buildOtpApi() {
|
|
|
2845
2845
|
});
|
|
2846
2846
|
return otpAPI;
|
|
2847
2847
|
}
|
|
2848
|
-
var otpLoginPlugin =
|
|
2848
|
+
var otpLoginPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
2849
2849
|
id: "otp-login",
|
|
2850
2850
|
version: "1.0.0",
|
|
2851
2851
|
name: "OTP Login",
|
|
@@ -3243,15 +3243,15 @@ function buildOauthApi() {
|
|
|
3243
3243
|
if (!user || !user.is_active) {
|
|
3244
3244
|
return c.redirect("/auth/login?error=Account is deactivated");
|
|
3245
3245
|
}
|
|
3246
|
-
const tokenTtl2 = await
|
|
3247
|
-
const jwt2 = await
|
|
3246
|
+
const tokenTtl2 = await chunk37V3RET3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
3247
|
+
const jwt2 = await chunk37V3RET3_cjs.AuthManager.generateToken(
|
|
3248
3248
|
user.id,
|
|
3249
3249
|
user.email,
|
|
3250
3250
|
user.role,
|
|
3251
3251
|
c.env.JWT_SECRET,
|
|
3252
3252
|
tokenTtl2
|
|
3253
3253
|
);
|
|
3254
|
-
|
|
3254
|
+
chunk37V3RET3_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax", maxAge: tokenTtl2 });
|
|
3255
3255
|
return c.redirect("/admin");
|
|
3256
3256
|
}
|
|
3257
3257
|
const existingUser = await oauthService.findUserByEmail(profile.email);
|
|
@@ -3268,15 +3268,15 @@ function buildOauthApi() {
|
|
|
3268
3268
|
tokenExpiresAt: tokenExpiresAt ?? void 0,
|
|
3269
3269
|
profileData: JSON.stringify(profile)
|
|
3270
3270
|
});
|
|
3271
|
-
const tokenTtl2 = await
|
|
3272
|
-
const jwt2 = await
|
|
3271
|
+
const tokenTtl2 = await chunk37V3RET3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
3272
|
+
const jwt2 = await chunk37V3RET3_cjs.AuthManager.generateToken(
|
|
3273
3273
|
existingUser.id,
|
|
3274
3274
|
existingUser.email,
|
|
3275
3275
|
existingUser.role,
|
|
3276
3276
|
c.env.JWT_SECRET,
|
|
3277
3277
|
tokenTtl2
|
|
3278
3278
|
);
|
|
3279
|
-
|
|
3279
|
+
chunk37V3RET3_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax", maxAge: tokenTtl2 });
|
|
3280
3280
|
return c.redirect("/admin");
|
|
3281
3281
|
}
|
|
3282
3282
|
const newUserId = await oauthService.createUserFromOAuth(profile);
|
|
@@ -3289,15 +3289,15 @@ function buildOauthApi() {
|
|
|
3289
3289
|
tokenExpiresAt: tokenExpiresAt ?? void 0,
|
|
3290
3290
|
profileData: JSON.stringify(profile)
|
|
3291
3291
|
});
|
|
3292
|
-
const tokenTtl = await
|
|
3293
|
-
const jwt = await
|
|
3292
|
+
const tokenTtl = await chunk37V3RET3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
3293
|
+
const jwt = await chunk37V3RET3_cjs.AuthManager.generateToken(
|
|
3294
3294
|
newUserId,
|
|
3295
3295
|
profile.email.toLowerCase(),
|
|
3296
3296
|
"viewer",
|
|
3297
3297
|
c.env.JWT_SECRET,
|
|
3298
3298
|
tokenTtl
|
|
3299
3299
|
);
|
|
3300
|
-
|
|
3300
|
+
chunk37V3RET3_cjs.AuthManager.setAuthCookie(c, jwt, { sameSite: "Lax", maxAge: tokenTtl });
|
|
3301
3301
|
return c.redirect("/admin");
|
|
3302
3302
|
} catch (error) {
|
|
3303
3303
|
console.error("OAuth callback error:", error);
|
|
@@ -3392,7 +3392,7 @@ function buildOauthApi() {
|
|
|
3392
3392
|
});
|
|
3393
3393
|
return oauthAPI;
|
|
3394
3394
|
}
|
|
3395
|
-
var oauthProvidersPlugin =
|
|
3395
|
+
var oauthProvidersPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
3396
3396
|
id: "oauth-providers",
|
|
3397
3397
|
version: "1.0.0",
|
|
3398
3398
|
name: "OAuth Providers",
|
|
@@ -3976,7 +3976,7 @@ var AISearchService = class {
|
|
|
3976
3976
|
*/
|
|
3977
3977
|
async detectNewCollections() {
|
|
3978
3978
|
try {
|
|
3979
|
-
const allCollections =
|
|
3979
|
+
const allCollections = chunkQCJHCSOK_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => ({
|
|
3980
3980
|
id: r.id,
|
|
3981
3981
|
name: r.name,
|
|
3982
3982
|
display_name: r.displayName,
|
|
@@ -4028,7 +4028,7 @@ var AISearchService = class {
|
|
|
4028
4028
|
*/
|
|
4029
4029
|
async getAllCollections() {
|
|
4030
4030
|
try {
|
|
4031
|
-
const allCollections =
|
|
4031
|
+
const allCollections = chunkQCJHCSOK_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).sort((a, b) => a.displayName.localeCompare(b.displayName)).map((r) => ({
|
|
4032
4032
|
id: r.id,
|
|
4033
4033
|
name: r.name,
|
|
4034
4034
|
display_name: r.displayName,
|
|
@@ -4367,7 +4367,7 @@ var IndexManager = class {
|
|
|
4367
4367
|
*/
|
|
4368
4368
|
async indexCollection(collectionId) {
|
|
4369
4369
|
try {
|
|
4370
|
-
const registry =
|
|
4370
|
+
const registry = chunkQCJHCSOK_cjs.getCollectionRegistry();
|
|
4371
4371
|
const record = registry.getById(collectionId) ?? registry.getByName(collectionId);
|
|
4372
4372
|
if (!record) {
|
|
4373
4373
|
throw new Error(`Collection ${collectionId} not found`);
|
|
@@ -4983,7 +4983,7 @@ function renderSettingsPage(data) {
|
|
|
4983
4983
|
}, 30000);
|
|
4984
4984
|
</script>
|
|
4985
4985
|
`;
|
|
4986
|
-
return
|
|
4986
|
+
return chunkE66UVONV_cjs.renderAdminLayout({
|
|
4987
4987
|
title: "AI Search Settings",
|
|
4988
4988
|
pageTitle: "AI Search Settings",
|
|
4989
4989
|
currentPath: "/admin/plugins/ai-search/settings",
|
|
@@ -4994,7 +4994,7 @@ function renderSettingsPage(data) {
|
|
|
4994
4994
|
|
|
4995
4995
|
// src/plugins/core-plugins/ai-search-plugin/routes/admin.ts
|
|
4996
4996
|
var adminRoutes2 = new hono.Hono();
|
|
4997
|
-
adminRoutes2.use("*",
|
|
4997
|
+
adminRoutes2.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
4998
4998
|
adminRoutes2.get("/", async (c) => {
|
|
4999
4999
|
try {
|
|
5000
5000
|
const user = c.get("user");
|
|
@@ -5235,7 +5235,7 @@ var manifest_default = {
|
|
|
5235
5235
|
author: "SonicJS"};
|
|
5236
5236
|
|
|
5237
5237
|
// src/plugins/core-plugins/ai-search-plugin/index.ts
|
|
5238
|
-
var aiSearchPlugin =
|
|
5238
|
+
var aiSearchPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
5239
5239
|
id: manifest_default.id,
|
|
5240
5240
|
version: manifest_default.version,
|
|
5241
5241
|
name: manifest_default.name,
|
|
@@ -5536,7 +5536,7 @@ function rowToEvent(row) {
|
|
|
5536
5536
|
}
|
|
5537
5537
|
|
|
5538
5538
|
// src/plugins/core-plugins/security-audit-plugin/components/dashboard-page.ts
|
|
5539
|
-
|
|
5539
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
5540
5540
|
function formatTimestamp(ts) {
|
|
5541
5541
|
const date = new Date(ts);
|
|
5542
5542
|
const now = Date.now();
|
|
@@ -5735,11 +5735,11 @@ function renderSecurityDashboard(data) {
|
|
|
5735
5735
|
version,
|
|
5736
5736
|
dynamicMenuItems
|
|
5737
5737
|
};
|
|
5738
|
-
return
|
|
5738
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
5739
5739
|
}
|
|
5740
5740
|
|
|
5741
5741
|
// src/plugins/core-plugins/security-audit-plugin/components/event-log-page.ts
|
|
5742
|
-
|
|
5742
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
5743
5743
|
function formatTimestamp2(ts) {
|
|
5744
5744
|
const date = new Date(ts);
|
|
5745
5745
|
return date.toLocaleDateString("en-US", {
|
|
@@ -5946,11 +5946,11 @@ function renderEventLogPage(data) {
|
|
|
5946
5946
|
version,
|
|
5947
5947
|
dynamicMenuItems
|
|
5948
5948
|
};
|
|
5949
|
-
return
|
|
5949
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
5950
5950
|
}
|
|
5951
5951
|
|
|
5952
5952
|
// src/plugins/core-plugins/security-audit-plugin/components/settings-page.ts
|
|
5953
|
-
|
|
5953
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
5954
5954
|
function renderSecuritySettingsPage(data) {
|
|
5955
5955
|
const { settings, user, version, message, dynamicMenuItems } = data;
|
|
5956
5956
|
const content2 = `
|
|
@@ -6103,12 +6103,12 @@ function renderSecuritySettingsPage(data) {
|
|
|
6103
6103
|
version,
|
|
6104
6104
|
dynamicMenuItems
|
|
6105
6105
|
};
|
|
6106
|
-
return
|
|
6106
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
6107
6107
|
}
|
|
6108
6108
|
|
|
6109
6109
|
// src/plugins/core-plugins/security-audit-plugin/routes/admin.ts
|
|
6110
6110
|
var adminRoutes3 = new hono.Hono();
|
|
6111
|
-
adminRoutes3.use("*",
|
|
6111
|
+
adminRoutes3.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
6112
6112
|
adminRoutes3.use("*", async (c, next) => {
|
|
6113
6113
|
const user = c.get("user");
|
|
6114
6114
|
if (user?.role !== "admin") {
|
|
@@ -6118,7 +6118,7 @@ adminRoutes3.use("*", async (c, next) => {
|
|
|
6118
6118
|
});
|
|
6119
6119
|
async function getSettings(db) {
|
|
6120
6120
|
try {
|
|
6121
|
-
const pluginService = new
|
|
6121
|
+
const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
|
|
6122
6122
|
const plugin2 = await pluginService.getPlugin("security-audit");
|
|
6123
6123
|
if (plugin2?.settings) {
|
|
6124
6124
|
const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
|
|
@@ -6223,7 +6223,7 @@ adminRoutes3.post("/settings", async (c) => {
|
|
|
6223
6223
|
autoPurge: body["retention.autoPurge"] === "true"
|
|
6224
6224
|
}
|
|
6225
6225
|
};
|
|
6226
|
-
const pluginService = new
|
|
6226
|
+
const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
|
|
6227
6227
|
await pluginService.updatePluginSettings("security-audit", settings);
|
|
6228
6228
|
if (c.req.header("HX-Request")) {
|
|
6229
6229
|
return c.json({ success: true });
|
|
@@ -6385,7 +6385,7 @@ var BruteForceDetector = class {
|
|
|
6385
6385
|
|
|
6386
6386
|
// src/plugins/core-plugins/security-audit-plugin/routes/api.ts
|
|
6387
6387
|
var apiRoutes2 = new hono.Hono();
|
|
6388
|
-
apiRoutes2.use("*",
|
|
6388
|
+
apiRoutes2.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
6389
6389
|
apiRoutes2.use("*", async (c, next) => {
|
|
6390
6390
|
const user = c.get("user");
|
|
6391
6391
|
if (user?.role !== "admin") {
|
|
@@ -6395,7 +6395,7 @@ apiRoutes2.use("*", async (c, next) => {
|
|
|
6395
6395
|
});
|
|
6396
6396
|
async function getSettings2(db) {
|
|
6397
6397
|
try {
|
|
6398
|
-
const pluginService = new
|
|
6398
|
+
const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
|
|
6399
6399
|
const plugin2 = await pluginService.getPlugin("security-audit");
|
|
6400
6400
|
if (plugin2?.settings) {
|
|
6401
6401
|
const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
|
|
@@ -6543,7 +6543,7 @@ function generateFingerprint(ip, userAgent) {
|
|
|
6543
6543
|
}
|
|
6544
6544
|
async function getPluginSettings(db) {
|
|
6545
6545
|
try {
|
|
6546
|
-
const pluginService = new
|
|
6546
|
+
const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
|
|
6547
6547
|
const plugin2 = await pluginService.getPlugin("security-audit");
|
|
6548
6548
|
if (plugin2?.settings) {
|
|
6549
6549
|
const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
|
|
@@ -6774,7 +6774,7 @@ async function logAuthEvent(c, db, settings, ip, userAgent, countryCode, fingerp
|
|
|
6774
6774
|
|
|
6775
6775
|
// src/plugins/core-plugins/security-audit-plugin/index.ts
|
|
6776
6776
|
var SECURITY_ICON = `<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>`;
|
|
6777
|
-
var securityAuditPlugin =
|
|
6777
|
+
var securityAuditPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
6778
6778
|
id: "security-audit",
|
|
6779
6779
|
version: "1.0.0",
|
|
6780
6780
|
name: "Security Audit",
|
|
@@ -6850,7 +6850,7 @@ var ApiKeyService = class {
|
|
|
6850
6850
|
const prefix = secret.slice(0, DISPLAY_PREFIX_LEN);
|
|
6851
6851
|
const expiresAt = input.expiresAt ?? null;
|
|
6852
6852
|
const doc = await this.docService().create(
|
|
6853
|
-
|
|
6853
|
+
chunkI767LVN7_cjs.createDocumentSchema.parse({
|
|
6854
6854
|
typeId: "api_key",
|
|
6855
6855
|
tenantId: this.tenantId,
|
|
6856
6856
|
title: name,
|
|
@@ -6943,7 +6943,7 @@ var ApiKeyService = class {
|
|
|
6943
6943
|
};
|
|
6944
6944
|
|
|
6945
6945
|
// src/plugins/core-plugins/api-keys-plugin/components/keys-page.ts
|
|
6946
|
-
|
|
6946
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
6947
6947
|
function fmtDate(ms) {
|
|
6948
6948
|
if (!ms) return "\u2014";
|
|
6949
6949
|
try {
|
|
@@ -7144,7 +7144,7 @@ function renderApiKeysPage(data) {
|
|
|
7144
7144
|
version,
|
|
7145
7145
|
dynamicMenuItems
|
|
7146
7146
|
};
|
|
7147
|
-
return
|
|
7147
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
7148
7148
|
}
|
|
7149
7149
|
|
|
7150
7150
|
// src/plugins/core-plugins/api-keys-plugin/types.ts
|
|
@@ -7163,7 +7163,7 @@ var createSchema = zod.z.object({
|
|
|
7163
7163
|
});
|
|
7164
7164
|
async function getSettings3(db) {
|
|
7165
7165
|
try {
|
|
7166
|
-
const plugin2 = await new
|
|
7166
|
+
const plugin2 = await new chunkQCJHCSOK_cjs.PluginService(db).getPlugin("api-keys");
|
|
7167
7167
|
if (plugin2?.settings) {
|
|
7168
7168
|
const s = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
|
|
7169
7169
|
return { ...DEFAULT_SETTINGS3, ...s };
|
|
@@ -7172,7 +7172,7 @@ async function getSettings3(db) {
|
|
|
7172
7172
|
}
|
|
7173
7173
|
return DEFAULT_SETTINGS3;
|
|
7174
7174
|
}
|
|
7175
|
-
adminRoutes4.use("*",
|
|
7175
|
+
adminRoutes4.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
7176
7176
|
adminRoutes4.use("*", async (c, next) => {
|
|
7177
7177
|
const user = c.get("user");
|
|
7178
7178
|
if (user?.role !== "admin") {
|
|
@@ -7257,7 +7257,7 @@ function apiKeyAuthMiddleware() {
|
|
|
7257
7257
|
|
|
7258
7258
|
// src/plugins/core-plugins/api-keys-plugin/index.ts
|
|
7259
7259
|
var KEY_ICON = `<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 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"/></svg>`;
|
|
7260
|
-
var apiKeysPlugin =
|
|
7260
|
+
var apiKeysPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
7261
7261
|
id: "api-keys",
|
|
7262
7262
|
version: "1.0.0-beta.1",
|
|
7263
7263
|
name: "API Keys",
|
|
@@ -7643,7 +7643,7 @@ var StripeEventService = class {
|
|
|
7643
7643
|
};
|
|
7644
7644
|
|
|
7645
7645
|
// src/plugins/core-plugins/stripe-plugin/components/subscriptions-page.ts
|
|
7646
|
-
|
|
7646
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
7647
7647
|
|
|
7648
7648
|
// src/plugins/core-plugins/stripe-plugin/components/tab-bar.ts
|
|
7649
7649
|
var TABS = [
|
|
@@ -7776,7 +7776,7 @@ function renderSubscriptionsPage(data) {
|
|
|
7776
7776
|
version,
|
|
7777
7777
|
dynamicMenuItems
|
|
7778
7778
|
};
|
|
7779
|
-
return
|
|
7779
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
7780
7780
|
}
|
|
7781
7781
|
function statsCard(label, value, colorClass) {
|
|
7782
7782
|
return `
|
|
@@ -7856,7 +7856,7 @@ function renderPagination2(page, totalPages, status) {
|
|
|
7856
7856
|
}
|
|
7857
7857
|
|
|
7858
7858
|
// src/plugins/core-plugins/stripe-plugin/components/events-page.ts
|
|
7859
|
-
|
|
7859
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
7860
7860
|
function renderEventsPage(data) {
|
|
7861
7861
|
const { events, stats, types, filters, user, version, dynamicMenuItems } = data;
|
|
7862
7862
|
const content2 = `
|
|
@@ -7929,7 +7929,7 @@ function renderEventsPage(data) {
|
|
|
7929
7929
|
version,
|
|
7930
7930
|
dynamicMenuItems
|
|
7931
7931
|
};
|
|
7932
|
-
return
|
|
7932
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
7933
7933
|
}
|
|
7934
7934
|
function eventStatsCard(label, value, colorClass) {
|
|
7935
7935
|
return `
|
|
@@ -8028,7 +8028,7 @@ var DEFAULT_SETTINGS4 = {
|
|
|
8028
8028
|
|
|
8029
8029
|
// src/plugins/core-plugins/stripe-plugin/routes/admin.ts
|
|
8030
8030
|
var adminRoutes5 = new hono.Hono();
|
|
8031
|
-
adminRoutes5.use("*",
|
|
8031
|
+
adminRoutes5.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
8032
8032
|
adminRoutes5.use("*", async (c, next) => {
|
|
8033
8033
|
const user = c.get("user");
|
|
8034
8034
|
if (user?.role !== "admin") {
|
|
@@ -8038,7 +8038,7 @@ adminRoutes5.use("*", async (c, next) => {
|
|
|
8038
8038
|
});
|
|
8039
8039
|
async function getSettings4(db) {
|
|
8040
8040
|
try {
|
|
8041
|
-
const pluginService = new
|
|
8041
|
+
const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
|
|
8042
8042
|
const plugin2 = await pluginService.getPlugin("stripe");
|
|
8043
8043
|
if (plugin2?.settings) {
|
|
8044
8044
|
const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
|
|
@@ -8101,7 +8101,7 @@ adminRoutes5.get("/settings", async (c) => {
|
|
|
8101
8101
|
const db = c.env.DB;
|
|
8102
8102
|
const user = c.get("user");
|
|
8103
8103
|
const settings = await getSettings4(db);
|
|
8104
|
-
const { renderAdminLayoutCatalyst: renderAdminLayoutCatalyst2 } = await import('./admin-layout-catalyst.template-
|
|
8104
|
+
const { renderAdminLayoutCatalyst: renderAdminLayoutCatalyst2 } = await import('./admin-layout-catalyst.template-3XZXDGF7.cjs');
|
|
8105
8105
|
const content2 = `
|
|
8106
8106
|
<div>
|
|
8107
8107
|
<div class="mb-6">
|
|
@@ -8361,7 +8361,7 @@ function timingSafeEqual(a, b) {
|
|
|
8361
8361
|
var apiRoutes3 = new hono.Hono();
|
|
8362
8362
|
async function getSettings5(db) {
|
|
8363
8363
|
try {
|
|
8364
|
-
const pluginService = new
|
|
8364
|
+
const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
|
|
8365
8365
|
const plugin2 = await pluginService.getPlugin("stripe");
|
|
8366
8366
|
if (plugin2?.settings) {
|
|
8367
8367
|
const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
|
|
@@ -8512,7 +8512,7 @@ apiRoutes3.post("/webhook", async (c) => {
|
|
|
8512
8512
|
}
|
|
8513
8513
|
return c.json({ received: true });
|
|
8514
8514
|
});
|
|
8515
|
-
apiRoutes3.post("/create-checkout-session",
|
|
8515
|
+
apiRoutes3.post("/create-checkout-session", chunk37V3RET3_cjs.requireAuth(), async (c) => {
|
|
8516
8516
|
const db = c.env.DB;
|
|
8517
8517
|
const user = c.get("user");
|
|
8518
8518
|
if (!user) return c.json({ error: "Unauthorized" }, 401);
|
|
@@ -8552,7 +8552,7 @@ apiRoutes3.post("/create-checkout-session", chunkFTXGZ3BF_cjs.requireAuth(), asy
|
|
|
8552
8552
|
});
|
|
8553
8553
|
return c.json({ sessionId: session.id, url: session.url });
|
|
8554
8554
|
});
|
|
8555
|
-
apiRoutes3.get("/subscription",
|
|
8555
|
+
apiRoutes3.get("/subscription", chunk37V3RET3_cjs.requireAuth(), async (c) => {
|
|
8556
8556
|
const user = c.get("user");
|
|
8557
8557
|
if (!user) return c.json({ error: "Unauthorized" }, 401);
|
|
8558
8558
|
const db = c.env.DB;
|
|
@@ -8564,7 +8564,7 @@ apiRoutes3.get("/subscription", chunkFTXGZ3BF_cjs.requireAuth(), async (c) => {
|
|
|
8564
8564
|
}
|
|
8565
8565
|
return c.json({ subscription });
|
|
8566
8566
|
});
|
|
8567
|
-
apiRoutes3.get("/subscriptions",
|
|
8567
|
+
apiRoutes3.get("/subscriptions", chunk37V3RET3_cjs.requireAuth(), async (c) => {
|
|
8568
8568
|
const user = c.get("user");
|
|
8569
8569
|
if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
|
|
8570
8570
|
const db = c.env.DB;
|
|
@@ -8580,7 +8580,7 @@ apiRoutes3.get("/subscriptions", chunkFTXGZ3BF_cjs.requireAuth(), async (c) => {
|
|
|
8580
8580
|
const result = await subscriptionService.list(filters);
|
|
8581
8581
|
return c.json(result);
|
|
8582
8582
|
});
|
|
8583
|
-
apiRoutes3.get("/stats",
|
|
8583
|
+
apiRoutes3.get("/stats", chunk37V3RET3_cjs.requireAuth(), async (c) => {
|
|
8584
8584
|
const user = c.get("user");
|
|
8585
8585
|
if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
|
|
8586
8586
|
const db = c.env.DB;
|
|
@@ -8589,7 +8589,7 @@ apiRoutes3.get("/stats", chunkFTXGZ3BF_cjs.requireAuth(), async (c) => {
|
|
|
8589
8589
|
const stats = await subscriptionService.getStats();
|
|
8590
8590
|
return c.json(stats);
|
|
8591
8591
|
});
|
|
8592
|
-
apiRoutes3.post("/sync-subscriptions",
|
|
8592
|
+
apiRoutes3.post("/sync-subscriptions", chunk37V3RET3_cjs.requireAuth(), async (c) => {
|
|
8593
8593
|
const user = c.get("user");
|
|
8594
8594
|
if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
|
|
8595
8595
|
const db = c.env.DB;
|
|
@@ -8637,7 +8637,7 @@ apiRoutes3.post("/sync-subscriptions", chunkFTXGZ3BF_cjs.requireAuth(), async (c
|
|
|
8637
8637
|
}, 500);
|
|
8638
8638
|
}
|
|
8639
8639
|
});
|
|
8640
|
-
apiRoutes3.get("/events",
|
|
8640
|
+
apiRoutes3.get("/events", chunk37V3RET3_cjs.requireAuth(), async (c) => {
|
|
8641
8641
|
const user = c.get("user");
|
|
8642
8642
|
if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
|
|
8643
8643
|
const db = c.env.DB;
|
|
@@ -8660,7 +8660,7 @@ apiRoutes3.get("/events", chunkFTXGZ3BF_cjs.requireAuth(), async (c) => {
|
|
|
8660
8660
|
|
|
8661
8661
|
// src/plugins/core-plugins/stripe-plugin/index.ts
|
|
8662
8662
|
var STRIPE_ICON = `<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 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/></svg>`;
|
|
8663
|
-
var stripePlugin =
|
|
8663
|
+
var stripePlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
8664
8664
|
id: "stripe",
|
|
8665
8665
|
version: "1.0.0",
|
|
8666
8666
|
name: "Stripe",
|
|
@@ -8681,7 +8681,7 @@ var stripePlugin = chunkEUJAEB6W_cjs.definePlugin({
|
|
|
8681
8681
|
});
|
|
8682
8682
|
|
|
8683
8683
|
// src/templates/pages/admin-forms-list.template.ts
|
|
8684
|
-
|
|
8684
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
8685
8685
|
function renderFormsListPage(data) {
|
|
8686
8686
|
const tableData = {
|
|
8687
8687
|
tableId: "forms-table",
|
|
@@ -8933,7 +8933,7 @@ function renderFormsListPage(data) {
|
|
|
8933
8933
|
|
|
8934
8934
|
<!-- Forms Table -->
|
|
8935
8935
|
<div class="bg-white dark:bg-zinc-900 rounded-lg border border-zinc-950/5 dark:border-white/10 overflow-hidden">
|
|
8936
|
-
${
|
|
8936
|
+
${chunkI767LVN7_cjs.renderTable(tableData)}
|
|
8937
8937
|
</div>
|
|
8938
8938
|
</div>
|
|
8939
8939
|
`;
|
|
@@ -8943,11 +8943,11 @@ function renderFormsListPage(data) {
|
|
|
8943
8943
|
user: data.user,
|
|
8944
8944
|
version: data.version
|
|
8945
8945
|
};
|
|
8946
|
-
return
|
|
8946
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
8947
8947
|
}
|
|
8948
8948
|
|
|
8949
8949
|
// src/templates/pages/admin-forms-builder.template.ts
|
|
8950
|
-
|
|
8950
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
8951
8951
|
function getTurnstileComponentScript() {
|
|
8952
8952
|
return `
|
|
8953
8953
|
(function() {
|
|
@@ -10160,11 +10160,11 @@ ${getTurnstileComponentScript()}
|
|
|
10160
10160
|
user: data.user,
|
|
10161
10161
|
version: data.version
|
|
10162
10162
|
};
|
|
10163
|
-
return
|
|
10163
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
10164
10164
|
}
|
|
10165
10165
|
|
|
10166
10166
|
// src/templates/pages/admin-forms-create.template.ts
|
|
10167
|
-
|
|
10167
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
10168
10168
|
function renderFormCreatePage(data) {
|
|
10169
10169
|
const pageContent = `
|
|
10170
10170
|
<div class="max-w-3xl mx-auto">
|
|
@@ -10357,13 +10357,13 @@ function renderFormCreatePage(data) {
|
|
|
10357
10357
|
user: data.user,
|
|
10358
10358
|
version: data.version
|
|
10359
10359
|
};
|
|
10360
|
-
return
|
|
10360
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
10361
10361
|
}
|
|
10362
10362
|
|
|
10363
10363
|
// src/routes/admin-forms.ts
|
|
10364
10364
|
var isTableMissing = (err) => String(err?.message ?? err?.cause?.message ?? "").includes("no such table: forms");
|
|
10365
10365
|
var adminFormsRoutes = new hono.Hono();
|
|
10366
|
-
adminFormsRoutes.use("*",
|
|
10366
|
+
adminFormsRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
10367
10367
|
adminFormsRoutes.get("/", async (c) => {
|
|
10368
10368
|
try {
|
|
10369
10369
|
const user = c.get("user");
|
|
@@ -10536,7 +10536,7 @@ adminFormsRoutes.get("/:id/builder", async (c) => {
|
|
|
10536
10536
|
if (!form) {
|
|
10537
10537
|
return c.html("<p>Form not found</p>", 404);
|
|
10538
10538
|
}
|
|
10539
|
-
const turnstileService = new
|
|
10539
|
+
const turnstileService = new chunkQJUJNTIU_cjs.TurnstileService(db);
|
|
10540
10540
|
const turnstileSettings = await turnstileService.getSettings();
|
|
10541
10541
|
const pageData = {
|
|
10542
10542
|
id: form.id,
|
|
@@ -10705,7 +10705,7 @@ publicFormsRoutes.get("/:identifier/turnstile-config", async (c) => {
|
|
|
10705
10705
|
if (!form) {
|
|
10706
10706
|
return c.json({ error: "Form not found" }, 404);
|
|
10707
10707
|
}
|
|
10708
|
-
const turnstileService = new
|
|
10708
|
+
const turnstileService = new chunkQJUJNTIU_cjs.TurnstileService(db);
|
|
10709
10709
|
const globalSettings = await turnstileService.getSettings();
|
|
10710
10710
|
const formSettings = form.turnstile_settings ? JSON.parse(form.turnstile_settings) : { inherit: true };
|
|
10711
10711
|
const enabled = form.turnstile_enabled === 1 || formSettings.inherit && globalSettings?.enabled;
|
|
@@ -11135,7 +11135,7 @@ publicFormsRoutes.post("/:identifier/submit", async (c) => {
|
|
|
11135
11135
|
const turnstileEnabled = form.turnstile_enabled === 1;
|
|
11136
11136
|
const turnstileSettings = form.turnstile_settings ? JSON.parse(form.turnstile_settings) : { inherit: true };
|
|
11137
11137
|
if (turnstileEnabled || turnstileSettings.inherit) {
|
|
11138
|
-
const turnstileService = new
|
|
11138
|
+
const turnstileService = new chunkQJUJNTIU_cjs.TurnstileService(db);
|
|
11139
11139
|
const globalEnabled = await turnstileService.isEnabled();
|
|
11140
11140
|
if (globalEnabled || turnstileEnabled) {
|
|
11141
11141
|
const turnstileToken = body.data?.turnstile || body.turnstile;
|
|
@@ -11197,7 +11197,7 @@ publicFormsRoutes.post("/:identifier/submit", async (c) => {
|
|
|
11197
11197
|
});
|
|
11198
11198
|
|
|
11199
11199
|
// src/plugins/core-plugins/forms-plugin/index.ts
|
|
11200
|
-
var formsPlugin =
|
|
11200
|
+
var formsPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
11201
11201
|
id: "forms",
|
|
11202
11202
|
version: "1.0.0",
|
|
11203
11203
|
name: "Forms",
|
|
@@ -11215,9 +11215,9 @@ var formsPlugin = chunkEUJAEB6W_cjs.definePlugin({
|
|
|
11215
11215
|
activate: async () => console.info("\u2705 Forms plugin activated"),
|
|
11216
11216
|
deactivate: async () => console.info("\u274C Forms plugin deactivated")
|
|
11217
11217
|
});
|
|
11218
|
-
|
|
11218
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
11219
11219
|
var adminRbacRoutes = new hono.Hono();
|
|
11220
|
-
adminRbacRoutes.use("*",
|
|
11220
|
+
adminRbacRoutes.use("*", chunk37V3RET3_cjs.requireRbac("rbac", "manage"));
|
|
11221
11221
|
var esc = (s) => String(s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
11222
11222
|
var TABS2 = `
|
|
11223
11223
|
<div class="border-b border-zinc-950/10 dark:border-white/10 mb-6">
|
|
@@ -11521,11 +11521,11 @@ adminRbacRoutes.get("/", async (c) => {
|
|
|
11521
11521
|
</script>`;
|
|
11522
11522
|
const u = c.get("user");
|
|
11523
11523
|
return c.html(
|
|
11524
|
-
|
|
11524
|
+
chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
|
|
11525
11525
|
title: "Roles & Permissions",
|
|
11526
11526
|
pageTitle: "Roles & Permissions",
|
|
11527
11527
|
currentPath: "/admin/users",
|
|
11528
|
-
version:
|
|
11528
|
+
version: chunkKKNEYIZJ_cjs.getCoreVersion(),
|
|
11529
11529
|
user: u ? { name: u.email || "Admin", email: u.email || "", role: u.role || "admin" } : void 0,
|
|
11530
11530
|
content: content2
|
|
11531
11531
|
})
|
|
@@ -11662,7 +11662,7 @@ adminRbacRoutes.get("/check", async (c) => {
|
|
|
11662
11662
|
});
|
|
11663
11663
|
|
|
11664
11664
|
// src/middleware/plugin-menu.ts
|
|
11665
|
-
var REGISTRY_MENU_PLUGINS = Object.values(
|
|
11665
|
+
var REGISTRY_MENU_PLUGINS = Object.values(chunkQCJHCSOK_cjs.PLUGIN_REGISTRY).filter((p) => p.adminMenu !== null).map((p) => ({
|
|
11666
11666
|
id: p.id,
|
|
11667
11667
|
label: p.adminMenu.label,
|
|
11668
11668
|
path: p.adminMenu.path,
|
|
@@ -11741,7 +11741,7 @@ function pluginMenuMiddleware() {
|
|
|
11741
11741
|
} catch {
|
|
11742
11742
|
}
|
|
11743
11743
|
const user = c.get("user");
|
|
11744
|
-
const singletonItems =
|
|
11744
|
+
const singletonItems = chunkBP52BFIV_cjs.resolvePluginMenuItems(user ? { role: user.role } : void 0);
|
|
11745
11745
|
const existingPaths = new Set(activeMenuItems.map((i) => i.path));
|
|
11746
11746
|
for (const item of singletonItems) {
|
|
11747
11747
|
if (!existingPaths.has(item.path)) {
|
|
@@ -11766,9 +11766,1439 @@ function pluginMenuMiddleware() {
|
|
|
11766
11766
|
}
|
|
11767
11767
|
};
|
|
11768
11768
|
}
|
|
11769
|
-
|
|
11769
|
+
|
|
11770
|
+
// src/plugins/core-plugins/menu-plugin/services/menu-repository.ts
|
|
11771
|
+
async function listMenuItems(db, opts) {
|
|
11772
|
+
try {
|
|
11773
|
+
let sql = `
|
|
11774
|
+
SELECT id, slug, sort_order, data
|
|
11775
|
+
FROM documents
|
|
11776
|
+
WHERE type_id = 'menu_item'
|
|
11777
|
+
AND tenant_id = 'default'
|
|
11778
|
+
AND is_current_draft = 1
|
|
11779
|
+
AND deleted_at IS NULL
|
|
11780
|
+
`;
|
|
11781
|
+
const binds = [];
|
|
11782
|
+
if (opts?.source) ;
|
|
11783
|
+
sql += ` ORDER BY sort_order ASC`;
|
|
11784
|
+
const stmt = db.prepare(sql);
|
|
11785
|
+
const result = await (binds.length ? stmt.bind(...binds) : stmt).all();
|
|
11786
|
+
return (result.results ?? []).map((row) => {
|
|
11787
|
+
const data = JSON.parse(row.data);
|
|
11788
|
+
return {
|
|
11789
|
+
...data,
|
|
11790
|
+
id: row.id,
|
|
11791
|
+
slug: row.slug,
|
|
11792
|
+
sortOrder: row.sort_order,
|
|
11793
|
+
tenantId: "default"
|
|
11794
|
+
};
|
|
11795
|
+
});
|
|
11796
|
+
} catch {
|
|
11797
|
+
return [];
|
|
11798
|
+
}
|
|
11799
|
+
}
|
|
11800
|
+
async function fetchPluginStatuses(db, pluginIds) {
|
|
11801
|
+
if (pluginIds.length === 0) return {};
|
|
11802
|
+
try {
|
|
11803
|
+
const rows = await db.prepare(
|
|
11804
|
+
`SELECT slug, json_extract(data, '$.status') AS status
|
|
11805
|
+
FROM documents
|
|
11806
|
+
WHERE type_id = 'plugin' AND tenant_id = 'default'
|
|
11807
|
+
AND is_current_draft = 1 AND deleted_at IS NULL`
|
|
11808
|
+
).all();
|
|
11809
|
+
const statusMap = /* @__PURE__ */ new Map();
|
|
11810
|
+
for (const row of rows.results ?? []) {
|
|
11811
|
+
statusMap.set(row.slug, row.status ?? "inactive");
|
|
11812
|
+
}
|
|
11813
|
+
const result = {};
|
|
11814
|
+
for (const id of pluginIds) {
|
|
11815
|
+
const s = statusMap.get(id);
|
|
11816
|
+
result[id] = s === "active" ? "active" : "inactive";
|
|
11817
|
+
}
|
|
11818
|
+
return result;
|
|
11819
|
+
} catch {
|
|
11820
|
+
return {};
|
|
11821
|
+
}
|
|
11822
|
+
}
|
|
11823
|
+
function buildSidebarTree(items) {
|
|
11824
|
+
const visible = items.filter((i) => i.visible);
|
|
11825
|
+
visible.sort((a, b) => a.sortOrder - b.sortOrder);
|
|
11826
|
+
const byId = /* @__PURE__ */ new Map();
|
|
11827
|
+
const roots = [];
|
|
11828
|
+
for (const item of visible) {
|
|
11829
|
+
byId.set(item.id, {
|
|
11830
|
+
id: item.id,
|
|
11831
|
+
label: item.label,
|
|
11832
|
+
url: item.url,
|
|
11833
|
+
icon: item.icon,
|
|
11834
|
+
target: item.target,
|
|
11835
|
+
isExternal: item.isExternal,
|
|
11836
|
+
visible: item.visible,
|
|
11837
|
+
source: item.source,
|
|
11838
|
+
sortOrder: item.sortOrder,
|
|
11839
|
+
children: []
|
|
11840
|
+
});
|
|
11841
|
+
}
|
|
11842
|
+
for (const item of visible) {
|
|
11843
|
+
const node = byId.get(item.id);
|
|
11844
|
+
if (item.parent && byId.has(item.parent)) {
|
|
11845
|
+
byId.get(item.parent).children.push(node);
|
|
11846
|
+
} else {
|
|
11847
|
+
roots.push(node);
|
|
11848
|
+
}
|
|
11849
|
+
}
|
|
11850
|
+
for (const node of byId.values()) {
|
|
11851
|
+
node.children.sort((a, b) => a.sortOrder - b.sortOrder);
|
|
11852
|
+
}
|
|
11853
|
+
return roots;
|
|
11854
|
+
}
|
|
11855
|
+
async function upsertSystemItem(db, slug, data, sortOrder) {
|
|
11856
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
11857
|
+
const existing = await db.prepare(
|
|
11858
|
+
`SELECT id FROM documents WHERE slug = ? AND type_id = 'menu_item' AND tenant_id = 'default' AND is_current_draft = 1 AND deleted_at IS NULL`
|
|
11859
|
+
).bind(slug).first();
|
|
11860
|
+
if (existing) {
|
|
11861
|
+
return;
|
|
11862
|
+
}
|
|
11863
|
+
const id = chunkKIGVVO6N_cjs.nanoid();
|
|
11864
|
+
await db.prepare(
|
|
11865
|
+
`INSERT INTO documents (
|
|
11866
|
+
id, root_id, type_id, type_version, version_of_id, version_number,
|
|
11867
|
+
is_current_draft, is_published, status, parent_root_id,
|
|
11868
|
+
slug, path, title, zone, sort_order, visible,
|
|
11869
|
+
published_at, scheduled_at, expires_at, deleted_at,
|
|
11870
|
+
tenant_id, locale, translation_group_id,
|
|
11871
|
+
data, metadata, owner_id, created_by, updated_by, created_at, updated_at
|
|
11872
|
+
) VALUES (
|
|
11873
|
+
?, ?, ?, ?, ?, ?,
|
|
11874
|
+
?, ?, ?, ?,
|
|
11875
|
+
?, ?, ?, ?, ?, ?,
|
|
11876
|
+
?, ?, ?, ?,
|
|
11877
|
+
?, ?, ?,
|
|
11878
|
+
?, ?, ?, ?, ?, ?, ?
|
|
11879
|
+
)`
|
|
11880
|
+
).bind(
|
|
11881
|
+
id,
|
|
11882
|
+
// id
|
|
11883
|
+
id,
|
|
11884
|
+
// root_id
|
|
11885
|
+
"menu_item",
|
|
11886
|
+
// type_id
|
|
11887
|
+
1,
|
|
11888
|
+
// type_version
|
|
11889
|
+
null,
|
|
11890
|
+
// version_of_id
|
|
11891
|
+
1,
|
|
11892
|
+
// version_number
|
|
11893
|
+
1,
|
|
11894
|
+
// is_current_draft
|
|
11895
|
+
1,
|
|
11896
|
+
// is_published
|
|
11897
|
+
"published",
|
|
11898
|
+
// status
|
|
11899
|
+
"",
|
|
11900
|
+
// parent_root_id
|
|
11901
|
+
slug,
|
|
11902
|
+
// slug
|
|
11903
|
+
null,
|
|
11904
|
+
// path
|
|
11905
|
+
data.label,
|
|
11906
|
+
// title
|
|
11907
|
+
null,
|
|
11908
|
+
// zone
|
|
11909
|
+
sortOrder,
|
|
11910
|
+
// sort_order
|
|
11911
|
+
data.visible ? 1 : 0,
|
|
11912
|
+
// visible
|
|
11913
|
+
now,
|
|
11914
|
+
// published_at
|
|
11915
|
+
null,
|
|
11916
|
+
// scheduled_at
|
|
11917
|
+
null,
|
|
11918
|
+
// expires_at
|
|
11919
|
+
null,
|
|
11920
|
+
// deleted_at
|
|
11921
|
+
"default",
|
|
11922
|
+
// tenant_id
|
|
11923
|
+
"default",
|
|
11924
|
+
// locale
|
|
11925
|
+
"",
|
|
11926
|
+
// translation_group_id
|
|
11927
|
+
JSON.stringify(data),
|
|
11928
|
+
// data
|
|
11929
|
+
"{}",
|
|
11930
|
+
// metadata
|
|
11931
|
+
null,
|
|
11932
|
+
// owner_id
|
|
11933
|
+
"system",
|
|
11934
|
+
// created_by
|
|
11935
|
+
"system",
|
|
11936
|
+
// updated_by
|
|
11937
|
+
now,
|
|
11938
|
+
// created_at
|
|
11939
|
+
now
|
|
11940
|
+
// updated_at
|
|
11941
|
+
).run();
|
|
11942
|
+
}
|
|
11943
|
+
async function reorderItems(db, items) {
|
|
11944
|
+
if (items.length === 0) return;
|
|
11945
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
11946
|
+
const stmts = items.map(
|
|
11947
|
+
(item) => db.prepare(
|
|
11948
|
+
`UPDATE documents SET
|
|
11949
|
+
sort_order = ?,
|
|
11950
|
+
data = json_set(data, '$.parent', ?),
|
|
11951
|
+
updated_at = ?
|
|
11952
|
+
WHERE id = ? AND tenant_id = 'default'`
|
|
11953
|
+
).bind(item.sortOrder, item.parent ?? null, now, item.id)
|
|
11954
|
+
);
|
|
11955
|
+
await db.batch(stmts);
|
|
11956
|
+
}
|
|
11957
|
+
async function toggleVisibility(db, id, visible) {
|
|
11958
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
11959
|
+
const visInt = visible ? 1 : 0;
|
|
11960
|
+
await db.prepare(
|
|
11961
|
+
`UPDATE documents SET
|
|
11962
|
+
data = json_set(data, '$.visible', ?),
|
|
11963
|
+
visible = ?,
|
|
11964
|
+
updated_at = ?
|
|
11965
|
+
WHERE id = ? AND tenant_id = 'default' AND type_id = 'menu_item'`
|
|
11966
|
+
).bind(visInt, visInt, now, id).run();
|
|
11967
|
+
}
|
|
11968
|
+
async function updateItem(db, id, changes, lockedFields) {
|
|
11969
|
+
const lockedKeys = new Set(lockedFields.filter((f) => f !== "parent"));
|
|
11970
|
+
for (const key of Object.keys(changes)) {
|
|
11971
|
+
if (lockedKeys.has(key)) {
|
|
11972
|
+
return false;
|
|
11973
|
+
}
|
|
11974
|
+
}
|
|
11975
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
11976
|
+
const jsonSetParts = [];
|
|
11977
|
+
const binds = [];
|
|
11978
|
+
const dataFields = ["label", "icon", "target", "permissions", "url", "parent", "visible"];
|
|
11979
|
+
for (const field of dataFields) {
|
|
11980
|
+
if (field in changes) {
|
|
11981
|
+
jsonSetParts.push(`'$.${field}'`, "?");
|
|
11982
|
+
binds.push(
|
|
11983
|
+
field === "permissions" ? JSON.stringify(changes[field]) : changes[field] ?? null
|
|
11984
|
+
);
|
|
11985
|
+
}
|
|
11986
|
+
}
|
|
11987
|
+
const setParts = [];
|
|
11988
|
+
if (jsonSetParts.length > 0) {
|
|
11989
|
+
setParts.push(`data = json_set(data, ${jsonSetParts.join(", ")})`);
|
|
11990
|
+
}
|
|
11991
|
+
if ("sortOrder" in changes && changes.sortOrder !== void 0) {
|
|
11992
|
+
setParts.push(`sort_order = ?`);
|
|
11993
|
+
binds.push(changes.sortOrder);
|
|
11994
|
+
}
|
|
11995
|
+
if ("visible" in changes && changes.visible !== void 0) {
|
|
11996
|
+
setParts.push(`visible = ?`);
|
|
11997
|
+
binds.push(changes.visible ? 1 : 0);
|
|
11998
|
+
}
|
|
11999
|
+
if (setParts.length === 0) {
|
|
12000
|
+
return true;
|
|
12001
|
+
}
|
|
12002
|
+
setParts.push(`updated_at = ?`);
|
|
12003
|
+
binds.push(now);
|
|
12004
|
+
binds.push(id);
|
|
12005
|
+
const sql = `UPDATE documents SET ${setParts.join(", ")} WHERE id = ? AND tenant_id = 'default' AND type_id = 'menu_item'`;
|
|
12006
|
+
await db.prepare(sql).bind(...binds).run();
|
|
12007
|
+
return true;
|
|
12008
|
+
}
|
|
12009
|
+
async function deleteItem(db, id) {
|
|
12010
|
+
try {
|
|
12011
|
+
const row = await db.prepare(
|
|
12012
|
+
`SELECT data FROM documents WHERE id = ? AND tenant_id = 'default' AND is_current_draft = 1 AND deleted_at IS NULL`
|
|
12013
|
+
).bind(id).first();
|
|
12014
|
+
if (!row) {
|
|
12015
|
+
return { ok: false, reason: "Item not found" };
|
|
12016
|
+
}
|
|
12017
|
+
const data = JSON.parse(row.data);
|
|
12018
|
+
if (data.source === "system" || data.source === "plugin") {
|
|
12019
|
+
return { ok: false, reason: "Cannot delete system or plugin items" };
|
|
12020
|
+
}
|
|
12021
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
12022
|
+
await db.prepare(
|
|
12023
|
+
`UPDATE documents SET deleted_at = ? WHERE id = ? AND tenant_id = 'default'`
|
|
12024
|
+
).bind(now, id).run();
|
|
12025
|
+
return { ok: true };
|
|
12026
|
+
} catch (err) {
|
|
12027
|
+
return { ok: false, reason: err instanceof Error ? err.message : "Unknown error" };
|
|
12028
|
+
}
|
|
12029
|
+
}
|
|
12030
|
+
|
|
12031
|
+
// src/services/menu-icons.ts
|
|
12032
|
+
var MENU_ICON_MAP = {
|
|
12033
|
+
"puzzle-piece": `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M14.5 2A1.5 1.5 0 0013 3.5V4H8.5A1.5 1.5 0 007 5.5V10h-.5a1.5 1.5 0 100 3H7v4.5A1.5 1.5 0 008.5 19H13v-.5a1.5 1.5 0 113 0V19h.5a1.5 1.5 0 001.5-1.5V13h-.5a1.5 1.5 0 110-3h.5V5.5A1.5 1.5 0 0017 4h-.5v-.5A1.5 1.5 0 0014.5 2z"/></svg>`,
|
|
12034
|
+
envelope: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z"/><path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"/></svg>`,
|
|
12035
|
+
cog: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" clip-rule="evenodd"/></svg>`,
|
|
12036
|
+
chart: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M2 11a1 1 0 011-1h2a1 1 0 011 1v5a1 1 0 01-1 1H3a1 1 0 01-1-1v-5zM8 7a1 1 0 011-1h2a1 1 0 011 1v9a1 1 0 01-1 1H9a1 1 0 01-1-1V7zM14 4a1 1 0 011-1h2a1 1 0 011 1v12a1 1 0 01-1 1h-2a1 1 0 01-1-1V4z"/></svg>`,
|
|
12037
|
+
sparkles: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9 4.804A7.968 7.968 0 005.5 4c-1.255 0-2.443.29-3.5.804v10A7.969 7.969 0 015.5 14c1.669 0 3.218.51 4.5 1.385A7.962 7.962 0 0114.5 14c1.255 0 2.443.29 3.5.804v-10A7.968 7.968 0 0014.5 4c-1.255 0-2.443.29-3.5.804V12a1 1 0 11-2 0V4.804z"/></svg>`,
|
|
12038
|
+
bolt: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M11.3 1.046A1 1 0 0112 2v5h4a1 1 0 01.82 1.573l-7 10A1 1 0 018 18v-5H4a1 1 0 01-.82-1.573l7-10a1 1 0 011.12-.38z" clip-rule="evenodd"/></svg>`,
|
|
12039
|
+
document: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M4 4a2 2 0 012-2h8a2 2 0 012 2v12a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm3 1h6v2H7V5zm0 4h6v2H7V9zm0 4h4v2H7v-2z" clip-rule="evenodd"/></svg>`,
|
|
12040
|
+
lock: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"/></svg>`,
|
|
12041
|
+
photo: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M4 3a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4zm12 12H4l4-8 3 6 2-4 3 6z" clip-rule="evenodd"/></svg>`,
|
|
12042
|
+
"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>`,
|
|
12043
|
+
"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>`,
|
|
12044
|
+
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>`,
|
|
12045
|
+
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>`,
|
|
12046
|
+
"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>`,
|
|
12047
|
+
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>`,
|
|
12048
|
+
"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>`,
|
|
12049
|
+
"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>`,
|
|
12050
|
+
"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>`,
|
|
12051
|
+
"document-text": `<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 12h6m-6 4h6m2 5H7a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5.586a1 1 0 0 1 .707.293l5.414 5.414a1 1 0 0 1 .293.707V19a2 2 0 0 1-2 2z"/></svg>`,
|
|
12052
|
+
"pencil-square": `<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="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10"/></svg>`,
|
|
12053
|
+
server: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M2 5a2 2 0 012-2h12a2 2 0 012 2v2a2 2 0 01-2 2H4a2 2 0 01-2-2V5zm14 1a1 1 0 11-2 0 1 1 0 012 0zM2 13a2 2 0 012-2h12a2 2 0 012 2v2a2 2 0 01-2 2H4a2 2 0 01-2-2v-2zm14 1a1 1 0 11-2 0 1 1 0 012 0z" clip-rule="evenodd"/></svg>`,
|
|
12054
|
+
"building-office": `<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.75 21h16.5M4.5 3h15M5.25 3v18m13.5-18v18M9 6.75h1.5m-1.5 3h1.5m-1.5 3h1.5m3-6H15m-1.5 3H15m-1.5 3H15M9 21v-3.375c0-.621.504-1.125 1.125-1.125h3.75c.621 0 1.125.504 1.125 1.125V21"/></svg>`,
|
|
12055
|
+
home: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"/></svg>`,
|
|
12056
|
+
users: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9 6a3 3 0 11-6 0 3 3 0 016 0zM17 6a3 3 0 11-6 0 3 3 0 016 0zM12.93 17c.046-.327.07-.66.07-1a6.97 6.97 0 00-1.5-4.33A5 5 0 0119 16v1h-6.07zM6 11a5 5 0 015 5v1H1v-1a5 5 0 015-5z"/></svg>`,
|
|
12057
|
+
collection: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M7 3a1 1 0 000 2h6a1 1 0 100-2H7zM4 7a1 1 0 011-1h10a1 1 0 110 2H5a1 1 0 01-1-1zM2 11a2 2 0 012-2h12a2 2 0 012 2v4a2 2 0 01-2 2H4a2 2 0 01-2-2v-4z"/></svg>`,
|
|
12058
|
+
"bars-3": `<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.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"/></svg>`,
|
|
12059
|
+
"cog-6-tooth": `<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.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"/></svg>`,
|
|
12060
|
+
star: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/></svg>`,
|
|
12061
|
+
tag: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M17.707 9.293a1 1 0 010 1.414l-7 7a1 1 0 01-1.414 0l-7-7A.997.997 0 012 10V5a3 3 0 013-3h5c.256 0 .512.098.707.293l7 7zM5 6a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"/></svg>`,
|
|
12062
|
+
link: `<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.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/></svg>`,
|
|
12063
|
+
"external-link": `<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 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/></svg>`,
|
|
12064
|
+
eye: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M10 12a2 2 0 100-4 2 2 0 000 4z"/><path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"/></svg>`,
|
|
12065
|
+
"eye-slash": `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M3.707 2.293a1 1 0 00-1.414 1.414l14 14a1 1 0 001.414-1.414l-1.473-1.473A10.014 10.014 0 0019.542 10C18.268 5.943 14.478 3 10 3a9.958 9.958 0 00-4.512 1.074l-1.78-1.781zm4.261 4.26l1.514 1.515a2.003 2.003 0 012.45 2.45l1.514 1.514a4 4 0 00-5.478-5.478z" clip-rule="evenodd"/><path d="M12.454 16.697L9.75 13.992a4 4 0 01-3.742-3.741L2.335 6.578A9.98 9.98 0 00.458 10c1.274 4.057 5.065 7 9.542 7 .847 0 1.669-.105 2.454-.303z"/></svg>`
|
|
12066
|
+
};
|
|
12067
|
+
var FALLBACK = `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M14.5 2A1.5 1.5 0 0013 3.5V4H8.5A1.5 1.5 0 007 5.5V10h-.5a1.5 1.5 0 100 3H7v4.5A1.5 1.5 0 008.5 19H13v-.5a1.5 1.5 0 113 0V19h.5a1.5 1.5 0 001.5-1.5V13h-.5a1.5 1.5 0 110-3h.5V5.5A1.5 1.5 0 0017 4h-.5v-.5A1.5 1.5 0 0014.5 2z"/></svg>`;
|
|
12068
|
+
function resolveIcon2(nameOrSvg) {
|
|
12069
|
+
if (!nameOrSvg) return FALLBACK;
|
|
12070
|
+
if (nameOrSvg.startsWith("<svg")) return nameOrSvg;
|
|
12071
|
+
return MENU_ICON_MAP[nameOrSvg] ?? FALLBACK;
|
|
12072
|
+
}
|
|
12073
|
+
|
|
12074
|
+
// src/middleware/menu.ts
|
|
12075
|
+
var EXTERNAL_ICON = `<svg class="h-3 w-3 ml-1 shrink-0 opacity-60" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/></svg>`;
|
|
12076
|
+
var CHEVRON = `<svg data-menu-chevron class="h-4 w-4 rotate-180 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>`;
|
|
12077
|
+
function renderTopLevelItem(item, currentPath) {
|
|
12078
|
+
const isActive = currentPath === item.url || item.url !== "/admin" && currentPath.startsWith(item.url);
|
|
12079
|
+
const icon = resolveIcon2(item.icon);
|
|
12080
|
+
const label = chunkMNWKYY5E_cjs.escapeHtml(item.label);
|
|
12081
|
+
const targetAttr = item.target === "_blank" ? ' target="_blank" rel="noopener noreferrer"' : "";
|
|
12082
|
+
const externalAffordance = item.isExternal ? EXTERNAL_ICON : "";
|
|
12083
|
+
if (item.children.length > 0) {
|
|
12084
|
+
const accordionId = `acc-${item.id.replace(/[^a-z0-9]/gi, "-")}`;
|
|
12085
|
+
const isChildActive = item.children.some(
|
|
12086
|
+
(c) => currentPath === c.url || currentPath.startsWith(c.url)
|
|
12087
|
+
);
|
|
12088
|
+
const accordionActive = isActive || isChildActive;
|
|
12089
|
+
return `
|
|
12090
|
+
<div data-menu-accordion class="relative">
|
|
12091
|
+
${accordionActive ? '<span class="absolute inset-y-2 -left-4 w-0.5 rounded-full bg-cyan-500 dark:bg-cyan-400"></span>' : ""}
|
|
12092
|
+
<div class="flex w-full items-center">
|
|
12093
|
+
<a href="${item.url}"${targetAttr}
|
|
12094
|
+
class="flex flex-1 items-center gap-3 rounded-lg px-2 py-2.5 text-left text-sm/5 font-medium ${accordionActive ? "text-zinc-950 dark:text-white" : "text-zinc-950 hover:bg-zinc-950/5 dark:text-white dark:hover:bg-white/5"}"
|
|
12095
|
+
${accordionActive ? 'data-current="true"' : ""}
|
|
12096
|
+
>
|
|
12097
|
+
<span class="shrink-0 ${accordionActive ? "fill-zinc-950 dark:fill-white" : "fill-zinc-500 dark:fill-zinc-400"}">${icon}</span>
|
|
12098
|
+
<span class="truncate">${label}</span>${externalAffordance}
|
|
12099
|
+
</a>
|
|
12100
|
+
<button
|
|
12101
|
+
onclick="toggleMenuAccordion('${accordionId}')"
|
|
12102
|
+
class="flex items-center justify-center rounded-lg p-2 text-zinc-500 hover:bg-zinc-950/5 dark:text-zinc-400 dark:hover:bg-white/5 flex-shrink-0"
|
|
12103
|
+
aria-label="Toggle ${label} submenu"
|
|
12104
|
+
>
|
|
12105
|
+
${CHEVRON}
|
|
12106
|
+
</button>
|
|
12107
|
+
</div>
|
|
12108
|
+
<div id="${accordionId}" class="pl-6 mt-0.5 flex flex-col gap-0.5">
|
|
12109
|
+
${item.children.map((child) => renderChildItem(child, currentPath)).join("")}
|
|
12110
|
+
</div>
|
|
12111
|
+
</div>`;
|
|
12112
|
+
}
|
|
12113
|
+
return `
|
|
12114
|
+
<span class="relative">
|
|
12115
|
+
${isActive ? '<span class="absolute inset-y-2 -left-4 w-0.5 rounded-full bg-cyan-500 dark:bg-cyan-400"></span>' : ""}
|
|
12116
|
+
<a href="${item.url}"${targetAttr}
|
|
12117
|
+
class="flex w-full items-center gap-3 rounded-lg px-2 py-2.5 text-left text-sm/5 font-medium ${isActive ? "text-zinc-950 dark:text-white" : "text-zinc-950 hover:bg-zinc-950/5 dark:text-white dark:hover:bg-white/5"}"
|
|
12118
|
+
${isActive ? 'data-current="true"' : ""}
|
|
12119
|
+
>
|
|
12120
|
+
<span class="shrink-0 ${isActive ? "fill-zinc-950 dark:fill-white" : "fill-zinc-500 dark:fill-zinc-400"}">${icon}</span>
|
|
12121
|
+
<span class="truncate">${label}</span>${externalAffordance}
|
|
12122
|
+
</a>
|
|
12123
|
+
</span>`;
|
|
12124
|
+
}
|
|
12125
|
+
function renderChildItem(item, currentPath) {
|
|
12126
|
+
const isActive = currentPath === item.url || item.url !== "/admin" && currentPath.startsWith(item.url);
|
|
12127
|
+
const icon = resolveIcon2(item.icon);
|
|
12128
|
+
const label = chunkMNWKYY5E_cjs.escapeHtml(item.label);
|
|
12129
|
+
const targetAttr = item.target === "_blank" ? ' target="_blank" rel="noopener noreferrer"' : "";
|
|
12130
|
+
const externalAffordance = item.isExternal ? EXTERNAL_ICON : "";
|
|
12131
|
+
return `
|
|
12132
|
+
<span class="relative">
|
|
12133
|
+
${isActive ? '<span class="absolute inset-y-2 -left-4 w-0.5 rounded-full bg-cyan-500 dark:bg-cyan-400"></span>' : ""}
|
|
12134
|
+
<a href="${item.url}"${targetAttr}
|
|
12135
|
+
class="flex w-full items-center gap-3 rounded-lg px-2 py-2 text-left text-sm/5 font-medium ${isActive ? "text-zinc-950 dark:text-white" : "text-zinc-600 hover:bg-zinc-950/5 dark:text-zinc-400 dark:hover:bg-white/5"}"
|
|
12136
|
+
${isActive ? 'data-current="true"' : ""}
|
|
12137
|
+
>
|
|
12138
|
+
<span class="shrink-0 ${isActive ? "fill-zinc-950 dark:fill-white" : "fill-zinc-500 dark:fill-zinc-400"}">${icon}</span>
|
|
12139
|
+
<span class="truncate">${label}</span>${externalAffordance}
|
|
12140
|
+
</a>
|
|
12141
|
+
</span>`;
|
|
12142
|
+
}
|
|
12143
|
+
var ACCORDION_SCRIPT = `
|
|
12144
|
+
<script>
|
|
12145
|
+
function toggleMenuAccordion(id) {
|
|
12146
|
+
var el = document.getElementById(id)
|
|
12147
|
+
if (!el) return
|
|
12148
|
+
var chevrons = el.parentElement ? el.parentElement.querySelectorAll('[data-menu-chevron]') : []
|
|
12149
|
+
if (el.style.display === 'none' || el.style.display === '') {
|
|
12150
|
+
el.style.display = 'flex'
|
|
12151
|
+
el.style.flexDirection = 'column'
|
|
12152
|
+
chevrons.forEach(function(c) { c.style.transform = 'rotate(180deg)' })
|
|
12153
|
+
} else {
|
|
12154
|
+
el.style.display = 'none'
|
|
12155
|
+
chevrons.forEach(function(c) { c.style.transform = 'rotate(0deg)' })
|
|
12156
|
+
}
|
|
12157
|
+
}
|
|
12158
|
+
// Open active accordions on load
|
|
12159
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
12160
|
+
document.querySelectorAll('[data-menu-accordion]').forEach(function(acc) {
|
|
12161
|
+
if (acc.querySelector('[data-current]')) {
|
|
12162
|
+
var sub = acc.querySelector('[id^="acc-"]')
|
|
12163
|
+
if (sub) { sub.style.display = 'flex'; sub.style.flexDirection = 'column' }
|
|
12164
|
+
}
|
|
12165
|
+
})
|
|
12166
|
+
})
|
|
12167
|
+
</script>`;
|
|
12168
|
+
async function isMenuPluginActive(db) {
|
|
12169
|
+
try {
|
|
12170
|
+
const row = await db.prepare(
|
|
12171
|
+
`SELECT json_extract(data, '$.status') AS status
|
|
12172
|
+
FROM documents
|
|
12173
|
+
WHERE slug = 'menu' AND type_id = 'plugin' AND tenant_id = 'default'
|
|
12174
|
+
AND is_current_draft = 1 AND deleted_at IS NULL
|
|
12175
|
+
LIMIT 1`
|
|
12176
|
+
).first();
|
|
12177
|
+
if (!row) return false;
|
|
12178
|
+
return row.status === "active";
|
|
12179
|
+
} catch {
|
|
12180
|
+
return false;
|
|
12181
|
+
}
|
|
12182
|
+
}
|
|
12183
|
+
function menuMiddleware() {
|
|
12184
|
+
return async (c, next) => {
|
|
12185
|
+
const path = new URL(c.req.url).pathname;
|
|
12186
|
+
if (!path.startsWith("/admin")) {
|
|
12187
|
+
return next();
|
|
12188
|
+
}
|
|
12189
|
+
await next();
|
|
12190
|
+
if (!c.res.headers.get("content-type")?.includes("text/html")) return;
|
|
12191
|
+
if (!await isMenuPluginActive(c.env.DB)) return;
|
|
12192
|
+
let items = [];
|
|
12193
|
+
try {
|
|
12194
|
+
items = await listMenuItems(c.env.DB);
|
|
12195
|
+
} catch {
|
|
12196
|
+
return;
|
|
12197
|
+
}
|
|
12198
|
+
if (items.length === 0) return;
|
|
12199
|
+
const tree = buildSidebarTree(items);
|
|
12200
|
+
const renderedItems = tree.map((item) => renderTopLevelItem(item, path)).join("");
|
|
12201
|
+
const navItemsHtml = renderedItems + ACCORDION_SCRIPT;
|
|
12202
|
+
const status = c.res.status;
|
|
12203
|
+
const headers = new Headers(c.res.headers);
|
|
12204
|
+
const html4 = await c.res.text();
|
|
12205
|
+
const markerRegex = /<!-- ADMIN_SIDEBAR_NAV_ITEMS -->[\s\S]*?<!-- \/ADMIN_SIDEBAR_NAV_ITEMS -->/g;
|
|
12206
|
+
if (markerRegex.test(html4)) {
|
|
12207
|
+
const newHtml = html4.replace(
|
|
12208
|
+
/<!-- ADMIN_SIDEBAR_NAV_ITEMS -->[\s\S]*?<!-- \/ADMIN_SIDEBAR_NAV_ITEMS -->/g,
|
|
12209
|
+
navItemsHtml
|
|
12210
|
+
);
|
|
12211
|
+
c.res = new Response(newHtml, { status, headers });
|
|
12212
|
+
} else {
|
|
12213
|
+
c.res = new Response(html4, { status, headers });
|
|
12214
|
+
}
|
|
12215
|
+
};
|
|
12216
|
+
}
|
|
12217
|
+
|
|
12218
|
+
// src/plugins/core-plugins/menu-plugin/services/menu-defaults.ts
|
|
12219
|
+
var SYSTEM_MENU_ITEMS = [
|
|
12220
|
+
{
|
|
12221
|
+
id: "menu:system:content",
|
|
12222
|
+
label: "Content",
|
|
12223
|
+
url: "/admin/content",
|
|
12224
|
+
icon: "document",
|
|
12225
|
+
target: "_self",
|
|
12226
|
+
isExternal: false,
|
|
12227
|
+
visible: true,
|
|
12228
|
+
parent: null,
|
|
12229
|
+
source: "system",
|
|
12230
|
+
pluginId: null,
|
|
12231
|
+
permissions: [],
|
|
12232
|
+
lockedFields: ["url"],
|
|
12233
|
+
sortOrder: 10
|
|
12234
|
+
},
|
|
12235
|
+
{
|
|
12236
|
+
id: "menu:system:collections",
|
|
12237
|
+
label: "Collections",
|
|
12238
|
+
url: "/admin/collections",
|
|
12239
|
+
icon: "collection",
|
|
12240
|
+
target: "_self",
|
|
12241
|
+
isExternal: false,
|
|
12242
|
+
visible: true,
|
|
12243
|
+
parent: null,
|
|
12244
|
+
source: "system",
|
|
12245
|
+
pluginId: null,
|
|
12246
|
+
permissions: [],
|
|
12247
|
+
lockedFields: ["url"],
|
|
12248
|
+
sortOrder: 20
|
|
12249
|
+
},
|
|
12250
|
+
{
|
|
12251
|
+
id: "menu:system:users",
|
|
12252
|
+
label: "Users",
|
|
12253
|
+
url: "/admin/users",
|
|
12254
|
+
icon: "users",
|
|
12255
|
+
target: "_self",
|
|
12256
|
+
isExternal: false,
|
|
12257
|
+
visible: true,
|
|
12258
|
+
parent: null,
|
|
12259
|
+
source: "system",
|
|
12260
|
+
pluginId: null,
|
|
12261
|
+
permissions: [],
|
|
12262
|
+
lockedFields: ["url"],
|
|
12263
|
+
sortOrder: 30
|
|
12264
|
+
},
|
|
12265
|
+
{
|
|
12266
|
+
id: "menu:system:settings",
|
|
12267
|
+
label: "Settings",
|
|
12268
|
+
url: "/admin/settings",
|
|
12269
|
+
icon: "cog",
|
|
12270
|
+
target: "_self",
|
|
12271
|
+
isExternal: false,
|
|
12272
|
+
visible: true,
|
|
12273
|
+
parent: null,
|
|
12274
|
+
source: "system",
|
|
12275
|
+
pluginId: null,
|
|
12276
|
+
permissions: [],
|
|
12277
|
+
lockedFields: ["url"],
|
|
12278
|
+
sortOrder: 40
|
|
12279
|
+
},
|
|
12280
|
+
{
|
|
12281
|
+
id: "menu:system:plugins",
|
|
12282
|
+
label: "Plugins",
|
|
12283
|
+
url: "/admin/plugins",
|
|
12284
|
+
icon: "collection",
|
|
12285
|
+
target: "_self",
|
|
12286
|
+
isExternal: false,
|
|
12287
|
+
visible: true,
|
|
12288
|
+
parent: null,
|
|
12289
|
+
source: "system",
|
|
12290
|
+
pluginId: null,
|
|
12291
|
+
permissions: [],
|
|
12292
|
+
lockedFields: ["url"],
|
|
12293
|
+
sortOrder: 50
|
|
12294
|
+
},
|
|
12295
|
+
{
|
|
12296
|
+
id: "menu:system:menu",
|
|
12297
|
+
label: "Menu",
|
|
12298
|
+
url: "/admin/menu",
|
|
12299
|
+
icon: "bars-3",
|
|
12300
|
+
target: "_self",
|
|
12301
|
+
isExternal: false,
|
|
12302
|
+
visible: true,
|
|
12303
|
+
parent: null,
|
|
12304
|
+
source: "system",
|
|
12305
|
+
pluginId: null,
|
|
12306
|
+
permissions: [],
|
|
12307
|
+
lockedFields: ["url"],
|
|
12308
|
+
sortOrder: 60
|
|
12309
|
+
}
|
|
12310
|
+
];
|
|
12311
|
+
|
|
12312
|
+
// src/plugins/core-plugins/menu-plugin/templates/admin-menu-list.template.ts
|
|
12313
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
12314
|
+
function pluginStatusBadge(status) {
|
|
12315
|
+
if (status === "inactive") {
|
|
12316
|
+
return `<span class="inline-flex items-center rounded-md px-2 py-0.5 text-xs font-medium bg-red-50 dark:bg-red-500/10 text-red-700 dark:text-red-400 ring-1 ring-inset ring-red-600/20 dark:ring-red-500/20 ml-1">disabled</span>`;
|
|
12317
|
+
}
|
|
12318
|
+
return `<span class="inline-flex items-center rounded-md px-2 py-0.5 text-xs font-medium bg-green-50 dark:bg-green-500/10 text-green-700 dark:text-green-400 ring-1 ring-inset ring-green-600/20 dark:ring-green-500/20 ml-1">enabled</span>`;
|
|
12319
|
+
}
|
|
12320
|
+
function sourceBadge(source) {
|
|
12321
|
+
switch (source) {
|
|
12322
|
+
case "system":
|
|
12323
|
+
return `<span class="inline-flex items-center rounded-md px-2 py-0.5 text-xs font-medium bg-zinc-100 dark:bg-zinc-700/50 text-zinc-600 dark:text-zinc-300 ring-1 ring-inset ring-zinc-300/50 dark:ring-zinc-600/50">system</span>`;
|
|
12324
|
+
case "plugin":
|
|
12325
|
+
return `<span class="inline-flex items-center rounded-md px-2 py-0.5 text-xs font-medium bg-blue-50 dark:bg-blue-500/10 text-blue-700 dark:text-blue-300 ring-1 ring-inset ring-blue-700/10 dark:ring-blue-400/20">plugin</span>`;
|
|
12326
|
+
default:
|
|
12327
|
+
return `<span class="inline-flex items-center rounded-md px-2 py-0.5 text-xs font-medium bg-green-50 dark:bg-green-500/10 text-green-700 dark:text-green-300 ring-1 ring-inset ring-green-700/10 dark:ring-green-400/20">user</span>`;
|
|
12328
|
+
}
|
|
12329
|
+
}
|
|
12330
|
+
function iconPreview(icon) {
|
|
12331
|
+
if (!icon) return '<span class="text-zinc-400 dark:text-zinc-500">\u2014</span>';
|
|
12332
|
+
if (icon.trim().startsWith("<")) {
|
|
12333
|
+
return `<span class="w-5 h-5 inline-flex items-center justify-center">${icon}</span>`;
|
|
12334
|
+
}
|
|
12335
|
+
return `<span class="text-xs font-mono text-zinc-500 dark:text-zinc-400 truncate max-w-[80px]">${chunkMNWKYY5E_cjs.escapeHtml(icon)}</span>`;
|
|
12336
|
+
}
|
|
12337
|
+
function renderMenuListPage(data) {
|
|
12338
|
+
const messageBanner = data.message ? `<div class="mb-6 rounded-lg bg-cyan-50 dark:bg-cyan-900/20 border border-cyan-200 dark:border-cyan-700 px-4 py-3 text-sm text-cyan-800 dark:text-cyan-200">
|
|
12339
|
+
${chunkMNWKYY5E_cjs.escapeHtml(data.message)}
|
|
12340
|
+
</div>` : "";
|
|
12341
|
+
const pluginStatuses = data.pluginStatuses ?? {};
|
|
12342
|
+
const rows = data.items.map((item, index) => {
|
|
12343
|
+
const isFirst = index === 0;
|
|
12344
|
+
const isLast = index === data.items.length - 1;
|
|
12345
|
+
const moveUpForm = !isFirst ? `<form method="POST" action="/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}/move-up" class="inline">
|
|
12346
|
+
<button type="submit" class="p-1 rounded hover:bg-zinc-100 dark:hover:bg-zinc-700 text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 transition-colors" title="Move up">
|
|
12347
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12348
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7"/>
|
|
12349
|
+
</svg>
|
|
12350
|
+
</button>
|
|
12351
|
+
</form>` : `<span class="w-6 inline-block"></span>`;
|
|
12352
|
+
const moveDownForm = !isLast ? `<form method="POST" action="/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}/move-down" class="inline">
|
|
12353
|
+
<button type="submit" class="p-1 rounded hover:bg-zinc-100 dark:hover:bg-zinc-700 text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 transition-colors" title="Move down">
|
|
12354
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12355
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
|
12356
|
+
</svg>
|
|
12357
|
+
</button>
|
|
12358
|
+
</form>` : `<span class="w-6 inline-block"></span>`;
|
|
12359
|
+
const deleteButton = item.source === "user" ? `<form method="POST" action="/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}/delete" onsubmit="return confirm('Delete this item?')" class="inline">
|
|
12360
|
+
<button type="submit" class="inline-flex items-center px-2.5 py-1.5 text-xs font-medium rounded-md text-red-700 dark:text-red-400 bg-red-50 dark:bg-red-500/10 hover:bg-red-100 dark:hover:bg-red-500/20 ring-1 ring-inset ring-red-600/20 dark:ring-red-500/20 transition-colors">
|
|
12361
|
+
Delete
|
|
12362
|
+
</button>
|
|
12363
|
+
</form>` : "";
|
|
12364
|
+
return `
|
|
12365
|
+
<tr class="border-b border-zinc-100 dark:border-zinc-800 hover:bg-zinc-50/50 dark:hover:bg-zinc-800/30 transition-colors cursor-pointer" onclick="if(!event.target.closest('a,button,input,form')){window.location='/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}'}">
|
|
12366
|
+
<td class="px-4 py-3 w-16">
|
|
12367
|
+
<div class="flex items-center gap-0.5">
|
|
12368
|
+
${moveUpForm}
|
|
12369
|
+
${moveDownForm}
|
|
12370
|
+
</div>
|
|
12371
|
+
</td>
|
|
12372
|
+
<td class="px-4 py-3 w-16">
|
|
12373
|
+
${iconPreview(item.icon)}
|
|
12374
|
+
</td>
|
|
12375
|
+
<td class="px-4 py-3">
|
|
12376
|
+
<span class="text-sm font-medium text-zinc-900 dark:text-zinc-100">${chunkMNWKYY5E_cjs.escapeHtml(item.label)}</span>
|
|
12377
|
+
${item.parent ? `<span class="ml-2 text-xs text-zinc-400 dark:text-zinc-500">child</span>` : ""}
|
|
12378
|
+
</td>
|
|
12379
|
+
<td class="px-4 py-3 max-w-[200px]">
|
|
12380
|
+
<span class="text-sm text-zinc-500 dark:text-zinc-400 truncate block">${chunkMNWKYY5E_cjs.escapeHtml(item.url)}</span>
|
|
12381
|
+
</td>
|
|
12382
|
+
<td class="px-4 py-3">
|
|
12383
|
+
${sourceBadge(item.source)}
|
|
12384
|
+
${item.source === "plugin" && item.pluginId ? pluginStatusBadge(pluginStatuses[item.pluginId] ?? "active") : ""}
|
|
12385
|
+
</td>
|
|
12386
|
+
<td class="px-4 py-3">
|
|
12387
|
+
<form method="POST" action="/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}/visibility" class="inline">
|
|
12388
|
+
<label class="relative inline-flex items-center cursor-pointer">
|
|
12389
|
+
<input
|
|
12390
|
+
type="checkbox"
|
|
12391
|
+
name="visible"
|
|
12392
|
+
value="true"
|
|
12393
|
+
${item.visible ? "checked" : ""}
|
|
12394
|
+
onchange="this.form.requestSubmit()"
|
|
12395
|
+
class="sr-only peer"
|
|
12396
|
+
>
|
|
12397
|
+
<div class="w-9 h-5 bg-zinc-200 dark:bg-zinc-700 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-cyan-500 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-zinc-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-cyan-600"></div>
|
|
12398
|
+
</label>
|
|
12399
|
+
</form>
|
|
12400
|
+
</td>
|
|
12401
|
+
<td class="px-4 py-3">
|
|
12402
|
+
<div class="flex items-center gap-2">
|
|
12403
|
+
<a href="/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}" class="inline-flex items-center px-2.5 py-1.5 text-xs font-medium rounded-md text-zinc-700 dark:text-zinc-300 bg-zinc-100 dark:bg-zinc-700 hover:bg-zinc-200 dark:hover:bg-zinc-600 ring-1 ring-inset ring-zinc-300/50 dark:ring-zinc-600/50 transition-colors">
|
|
12404
|
+
Edit
|
|
12405
|
+
</a>
|
|
12406
|
+
${deleteButton}
|
|
12407
|
+
</div>
|
|
12408
|
+
</td>
|
|
12409
|
+
</tr>`;
|
|
12410
|
+
}).join("\n");
|
|
12411
|
+
const emptyState = data.items.length === 0 ? `<tr>
|
|
12412
|
+
<td colspan="7" class="px-4 py-12 text-center text-sm text-zinc-400 dark:text-zinc-500">
|
|
12413
|
+
No menu items yet. <a href="/admin/menu/new" class="text-cyan-600 dark:text-cyan-400 underline hover:no-underline">Add a link</a> to get started.
|
|
12414
|
+
</td>
|
|
12415
|
+
</tr>` : "";
|
|
12416
|
+
const pageContent = `
|
|
12417
|
+
<div>
|
|
12418
|
+
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6">
|
|
12419
|
+
<div>
|
|
12420
|
+
<h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">Menu Manager</h1>
|
|
12421
|
+
<p class="mt-1 text-sm/6 text-zinc-500 dark:text-zinc-400">Manage navigation links and their order</p>
|
|
12422
|
+
</div>
|
|
12423
|
+
<div class="mt-4 sm:mt-0">
|
|
12424
|
+
<a href="/admin/menu/new" 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">
|
|
12425
|
+
<svg class="-ml-0.5 mr-1.5 h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
|
12426
|
+
<path d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"/>
|
|
12427
|
+
</svg>
|
|
12428
|
+
Add Link
|
|
12429
|
+
</a>
|
|
12430
|
+
</div>
|
|
12431
|
+
</div>
|
|
12432
|
+
|
|
12433
|
+
${messageBanner}
|
|
12434
|
+
|
|
12435
|
+
<div class="rounded-xl overflow-hidden bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10">
|
|
12436
|
+
<table class="min-w-full divide-y divide-zinc-200 dark:divide-zinc-800">
|
|
12437
|
+
<thead>
|
|
12438
|
+
<tr class="bg-zinc-50 dark:bg-zinc-800/50">
|
|
12439
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider w-16">Order</th>
|
|
12440
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider w-16">Icon</th>
|
|
12441
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Label</th>
|
|
12442
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">URL</th>
|
|
12443
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Source</th>
|
|
12444
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Visible</th>
|
|
12445
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Actions</th>
|
|
12446
|
+
</tr>
|
|
12447
|
+
</thead>
|
|
12448
|
+
<tbody class="divide-y divide-zinc-100 dark:divide-zinc-800">
|
|
12449
|
+
${rows}
|
|
12450
|
+
${emptyState}
|
|
12451
|
+
</tbody>
|
|
12452
|
+
</table>
|
|
12453
|
+
</div>
|
|
12454
|
+
</div>
|
|
12455
|
+
`;
|
|
12456
|
+
const layoutData = {
|
|
12457
|
+
title: "Menu Manager",
|
|
12458
|
+
pageTitle: "Menu Manager",
|
|
12459
|
+
currentPath: data.currentPath ?? "/admin/menu",
|
|
12460
|
+
user: data.user,
|
|
12461
|
+
version: data.version,
|
|
12462
|
+
dynamicMenuItems: data.dynamicMenuItems,
|
|
12463
|
+
content: pageContent
|
|
12464
|
+
};
|
|
12465
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
12466
|
+
}
|
|
12467
|
+
function renderMenuSettingsContent(items, pluginStatuses = {}, message) {
|
|
12468
|
+
const messageBanner = "";
|
|
12469
|
+
const rows = items.map((item, index) => {
|
|
12470
|
+
const isFirst = index === 0;
|
|
12471
|
+
const isLast = index === items.length - 1;
|
|
12472
|
+
const moveUpForm = !isFirst ? `<form method="POST" action="/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}/move-up" class="inline">
|
|
12473
|
+
<button type="submit" class="p-1 rounded hover:bg-zinc-100 dark:hover:bg-zinc-700 text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 transition-colors" title="Move up">
|
|
12474
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7"/></svg>
|
|
12475
|
+
</button>
|
|
12476
|
+
</form>` : `<span class="w-6 inline-block"></span>`;
|
|
12477
|
+
const moveDownForm = !isLast ? `<form method="POST" action="/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}/move-down" class="inline">
|
|
12478
|
+
<button type="submit" class="p-1 rounded hover:bg-zinc-100 dark:hover:bg-zinc-700 text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 transition-colors" title="Move down">
|
|
12479
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
|
|
12480
|
+
</button>
|
|
12481
|
+
</form>` : `<span class="w-6 inline-block"></span>`;
|
|
12482
|
+
const deleteButton = item.source === "user" ? `<form method="POST" action="/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}/delete" onsubmit="return confirm('Delete this item?')" class="inline">
|
|
12483
|
+
<button type="submit" class="inline-flex items-center px-2.5 py-1.5 text-xs font-medium rounded-md text-red-700 dark:text-red-400 bg-red-50 dark:bg-red-500/10 hover:bg-red-100 dark:hover:bg-red-500/20 ring-1 ring-inset ring-red-600/20 dark:ring-red-500/20 transition-colors">Delete</button>
|
|
12484
|
+
</form>` : "";
|
|
12485
|
+
return `
|
|
12486
|
+
<tr class="border-b border-zinc-100 dark:border-zinc-800 hover:bg-zinc-50/50 dark:hover:bg-zinc-800/30 transition-colors cursor-pointer" onclick="if(!event.target.closest('a,button,input,form')){window.location='/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}'}">
|
|
12487
|
+
<td class="px-4 py-3 w-16">
|
|
12488
|
+
<div class="flex items-center gap-0.5">${moveUpForm}${moveDownForm}</div>
|
|
12489
|
+
</td>
|
|
12490
|
+
<td class="px-4 py-3 w-16">${iconPreview(item.icon)}</td>
|
|
12491
|
+
<td class="px-4 py-3">
|
|
12492
|
+
<span class="text-sm font-medium text-zinc-900 dark:text-zinc-100">${chunkMNWKYY5E_cjs.escapeHtml(item.label)}</span>
|
|
12493
|
+
${item.parent ? `<span class="ml-2 text-xs text-zinc-400 dark:text-zinc-500">child</span>` : ""}
|
|
12494
|
+
</td>
|
|
12495
|
+
<td class="px-4 py-3 max-w-[200px]">
|
|
12496
|
+
<span class="text-sm text-zinc-500 dark:text-zinc-400 truncate block">${chunkMNWKYY5E_cjs.escapeHtml(item.url)}</span>
|
|
12497
|
+
</td>
|
|
12498
|
+
<td class="px-4 py-3">${sourceBadge(item.source)}${item.source === "plugin" && item.pluginId ? pluginStatusBadge(pluginStatuses[item.pluginId] ?? "active") : ""}</td>
|
|
12499
|
+
<td class="px-4 py-3">
|
|
12500
|
+
<form method="POST" action="/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}/visibility" class="inline">
|
|
12501
|
+
<label class="relative inline-flex items-center cursor-pointer">
|
|
12502
|
+
<input type="checkbox" name="visible" value="true" ${item.visible ? "checked" : ""} onchange="this.form.requestSubmit()" class="sr-only peer">
|
|
12503
|
+
<div class="w-9 h-5 bg-zinc-200 dark:bg-zinc-700 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-cyan-500 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-zinc-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-cyan-600"></div>
|
|
12504
|
+
</label>
|
|
12505
|
+
</form>
|
|
12506
|
+
</td>
|
|
12507
|
+
<td class="px-4 py-3">
|
|
12508
|
+
<div class="flex items-center gap-2">
|
|
12509
|
+
<a href="/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}" class="inline-flex items-center px-2.5 py-1.5 text-xs font-medium rounded-md text-zinc-700 dark:text-zinc-300 bg-zinc-100 dark:bg-zinc-700 hover:bg-zinc-200 dark:hover:bg-zinc-600 ring-1 ring-inset ring-zinc-300/50 dark:ring-zinc-600/50 transition-colors">Edit</a>
|
|
12510
|
+
${deleteButton}
|
|
12511
|
+
</div>
|
|
12512
|
+
</td>
|
|
12513
|
+
</tr>`;
|
|
12514
|
+
}).join("\n");
|
|
12515
|
+
const emptyState = items.length === 0 ? `<tr><td colspan="7" class="px-4 py-12 text-center text-sm text-zinc-400 dark:text-zinc-500">No menu items yet. <a href="/admin/menu/new" class="text-cyan-600 dark:text-cyan-400 underline hover:no-underline">Add a link</a> to get started.</td></tr>` : "";
|
|
12516
|
+
return `
|
|
12517
|
+
<script>
|
|
12518
|
+
(function() {
|
|
12519
|
+
function getCsrfToken() {
|
|
12520
|
+
var c = document.cookie.split('; ').find(function(r) { return r.startsWith('csrf_token='); });
|
|
12521
|
+
return c ? c.substring(c.indexOf('=') + 1) : '';
|
|
12522
|
+
}
|
|
12523
|
+
document.addEventListener('submit', function(e) {
|
|
12524
|
+
var form = e.target;
|
|
12525
|
+
if (!form || form.tagName !== 'FORM') return;
|
|
12526
|
+
if ((form.method || 'GET').toUpperCase() === 'GET') return;
|
|
12527
|
+
if (!form.querySelector('input[name="_csrf"]')) {
|
|
12528
|
+
var input = document.createElement('input');
|
|
12529
|
+
input.type = 'hidden';
|
|
12530
|
+
input.name = '_csrf';
|
|
12531
|
+
input.value = getCsrfToken();
|
|
12532
|
+
form.appendChild(input);
|
|
12533
|
+
}
|
|
12534
|
+
});
|
|
12535
|
+
})();
|
|
12536
|
+
</script>
|
|
12537
|
+
<div>
|
|
12538
|
+
<div class="flex items-center justify-between mb-4">
|
|
12539
|
+
<p class="text-sm text-zinc-500 dark:text-zinc-400">Manage navigation links and their order in the sidebar.</p>
|
|
12540
|
+
<a href="/admin/menu/new" class="inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3 py-2 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm">
|
|
12541
|
+
<svg class="-ml-0.5 mr-1.5 h-4 w-4" viewBox="0 0 20 20" fill="currentColor"><path d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"/></svg>
|
|
12542
|
+
Add Link
|
|
12543
|
+
</a>
|
|
12544
|
+
</div>
|
|
12545
|
+
${messageBanner}
|
|
12546
|
+
<div class="rounded-xl overflow-hidden bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10">
|
|
12547
|
+
<table class="min-w-full divide-y divide-zinc-200 dark:divide-zinc-800">
|
|
12548
|
+
<thead>
|
|
12549
|
+
<tr class="bg-zinc-50 dark:bg-zinc-800/50">
|
|
12550
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider w-16">Order</th>
|
|
12551
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider w-16">Icon</th>
|
|
12552
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Label</th>
|
|
12553
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">URL</th>
|
|
12554
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Source</th>
|
|
12555
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Visible</th>
|
|
12556
|
+
<th class="px-4 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Actions</th>
|
|
12557
|
+
</tr>
|
|
12558
|
+
</thead>
|
|
12559
|
+
<tbody class="divide-y divide-zinc-100 dark:divide-zinc-800">
|
|
12560
|
+
${rows}
|
|
12561
|
+
${emptyState}
|
|
12562
|
+
</tbody>
|
|
12563
|
+
</table>
|
|
12564
|
+
</div>
|
|
12565
|
+
</div>
|
|
12566
|
+
`;
|
|
12567
|
+
}
|
|
12568
|
+
|
|
12569
|
+
// src/plugins/core-plugins/menu-plugin/templates/admin-menu-form.template.ts
|
|
12570
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
12571
|
+
|
|
12572
|
+
// src/plugins/core-plugins/menu-plugin/templates/icon-picker.template.ts
|
|
12573
|
+
var ICONS = [
|
|
12574
|
+
{
|
|
12575
|
+
name: "puzzle-piece",
|
|
12576
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 4a2 2 0 114 0v1a1 1 0 001 1h3a1 1 0 011 1v3a1 1 0 01-1 1h-1a2 2 0 100 4h1a1 1 0 011 1v3a1 1 0 01-1 1h-3a1 1 0 01-1-1v-1a2 2 0 10-4 0v1a1 1 0 01-1 1H7a1 1 0 01-1-1v-3a1 1 0 00-1-1H4a2 2 0 110-4h1a1 1 0 001-1V7a1 1 0 011-1h3a1 1 0 001-1V4z"/>'
|
|
12577
|
+
},
|
|
12578
|
+
{
|
|
12579
|
+
name: "document",
|
|
12580
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"/>'
|
|
12581
|
+
},
|
|
12582
|
+
{
|
|
12583
|
+
name: "collection",
|
|
12584
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"/>'
|
|
12585
|
+
},
|
|
12586
|
+
{
|
|
12587
|
+
name: "users",
|
|
12588
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"/>'
|
|
12589
|
+
},
|
|
12590
|
+
{
|
|
12591
|
+
name: "cog",
|
|
12592
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>'
|
|
12593
|
+
},
|
|
12594
|
+
{
|
|
12595
|
+
name: "envelope",
|
|
12596
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>'
|
|
12597
|
+
},
|
|
12598
|
+
{
|
|
12599
|
+
name: "chart",
|
|
12600
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>'
|
|
12601
|
+
},
|
|
12602
|
+
{
|
|
12603
|
+
name: "bolt",
|
|
12604
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>'
|
|
12605
|
+
},
|
|
12606
|
+
{
|
|
12607
|
+
name: "sparkles",
|
|
12608
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z"/>'
|
|
12609
|
+
},
|
|
12610
|
+
{
|
|
12611
|
+
name: "photo",
|
|
12612
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/>'
|
|
12613
|
+
},
|
|
12614
|
+
{
|
|
12615
|
+
name: "lock",
|
|
12616
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>'
|
|
12617
|
+
},
|
|
12618
|
+
{
|
|
12619
|
+
name: "magnifying-glass",
|
|
12620
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>'
|
|
12621
|
+
},
|
|
12622
|
+
{
|
|
12623
|
+
name: "chart-bar",
|
|
12624
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>'
|
|
12625
|
+
},
|
|
12626
|
+
{
|
|
12627
|
+
name: "image",
|
|
12628
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/>'
|
|
12629
|
+
},
|
|
12630
|
+
{
|
|
12631
|
+
name: "key",
|
|
12632
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"/>'
|
|
12633
|
+
},
|
|
12634
|
+
{
|
|
12635
|
+
name: "shield-check",
|
|
12636
|
+
svg: '<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"/>'
|
|
12637
|
+
},
|
|
12638
|
+
{
|
|
12639
|
+
name: "credit-card",
|
|
12640
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/>'
|
|
12641
|
+
},
|
|
12642
|
+
{
|
|
12643
|
+
name: "document-text",
|
|
12644
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>'
|
|
12645
|
+
},
|
|
12646
|
+
{
|
|
12647
|
+
name: "pencil-square",
|
|
12648
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>'
|
|
12649
|
+
},
|
|
12650
|
+
{
|
|
12651
|
+
name: "server",
|
|
12652
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01"/>'
|
|
12653
|
+
},
|
|
12654
|
+
{
|
|
12655
|
+
name: "building-office",
|
|
12656
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"/>'
|
|
12657
|
+
},
|
|
12658
|
+
{
|
|
12659
|
+
name: "home",
|
|
12660
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>'
|
|
12661
|
+
},
|
|
12662
|
+
{
|
|
12663
|
+
name: "star",
|
|
12664
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"/>'
|
|
12665
|
+
},
|
|
12666
|
+
{
|
|
12667
|
+
name: "tag",
|
|
12668
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"/>'
|
|
12669
|
+
},
|
|
12670
|
+
{
|
|
12671
|
+
name: "link",
|
|
12672
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/>'
|
|
12673
|
+
},
|
|
12674
|
+
{
|
|
12675
|
+
name: "external-link",
|
|
12676
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/>'
|
|
12677
|
+
},
|
|
12678
|
+
{
|
|
12679
|
+
name: "eye",
|
|
12680
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/>'
|
|
12681
|
+
},
|
|
12682
|
+
{
|
|
12683
|
+
name: "bars-3",
|
|
12684
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>'
|
|
12685
|
+
},
|
|
12686
|
+
{
|
|
12687
|
+
name: "arrow-right",
|
|
12688
|
+
svg: '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"/>'
|
|
12689
|
+
}
|
|
12690
|
+
];
|
|
12691
|
+
function renderIconPicker(selectedIcon) {
|
|
12692
|
+
const safeSelected = chunkMNWKYY5E_cjs.escapeHtml(selectedIcon);
|
|
12693
|
+
const iconButtons = ICONS.map(({ name, svg }) => {
|
|
12694
|
+
const isSelected = name === selectedIcon;
|
|
12695
|
+
const selectedClasses = isSelected ? "ring-2 ring-cyan-500 bg-cyan-50 dark:bg-cyan-900/30" : "ring-1 ring-zinc-200 dark:ring-zinc-700 hover:ring-cyan-300 dark:hover:ring-cyan-600 hover:bg-zinc-50 dark:hover:bg-zinc-800";
|
|
12696
|
+
return `
|
|
12697
|
+
<button
|
|
12698
|
+
type="button"
|
|
12699
|
+
data-icon-name="${name}"
|
|
12700
|
+
onclick="selectIcon('${name}')"
|
|
12701
|
+
class="icon-btn flex flex-col items-center gap-1 p-2 rounded-lg transition-all duration-150 ${selectedClasses}"
|
|
12702
|
+
title="${name}"
|
|
12703
|
+
>
|
|
12704
|
+
<svg class="w-6 h-6 text-zinc-700 dark:text-zinc-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12705
|
+
${svg}
|
|
12706
|
+
</svg>
|
|
12707
|
+
<span class="text-[10px] text-zinc-500 dark:text-zinc-400 truncate max-w-[56px] text-center leading-tight">${name}</span>
|
|
12708
|
+
</button>`;
|
|
12709
|
+
}).join("\n");
|
|
12710
|
+
return `
|
|
12711
|
+
<div class="space-y-4">
|
|
12712
|
+
<input type="hidden" name="icon" id="icon-input" value="${safeSelected}">
|
|
12713
|
+
|
|
12714
|
+
<div>
|
|
12715
|
+
<p class="text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Choose an icon</p>
|
|
12716
|
+
<div class="grid grid-cols-6 sm:grid-cols-8 md:grid-cols-10 gap-2 max-h-64 overflow-y-auto p-1 rounded-lg border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-900">
|
|
12717
|
+
${iconButtons}
|
|
12718
|
+
</div>
|
|
12719
|
+
</div>
|
|
12720
|
+
|
|
12721
|
+
<div>
|
|
12722
|
+
<label class="text-sm font-medium text-zinc-700 dark:text-zinc-300 block mb-1">Custom SVG (overrides selection above)</label>
|
|
12723
|
+
<textarea
|
|
12724
|
+
id="custom-svg-input"
|
|
12725
|
+
rows="3"
|
|
12726
|
+
placeholder='<svg xmlns="http://www.w3.org/2000/svg" ...>...</svg>'
|
|
12727
|
+
oninput="handleCustomSvg(this.value)"
|
|
12728
|
+
class="w-full rounded-lg border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-cyan-500 font-mono"
|
|
12729
|
+
></textarea>
|
|
12730
|
+
<p class="mt-1 text-xs text-zinc-400 dark:text-zinc-500">Paste raw SVG markup to use a custom icon.</p>
|
|
12731
|
+
</div>
|
|
12732
|
+
</div>
|
|
12733
|
+
|
|
12734
|
+
<script>
|
|
12735
|
+
(function () {
|
|
12736
|
+
function selectIcon(name) {
|
|
12737
|
+
document.getElementById('icon-input').value = name;
|
|
12738
|
+
document.getElementById('custom-svg-input').value = '';
|
|
12739
|
+
document.querySelectorAll('.icon-btn').forEach(function (btn) {
|
|
12740
|
+
var isSelected = btn.getAttribute('data-icon-name') === name;
|
|
12741
|
+
btn.className = btn.className
|
|
12742
|
+
.replace(/ring-2 ring-cyan-500 bg-cyan-50 dark:bg-cyan-900\\/30/g, '')
|
|
12743
|
+
.replace(/ring-1 ring-zinc-200 dark:ring-zinc-700 hover:ring-cyan-300 dark:hover:ring-cyan-600 hover:bg-zinc-50 dark:hover:bg-zinc-800/g, '')
|
|
12744
|
+
.trim();
|
|
12745
|
+
if (isSelected) {
|
|
12746
|
+
btn.className += ' ring-2 ring-cyan-500 bg-cyan-50 dark:bg-cyan-900/30';
|
|
12747
|
+
} else {
|
|
12748
|
+
btn.className += ' ring-1 ring-zinc-200 dark:ring-zinc-700 hover:ring-cyan-300 dark:hover:ring-cyan-600 hover:bg-zinc-50 dark:hover:bg-zinc-800';
|
|
12749
|
+
}
|
|
12750
|
+
});
|
|
12751
|
+
}
|
|
12752
|
+
|
|
12753
|
+
function handleCustomSvg(value) {
|
|
12754
|
+
var trimmed = value.trim();
|
|
12755
|
+
if (trimmed) {
|
|
12756
|
+
document.getElementById('icon-input').value = trimmed;
|
|
12757
|
+
document.querySelectorAll('.icon-btn').forEach(function (btn) {
|
|
12758
|
+
btn.className = btn.className
|
|
12759
|
+
.replace(/ring-2 ring-cyan-500 bg-cyan-50 dark:bg-cyan-900\\/30/g, '')
|
|
12760
|
+
.replace(/ring-1 ring-zinc-200 dark:ring-zinc-700 hover:ring-cyan-300 dark:hover:ring-cyan-600 hover:bg-zinc-50 dark:hover:bg-zinc-800/g, '')
|
|
12761
|
+
.trim();
|
|
12762
|
+
btn.className += ' ring-1 ring-zinc-200 dark:ring-zinc-700 hover:ring-cyan-300 dark:hover:ring-cyan-600 hover:bg-zinc-50 dark:hover:bg-zinc-800';
|
|
12763
|
+
});
|
|
12764
|
+
}
|
|
12765
|
+
}
|
|
12766
|
+
|
|
12767
|
+
window.selectIcon = selectIcon;
|
|
12768
|
+
window.handleCustomSvg = handleCustomSvg;
|
|
12769
|
+
})();
|
|
12770
|
+
</script>
|
|
12771
|
+
`;
|
|
12772
|
+
}
|
|
12773
|
+
|
|
12774
|
+
// src/plugins/core-plugins/menu-plugin/templates/admin-menu-form.template.ts
|
|
12775
|
+
function renderMenuFormPage(data) {
|
|
12776
|
+
const { item, topLevelItems } = data;
|
|
12777
|
+
const isEdit = item !== null;
|
|
12778
|
+
const errorBanner = data.error ? `<div class="mb-6 rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-700 px-4 py-3 text-sm text-red-800 dark:text-red-300">
|
|
12779
|
+
${chunkMNWKYY5E_cjs.escapeHtml(data.error)}
|
|
12780
|
+
</div>` : "";
|
|
12781
|
+
const parentOptions = topLevelItems.filter((t) => !isEdit || t.id !== item?.id).sort((a, b) => a.label.localeCompare(b.label)).map((t) => {
|
|
12782
|
+
const selected = item?.parent === t.id ? "selected" : "";
|
|
12783
|
+
return `<option value="${chunkMNWKYY5E_cjs.escapeHtml(t.id)}" ${selected}>${chunkMNWKYY5E_cjs.escapeHtml(t.label)}</option>`;
|
|
12784
|
+
}).join("\n");
|
|
12785
|
+
const targetSelfSelected = !item || item.target === "_self" ? "selected" : "";
|
|
12786
|
+
const targetBlankSelected = item?.target === "_blank" ? "selected" : "";
|
|
12787
|
+
const visibleChecked = item ? item.visible ? "checked" : "" : "checked";
|
|
12788
|
+
const formAttrs = isEdit ? `method="POST" action="/admin/menu/${chunkMNWKYY5E_cjs.escapeHtml(item.id)}/update"` : `method="POST" action="/admin/menu"`;
|
|
12789
|
+
const submitLabel = isEdit ? "Save Changes" : "Add Item";
|
|
12790
|
+
const pageTitle = isEdit ? `Edit: ${chunkMNWKYY5E_cjs.escapeHtml(item.label)}` : "Add Menu Item";
|
|
12791
|
+
const pageContent = `
|
|
12792
|
+
<div class="max-w-2xl">
|
|
12793
|
+
<div class="mb-6">
|
|
12794
|
+
<a href="/admin/menu" class="inline-flex items-center gap-1.5 text-sm text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 transition-colors">
|
|
12795
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12796
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
|
|
12797
|
+
</svg>
|
|
12798
|
+
Back to Menu Manager
|
|
12799
|
+
</a>
|
|
12800
|
+
<h1 class="mt-3 text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">${pageTitle}</h1>
|
|
12801
|
+
</div>
|
|
12802
|
+
|
|
12803
|
+
${errorBanner}
|
|
12804
|
+
|
|
12805
|
+
<div class="rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6">
|
|
12806
|
+
<form ${formAttrs} class="space-y-6">
|
|
12807
|
+
|
|
12808
|
+
<div>
|
|
12809
|
+
<label for="menu-label" class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1">
|
|
12810
|
+
Label <span class="text-red-500">*</span>
|
|
12811
|
+
</label>
|
|
12812
|
+
<input
|
|
12813
|
+
id="menu-label"
|
|
12814
|
+
type="text"
|
|
12815
|
+
name="label"
|
|
12816
|
+
required
|
|
12817
|
+
value="${isEdit ? chunkMNWKYY5E_cjs.escapeHtml(item.label) : ""}"
|
|
12818
|
+
placeholder="e.g. Documentation"
|
|
12819
|
+
class="w-full rounded-lg border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-cyan-500 transition-shadow"
|
|
12820
|
+
>
|
|
12821
|
+
</div>
|
|
12822
|
+
|
|
12823
|
+
<div>
|
|
12824
|
+
<label for="menu-url" class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1">URL</label>
|
|
12825
|
+
<input
|
|
12826
|
+
id="menu-url"
|
|
12827
|
+
type="text"
|
|
12828
|
+
name="url"
|
|
12829
|
+
value="${isEdit ? chunkMNWKYY5E_cjs.escapeHtml(item.url) : ""}"
|
|
12830
|
+
placeholder="/path/to/page or https://example.com"
|
|
12831
|
+
class="w-full rounded-lg border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-cyan-500 transition-shadow"
|
|
12832
|
+
>
|
|
12833
|
+
</div>
|
|
12834
|
+
|
|
12835
|
+
<div class="grid grid-cols-2 gap-4">
|
|
12836
|
+
<div>
|
|
12837
|
+
<label for="menu-target" class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1">Open in</label>
|
|
12838
|
+
<select
|
|
12839
|
+
id="menu-target"
|
|
12840
|
+
name="target"
|
|
12841
|
+
class="w-full rounded-lg border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-cyan-500 transition-shadow"
|
|
12842
|
+
>
|
|
12843
|
+
<option value="_self" ${targetSelfSelected}>Same tab</option>
|
|
12844
|
+
<option value="_blank" ${targetBlankSelected}>New tab</option>
|
|
12845
|
+
</select>
|
|
12846
|
+
</div>
|
|
12847
|
+
|
|
12848
|
+
<div>
|
|
12849
|
+
<label for="menu-parent" class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1">Parent</label>
|
|
12850
|
+
<select
|
|
12851
|
+
id="menu-parent"
|
|
12852
|
+
name="parent"
|
|
12853
|
+
class="w-full rounded-lg border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-cyan-500 transition-shadow"
|
|
12854
|
+
>
|
|
12855
|
+
<option value="">Top level (none)</option>
|
|
12856
|
+
${parentOptions}
|
|
12857
|
+
</select>
|
|
12858
|
+
</div>
|
|
12859
|
+
</div>
|
|
12860
|
+
|
|
12861
|
+
<div class="flex items-center gap-3">
|
|
12862
|
+
<label class="relative inline-flex items-center cursor-pointer">
|
|
12863
|
+
<input
|
|
12864
|
+
id="menu-visible"
|
|
12865
|
+
type="checkbox"
|
|
12866
|
+
name="visible"
|
|
12867
|
+
value="1"
|
|
12868
|
+
${visibleChecked}
|
|
12869
|
+
class="sr-only peer"
|
|
12870
|
+
>
|
|
12871
|
+
<div class="w-9 h-5 bg-zinc-200 dark:bg-zinc-700 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-cyan-500 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-zinc-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all peer-checked:bg-cyan-600"></div>
|
|
12872
|
+
</label>
|
|
12873
|
+
<label for="menu-visible" class="text-sm font-medium text-zinc-700 dark:text-zinc-300 cursor-pointer">Visible in navigation</label>
|
|
12874
|
+
</div>
|
|
12875
|
+
|
|
12876
|
+
<div>
|
|
12877
|
+
<p class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Icon</p>
|
|
12878
|
+
${renderIconPicker(item?.icon ?? "link")}
|
|
12879
|
+
</div>
|
|
12880
|
+
|
|
12881
|
+
<div class="flex items-center justify-end gap-3 pt-2 border-t border-zinc-100 dark:border-zinc-800">
|
|
12882
|
+
<a href="/admin/menu" class="inline-flex items-center px-3.5 py-2 text-sm font-medium rounded-lg text-zinc-700 dark:text-zinc-300 bg-zinc-100 dark:bg-zinc-700 hover:bg-zinc-200 dark:hover:bg-zinc-600 transition-colors">
|
|
12883
|
+
Cancel
|
|
12884
|
+
</a>
|
|
12885
|
+
<button
|
|
12886
|
+
type="submit"
|
|
12887
|
+
class="inline-flex items-center px-3.5 py-2 text-sm font-semibold rounded-lg bg-zinc-950 dark:bg-white text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm"
|
|
12888
|
+
>
|
|
12889
|
+
${submitLabel}
|
|
12890
|
+
</button>
|
|
12891
|
+
</div>
|
|
12892
|
+
|
|
12893
|
+
</form>
|
|
12894
|
+
</div>
|
|
12895
|
+
</div>
|
|
12896
|
+
`;
|
|
12897
|
+
const layoutData = {
|
|
12898
|
+
title: isEdit ? "Edit Menu Item" : "Add Menu Item",
|
|
12899
|
+
pageTitle: isEdit ? "Edit Menu Item" : "Add Menu Item",
|
|
12900
|
+
currentPath: data.currentPath ?? "/admin/menu",
|
|
12901
|
+
user: data.user,
|
|
12902
|
+
version: data.version,
|
|
12903
|
+
dynamicMenuItems: data.dynamicMenuItems,
|
|
12904
|
+
content: pageContent
|
|
12905
|
+
};
|
|
12906
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
12907
|
+
}
|
|
12908
|
+
|
|
12909
|
+
// src/plugins/core-plugins/menu-plugin/routes/admin-menu.ts
|
|
12910
|
+
function sanitizeUrl(url) {
|
|
12911
|
+
const trimmed = url.trim();
|
|
12912
|
+
if (/^javascript:/i.test(trimmed) || /^data:/i.test(trimmed)) return "";
|
|
12913
|
+
return trimmed;
|
|
12914
|
+
}
|
|
12915
|
+
var adminMenuRoutes = new hono.Hono();
|
|
12916
|
+
adminMenuRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
12917
|
+
adminMenuRoutes.use("*", chunk37V3RET3_cjs.requireRole(["admin"]));
|
|
12918
|
+
adminMenuRoutes.get("/", async (c) => {
|
|
12919
|
+
const db = c.env.DB;
|
|
12920
|
+
const user = c.get("user");
|
|
12921
|
+
const items = await listMenuItems(db);
|
|
12922
|
+
buildSidebarTree(items);
|
|
12923
|
+
const pluginIds = [...new Set(items.filter((i) => i.pluginId).map((i) => i.pluginId))];
|
|
12924
|
+
const pluginStatuses = await fetchPluginStatuses(db, pluginIds);
|
|
12925
|
+
return c.html(renderMenuListPage({
|
|
12926
|
+
items,
|
|
12927
|
+
pluginStatuses,
|
|
12928
|
+
user,
|
|
12929
|
+
currentPath: "/admin/menu",
|
|
12930
|
+
version: c.get("appVersion"),
|
|
12931
|
+
dynamicMenuItems: c.get("pluginMenuItems"),
|
|
12932
|
+
message: c.req.query("message")
|
|
12933
|
+
}));
|
|
12934
|
+
});
|
|
12935
|
+
adminMenuRoutes.get("/new", async (c) => {
|
|
12936
|
+
const db = c.env.DB;
|
|
12937
|
+
const topLevelItems = await listMenuItems(db);
|
|
12938
|
+
return c.html(renderMenuFormPage({
|
|
12939
|
+
item: null,
|
|
12940
|
+
topLevelItems: topLevelItems.filter((i) => !i.parent),
|
|
12941
|
+
user: c.get("user"),
|
|
12942
|
+
currentPath: "/admin/menu",
|
|
12943
|
+
version: c.get("appVersion"),
|
|
12944
|
+
dynamicMenuItems: c.get("pluginMenuItems")
|
|
12945
|
+
}));
|
|
12946
|
+
});
|
|
12947
|
+
adminMenuRoutes.get("/:id", async (c) => {
|
|
12948
|
+
const db = c.env.DB;
|
|
12949
|
+
const id = c.req.param("id");
|
|
12950
|
+
const items = await listMenuItems(db);
|
|
12951
|
+
const item = items.find((i) => i.id === id);
|
|
12952
|
+
if (!item) return c.notFound();
|
|
12953
|
+
const topLevelItems = items.filter((i) => !i.parent && i.id !== id);
|
|
12954
|
+
return c.html(renderMenuFormPage({
|
|
12955
|
+
item,
|
|
12956
|
+
topLevelItems,
|
|
12957
|
+
user: c.get("user"),
|
|
12958
|
+
currentPath: "/admin/menu",
|
|
12959
|
+
version: c.get("appVersion"),
|
|
12960
|
+
dynamicMenuItems: c.get("pluginMenuItems")
|
|
12961
|
+
}));
|
|
12962
|
+
});
|
|
12963
|
+
adminMenuRoutes.post("/", async (c) => {
|
|
12964
|
+
const db = c.env.DB;
|
|
12965
|
+
const form = await c.req.formData();
|
|
12966
|
+
const label = String(form.get("label") ?? "").trim();
|
|
12967
|
+
const url = String(form.get("url") ?? "").trim();
|
|
12968
|
+
const icon = String(form.get("icon") ?? "link").trim();
|
|
12969
|
+
const target = form.get("target") === "_blank" ? "_blank" : "_self";
|
|
12970
|
+
const parent = String(form.get("parent") ?? "").trim() || null;
|
|
12971
|
+
const visible = form.has("visible");
|
|
12972
|
+
if (!label) {
|
|
12973
|
+
return c.html(renderMenuFormPage({
|
|
12974
|
+
item: null,
|
|
12975
|
+
topLevelItems: [],
|
|
12976
|
+
user: c.get("user"),
|
|
12977
|
+
currentPath: "/admin/menu",
|
|
12978
|
+
version: c.get("appVersion"),
|
|
12979
|
+
dynamicMenuItems: c.get("pluginMenuItems"),
|
|
12980
|
+
error: "Label is required"
|
|
12981
|
+
}), 400);
|
|
12982
|
+
}
|
|
12983
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
12984
|
+
const id = chunkKIGVVO6N_cjs.nanoid();
|
|
12985
|
+
const slug = `menu:user:${id}`;
|
|
12986
|
+
const safeUrl = sanitizeUrl(url);
|
|
12987
|
+
const isExternal = /^https?:\/\//.test(safeUrl);
|
|
12988
|
+
const data = JSON.stringify({
|
|
12989
|
+
label,
|
|
12990
|
+
url: safeUrl,
|
|
12991
|
+
icon,
|
|
12992
|
+
target,
|
|
12993
|
+
isExternal,
|
|
12994
|
+
visible,
|
|
12995
|
+
parent,
|
|
12996
|
+
source: "user",
|
|
12997
|
+
pluginId: null,
|
|
12998
|
+
permissions: [],
|
|
12999
|
+
lockedFields: []
|
|
13000
|
+
});
|
|
13001
|
+
const items = await listMenuItems(db);
|
|
13002
|
+
const maxSort = items.reduce((m, i) => Math.max(m, i.sortOrder), 0);
|
|
13003
|
+
const sortOrder = maxSort + 10;
|
|
13004
|
+
await db.prepare(
|
|
13005
|
+
`INSERT INTO documents (id, root_id, type_id, type_version, version_of_id, version_number,
|
|
13006
|
+
is_current_draft, is_published, status, parent_root_id, slug, path, title, zone,
|
|
13007
|
+
sort_order, visible, published_at, scheduled_at, expires_at, deleted_at,
|
|
13008
|
+
tenant_id, locale, translation_group_id, data, metadata,
|
|
13009
|
+
owner_id, created_by, updated_by, created_at, updated_at)
|
|
13010
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`
|
|
13011
|
+
).bind(
|
|
13012
|
+
id,
|
|
13013
|
+
id,
|
|
13014
|
+
"menu_item",
|
|
13015
|
+
1,
|
|
13016
|
+
null,
|
|
13017
|
+
1,
|
|
13018
|
+
1,
|
|
13019
|
+
1,
|
|
13020
|
+
"published",
|
|
13021
|
+
"",
|
|
13022
|
+
slug,
|
|
13023
|
+
null,
|
|
13024
|
+
label,
|
|
13025
|
+
null,
|
|
13026
|
+
sortOrder,
|
|
13027
|
+
visible ? 1 : 0,
|
|
13028
|
+
now,
|
|
13029
|
+
null,
|
|
13030
|
+
null,
|
|
13031
|
+
null,
|
|
13032
|
+
"default",
|
|
13033
|
+
"default",
|
|
13034
|
+
"",
|
|
13035
|
+
data,
|
|
13036
|
+
"{}",
|
|
13037
|
+
null,
|
|
13038
|
+
c.get("user")?.userId ?? "system",
|
|
13039
|
+
c.get("user")?.userId ?? "system",
|
|
13040
|
+
now,
|
|
13041
|
+
now
|
|
13042
|
+
).run();
|
|
13043
|
+
return c.redirect("/admin/menu?message=Item+created");
|
|
13044
|
+
});
|
|
13045
|
+
adminMenuRoutes.put("/reorder", async (c) => {
|
|
13046
|
+
const db = c.env.DB;
|
|
13047
|
+
const body = await c.req.json();
|
|
13048
|
+
if (!Array.isArray(body)) return c.json({ error: "Invalid body" }, 400);
|
|
13049
|
+
await reorderItems(db, body);
|
|
13050
|
+
return c.json({ ok: true });
|
|
13051
|
+
});
|
|
13052
|
+
adminMenuRoutes.post("/:id/visibility", async (c) => {
|
|
13053
|
+
const db = c.env.DB;
|
|
13054
|
+
const id = c.req.param("id");
|
|
13055
|
+
const form = await c.req.formData();
|
|
13056
|
+
const visible = form.get("visible") === "true";
|
|
13057
|
+
await toggleVisibility(db, id, visible);
|
|
13058
|
+
return c.redirect("/admin/menu?message=Visibility+updated");
|
|
13059
|
+
});
|
|
13060
|
+
async function handleMenuItemUpdate(c) {
|
|
13061
|
+
const db = c.env.DB;
|
|
13062
|
+
const id = c.req.param("id");
|
|
13063
|
+
const form = await c.req.formData();
|
|
13064
|
+
const items = await listMenuItems(db);
|
|
13065
|
+
const item = items.find((i) => i.id === id);
|
|
13066
|
+
if (!item) return c.json({ error: "Not found" }, 404);
|
|
13067
|
+
const locked = new Set(item.lockedFields);
|
|
13068
|
+
const changes = {};
|
|
13069
|
+
if (form.has("label") && !locked.has("label")) changes.label = String(form.get("label")).trim();
|
|
13070
|
+
if (form.has("icon") && !locked.has("icon")) changes.icon = String(form.get("icon")).trim();
|
|
13071
|
+
if (form.has("target") && !locked.has("target")) changes.target = form.get("target") === "_blank" ? "_blank" : "_self";
|
|
13072
|
+
if (form.has("url") && !locked.has("url")) changes.url = sanitizeUrl(String(form.get("url")));
|
|
13073
|
+
if (form.has("parent")) changes.parent = String(form.get("parent")).trim() || null;
|
|
13074
|
+
changes.visible = form.has("visible");
|
|
13075
|
+
const ok = await updateItem(db, id, changes, item.lockedFields);
|
|
13076
|
+
if (!ok) return c.json({ error: "Cannot modify locked fields" }, 403);
|
|
13077
|
+
return c.redirect("/admin/menu?message=Item+updated");
|
|
13078
|
+
}
|
|
13079
|
+
adminMenuRoutes.put("/:id", handleMenuItemUpdate);
|
|
13080
|
+
adminMenuRoutes.post("/:id/update", handleMenuItemUpdate);
|
|
13081
|
+
adminMenuRoutes.delete("/:id", async (c) => {
|
|
13082
|
+
const db = c.env.DB;
|
|
13083
|
+
const id = c.req.param("id");
|
|
13084
|
+
const result = await deleteItem(db, id);
|
|
13085
|
+
if (!result.ok) return c.json({ error: result.reason }, 403);
|
|
13086
|
+
return c.redirect("/admin/menu?message=Item+deleted");
|
|
13087
|
+
});
|
|
13088
|
+
adminMenuRoutes.post("/:id/delete", async (c) => {
|
|
13089
|
+
const db = c.env.DB;
|
|
13090
|
+
const id = c.req.param("id");
|
|
13091
|
+
const result = await deleteItem(db, id);
|
|
13092
|
+
if (!result.ok) return c.json({ error: result.reason }, 403);
|
|
13093
|
+
return c.redirect("/admin/menu?message=Item+deleted");
|
|
13094
|
+
});
|
|
13095
|
+
adminMenuRoutes.post("/:id/move-up", async (c) => {
|
|
13096
|
+
const db = c.env.DB;
|
|
13097
|
+
const id = c.req.param("id");
|
|
13098
|
+
const allItems = await listMenuItems(db);
|
|
13099
|
+
const cur = allItems.find((i) => i.id === id);
|
|
13100
|
+
if (!cur) return c.redirect("/admin/menu");
|
|
13101
|
+
const siblings = allItems.filter((i) => i.parent === cur.parent);
|
|
13102
|
+
const idx = siblings.findIndex((i) => i.id === id);
|
|
13103
|
+
const prev = siblings[idx - 1];
|
|
13104
|
+
if (idx > 0 && prev) {
|
|
13105
|
+
await reorderItems(db, [
|
|
13106
|
+
{ id: cur.id, sortOrder: prev.sortOrder, parent: cur.parent },
|
|
13107
|
+
{ id: prev.id, sortOrder: cur.sortOrder, parent: prev.parent }
|
|
13108
|
+
]);
|
|
13109
|
+
return c.redirect("/admin/menu?message=Reordered");
|
|
13110
|
+
}
|
|
13111
|
+
return c.redirect("/admin/menu");
|
|
13112
|
+
});
|
|
13113
|
+
adminMenuRoutes.post("/:id/move-down", async (c) => {
|
|
13114
|
+
const db = c.env.DB;
|
|
13115
|
+
const id = c.req.param("id");
|
|
13116
|
+
const allItems = await listMenuItems(db);
|
|
13117
|
+
const cur = allItems.find((i) => i.id === id);
|
|
13118
|
+
if (!cur) return c.redirect("/admin/menu");
|
|
13119
|
+
const siblings = allItems.filter((i) => i.parent === cur.parent);
|
|
13120
|
+
const idx = siblings.findIndex((i) => i.id === id);
|
|
13121
|
+
const next = siblings[idx + 1];
|
|
13122
|
+
if (idx !== -1 && idx < siblings.length - 1 && next) {
|
|
13123
|
+
await reorderItems(db, [
|
|
13124
|
+
{ id: cur.id, sortOrder: next.sortOrder, parent: cur.parent },
|
|
13125
|
+
{ id: next.id, sortOrder: cur.sortOrder, parent: next.parent }
|
|
13126
|
+
]);
|
|
13127
|
+
return c.redirect("/admin/menu?message=Reordered");
|
|
13128
|
+
}
|
|
13129
|
+
return c.redirect("/admin/menu");
|
|
13130
|
+
});
|
|
13131
|
+
var menuPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
13132
|
+
id: "menu",
|
|
13133
|
+
version: "1.0.0",
|
|
13134
|
+
name: "Menu Manager",
|
|
13135
|
+
description: "Admin sidebar navigation manager.",
|
|
13136
|
+
sonicjsVersionRange: "^3.0.0",
|
|
13137
|
+
author: { name: "SonicJS Team", email: "team@sonicjs.com" },
|
|
13138
|
+
register(app2) {
|
|
13139
|
+
app2.route("/admin/menu", adminMenuRoutes);
|
|
13140
|
+
},
|
|
13141
|
+
async onBoot(ctx) {
|
|
13142
|
+
const env = ctx.env ?? {};
|
|
13143
|
+
const db = env.DB;
|
|
13144
|
+
if (!db) return;
|
|
13145
|
+
try {
|
|
13146
|
+
const typeRegistry = new chunk37V3RET3_cjs.DocumentTypeRegistry(db);
|
|
13147
|
+
await typeRegistry.register({
|
|
13148
|
+
id: "menu_item",
|
|
13149
|
+
name: "menu_item",
|
|
13150
|
+
displayName: "Menu Item",
|
|
13151
|
+
description: "Admin sidebar navigation item",
|
|
13152
|
+
schema: zod.z.object({}),
|
|
13153
|
+
pluginId: "menu",
|
|
13154
|
+
source: "plugin",
|
|
13155
|
+
queryableFields: [
|
|
13156
|
+
{ name: "parent", path: "$.parent", kind: "scalar", type: "text", column: "q_menu_parent" },
|
|
13157
|
+
{ name: "visible", path: "$.visible", kind: "scalar", type: "boolean", column: "q_menu_visible" },
|
|
13158
|
+
{ name: "source", path: "$.source", kind: "scalar", type: "text", column: "q_menu_source" },
|
|
13159
|
+
{ name: "pluginId", path: "$.pluginId", kind: "scalar", type: "text", column: "q_menu_plugin_id" }
|
|
13160
|
+
],
|
|
13161
|
+
settings: {
|
|
13162
|
+
baseGrants: { admin: ["read", "create", "update", "delete", "manage"] },
|
|
13163
|
+
internal: true
|
|
13164
|
+
}
|
|
13165
|
+
});
|
|
13166
|
+
for (const item of SYSTEM_MENU_ITEMS) {
|
|
13167
|
+
await upsertSystemItem(db, item.id, {
|
|
13168
|
+
label: item.label,
|
|
13169
|
+
url: item.url,
|
|
13170
|
+
icon: item.icon,
|
|
13171
|
+
target: item.target,
|
|
13172
|
+
isExternal: item.isExternal,
|
|
13173
|
+
visible: item.visible,
|
|
13174
|
+
parent: item.parent,
|
|
13175
|
+
source: item.source,
|
|
13176
|
+
pluginId: item.pluginId,
|
|
13177
|
+
permissions: [...item.permissions],
|
|
13178
|
+
lockedFields: [...item.lockedFields]
|
|
13179
|
+
}, item.sortOrder);
|
|
13180
|
+
}
|
|
13181
|
+
await chunkI767LVN7_cjs.reconcileMenuFromPlugins(db);
|
|
13182
|
+
} catch {
|
|
13183
|
+
}
|
|
13184
|
+
},
|
|
13185
|
+
settingsTabContent: {
|
|
13186
|
+
async loadData(db) {
|
|
13187
|
+
const items = await listMenuItems(db);
|
|
13188
|
+
const pluginIds = [...new Set(items.filter((i) => i.pluginId).map((i) => i.pluginId))];
|
|
13189
|
+
const pluginStatuses = await fetchPluginStatuses(db, pluginIds);
|
|
13190
|
+
return { items, pluginStatuses };
|
|
13191
|
+
},
|
|
13192
|
+
render({ data }) {
|
|
13193
|
+
const items = data?.items ?? [];
|
|
13194
|
+
const pluginStatuses = data?.pluginStatuses ?? {};
|
|
13195
|
+
return renderMenuSettingsContent(items, pluginStatuses);
|
|
13196
|
+
}
|
|
13197
|
+
}
|
|
13198
|
+
});
|
|
13199
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
11770
13200
|
var adminRoutes6 = new hono.Hono();
|
|
11771
|
-
adminRoutes6.use("*",
|
|
13201
|
+
adminRoutes6.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
11772
13202
|
adminRoutes6.use("*", async (c, next) => {
|
|
11773
13203
|
const user = c.get("user");
|
|
11774
13204
|
if (user?.role !== "admin") {
|
|
@@ -11884,7 +13314,7 @@ adminRoutes6.get("/", async (c) => {
|
|
|
11884
13314
|
</div>
|
|
11885
13315
|
</div>
|
|
11886
13316
|
`;
|
|
11887
|
-
return c.html(
|
|
13317
|
+
return c.html(chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
|
|
11888
13318
|
title: "Analytics",
|
|
11889
13319
|
pageTitle: "Analytics Dashboard",
|
|
11890
13320
|
currentPath: "/admin/analytics",
|
|
@@ -12124,7 +13554,7 @@ apiRoutes4.get("/stats", async (c) => {
|
|
|
12124
13554
|
});
|
|
12125
13555
|
|
|
12126
13556
|
// src/plugins/core-plugins/analytics/index.ts
|
|
12127
|
-
var analyticsPlugin =
|
|
13557
|
+
var analyticsPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
12128
13558
|
id: "core-analytics",
|
|
12129
13559
|
version: "1.0.0",
|
|
12130
13560
|
name: "Analytics",
|
|
@@ -12271,7 +13701,7 @@ function esc2(s) {
|
|
|
12271
13701
|
return (s || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
12272
13702
|
}
|
|
12273
13703
|
async function getVariablesMap(db) {
|
|
12274
|
-
let variables =
|
|
13704
|
+
let variables = chunkI767LVN7_cjs.getVariablesCached();
|
|
12275
13705
|
if (variables) return variables;
|
|
12276
13706
|
try {
|
|
12277
13707
|
const { results } = await db.prepare(
|
|
@@ -12281,7 +13711,7 @@ async function getVariablesMap(db) {
|
|
|
12281
13711
|
for (const row of results || []) {
|
|
12282
13712
|
variables.set(row.key, row.value);
|
|
12283
13713
|
}
|
|
12284
|
-
|
|
13714
|
+
chunkI767LVN7_cjs.setVariablesCache(variables);
|
|
12285
13715
|
return variables;
|
|
12286
13716
|
} catch {
|
|
12287
13717
|
return /* @__PURE__ */ new Map();
|
|
@@ -12350,7 +13780,7 @@ apiRoutes5.post("/", async (c) => {
|
|
|
12350
13780
|
await db.prepare(
|
|
12351
13781
|
"INSERT INTO global_variables (key, value, description, category, is_active) VALUES (?, ?, ?, ?, ?)"
|
|
12352
13782
|
).bind(key, value || "", description || "", category || "general", isActive !== false ? 1 : 0).run();
|
|
12353
|
-
|
|
13783
|
+
chunkI767LVN7_cjs.invalidateVariablesCache();
|
|
12354
13784
|
const created = await db.prepare("SELECT * FROM global_variables WHERE key = ?").bind(key).first();
|
|
12355
13785
|
return c.json({ success: true, data: formatVariable(created) }, 201);
|
|
12356
13786
|
} catch {
|
|
@@ -12395,7 +13825,7 @@ apiRoutes5.put("/:id", async (c) => {
|
|
|
12395
13825
|
updates.push("updated_at = strftime('%s', 'now')");
|
|
12396
13826
|
params.push(id);
|
|
12397
13827
|
await db.prepare(`UPDATE global_variables SET ${updates.join(", ")} WHERE id = ?`).bind(...params).run();
|
|
12398
|
-
|
|
13828
|
+
chunkI767LVN7_cjs.invalidateVariablesCache();
|
|
12399
13829
|
const updated = await db.prepare("SELECT * FROM global_variables WHERE id = ?").bind(id).first();
|
|
12400
13830
|
return c.json({ success: true, data: formatVariable(updated) });
|
|
12401
13831
|
} catch {
|
|
@@ -12409,7 +13839,7 @@ apiRoutes5.delete("/:id", async (c) => {
|
|
|
12409
13839
|
const existing = await db.prepare("SELECT id FROM global_variables WHERE id = ?").bind(id).first();
|
|
12410
13840
|
if (!existing) return c.json({ error: "Variable not found" }, 404);
|
|
12411
13841
|
await db.prepare("DELETE FROM global_variables WHERE id = ?").bind(id).run();
|
|
12412
|
-
|
|
13842
|
+
chunkI767LVN7_cjs.invalidateVariablesCache();
|
|
12413
13843
|
return c.json({ success: true });
|
|
12414
13844
|
} catch {
|
|
12415
13845
|
return c.json({ success: false, error: "Failed to delete variable" }, 500);
|
|
@@ -12469,7 +13899,7 @@ adminRoutes7.put("/:id", async (c) => {
|
|
|
12469
13899
|
const value = body.value;
|
|
12470
13900
|
if (value !== void 0) {
|
|
12471
13901
|
await db.prepare("UPDATE global_variables SET value = ?, updated_at = strftime('%s', 'now') WHERE id = ?").bind(value, id).run();
|
|
12472
|
-
|
|
13902
|
+
chunkI767LVN7_cjs.invalidateVariablesCache();
|
|
12473
13903
|
}
|
|
12474
13904
|
return c.html('<span class="text-green-400 text-xs">Saved</span>');
|
|
12475
13905
|
});
|
|
@@ -12477,7 +13907,7 @@ adminRoutes7.post("/:id/toggle", async (c) => {
|
|
|
12477
13907
|
const db = c.env.DB;
|
|
12478
13908
|
const id = c.req.param("id");
|
|
12479
13909
|
await db.prepare("UPDATE global_variables SET is_active = CASE WHEN is_active = 1 THEN 0 ELSE 1 END, updated_at = strftime('%s', 'now') WHERE id = ?").bind(id).run();
|
|
12480
|
-
|
|
13910
|
+
chunkI767LVN7_cjs.invalidateVariablesCache();
|
|
12481
13911
|
c.header("HX-Redirect", "/admin/global-variables");
|
|
12482
13912
|
return c.body(null, 204);
|
|
12483
13913
|
});
|
|
@@ -12498,7 +13928,7 @@ adminRoutes7.post("/", async (c) => {
|
|
|
12498
13928
|
await db.prepare(
|
|
12499
13929
|
"INSERT INTO global_variables (key, value, description, category) VALUES (?, ?, ?, ?)"
|
|
12500
13930
|
).bind(key, value, description, category).run();
|
|
12501
|
-
|
|
13931
|
+
chunkI767LVN7_cjs.invalidateVariablesCache();
|
|
12502
13932
|
c.header("HX-Redirect", "/admin/global-variables");
|
|
12503
13933
|
return c.body(null, 204);
|
|
12504
13934
|
});
|
|
@@ -12517,7 +13947,7 @@ adminRoutes7.post("/settings/editor-integration", async (c) => {
|
|
|
12517
13947
|
adminRoutes7.delete("/:id", async (c) => {
|
|
12518
13948
|
const db = c.env.DB;
|
|
12519
13949
|
await db.prepare("DELETE FROM global_variables WHERE id = ?").bind(c.req.param("id")).run();
|
|
12520
|
-
|
|
13950
|
+
chunkI767LVN7_cjs.invalidateVariablesCache();
|
|
12521
13951
|
return c.html("");
|
|
12522
13952
|
});
|
|
12523
13953
|
function renderAdminPage(variables, editorStatus = { editorActive: false, activeEditorName: "", enableEditorIntegration: true }) {
|
|
@@ -12835,7 +14265,7 @@ function renderAdminPage(variables, editorStatus = { editorActive: false, active
|
|
|
12835
14265
|
</div>
|
|
12836
14266
|
` });
|
|
12837
14267
|
}
|
|
12838
|
-
var globalVariablesPlugin =
|
|
14268
|
+
var globalVariablesPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
12839
14269
|
id: "global-variables",
|
|
12840
14270
|
version: "1.1.0",
|
|
12841
14271
|
name: "Global Variables",
|
|
@@ -12858,7 +14288,7 @@ var globalVariablesPlugin = chunkEUJAEB6W_cjs.definePlugin({
|
|
|
12858
14288
|
if (!db || !data) return data;
|
|
12859
14289
|
const variables = await getVariablesMap(db);
|
|
12860
14290
|
if (variables.size === 0) return data;
|
|
12861
|
-
return
|
|
14291
|
+
return chunkI767LVN7_cjs.resolveVariablesInObject(data, variables);
|
|
12862
14292
|
} catch {
|
|
12863
14293
|
return data;
|
|
12864
14294
|
}
|
|
@@ -12876,7 +14306,7 @@ var globalVariablesPlugin = chunkEUJAEB6W_cjs.definePlugin({
|
|
|
12876
14306
|
},
|
|
12877
14307
|
activate: async () => console.info("[GlobalVariables] Plugin activated"),
|
|
12878
14308
|
deactivate: async () => {
|
|
12879
|
-
|
|
14309
|
+
chunkI767LVN7_cjs.invalidateVariablesCache();
|
|
12880
14310
|
console.info("[GlobalVariables] Plugin deactivated, cache cleared");
|
|
12881
14311
|
},
|
|
12882
14312
|
uninstall: async (ctx) => {
|
|
@@ -13442,7 +14872,7 @@ function renderAdminPage2(shortcodes, editorStatus = { editorActive: false, acti
|
|
|
13442
14872
|
</div>
|
|
13443
14873
|
` });
|
|
13444
14874
|
}
|
|
13445
|
-
var shortcodesPlugin =
|
|
14875
|
+
var shortcodesPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
13446
14876
|
id: "shortcodes",
|
|
13447
14877
|
version: "1.0.0",
|
|
13448
14878
|
name: "Shortcodes",
|
|
@@ -13526,7 +14956,7 @@ helloWorldRoutes.get("/", async (c) => {
|
|
|
13526
14956
|
</html>
|
|
13527
14957
|
`);
|
|
13528
14958
|
});
|
|
13529
|
-
var helloWorldPlugin =
|
|
14959
|
+
var helloWorldPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
13530
14960
|
id: "hello-world",
|
|
13531
14961
|
version: "1.0.0",
|
|
13532
14962
|
name: "Hello World",
|
|
@@ -13573,7 +15003,7 @@ var manifest_default2 = {
|
|
|
13573
15003
|
author: "SonicJS Team"};
|
|
13574
15004
|
|
|
13575
15005
|
// src/plugins/core-plugins/multi-tenant-plugin/templates/tenants-list.template.ts
|
|
13576
|
-
|
|
15006
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
13577
15007
|
function statusBadge2(status) {
|
|
13578
15008
|
return status === "active" ? '<span class="inline-flex items-center rounded-md bg-emerald-500/10 px-2 py-1 text-xs font-medium text-emerald-600 dark:text-emerald-400">Active</span>' : '<span class="inline-flex items-center rounded-md bg-zinc-500/10 px-2 py-1 text-xs font-medium text-zinc-600 dark:text-zinc-400">Inactive</span>';
|
|
13579
15009
|
}
|
|
@@ -13646,7 +15076,7 @@ function renderTenantsList(data) {
|
|
|
13646
15076
|
</table>
|
|
13647
15077
|
</div>
|
|
13648
15078
|
</div>`;
|
|
13649
|
-
return
|
|
15079
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
|
|
13650
15080
|
title: "Tenants - SonicJS",
|
|
13651
15081
|
pageTitle: "Tenants",
|
|
13652
15082
|
currentPath: "/admin/tenants",
|
|
@@ -13665,7 +15095,7 @@ function renderTenantsInactive(data) {
|
|
|
13665
15095
|
<a href="/admin/plugins" class="mt-6 inline-flex items-center rounded-lg bg-zinc-950 px-3.5 py-2 text-sm font-semibold text-white hover:bg-zinc-800 dark:bg-white dark:text-zinc-950 dark:hover:bg-zinc-200">Go to Plugins</a>
|
|
13666
15096
|
</div>
|
|
13667
15097
|
</div>`;
|
|
13668
|
-
return
|
|
15098
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
|
|
13669
15099
|
title: "Tenants - SonicJS",
|
|
13670
15100
|
pageTitle: "Tenants",
|
|
13671
15101
|
currentPath: "/admin/tenants",
|
|
@@ -13676,7 +15106,7 @@ function renderTenantsInactive(data) {
|
|
|
13676
15106
|
}
|
|
13677
15107
|
|
|
13678
15108
|
// src/plugins/core-plugins/multi-tenant-plugin/templates/tenant-form.template.ts
|
|
13679
|
-
|
|
15109
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
13680
15110
|
function fieldErrors(errors, field) {
|
|
13681
15111
|
const list = errors?.[field];
|
|
13682
15112
|
if (!list || list.length === 0) return "";
|
|
@@ -13744,7 +15174,7 @@ function renderTenantForm(data) {
|
|
|
13744
15174
|
</form>
|
|
13745
15175
|
</div>
|
|
13746
15176
|
</div>`;
|
|
13747
|
-
return
|
|
15177
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
|
|
13748
15178
|
title: `${data.isEdit ? "Edit Tenant" : "New Tenant"} - SonicJS`,
|
|
13749
15179
|
pageTitle: data.isEdit ? "Edit Tenant" : "New Tenant",
|
|
13750
15180
|
currentPath: "/admin/tenants",
|
|
@@ -13755,9 +15185,9 @@ function renderTenantForm(data) {
|
|
|
13755
15185
|
}
|
|
13756
15186
|
|
|
13757
15187
|
// src/plugins/core-plugins/multi-tenant-plugin/templates/tenant-members.template.ts
|
|
13758
|
-
|
|
15188
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
13759
15189
|
function roleOptions(selected) {
|
|
13760
|
-
return
|
|
15190
|
+
return chunkI767LVN7_cjs.VALID_MEMBER_ROLES.map(
|
|
13761
15191
|
(r) => `<option value="${r}" ${r === selected ? "selected" : ""}>${r}</option>`
|
|
13762
15192
|
).join("");
|
|
13763
15193
|
}
|
|
@@ -13819,7 +15249,7 @@ function renderInvitations(slug, invitations) {
|
|
|
13819
15249
|
<div>
|
|
13820
15250
|
<label for="invite-role" class="mb-1 block text-xs font-medium text-zinc-500 dark:text-zinc-400">Role</label>
|
|
13821
15251
|
<select id="invite-role" name="role" class="rounded-lg border border-zinc-950/10 bg-white px-2 py-2 text-sm text-zinc-950 dark:border-white/10 dark:bg-zinc-800 dark:text-white">
|
|
13822
|
-
${
|
|
15252
|
+
${chunkI767LVN7_cjs.VALID_MEMBER_ROLES.map((r) => `<option value="${r}" ${r === "viewer" ? "selected" : ""}>${r}</option>`).join("")}
|
|
13823
15253
|
</select>
|
|
13824
15254
|
</div>
|
|
13825
15255
|
<button type="submit" data-send-invite class="rounded-lg bg-zinc-950 px-3.5 py-2 text-sm font-semibold text-white hover:bg-zinc-800 dark:bg-white dark:text-zinc-950 dark:hover:bg-zinc-200">Invite</button>
|
|
@@ -13902,7 +15332,7 @@ function renderTenantMembers(data) {
|
|
|
13902
15332
|
|
|
13903
15333
|
${renderInvitations(data.slug, data.invitations)}
|
|
13904
15334
|
</div>`;
|
|
13905
|
-
return
|
|
15335
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
|
|
13906
15336
|
title: `Members - ${data.tenantName} - SonicJS`,
|
|
13907
15337
|
pageTitle: "Tenant Members",
|
|
13908
15338
|
currentPath: "/admin/tenants",
|
|
@@ -13913,9 +15343,9 @@ function renderTenantMembers(data) {
|
|
|
13913
15343
|
}
|
|
13914
15344
|
|
|
13915
15345
|
// src/plugins/core-plugins/multi-tenant-plugin/templates/user-memberships.template.ts
|
|
13916
|
-
|
|
15346
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
13917
15347
|
function roleOptions2(selected) {
|
|
13918
|
-
return
|
|
15348
|
+
return chunkI767LVN7_cjs.VALID_MEMBER_ROLES.map(
|
|
13919
15349
|
(r) => `<option value="${r}" ${r === selected ? "selected" : ""}>${r}</option>`
|
|
13920
15350
|
).join("");
|
|
13921
15351
|
}
|
|
@@ -13988,7 +15418,7 @@ function renderUserMemberships(data) {
|
|
|
13988
15418
|
</table>
|
|
13989
15419
|
</div>
|
|
13990
15420
|
</div>`;
|
|
13991
|
-
return
|
|
15421
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
|
|
13992
15422
|
title: `Tenant memberships - ${data.userEmail} - SonicJS`,
|
|
13993
15423
|
pageTitle: "Tenant memberships",
|
|
13994
15424
|
currentPath: "/admin/users",
|
|
@@ -13999,7 +15429,7 @@ function renderUserMemberships(data) {
|
|
|
13999
15429
|
}
|
|
14000
15430
|
|
|
14001
15431
|
// src/plugins/core-plugins/multi-tenant-plugin/templates/role-usage.template.ts
|
|
14002
|
-
|
|
15432
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
14003
15433
|
function renderRoleUsage(data) {
|
|
14004
15434
|
const role = chunkMNWKYY5E_cjs.escapeHtml(data.roleName);
|
|
14005
15435
|
const rows = data.assignments.length ? data.assignments.map((a) => `
|
|
@@ -14034,7 +15464,7 @@ function renderRoleUsage(data) {
|
|
|
14034
15464
|
</table>
|
|
14035
15465
|
</div>
|
|
14036
15466
|
</div>`;
|
|
14037
|
-
return
|
|
15467
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
|
|
14038
15468
|
title: `Role usage - ${data.roleName} - SonicJS`,
|
|
14039
15469
|
pageTitle: "Role usage",
|
|
14040
15470
|
currentPath: "/admin/tenants",
|
|
@@ -14077,7 +15507,7 @@ function zodToFieldErrors(error) {
|
|
|
14077
15507
|
}
|
|
14078
15508
|
async function isMultiTenantActive(db) {
|
|
14079
15509
|
try {
|
|
14080
|
-
const plugin2 = await new
|
|
15510
|
+
const plugin2 = await new chunkQCJHCSOK_cjs.PluginService(db).getPlugin(chunkQCJHCSOK_cjs.MULTI_TENANT_PLUGIN_ID);
|
|
14081
15511
|
return plugin2?.status === "active";
|
|
14082
15512
|
} catch {
|
|
14083
15513
|
return false;
|
|
@@ -14085,7 +15515,7 @@ async function isMultiTenantActive(db) {
|
|
|
14085
15515
|
}
|
|
14086
15516
|
function createTenantAdminRoutes() {
|
|
14087
15517
|
const routes2 = new hono.Hono();
|
|
14088
|
-
routes2.use("*",
|
|
15518
|
+
routes2.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
14089
15519
|
routes2.use("*", async (c, next) => {
|
|
14090
15520
|
const user = c.get("user");
|
|
14091
15521
|
if (user?.role !== "admin") {
|
|
@@ -14099,7 +15529,7 @@ function createTenantAdminRoutes() {
|
|
|
14099
15529
|
const form = await c.req.formData();
|
|
14100
15530
|
const slug = String(form.get("tenant") ?? "").trim().toLowerCase();
|
|
14101
15531
|
const redirect = String(form.get("redirect") ?? "");
|
|
14102
|
-
const svc = new
|
|
15532
|
+
const svc = new chunkI767LVN7_cjs.TenantService(db);
|
|
14103
15533
|
const tenant = await svc.getTenantBySlug(slug);
|
|
14104
15534
|
if (!tenant || tenant.status !== "active") {
|
|
14105
15535
|
return c.json({ error: "Unknown or inactive tenant" }, 400);
|
|
@@ -14109,7 +15539,7 @@ function createTenantAdminRoutes() {
|
|
|
14109
15539
|
if (!user.isSuperAdmin && !await svc.isMember(user.userId, slug)) {
|
|
14110
15540
|
return c.json({ error: "You are not a member of this tenant" }, 403);
|
|
14111
15541
|
}
|
|
14112
|
-
cookie.setCookie(c,
|
|
15542
|
+
cookie.setCookie(c, chunkQCJHCSOK_cjs.TENANT_COOKIE, slug, {
|
|
14113
15543
|
path: "/",
|
|
14114
15544
|
httpOnly: true,
|
|
14115
15545
|
sameSite: "Lax",
|
|
@@ -14126,7 +15556,7 @@ function createTenantAdminRoutes() {
|
|
|
14126
15556
|
if (!user) return c.redirect("/auth/login");
|
|
14127
15557
|
const token = c.req.query("token") ?? "";
|
|
14128
15558
|
try {
|
|
14129
|
-
const { slug } = await new
|
|
15559
|
+
const { slug } = await new chunkI767LVN7_cjs.TenantService(db).acceptInvitation(token, user.userId, user.email);
|
|
14130
15560
|
return c.redirect(`/admin/tenants/${slug}/members?message=Invitation accepted`);
|
|
14131
15561
|
} catch (error) {
|
|
14132
15562
|
const message = error instanceof Error ? error.message : "Failed to accept invitation";
|
|
@@ -14154,7 +15584,7 @@ function createTenantAdminRoutes() {
|
|
|
14154
15584
|
const userId = c.req.param("userId");
|
|
14155
15585
|
const target = await db.prepare("SELECT id, email FROM auth_user WHERE id = ?").bind(userId).first();
|
|
14156
15586
|
if (!target?.id) return c.redirect("/admin/users?message=User not found&type=error");
|
|
14157
|
-
const svc = new
|
|
15587
|
+
const svc = new chunkI767LVN7_cjs.TenantService(db);
|
|
14158
15588
|
const [memberships, allTenants] = await Promise.all([svc.listUserMemberships(userId), svc.listTenants()]);
|
|
14159
15589
|
const memberSlugs = new Set(memberships.map((m) => m.slug));
|
|
14160
15590
|
const availableTenants = allTenants.filter((t) => t.status === "active" && !memberSlugs.has(t.slug)).map((t) => ({ slug: t.slug, name: t.name }));
|
|
@@ -14179,10 +15609,10 @@ function createTenantAdminRoutes() {
|
|
|
14179
15609
|
const slug = String(form.get("slug") ?? "").trim().toLowerCase();
|
|
14180
15610
|
const role = String(form.get("role") ?? "viewer");
|
|
14181
15611
|
const redirectTo = String(form.get("_redirect") ?? "") || `/admin/tenants/users/${userId}`;
|
|
14182
|
-
if (!
|
|
15612
|
+
if (!chunkI767LVN7_cjs.isValidMemberRole(role)) throw new Error(`Invalid role '${role}'`);
|
|
14183
15613
|
const target = await db.prepare("SELECT email FROM auth_user WHERE id = ?").bind(userId).first();
|
|
14184
15614
|
if (!target) throw new Error("User not found");
|
|
14185
|
-
const svc = new
|
|
15615
|
+
const svc = new chunkI767LVN7_cjs.TenantService(db);
|
|
14186
15616
|
if (!await svc.getTenantBySlug(slug)) throw new Error("Tenant not found");
|
|
14187
15617
|
if (await svc.isMember(userId, slug)) throw new Error(`Already a member of '${slug}'`);
|
|
14188
15618
|
await svc.addMember(slug, userId, role, target.email ?? null);
|
|
@@ -14201,7 +15631,7 @@ function createTenantAdminRoutes() {
|
|
|
14201
15631
|
const form = await c.req.formData();
|
|
14202
15632
|
const role = String(form.get("role") ?? "");
|
|
14203
15633
|
const redirectTo = String(form.get("_redirect") ?? "") || `/admin/tenants/users/${userId}`;
|
|
14204
|
-
await new
|
|
15634
|
+
await new chunkI767LVN7_cjs.TenantService(db).setMemberRole(slug, userId, role);
|
|
14205
15635
|
return c.redirect(`${redirectTo}?message=Role updated`);
|
|
14206
15636
|
} catch (error) {
|
|
14207
15637
|
const message = error instanceof Error ? error.message : "Failed to update role";
|
|
@@ -14216,7 +15646,7 @@ function createTenantAdminRoutes() {
|
|
|
14216
15646
|
try {
|
|
14217
15647
|
const form = await c.req.formData();
|
|
14218
15648
|
const redirectTo = String(form.get("_redirect") ?? "") || `/admin/tenants/users/${userId}`;
|
|
14219
|
-
await new
|
|
15649
|
+
await new chunkI767LVN7_cjs.TenantService(db).removeMember(slug, userId);
|
|
14220
15650
|
return c.redirect(`${redirectTo}?message=Removed from ${encodeURIComponent(slug)}`);
|
|
14221
15651
|
} catch (error) {
|
|
14222
15652
|
const message = error instanceof Error ? error.message : "Failed to remove membership";
|
|
@@ -14231,7 +15661,7 @@ function createTenantAdminRoutes() {
|
|
|
14231
15661
|
return c.html(renderTenantsInactive({ user: userShape(cur), version }));
|
|
14232
15662
|
}
|
|
14233
15663
|
const roleName = c.req.param("roleName");
|
|
14234
|
-
const assignments = await new
|
|
15664
|
+
const assignments = await new chunkI767LVN7_cjs.TenantService(db).listAssignmentsByRole(roleName);
|
|
14235
15665
|
return c.html(renderRoleUsage({ roleName, assignments, user: userShape(cur), version }));
|
|
14236
15666
|
});
|
|
14237
15667
|
routes2.get("/", async (c) => {
|
|
@@ -14241,7 +15671,7 @@ function createTenantAdminRoutes() {
|
|
|
14241
15671
|
if (!await isMultiTenantActive(db)) {
|
|
14242
15672
|
return c.html(renderTenantsInactive({ user: userShape(user), version }));
|
|
14243
15673
|
}
|
|
14244
|
-
const svc = new
|
|
15674
|
+
const svc = new chunkI767LVN7_cjs.TenantService(db);
|
|
14245
15675
|
await svc.ensureDefaultTenant();
|
|
14246
15676
|
const tenants = await svc.listTenants();
|
|
14247
15677
|
const [docRes, memberRes] = await db.batch([
|
|
@@ -14280,7 +15710,7 @@ function createTenantAdminRoutes() {
|
|
|
14280
15710
|
formEntries = Object.fromEntries(form.entries());
|
|
14281
15711
|
const validated = tenantFormSchema.parse(formEntries);
|
|
14282
15712
|
if (!validated.slug) throw new zod.z.ZodError([{ code: "custom", message: "Slug is required", path: ["slug"] }]);
|
|
14283
|
-
const svc = new
|
|
15713
|
+
const svc = new chunkI767LVN7_cjs.TenantService(db);
|
|
14284
15714
|
await svc.createTenant({
|
|
14285
15715
|
name: validated.name,
|
|
14286
15716
|
slug: validated.slug,
|
|
@@ -14305,7 +15735,7 @@ function createTenantAdminRoutes() {
|
|
|
14305
15735
|
if (!await isMultiTenantActive(db)) {
|
|
14306
15736
|
return c.html(renderTenantsInactive({ user: userShape(user), version }));
|
|
14307
15737
|
}
|
|
14308
|
-
const tenant = await new
|
|
15738
|
+
const tenant = await new chunkI767LVN7_cjs.TenantService(db).getTenantBySlug(c.req.param("slug"));
|
|
14309
15739
|
if (!tenant) return c.redirect("/admin/tenants?message=Tenant not found&type=error");
|
|
14310
15740
|
return c.html(renderTenantForm({ tenant, isEdit: true, user: userShape(user), version }));
|
|
14311
15741
|
});
|
|
@@ -14315,7 +15745,7 @@ function createTenantAdminRoutes() {
|
|
|
14315
15745
|
const version = c.get("appVersion");
|
|
14316
15746
|
const slug = c.req.param("slug");
|
|
14317
15747
|
if (!await isMultiTenantActive(db)) return c.json({ error: "Multi-tenant plugin is not active" }, 403);
|
|
14318
|
-
const svc = new
|
|
15748
|
+
const svc = new chunkI767LVN7_cjs.TenantService(db);
|
|
14319
15749
|
try {
|
|
14320
15750
|
const form = await c.req.formData();
|
|
14321
15751
|
const validated = tenantFormSchema.parse(Object.fromEntries(form.entries()));
|
|
@@ -14340,7 +15770,7 @@ function createTenantAdminRoutes() {
|
|
|
14340
15770
|
const slug = c.req.param("slug");
|
|
14341
15771
|
if (!await isMultiTenantActive(db)) return c.json({ error: "Multi-tenant plugin is not active" }, 403);
|
|
14342
15772
|
try {
|
|
14343
|
-
await new
|
|
15773
|
+
await new chunkI767LVN7_cjs.TenantService(db).deleteTenant(slug);
|
|
14344
15774
|
return c.redirect("/admin/tenants?message=Tenant deleted successfully");
|
|
14345
15775
|
} catch (error) {
|
|
14346
15776
|
const message = error instanceof Error ? error.message : "Failed to delete tenant";
|
|
@@ -14355,7 +15785,7 @@ function createTenantAdminRoutes() {
|
|
|
14355
15785
|
return c.html(renderTenantsInactive({ user: userShape(user), version }));
|
|
14356
15786
|
}
|
|
14357
15787
|
const slug = c.req.param("slug");
|
|
14358
|
-
const svc = new
|
|
15788
|
+
const svc = new chunkI767LVN7_cjs.TenantService(db);
|
|
14359
15789
|
const tenant = await svc.getTenantBySlug(slug);
|
|
14360
15790
|
if (!tenant) return c.redirect("/admin/tenants?message=Tenant not found&type=error");
|
|
14361
15791
|
const [members, invitations] = await Promise.all([svc.listMembers(slug), svc.listInvitations(slug)]);
|
|
@@ -14381,7 +15811,7 @@ function createTenantAdminRoutes() {
|
|
|
14381
15811
|
const form = await c.req.formData();
|
|
14382
15812
|
const email = String(form.get("email") ?? "");
|
|
14383
15813
|
const role = String(form.get("role") ?? "viewer");
|
|
14384
|
-
await new
|
|
15814
|
+
await new chunkI767LVN7_cjs.TenantService(db).addMemberByEmail(slug, email, role);
|
|
14385
15815
|
return c.redirect(`/admin/tenants/${slug}/members?message=Member added`);
|
|
14386
15816
|
} catch (error) {
|
|
14387
15817
|
const message = error instanceof Error ? error.message : "Failed to add member";
|
|
@@ -14396,7 +15826,7 @@ function createTenantAdminRoutes() {
|
|
|
14396
15826
|
try {
|
|
14397
15827
|
const form = await c.req.formData();
|
|
14398
15828
|
const role = String(form.get("role") ?? "");
|
|
14399
|
-
await new
|
|
15829
|
+
await new chunkI767LVN7_cjs.TenantService(db).setMemberRole(slug, userId, role);
|
|
14400
15830
|
return c.redirect(`/admin/tenants/${slug}/members?message=Role updated`);
|
|
14401
15831
|
} catch (error) {
|
|
14402
15832
|
const message = error instanceof Error ? error.message : "Failed to update role";
|
|
@@ -14409,7 +15839,7 @@ function createTenantAdminRoutes() {
|
|
|
14409
15839
|
const userId = c.req.param("userId");
|
|
14410
15840
|
if (!await isMultiTenantActive(db)) return c.json({ error: "Multi-tenant plugin is not active" }, 403);
|
|
14411
15841
|
try {
|
|
14412
|
-
await new
|
|
15842
|
+
await new chunkI767LVN7_cjs.TenantService(db).removeMember(slug, userId);
|
|
14413
15843
|
return c.redirect(`/admin/tenants/${slug}/members?message=Member removed`);
|
|
14414
15844
|
} catch (error) {
|
|
14415
15845
|
const message = error instanceof Error ? error.message : "Failed to remove member";
|
|
@@ -14425,12 +15855,12 @@ function createTenantAdminRoutes() {
|
|
|
14425
15855
|
const form = await c.req.formData();
|
|
14426
15856
|
const email = String(form.get("email") ?? "");
|
|
14427
15857
|
const role = String(form.get("role") ?? "viewer");
|
|
14428
|
-
const token = await new
|
|
15858
|
+
const token = await new chunkI767LVN7_cjs.TenantService(db).createInvitation(slug, email, role, user?.userId ?? null);
|
|
14429
15859
|
const origin = c.req.header("origin") || new URL(c.req.url).origin;
|
|
14430
15860
|
const acceptUrl = `${origin}/join/invite?token=${encodeURIComponent(token)}`;
|
|
14431
15861
|
let note;
|
|
14432
15862
|
let noteType = "";
|
|
14433
|
-
const svc2 =
|
|
15863
|
+
const svc2 = chunkI767LVN7_cjs.hasEmailService() ? chunkI767LVN7_cjs.getEmailService() : null;
|
|
14434
15864
|
const hasRealProvider = !!svc2 && svc2.getProviderName() !== "console";
|
|
14435
15865
|
if (hasRealProvider) {
|
|
14436
15866
|
const result = await svc2.send({
|
|
@@ -14471,7 +15901,7 @@ function createTenantAdminRoutes() {
|
|
|
14471
15901
|
WHERE i.id = ? AND t.slug = ? AND i.status = 'pending'`
|
|
14472
15902
|
).bind(id, slug).first();
|
|
14473
15903
|
if (!inv) throw new Error("Invitation not found or already used");
|
|
14474
|
-
const svc2 =
|
|
15904
|
+
const svc2 = chunkI767LVN7_cjs.hasEmailService() ? chunkI767LVN7_cjs.getEmailService() : null;
|
|
14475
15905
|
const hasRealProvider = !!svc2 && svc2.getProviderName() !== "console";
|
|
14476
15906
|
if (!hasRealProvider) throw new Error("No email plugin active");
|
|
14477
15907
|
const origin = c.req.header("origin") || new URL(c.req.url).origin;
|
|
@@ -14496,7 +15926,7 @@ function createTenantAdminRoutes() {
|
|
|
14496
15926
|
const id = c.req.param("id");
|
|
14497
15927
|
if (!await isMultiTenantActive(db)) return c.json({ error: "Multi-tenant plugin is not active" }, 403);
|
|
14498
15928
|
try {
|
|
14499
|
-
await new
|
|
15929
|
+
await new chunkI767LVN7_cjs.TenantService(db).revokeInvitation(slug, id);
|
|
14500
15930
|
return c.redirect(`/admin/tenants/${slug}/members?message=Invitation revoked`);
|
|
14501
15931
|
} catch (error) {
|
|
14502
15932
|
const message = error instanceof Error ? error.message : "Failed to revoke invitation";
|
|
@@ -14726,7 +16156,7 @@ function createJoinRoutes() {
|
|
|
14726
16156
|
if (existing) return rerender("An account with this email already exists. Please sign in instead.");
|
|
14727
16157
|
try {
|
|
14728
16158
|
const userId = crypto.randomUUID();
|
|
14729
|
-
const passwordHash = await
|
|
16159
|
+
const passwordHash = await chunk37V3RET3_cjs.AuthManager.hashPassword(password);
|
|
14730
16160
|
const now = Date.now();
|
|
14731
16161
|
const nowSec = Math.floor(now / 1e3);
|
|
14732
16162
|
await db.batch([
|
|
@@ -14739,7 +16169,7 @@ function createJoinRoutes() {
|
|
|
14739
16169
|
VALUES (?, ?, ?, 'credential', ?, ?, ?)`
|
|
14740
16170
|
).bind(`cred-${userId}`, userId, userId, passwordHash, nowSec, nowSec)
|
|
14741
16171
|
]);
|
|
14742
|
-
await new
|
|
16172
|
+
await new chunkI767LVN7_cjs.TenantService(db).acceptInvitation(token, userId, inv.email);
|
|
14743
16173
|
const auth = chunkGMMCCIQO_cjs.createAuth(c.env);
|
|
14744
16174
|
const origin = new URL(c.req.url).origin;
|
|
14745
16175
|
const baReq = new Request(`${origin}/auth/sign-in/email`, {
|
|
@@ -14807,7 +16237,7 @@ function createJoinRoutes() {
|
|
|
14807
16237
|
const baBody = await baRes.json();
|
|
14808
16238
|
const userId = baBody?.user?.id;
|
|
14809
16239
|
if (!userId) return rerender("Sign-in succeeded but could not read user ID.");
|
|
14810
|
-
await new
|
|
16240
|
+
await new chunkI767LVN7_cjs.TenantService(db).acceptInvitation(token, userId, inv.email);
|
|
14811
16241
|
const headers = new Headers({ Location: "/admin?message=Welcome! You have joined " + encodeURIComponent(inv.tenantName) });
|
|
14812
16242
|
copyBaCookies(baRes, headers);
|
|
14813
16243
|
return new Response(null, { status: 302, headers });
|
|
@@ -14821,7 +16251,7 @@ function createJoinRoutes() {
|
|
|
14821
16251
|
|
|
14822
16252
|
// src/plugins/core-plugins/multi-tenant-plugin/index.ts
|
|
14823
16253
|
var TENANT_ICON = `<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.75 21h16.5M4.5 3h15M5.25 3v18m13.5-18v18M9 6.75h1.5m-1.5 3h1.5m-1.5 3h1.5m3-6H15m-1.5 3H15m-1.5 3H15M9 21v-3.375c0-.621.504-1.125 1.125-1.125h3.75c.621 0 1.125.504 1.125 1.125V21"/></svg>`;
|
|
14824
|
-
var multiTenantPlugin =
|
|
16254
|
+
var multiTenantPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
14825
16255
|
id: manifest_default2.id,
|
|
14826
16256
|
version: "1.0.0",
|
|
14827
16257
|
name: manifest_default2.name,
|
|
@@ -14836,30 +16266,30 @@ var multiTenantPlugin = chunkEUJAEB6W_cjs.definePlugin({
|
|
|
14836
16266
|
{ label: "Tenants", path: "/admin/tenants", icon: TENANT_ICON, order: 80 }
|
|
14837
16267
|
],
|
|
14838
16268
|
activate: async () => {
|
|
14839
|
-
|
|
16269
|
+
chunkQCJHCSOK_cjs.invalidateTenantCache();
|
|
14840
16270
|
console.info("\u2705 Multi-Tenant plugin activated");
|
|
14841
16271
|
},
|
|
14842
16272
|
deactivate: async () => {
|
|
14843
|
-
|
|
16273
|
+
chunkQCJHCSOK_cjs.invalidateTenantCache();
|
|
14844
16274
|
console.info("\u274C Multi-Tenant plugin deactivated");
|
|
14845
16275
|
}
|
|
14846
16276
|
});
|
|
14847
16277
|
var routes = new hono.Hono();
|
|
14848
|
-
routes.use("*",
|
|
14849
|
-
routes.use("*",
|
|
16278
|
+
routes.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
16279
|
+
routes.use("*", chunk37V3RET3_cjs.requireRole(["admin", "editor"]));
|
|
14850
16280
|
routes.get("/:rootId", async (c) => {
|
|
14851
16281
|
const { rootId } = c.req.param();
|
|
14852
16282
|
const db = c.env.DB;
|
|
14853
|
-
const scope = await
|
|
16283
|
+
const scope = await chunkI767LVN7_cjs.resolveDocScope(c, db, { rootId });
|
|
14854
16284
|
if (!scope) {
|
|
14855
16285
|
return c.html('<p class="text-zinc-500 dark:text-zinc-400 p-4">Document not found.</p>', 404);
|
|
14856
16286
|
}
|
|
14857
16287
|
if (!scope.docType?.settings?.versioning) {
|
|
14858
16288
|
return c.html('<p class="text-zinc-500 dark:text-zinc-400 p-4">Versioning not enabled for this type.</p>', 404);
|
|
14859
16289
|
}
|
|
14860
|
-
const denied = await
|
|
16290
|
+
const denied = await chunkI767LVN7_cjs.denyIfNotAllowed(c, db, rootId, "read", scope.docType?.settings, scope.tenantId);
|
|
14861
16291
|
if (denied) return denied;
|
|
14862
|
-
const repo = new
|
|
16292
|
+
const repo = new chunkI767LVN7_cjs.DocumentRepository(db, scope.tenantId);
|
|
14863
16293
|
const versions = await repo.getVersionHistory(rootId);
|
|
14864
16294
|
const safeRootIdAttr = chunkMNWKYY5E_cjs.escapeHtml(rootId);
|
|
14865
16295
|
const rows = versions.map((v) => {
|
|
@@ -14952,14 +16382,14 @@ routes.post("/:rootId/restore/:versionNumber", async (c) => {
|
|
|
14952
16382
|
const { rootId, versionNumber } = c.req.param();
|
|
14953
16383
|
const db = c.env.DB;
|
|
14954
16384
|
const user = c.get("user");
|
|
14955
|
-
const scope = await
|
|
16385
|
+
const scope = await chunkI767LVN7_cjs.resolveDocScope(c, db, { rootId });
|
|
14956
16386
|
if (!scope) {
|
|
14957
16387
|
return c.json({ error: "Document not found" }, 404);
|
|
14958
16388
|
}
|
|
14959
16389
|
if (!scope.docType?.settings?.versioning) {
|
|
14960
16390
|
return c.json({ error: "Versioning not enabled for this type" }, 404);
|
|
14961
16391
|
}
|
|
14962
|
-
const denied = await
|
|
16392
|
+
const denied = await chunkI767LVN7_cjs.denyIfNotAllowed(c, db, rootId, "update", scope.docType?.settings, scope.tenantId);
|
|
14963
16393
|
if (denied) return denied;
|
|
14964
16394
|
const row = await db.prepare("SELECT * FROM documents WHERE root_id = ? AND tenant_id = ? AND version_number = ? LIMIT 1").bind(rootId, scope.tenantId, Number(versionNumber)).first();
|
|
14965
16395
|
if (!row) {
|
|
@@ -14982,7 +16412,7 @@ routes.post("/:rootId/restore/:versionNumber", async (c) => {
|
|
|
14982
16412
|
var routes_default = routes;
|
|
14983
16413
|
|
|
14984
16414
|
// src/plugins/core-plugins/versioning-plugin/index.ts
|
|
14985
|
-
var versioningPlugin =
|
|
16415
|
+
var versioningPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
14986
16416
|
id: "versioning",
|
|
14987
16417
|
version: "1.0.0",
|
|
14988
16418
|
name: "Versioning",
|
|
@@ -15059,8 +16489,8 @@ function createMagicLinkAuthPlugin() {
|
|
|
15059
16489
|
const baseUrl = new URL(c.req.url).origin;
|
|
15060
16490
|
const magicLink = `${baseUrl}/auth/magic-link/verify?token=${token}`;
|
|
15061
16491
|
try {
|
|
15062
|
-
if (
|
|
15063
|
-
await
|
|
16492
|
+
if (chunkI767LVN7_cjs.hasEmailService()) {
|
|
16493
|
+
await chunkI767LVN7_cjs.getEmailService().send({
|
|
15064
16494
|
to: normalizedEmail,
|
|
15065
16495
|
subject: "Your Magic Link to Sign In",
|
|
15066
16496
|
flow: "magic-link",
|
|
@@ -15137,19 +16567,19 @@ function createMagicLinkAuthPlugin() {
|
|
|
15137
16567
|
SET used = 1, used_at = ?
|
|
15138
16568
|
WHERE id = ?
|
|
15139
16569
|
`).bind(Date.now(), magicLink.id).run();
|
|
15140
|
-
const tokenTtl = await
|
|
15141
|
-
const jwtToken = await
|
|
16570
|
+
const tokenTtl = await chunk37V3RET3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
16571
|
+
const jwtToken = await chunk37V3RET3_cjs.AuthManager.generateToken(
|
|
15142
16572
|
user.id,
|
|
15143
16573
|
user.email,
|
|
15144
16574
|
user.role,
|
|
15145
16575
|
c.env.JWT_SECRET,
|
|
15146
16576
|
tokenTtl
|
|
15147
16577
|
);
|
|
15148
|
-
|
|
16578
|
+
chunk37V3RET3_cjs.AuthManager.setAuthCookie(c, jwtToken, { maxAge: tokenTtl });
|
|
15149
16579
|
await db.prepare(`
|
|
15150
16580
|
UPDATE auth_user SET last_login_at = ? WHERE id = ?
|
|
15151
16581
|
`).bind(Date.now(), user.id).run();
|
|
15152
|
-
|
|
16582
|
+
chunkI767LVN7_cjs.dispatchHookEvent(
|
|
15153
16583
|
c,
|
|
15154
16584
|
"auth:magic-link:consumed",
|
|
15155
16585
|
{ user: { id: user.id, email: user.email, role: user.role } },
|
|
@@ -15634,7 +17064,7 @@ async function warmCollections(db) {
|
|
|
15634
17064
|
const collectionCache = chunkYA3TJ65D_cjs.getCacheService(config);
|
|
15635
17065
|
let count = 0;
|
|
15636
17066
|
try {
|
|
15637
|
-
const results =
|
|
17067
|
+
const results = chunkQCJHCSOK_cjs.getCollectionRegistry().listActive().map(chunkQCJHCSOK_cjs.collectionRecordToRow);
|
|
15638
17068
|
for (const collection of results) {
|
|
15639
17069
|
const key = collectionCache.generateKey("item", collection.id);
|
|
15640
17070
|
await collectionCache.set(key, collection);
|
|
@@ -15701,7 +17131,7 @@ async function warmNamespace(namespace, entries) {
|
|
|
15701
17131
|
}
|
|
15702
17132
|
|
|
15703
17133
|
// src/templates/pages/admin-cache.template.ts
|
|
15704
|
-
|
|
17134
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
15705
17135
|
function renderCacheDashboard(data) {
|
|
15706
17136
|
const pageContent = `
|
|
15707
17137
|
<div class="space-y-6">
|
|
@@ -15905,7 +17335,7 @@ function renderCacheDashboard(data) {
|
|
|
15905
17335
|
</script>
|
|
15906
17336
|
|
|
15907
17337
|
<!-- Confirmation Dialogs -->
|
|
15908
|
-
${
|
|
17338
|
+
${chunkI767LVN7_cjs.renderConfirmationDialog({
|
|
15909
17339
|
id: "clear-all-cache-confirm",
|
|
15910
17340
|
title: "Clear All Cache",
|
|
15911
17341
|
message: "Are you sure you want to clear all cache entries? This cannot be undone.",
|
|
@@ -15916,7 +17346,7 @@ function renderCacheDashboard(data) {
|
|
|
15916
17346
|
onConfirm: "performClearAllCaches()"
|
|
15917
17347
|
})}
|
|
15918
17348
|
|
|
15919
|
-
${
|
|
17349
|
+
${chunkI767LVN7_cjs.renderConfirmationDialog({
|
|
15920
17350
|
id: "clear-namespace-cache-confirm",
|
|
15921
17351
|
title: "Clear Namespace Cache",
|
|
15922
17352
|
message: "Clear cache for this namespace?",
|
|
@@ -15927,7 +17357,7 @@ function renderCacheDashboard(data) {
|
|
|
15927
17357
|
onConfirm: "performClearNamespaceCache()"
|
|
15928
17358
|
})}
|
|
15929
17359
|
|
|
15930
|
-
${
|
|
17360
|
+
${chunkI767LVN7_cjs.getConfirmationDialogScript()}
|
|
15931
17361
|
`;
|
|
15932
17362
|
const layoutData = {
|
|
15933
17363
|
title: "Cache System",
|
|
@@ -15937,7 +17367,7 @@ function renderCacheDashboard(data) {
|
|
|
15937
17367
|
version: data.version,
|
|
15938
17368
|
content: pageContent
|
|
15939
17369
|
};
|
|
15940
|
-
return
|
|
17370
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
15941
17371
|
}
|
|
15942
17372
|
function renderCollectionSettingsTab(collections) {
|
|
15943
17373
|
if (collections.length === 0) {
|
|
@@ -16193,7 +17623,7 @@ app.get("/", async (c) => {
|
|
|
16193
17623
|
const totalRequests = totalHits + totalMisses;
|
|
16194
17624
|
const overallHitRate = totalRequests > 0 ? totalHits / totalRequests * 100 : 0;
|
|
16195
17625
|
const DEFAULT_TTL = chunkYA3TJ65D_cjs.CACHE_CONFIGS.api?.ttl ?? 300;
|
|
16196
|
-
const collections =
|
|
17626
|
+
const collections = chunkQCJHCSOK_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => {
|
|
16197
17627
|
const cacheOverride = r.cache;
|
|
16198
17628
|
const cacheEnabled = cacheOverride?.enabled !== false;
|
|
16199
17629
|
const hasCustomTtl = typeof cacheOverride?.ttl === "number";
|
|
@@ -16730,9 +18160,9 @@ var faviconSvg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
|
16730
18160
|
// src/app.ts
|
|
16731
18161
|
function createSonicJSApp(config = {}) {
|
|
16732
18162
|
const app2 = new hono.Hono();
|
|
16733
|
-
const appVersion = config.version ||
|
|
18163
|
+
const appVersion = config.version || chunkKKNEYIZJ_cjs.getCoreVersion();
|
|
16734
18164
|
const appName = config.name || "SonicJS AI";
|
|
16735
|
-
const hookSystem = new
|
|
18165
|
+
const hookSystem = new chunkQJUJNTIU_cjs.HookSystemImpl();
|
|
16736
18166
|
chunkJ6JTWD2A_cjs.setHookSystem(hookSystem);
|
|
16737
18167
|
const magicLinkPlugin = createMagicLinkAuthPlugin();
|
|
16738
18168
|
const corePluginsBeforeCatchAll = [
|
|
@@ -16740,7 +18170,7 @@ function createSonicJSApp(config = {}) {
|
|
|
16740
18170
|
apiKeysPlugin,
|
|
16741
18171
|
aiSearchPlugin,
|
|
16742
18172
|
oauthProvidersPlugin,
|
|
16743
|
-
|
|
18173
|
+
chunkI767LVN7_cjs.userProfilesPlugin,
|
|
16744
18174
|
otpLoginPlugin,
|
|
16745
18175
|
analyticsPlugin,
|
|
16746
18176
|
stripePlugin,
|
|
@@ -16750,23 +18180,24 @@ function createSonicJSApp(config = {}) {
|
|
|
16750
18180
|
shortcodesPlugin,
|
|
16751
18181
|
helloWorldPlugin,
|
|
16752
18182
|
multiTenantPlugin,
|
|
16753
|
-
|
|
16754
|
-
versioningPlugin
|
|
18183
|
+
chunkI767LVN7_cjs.lexicalEditorPlugin,
|
|
18184
|
+
versioningPlugin,
|
|
18185
|
+
menuPlugin
|
|
16755
18186
|
];
|
|
16756
18187
|
const corePluginsAfterCatchAll = [emailPluginV3, magicLinkPlugin, emailReconciliationPlugin];
|
|
16757
|
-
const wirePlugins =
|
|
18188
|
+
const wirePlugins = chunkQJUJNTIU_cjs.createPluginWirer(
|
|
16758
18189
|
() => [...corePluginsBeforeCatchAll, ...corePluginsAfterCatchAll, ...config.plugins?.register ?? []],
|
|
16759
18190
|
// The capability-gated `ctx.cap.email` resolves to the app EmailService, which
|
|
16760
18191
|
// is initialized (below) just before wiring on the first request.
|
|
16761
18192
|
() => ({
|
|
16762
18193
|
hooks: hookSystem,
|
|
16763
18194
|
env: firstRequestEnv,
|
|
16764
|
-
providers: { email: () =>
|
|
18195
|
+
providers: { email: () => chunkI767LVN7_cjs.getEmailService() }
|
|
16765
18196
|
})
|
|
16766
18197
|
);
|
|
16767
18198
|
let firstRequestEnv;
|
|
16768
18199
|
const initEmailService = async (env = {}) => {
|
|
16769
|
-
if (
|
|
18200
|
+
if (chunkI767LVN7_cjs.hasEmailService()) return;
|
|
16770
18201
|
let provider;
|
|
16771
18202
|
let defaultFrom = config.email?.from;
|
|
16772
18203
|
let defaultReplyTo;
|
|
@@ -16801,14 +18232,14 @@ function createSonicJSApp(config = {}) {
|
|
|
16801
18232
|
}
|
|
16802
18233
|
}
|
|
16803
18234
|
defaultFrom = defaultFrom || env.DEFAULT_FROM_EMAIL || "noreply@sonicjs.local";
|
|
16804
|
-
|
|
18235
|
+
chunkI767LVN7_cjs.setEmailService(new EmailService({ provider, defaultFrom, defaultReplyTo, db: env.DB }));
|
|
16805
18236
|
};
|
|
16806
18237
|
app2.use("*", async (c, next) => {
|
|
16807
18238
|
c.set("appVersion", appVersion);
|
|
16808
18239
|
await next();
|
|
16809
18240
|
});
|
|
16810
|
-
app2.use("*",
|
|
16811
|
-
app2.use("*",
|
|
18241
|
+
app2.use("*", chunk37V3RET3_cjs.metricsMiddleware());
|
|
18242
|
+
app2.use("*", chunk37V3RET3_cjs.bootstrapMiddleware(config));
|
|
16812
18243
|
const boot = async (env) => {
|
|
16813
18244
|
if (config.plugins?.disableAll) return;
|
|
16814
18245
|
firstRequestEnv = env;
|
|
@@ -16846,8 +18277,8 @@ function createSonicJSApp(config = {}) {
|
|
|
16846
18277
|
allowHeaders: ["Content-Type", "Authorization", "X-API-Key"],
|
|
16847
18278
|
credentials: true
|
|
16848
18279
|
}));
|
|
16849
|
-
app2.use("*",
|
|
16850
|
-
app2.use("*",
|
|
18280
|
+
app2.use("*", chunk37V3RET3_cjs.securityHeadersMiddleware());
|
|
18281
|
+
app2.use("*", chunk37V3RET3_cjs.csrfProtection());
|
|
16851
18282
|
app2.use("*", async (c, next) => {
|
|
16852
18283
|
try {
|
|
16853
18284
|
const reqUrl = new URL(c.req.url);
|
|
@@ -16885,10 +18316,11 @@ function createSonicJSApp(config = {}) {
|
|
|
16885
18316
|
app2.use("*", middleware);
|
|
16886
18317
|
}
|
|
16887
18318
|
}
|
|
16888
|
-
app2.use("*",
|
|
16889
|
-
app2.use("/admin/*",
|
|
16890
|
-
app2.use("/admin/*",
|
|
18319
|
+
app2.use("*", chunkQCJHCSOK_cjs.tenantMiddleware());
|
|
18320
|
+
app2.use("/admin/*", chunk37V3RET3_cjs.requireAuth());
|
|
18321
|
+
app2.use("/admin/*", chunk37V3RET3_cjs.requireRbac("portal", "access"));
|
|
16891
18322
|
app2.use("/admin/*", pluginMenuMiddleware());
|
|
18323
|
+
app2.use("/admin/*", menuMiddleware());
|
|
16892
18324
|
const NAV_LANDING = [
|
|
16893
18325
|
{ path: "/admin/content", perm: "content:read" },
|
|
16894
18326
|
{ path: "/admin/media", perm: "media:read" },
|
|
@@ -16933,43 +18365,43 @@ function createSonicJSApp(config = {}) {
|
|
|
16933
18365
|
});
|
|
16934
18366
|
app2.route("/api/security-audit", apiRoutes2);
|
|
16935
18367
|
app2.route("/admin/plugins/security-audit", adminRoutes3);
|
|
16936
|
-
app2.route("/api/media",
|
|
16937
|
-
app2.route("/api/system",
|
|
16938
|
-
app2.route("/api/documents",
|
|
16939
|
-
app2.route("/api",
|
|
16940
|
-
app2.route("/admin/documents",
|
|
16941
|
-
|
|
16942
|
-
app2.route("/admin/api",
|
|
16943
|
-
app2.route("/admin/collections",
|
|
16944
|
-
app2.route("/admin/settings",
|
|
16945
|
-
app2.route("/admin/api-reference",
|
|
18368
|
+
app2.route("/api/media", chunkI767LVN7_cjs.api_media_default);
|
|
18369
|
+
app2.route("/api/system", chunkI767LVN7_cjs.api_system_default);
|
|
18370
|
+
app2.route("/api/documents", chunkI767LVN7_cjs.apiDocumentsRoutes);
|
|
18371
|
+
app2.route("/api", chunkI767LVN7_cjs.api_default);
|
|
18372
|
+
app2.route("/admin/documents", chunkI767LVN7_cjs.adminDocumentsRoutes);
|
|
18373
|
+
chunkQJUJNTIU_cjs.registerPluginRoutes(app2, [formsPlugin], { source: "core" });
|
|
18374
|
+
app2.route("/admin/api", chunkI767LVN7_cjs.admin_api_default);
|
|
18375
|
+
app2.route("/admin/collections", chunkI767LVN7_cjs.adminCollectionsRoutes);
|
|
18376
|
+
app2.route("/admin/settings", chunkI767LVN7_cjs.adminSettingsRoutes);
|
|
18377
|
+
app2.route("/admin/api-reference", chunkI767LVN7_cjs.router2);
|
|
16946
18378
|
app2.route("/admin/database-tools", createDatabaseToolsAdminRoutes());
|
|
16947
|
-
app2.route("/admin/content",
|
|
16948
|
-
app2.route("/admin/media",
|
|
18379
|
+
app2.route("/admin/content", chunkI767LVN7_cjs.admin_content_default);
|
|
18380
|
+
app2.route("/admin/media", chunkI767LVN7_cjs.adminMediaRoutes);
|
|
16949
18381
|
app2.use("/auth/*", securityAuditMiddleware());
|
|
16950
18382
|
if (!config.plugins?.disableAll) {
|
|
16951
|
-
|
|
18383
|
+
chunkQJUJNTIU_cjs.registerPluginRoutes(app2, corePluginsBeforeCatchAll, { source: "core" });
|
|
16952
18384
|
app2.route("/admin/cache", cache_default.getRoutes());
|
|
16953
18385
|
if (config.plugins?.register && config.plugins.register.length > 0) {
|
|
16954
|
-
|
|
18386
|
+
chunkQJUJNTIU_cjs.registerPluginRoutes(app2, config.plugins.register, { source: "user" });
|
|
16955
18387
|
}
|
|
16956
18388
|
}
|
|
16957
18389
|
app2.route("/api/events", apiRoutes4);
|
|
16958
|
-
app2.route("/admin/dashboard",
|
|
16959
|
-
app2.route("/admin/plugins",
|
|
16960
|
-
app2.route("/admin/logs",
|
|
18390
|
+
app2.route("/admin/dashboard", chunkI767LVN7_cjs.router);
|
|
18391
|
+
app2.route("/admin/plugins", chunkI767LVN7_cjs.adminPluginRoutes);
|
|
18392
|
+
app2.route("/admin/logs", chunkI767LVN7_cjs.adminLogsRoutes);
|
|
16961
18393
|
app2.route("/admin/rbac", adminRbacRoutes);
|
|
16962
|
-
app2.route("/admin",
|
|
16963
|
-
app2.route("/auth",
|
|
18394
|
+
app2.route("/admin", chunkI767LVN7_cjs.userRoutes);
|
|
18395
|
+
app2.route("/auth", chunkI767LVN7_cjs.auth_default);
|
|
16964
18396
|
app2.on(["GET", "POST"], "/auth/*", (c) => {
|
|
16965
18397
|
const reqUrl = new URL(c.req.url);
|
|
16966
18398
|
const requestBaseURL = `${reqUrl.protocol}//${reqUrl.host}`;
|
|
16967
18399
|
const auth = chunkGMMCCIQO_cjs.createAuth(c.env, config.auth?.extendBetterAuth, requestBaseURL);
|
|
16968
18400
|
return auth.handler(c.req.raw);
|
|
16969
18401
|
});
|
|
16970
|
-
app2.route("/",
|
|
18402
|
+
app2.route("/", chunkI767LVN7_cjs.test_cleanup_default);
|
|
16971
18403
|
if (!config.plugins?.disableAll) {
|
|
16972
|
-
|
|
18404
|
+
chunkQJUJNTIU_cjs.registerPluginRoutes(app2, corePluginsAfterCatchAll, { source: "core" });
|
|
16973
18405
|
}
|
|
16974
18406
|
if (!config.plugins?.disableAll) {
|
|
16975
18407
|
const allMountedPlugins = [
|
|
@@ -16979,10 +18411,10 @@ function createSonicJSApp(config = {}) {
|
|
|
16979
18411
|
...config.plugins?.register ?? []
|
|
16980
18412
|
];
|
|
16981
18413
|
const userPlugins = (config.plugins?.register ?? []).filter(
|
|
16982
|
-
(p) => !
|
|
18414
|
+
(p) => !chunkQCJHCSOK_cjs.PLUGIN_REGISTRY[p.id]
|
|
16983
18415
|
);
|
|
16984
|
-
|
|
16985
|
-
|
|
18416
|
+
chunkBP52BFIV_cjs.setPluginMenu(userPlugins.flatMap((p) => p.menu ?? []));
|
|
18417
|
+
chunkBP52BFIV_cjs.setPluginDefinitions(allMountedPlugins);
|
|
16986
18418
|
}
|
|
16987
18419
|
app2.get("/favicon.svg", (c) => {
|
|
16988
18420
|
return new Response(faviconSvg, {
|
|
@@ -19153,7 +20585,7 @@ function renderLayout(title, content2) {
|
|
|
19153
20585
|
}
|
|
19154
20586
|
</style>
|
|
19155
20587
|
`;
|
|
19156
|
-
return
|
|
20588
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
|
|
19157
20589
|
title,
|
|
19158
20590
|
currentPath: "/admin/redirects",
|
|
19159
20591
|
content: customStyles + content2.toString()
|
|
@@ -19518,7 +20950,7 @@ function getFormScripts() {
|
|
|
19518
20950
|
`;
|
|
19519
20951
|
}
|
|
19520
20952
|
function renderLayout2(title, content2) {
|
|
19521
|
-
return
|
|
20953
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
|
|
19522
20954
|
title,
|
|
19523
20955
|
currentPath: "/admin/redirects",
|
|
19524
20956
|
content: content2.toString()
|
|
@@ -20476,7 +21908,7 @@ function createRedirectApiRoutes() {
|
|
|
20476
21908
|
});
|
|
20477
21909
|
return api;
|
|
20478
21910
|
}
|
|
20479
|
-
var redirectPlugin =
|
|
21911
|
+
var redirectPlugin = chunkBP52BFIV_cjs.definePlugin({
|
|
20480
21912
|
id: manifest_default3.id,
|
|
20481
21913
|
version: manifest_default3.version,
|
|
20482
21914
|
name: manifest_default3.name,
|
|
@@ -20494,7 +21926,7 @@ var redirectPlugin = chunkEUJAEB6W_cjs.definePlugin({
|
|
|
20494
21926
|
async onBoot(ctx) {
|
|
20495
21927
|
const db = ctx.env?.DB;
|
|
20496
21928
|
if (!db) return;
|
|
20497
|
-
const registry = new
|
|
21929
|
+
const registry = new chunk37V3RET3_cjs.DocumentTypeRegistry(db);
|
|
20498
21930
|
await registry.register({
|
|
20499
21931
|
id: "redirect",
|
|
20500
21932
|
name: "redirect",
|
|
@@ -20608,93 +22040,920 @@ var site_settings_collection_default = {
|
|
|
20608
22040
|
function createDb(d1$1) {
|
|
20609
22041
|
return d1.drizzle(d1$1, { schema: chunkYP7GW2G5_cjs.schema_exports });
|
|
20610
22042
|
}
|
|
22043
|
+
var mcpTypeConfigSchema = zod.z.object({
|
|
22044
|
+
read: zod.z.boolean().default(true),
|
|
22045
|
+
write: zod.z.boolean().default(true)
|
|
22046
|
+
});
|
|
22047
|
+
var mcpConfigSchema = zod.z.object({
|
|
22048
|
+
/** Collections exposed over MCP. Omitted → every active collection. */
|
|
22049
|
+
expose: zod.z.array(zod.z.string()).optional(),
|
|
22050
|
+
/** Per-collection read/write overrides, keyed by collection name. */
|
|
22051
|
+
types: zod.z.record(zod.z.string(), mcpTypeConfigSchema).default({}),
|
|
22052
|
+
/** Field names stripped from every tool response + write schema. */
|
|
22053
|
+
redactFields: zod.z.array(zod.z.string()).default([]),
|
|
22054
|
+
/** Max documents returned by list_* tools and document resources. */
|
|
22055
|
+
listLimit: zod.z.number().int().positive().max(200).default(50)
|
|
22056
|
+
});
|
|
22057
|
+
function resolveMcpConfig(raw, collections) {
|
|
22058
|
+
const cfg = mcpConfigSchema.parse(raw ?? {});
|
|
22059
|
+
const exposeSet = cfg.expose ? new Set(cfg.expose) : null;
|
|
22060
|
+
const types = collections.filter((c) => exposeSet ? exposeSet.has(c.name) : true).map((c) => {
|
|
22061
|
+
const override = cfg.types[c.name];
|
|
22062
|
+
return {
|
|
22063
|
+
typeId: c.name,
|
|
22064
|
+
displayName: c.displayName ?? c.name,
|
|
22065
|
+
read: override?.read ?? true,
|
|
22066
|
+
write: override?.write ?? true
|
|
22067
|
+
};
|
|
22068
|
+
});
|
|
22069
|
+
return { types, redactFields: cfg.redactFields, listLimit: cfg.listLimit };
|
|
22070
|
+
}
|
|
22071
|
+
|
|
22072
|
+
// src/plugins/core-plugins/mcp-plugin/schema/field-to-jsonschema.ts
|
|
22073
|
+
var SYSTEM_FIELDS = /* @__PURE__ */ new Set([
|
|
22074
|
+
"id",
|
|
22075
|
+
"root_id",
|
|
22076
|
+
"rootId",
|
|
22077
|
+
"created_at",
|
|
22078
|
+
"createdAt",
|
|
22079
|
+
"updated_at",
|
|
22080
|
+
"updatedAt",
|
|
22081
|
+
"version_number",
|
|
22082
|
+
"versionNumber"
|
|
22083
|
+
]);
|
|
22084
|
+
function fieldToJsonSchema(field) {
|
|
22085
|
+
const base = {};
|
|
22086
|
+
if (field.title) base.title = field.title;
|
|
22087
|
+
if (field.description) base.description = field.description;
|
|
22088
|
+
switch (field.type) {
|
|
22089
|
+
case "number":
|
|
22090
|
+
return {
|
|
22091
|
+
...base,
|
|
22092
|
+
type: "number",
|
|
22093
|
+
...field.min != null ? { minimum: field.min } : {},
|
|
22094
|
+
...field.max != null ? { maximum: field.max } : {}
|
|
22095
|
+
};
|
|
22096
|
+
case "boolean":
|
|
22097
|
+
case "checkbox":
|
|
22098
|
+
return { ...base, type: "boolean" };
|
|
22099
|
+
case "date":
|
|
22100
|
+
case "datetime":
|
|
22101
|
+
return { ...base, type: "string", format: "date-time" };
|
|
22102
|
+
case "select":
|
|
22103
|
+
case "radio":
|
|
22104
|
+
return { ...base, type: "string", ...field.enum ? { enum: field.enum } : {} };
|
|
22105
|
+
case "multiselect":
|
|
22106
|
+
return {
|
|
22107
|
+
...base,
|
|
22108
|
+
type: "array",
|
|
22109
|
+
items: { type: "string", ...field.enum ? { enum: field.enum } : {} }
|
|
22110
|
+
};
|
|
22111
|
+
case "array":
|
|
22112
|
+
return {
|
|
22113
|
+
...base,
|
|
22114
|
+
type: "array",
|
|
22115
|
+
items: field.items ? fieldToJsonSchema(field.items) : {}
|
|
22116
|
+
};
|
|
22117
|
+
case "object":
|
|
22118
|
+
return {
|
|
22119
|
+
...base,
|
|
22120
|
+
type: "object",
|
|
22121
|
+
...field.properties ? { properties: mapProperties(field.properties) } : {}
|
|
22122
|
+
};
|
|
22123
|
+
case "json":
|
|
22124
|
+
return { ...base };
|
|
22125
|
+
// string-like: string, slug, email, url, richtext, markdown, textarea, editors,
|
|
22126
|
+
// reference, media, color, file, user
|
|
22127
|
+
default: {
|
|
22128
|
+
const node = { ...base, type: "string" };
|
|
22129
|
+
if (field.minLength != null) node.minLength = field.minLength;
|
|
22130
|
+
if (field.maxLength != null) node.maxLength = field.maxLength;
|
|
22131
|
+
if (field.pattern) node.pattern = field.pattern;
|
|
22132
|
+
if (field.format) node.format = field.format;
|
|
22133
|
+
return node;
|
|
22134
|
+
}
|
|
22135
|
+
}
|
|
22136
|
+
}
|
|
22137
|
+
function mapProperties(props) {
|
|
22138
|
+
const out = {};
|
|
22139
|
+
for (const [name, field] of Object.entries(props)) {
|
|
22140
|
+
out[name] = fieldToJsonSchema(field);
|
|
22141
|
+
}
|
|
22142
|
+
return out;
|
|
22143
|
+
}
|
|
22144
|
+
function collectionToJsonSchema(schema, opts = {}) {
|
|
22145
|
+
const properties = {};
|
|
22146
|
+
const required = [];
|
|
22147
|
+
const redact2 = new Set(opts.redactFields ?? []);
|
|
22148
|
+
const schemaRequired = new Set(schema.required ?? []);
|
|
22149
|
+
for (const [name, field] of Object.entries(schema.properties ?? {})) {
|
|
22150
|
+
if (redact2.has(name)) continue;
|
|
22151
|
+
if (opts.forWrite && SYSTEM_FIELDS.has(name)) continue;
|
|
22152
|
+
properties[name] = fieldToJsonSchema(field);
|
|
22153
|
+
if (field.required || schemaRequired.has(name)) required.push(name);
|
|
22154
|
+
}
|
|
22155
|
+
return { type: "object", properties, ...required.length ? { required } : {} };
|
|
22156
|
+
}
|
|
22157
|
+
|
|
22158
|
+
// src/plugins/core-plugins/mcp-plugin/tools/registry.ts
|
|
22159
|
+
var PHASE_FLAGS = { includeWrite: true, includeSearch: false };
|
|
22160
|
+
var EMPTY_OBJECT_SCHEMA = { type: "object", properties: {} };
|
|
22161
|
+
function buildToolRegistry(cfg, collections, opts = {}) {
|
|
22162
|
+
const tools = [];
|
|
22163
|
+
tools.push({
|
|
22164
|
+
name: "list_collections",
|
|
22165
|
+
description: "List every content collection exposed over MCP, with its read/write access.",
|
|
22166
|
+
inputSchema: EMPTY_OBJECT_SCHEMA,
|
|
22167
|
+
op: "list_collections"
|
|
22168
|
+
});
|
|
22169
|
+
if (opts.includeSearch) {
|
|
22170
|
+
tools.push({
|
|
22171
|
+
name: "search_content",
|
|
22172
|
+
description: "Search content across exposed collections by title or slug.",
|
|
22173
|
+
inputSchema: {
|
|
22174
|
+
type: "object",
|
|
22175
|
+
properties: { query: { type: "string", description: "Text matched against document title and slug." } },
|
|
22176
|
+
required: ["query"]
|
|
22177
|
+
},
|
|
22178
|
+
op: "search_content"
|
|
22179
|
+
});
|
|
22180
|
+
}
|
|
22181
|
+
for (const t of cfg.types) {
|
|
22182
|
+
const col = collections.get(t.typeId);
|
|
22183
|
+
const writeSchema = col ? collectionToJsonSchema(col.schema, { forWrite: true, redactFields: cfg.redactFields }) : EMPTY_OBJECT_SCHEMA;
|
|
22184
|
+
if (t.read) {
|
|
22185
|
+
tools.push({
|
|
22186
|
+
name: `list_${t.typeId}`,
|
|
22187
|
+
description: `List ${t.displayName} documents.`,
|
|
22188
|
+
inputSchema: {
|
|
22189
|
+
type: "object",
|
|
22190
|
+
properties: {
|
|
22191
|
+
status: {
|
|
22192
|
+
type: "string",
|
|
22193
|
+
enum: ["published", "draft"],
|
|
22194
|
+
description: "Lifecycle to list. Defaults to published."
|
|
22195
|
+
},
|
|
22196
|
+
limit: { type: "number", description: `Max documents to return (capped at ${cfg.listLimit}).` }
|
|
22197
|
+
}
|
|
22198
|
+
},
|
|
22199
|
+
op: "list",
|
|
22200
|
+
typeId: t.typeId
|
|
22201
|
+
});
|
|
22202
|
+
tools.push({
|
|
22203
|
+
name: `get_${t.typeId}`,
|
|
22204
|
+
description: `Get one ${t.displayName} document by id or slug.`,
|
|
22205
|
+
inputSchema: {
|
|
22206
|
+
type: "object",
|
|
22207
|
+
properties: {
|
|
22208
|
+
id: { type: "string", description: "Document id or root id." },
|
|
22209
|
+
slug: { type: "string", description: "Document slug (alternative to id)." }
|
|
22210
|
+
}
|
|
22211
|
+
},
|
|
22212
|
+
op: "get",
|
|
22213
|
+
typeId: t.typeId
|
|
22214
|
+
});
|
|
22215
|
+
}
|
|
22216
|
+
if (opts.includeWrite && t.write) {
|
|
22217
|
+
tools.push({
|
|
22218
|
+
name: `create_${t.typeId}`,
|
|
22219
|
+
description: `Create a ${t.displayName} document.`,
|
|
22220
|
+
inputSchema: {
|
|
22221
|
+
type: "object",
|
|
22222
|
+
properties: {
|
|
22223
|
+
title: { type: "string" },
|
|
22224
|
+
slug: { type: "string" },
|
|
22225
|
+
data: writeSchema,
|
|
22226
|
+
publish: { type: "boolean", description: "Publish immediately. Defaults to false (draft)." }
|
|
22227
|
+
}
|
|
22228
|
+
},
|
|
22229
|
+
op: "create",
|
|
22230
|
+
typeId: t.typeId
|
|
22231
|
+
});
|
|
22232
|
+
tools.push({
|
|
22233
|
+
name: `update_${t.typeId}`,
|
|
22234
|
+
description: `Update a ${t.displayName} document (saves a new draft).`,
|
|
22235
|
+
inputSchema: {
|
|
22236
|
+
type: "object",
|
|
22237
|
+
properties: {
|
|
22238
|
+
id: { type: "string", description: "Root id of the document to update." },
|
|
22239
|
+
title: { type: "string" },
|
|
22240
|
+
slug: { type: "string" },
|
|
22241
|
+
data: writeSchema
|
|
22242
|
+
},
|
|
22243
|
+
required: ["id"]
|
|
22244
|
+
},
|
|
22245
|
+
op: "update",
|
|
22246
|
+
typeId: t.typeId
|
|
22247
|
+
});
|
|
22248
|
+
tools.push({
|
|
22249
|
+
name: `publish_${t.typeId}`,
|
|
22250
|
+
description: `Publish a ${t.displayName} document.`,
|
|
22251
|
+
inputSchema: {
|
|
22252
|
+
type: "object",
|
|
22253
|
+
properties: { id: { type: "string", description: "Root id of the document to publish." } },
|
|
22254
|
+
required: ["id"]
|
|
22255
|
+
},
|
|
22256
|
+
op: "publish",
|
|
22257
|
+
typeId: t.typeId
|
|
22258
|
+
});
|
|
22259
|
+
tools.push({
|
|
22260
|
+
name: `delete_${t.typeId}`,
|
|
22261
|
+
description: `Delete a ${t.displayName} document.`,
|
|
22262
|
+
inputSchema: {
|
|
22263
|
+
type: "object",
|
|
22264
|
+
properties: { id: { type: "string", description: "Root id of the document to delete." } },
|
|
22265
|
+
required: ["id"]
|
|
22266
|
+
},
|
|
22267
|
+
op: "delete",
|
|
22268
|
+
typeId: t.typeId
|
|
22269
|
+
});
|
|
22270
|
+
}
|
|
22271
|
+
}
|
|
22272
|
+
return tools;
|
|
22273
|
+
}
|
|
22274
|
+
|
|
22275
|
+
// src/plugins/core-plugins/mcp-plugin/jsonrpc.ts
|
|
22276
|
+
var JSON_RPC = {
|
|
22277
|
+
PARSE_ERROR: -32700,
|
|
22278
|
+
INVALID_REQUEST: -32600,
|
|
22279
|
+
METHOD_NOT_FOUND: -32601,
|
|
22280
|
+
INVALID_PARAMS: -32602,
|
|
22281
|
+
INTERNAL_ERROR: -32603,
|
|
22282
|
+
/** Custom: no valid API key on the request. */
|
|
22283
|
+
UNAUTHORIZED: -32001
|
|
22284
|
+
};
|
|
22285
|
+
var McpToolError = class extends Error {
|
|
22286
|
+
constructor(message) {
|
|
22287
|
+
super(message);
|
|
22288
|
+
this.name = "McpToolError";
|
|
22289
|
+
}
|
|
22290
|
+
};
|
|
22291
|
+
function rpcResult(id, result) {
|
|
22292
|
+
return { jsonrpc: "2.0", id: id ?? null, result };
|
|
22293
|
+
}
|
|
22294
|
+
function rpcError(id, code, message, data) {
|
|
22295
|
+
return { jsonrpc: "2.0", id: id ?? null, error: { code, message, ...{} } };
|
|
22296
|
+
}
|
|
22297
|
+
function parseJsonRpc(body) {
|
|
22298
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
22299
|
+
return { error: { code: JSON_RPC.INVALID_REQUEST, message: "Request must be a JSON object" } };
|
|
22300
|
+
}
|
|
22301
|
+
const b = body;
|
|
22302
|
+
if (b.jsonrpc !== "2.0") {
|
|
22303
|
+
return { error: { code: JSON_RPC.INVALID_REQUEST, message: 'jsonrpc must be "2.0"' } };
|
|
22304
|
+
}
|
|
22305
|
+
if (typeof b.method !== "string" || b.method.length === 0) {
|
|
22306
|
+
return { error: { code: JSON_RPC.INVALID_REQUEST, message: "method must be a non-empty string" } };
|
|
22307
|
+
}
|
|
22308
|
+
const id = b.id === void 0 ? null : b.id;
|
|
22309
|
+
const params = b.params && typeof b.params === "object" && !Array.isArray(b.params) ? b.params : {};
|
|
22310
|
+
return { jsonrpc: "2.0", id, method: b.method, params };
|
|
22311
|
+
}
|
|
22312
|
+
|
|
22313
|
+
// src/plugins/core-plugins/mcp-plugin/tools/documents.ts
|
|
22314
|
+
function redact(data, fields) {
|
|
22315
|
+
if (!fields.length) return data;
|
|
22316
|
+
const out = { ...data };
|
|
22317
|
+
for (const f of fields) delete out[f];
|
|
22318
|
+
return out;
|
|
22319
|
+
}
|
|
22320
|
+
function shapeDocument(doc, redactFields) {
|
|
22321
|
+
return {
|
|
22322
|
+
id: doc.id,
|
|
22323
|
+
rootId: doc.rootId,
|
|
22324
|
+
typeId: doc.typeId,
|
|
22325
|
+
title: doc.title,
|
|
22326
|
+
slug: doc.slug,
|
|
22327
|
+
status: doc.status,
|
|
22328
|
+
isPublished: doc.isPublished,
|
|
22329
|
+
publishedAt: doc.publishedAt,
|
|
22330
|
+
updatedAt: doc.updatedAt,
|
|
22331
|
+
data: redact(doc.data, redactFields)
|
|
22332
|
+
};
|
|
22333
|
+
}
|
|
22334
|
+
async function resolveType(ctx, typeId) {
|
|
22335
|
+
const docType = await new chunk37V3RET3_cjs.DocumentTypeRegistry(ctx.db).findById(typeId);
|
|
22336
|
+
if (!docType || !docType.isActive) throw new McpToolError(`Unknown document type: ${typeId}`);
|
|
22337
|
+
const effTenant = chunkI767LVN7_cjs.effectiveTenantForType(ctx.tenantId, docType.settings);
|
|
22338
|
+
const repo = new chunkI767LVN7_cjs.DocumentRepository(ctx.db, effTenant);
|
|
22339
|
+
return { docType, repo };
|
|
22340
|
+
}
|
|
22341
|
+
async function execList(ctx, typeId, args) {
|
|
22342
|
+
const { docType, repo } = await resolveType(ctx, typeId);
|
|
22343
|
+
const status = args.status === "draft" ? "draft" : "published";
|
|
22344
|
+
const limit = Math.min(Math.max(1, args.limit ?? ctx.listLimit), ctx.listLimit);
|
|
22345
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
22346
|
+
const docs = await repo.list({
|
|
22347
|
+
typeId,
|
|
22348
|
+
status,
|
|
22349
|
+
timeWindow: status === "published",
|
|
22350
|
+
now,
|
|
22351
|
+
limit
|
|
22352
|
+
});
|
|
22353
|
+
const allowed = await Promise.all(
|
|
22354
|
+
docs.map((d) => repo.isAllowed(ctx.principalSet, d.rootId, "read", docType.settings))
|
|
22355
|
+
);
|
|
22356
|
+
return docs.filter((_, i) => allowed[i]).map((d) => shapeDocument(d, ctx.redactFields));
|
|
22357
|
+
}
|
|
22358
|
+
async function execGet(ctx, typeId, args) {
|
|
22359
|
+
const { docType, repo } = await resolveType(ctx, typeId);
|
|
22360
|
+
let doc = null;
|
|
22361
|
+
if (args.id) {
|
|
22362
|
+
doc = await repo.getById(args.id) ?? await repo.getPublished(args.id) ?? await repo.getCurrentDraft(args.id);
|
|
22363
|
+
} else if (args.slug) {
|
|
22364
|
+
doc = await repo.getBySlug(typeId, args.slug);
|
|
22365
|
+
} else {
|
|
22366
|
+
throw new McpToolError('get requires an "id" or "slug" argument');
|
|
22367
|
+
}
|
|
22368
|
+
if (!doc || doc.typeId !== typeId) throw new McpToolError("Document not found");
|
|
22369
|
+
const ok = await repo.isAllowed(ctx.principalSet, doc.rootId, "read", docType.settings);
|
|
22370
|
+
if (!ok) throw new McpToolError("Document not found");
|
|
22371
|
+
return shapeDocument(doc, ctx.redactFields);
|
|
22372
|
+
}
|
|
22373
|
+
|
|
22374
|
+
// src/plugins/core-plugins/mcp-plugin/tools/mutations.ts
|
|
22375
|
+
async function resolveWriteScope(ctx, typeId) {
|
|
22376
|
+
const docType = await new chunk37V3RET3_cjs.DocumentTypeRegistry(ctx.db).findById(typeId);
|
|
22377
|
+
if (!docType || !docType.isActive) throw new McpToolError(`Unknown document type: ${typeId}`);
|
|
22378
|
+
const effTenant = chunkI767LVN7_cjs.effectiveTenantForType(ctx.tenantId, docType.settings);
|
|
22379
|
+
const repo = new chunkI767LVN7_cjs.DocumentRepository(ctx.db, effTenant);
|
|
22380
|
+
const svc = new chunkLTZ5WYOK_cjs.DocumentsService(ctx.db, {
|
|
22381
|
+
queryableFields: docType.queryableFields ?? [],
|
|
22382
|
+
typeSchemaVersion: docType.schemaVersion,
|
|
22383
|
+
maxVersionsPerRoot: docType.settings?.maxVersionsPerRoot,
|
|
22384
|
+
tenantId: effTenant,
|
|
22385
|
+
versioning: docType.settings?.versioning ?? false
|
|
22386
|
+
});
|
|
22387
|
+
return { docType, effTenant, repo, svc };
|
|
22388
|
+
}
|
|
22389
|
+
async function assertAllowed(scope, ctx, rootId, permission) {
|
|
22390
|
+
const ok = await scope.repo.isAllowed(ctx.principalSet, rootId, permission, scope.docType.settings ?? {});
|
|
22391
|
+
if (!ok) throw new McpToolError(`Permission denied: cannot ${permission} ${scope.docType.id}`);
|
|
22392
|
+
}
|
|
22393
|
+
function applyUserFieldDefaults(data, typeId, userId) {
|
|
22394
|
+
const col = chunkQCJHCSOK_cjs.getCollectionRegistry().getByName(typeId);
|
|
22395
|
+
if (!col?.schema?.properties) return data;
|
|
22396
|
+
const props = col.schema.properties;
|
|
22397
|
+
const patched = { ...data };
|
|
22398
|
+
for (const [name, field] of Object.entries(props)) {
|
|
22399
|
+
if (field.type === "user" && !patched[name]) patched[name] = userId;
|
|
22400
|
+
}
|
|
22401
|
+
return patched;
|
|
22402
|
+
}
|
|
22403
|
+
async function execCreate(ctx, typeId, args) {
|
|
22404
|
+
const scope = await resolveWriteScope(ctx, typeId);
|
|
22405
|
+
await assertAllowed(scope, ctx, "", "create");
|
|
22406
|
+
const data = redact(applyUserFieldDefaults(args.data ?? {}, typeId, ctx.userId), ctx.redactFields);
|
|
22407
|
+
const input = chunkI767LVN7_cjs.createDocumentSchema.parse({
|
|
22408
|
+
typeId,
|
|
22409
|
+
tenantId: scope.effTenant,
|
|
22410
|
+
title: args.title ?? null,
|
|
22411
|
+
slug: args.slug ?? null,
|
|
22412
|
+
data,
|
|
22413
|
+
ownerId: ctx.userId,
|
|
22414
|
+
publishOnCreate: Boolean(args.publish)
|
|
22415
|
+
});
|
|
22416
|
+
const doc = await scope.svc.create(input, ctx.userId);
|
|
22417
|
+
return shapeDocument(doc, ctx.redactFields);
|
|
22418
|
+
}
|
|
22419
|
+
async function execUpdate(ctx, typeId, args) {
|
|
22420
|
+
if (!args.id) throw new McpToolError('update requires an "id" (root id)');
|
|
22421
|
+
const scope = await resolveWriteScope(ctx, typeId);
|
|
22422
|
+
const current = await scope.repo.getCurrentDraft(args.id);
|
|
22423
|
+
if (!current || current.typeId !== typeId) throw new McpToolError("Document not found");
|
|
22424
|
+
await assertAllowed(scope, ctx, args.id, "update");
|
|
22425
|
+
const patch = chunkI767LVN7_cjs.updateDocumentSchema.parse({
|
|
22426
|
+
...args.title !== void 0 ? { title: args.title } : {},
|
|
22427
|
+
...args.slug !== void 0 ? { slug: args.slug } : {},
|
|
22428
|
+
...args.data !== void 0 ? { data: redact(args.data, ctx.redactFields) } : {}
|
|
22429
|
+
});
|
|
22430
|
+
const doc = await scope.svc.saveDraft(args.id, patch, ctx.userId);
|
|
22431
|
+
return shapeDocument(doc, ctx.redactFields);
|
|
22432
|
+
}
|
|
22433
|
+
async function execPublish(ctx, typeId, args) {
|
|
22434
|
+
if (!args.id) throw new McpToolError('publish requires an "id" (root id)');
|
|
22435
|
+
const scope = await resolveWriteScope(ctx, typeId);
|
|
22436
|
+
const current = await scope.repo.getCurrentDraft(args.id);
|
|
22437
|
+
if (!current || current.typeId !== typeId) throw new McpToolError("Document not found");
|
|
22438
|
+
await assertAllowed(scope, ctx, args.id, "publish");
|
|
22439
|
+
const doc = await scope.svc.publish(current.id, ctx.userId);
|
|
22440
|
+
return shapeDocument(doc, ctx.redactFields);
|
|
22441
|
+
}
|
|
22442
|
+
async function execDelete(ctx, typeId, args) {
|
|
22443
|
+
if (!args.id) throw new McpToolError('delete requires an "id" (root id)');
|
|
22444
|
+
const scope = await resolveWriteScope(ctx, typeId);
|
|
22445
|
+
const current = await scope.repo.getCurrentDraft(args.id) ?? await scope.repo.getPublished(args.id);
|
|
22446
|
+
if (!current || current.typeId !== typeId) throw new McpToolError("Document not found");
|
|
22447
|
+
await assertAllowed(scope, ctx, args.id, "delete");
|
|
22448
|
+
if (scope.docType.settings?.pii) {
|
|
22449
|
+
await scope.svc.erase(args.id, scope.effTenant);
|
|
22450
|
+
return { rootId: args.id, deleted: true, erased: true };
|
|
22451
|
+
}
|
|
22452
|
+
const ids = /* @__PURE__ */ new Set();
|
|
22453
|
+
ids.add(current.id);
|
|
22454
|
+
if (current.isCurrentDraft) {
|
|
22455
|
+
const published = await scope.repo.getPublished(args.id);
|
|
22456
|
+
if (published) ids.add(published.id);
|
|
22457
|
+
} else {
|
|
22458
|
+
const draft = await scope.repo.getCurrentDraft(args.id);
|
|
22459
|
+
if (draft) ids.add(draft.id);
|
|
22460
|
+
}
|
|
22461
|
+
for (const id of ids) await scope.svc.softDelete(id);
|
|
22462
|
+
return { rootId: args.id, deleted: true, erased: false };
|
|
22463
|
+
}
|
|
22464
|
+
|
|
22465
|
+
// src/plugins/core-plugins/mcp-plugin/tools/static.ts
|
|
22466
|
+
function execListCollections(types) {
|
|
22467
|
+
return types.map((t) => ({ typeId: t.typeId, displayName: t.displayName, read: t.read, write: t.write }));
|
|
22468
|
+
}
|
|
22469
|
+
|
|
22470
|
+
// src/plugins/core-plugins/mcp-plugin/resources/schemas.ts
|
|
22471
|
+
function buildResourceList(cfg) {
|
|
22472
|
+
const out = [
|
|
22473
|
+
{ uri: "sonicjs://collections", name: "All collections", mimeType: "application/json" }
|
|
22474
|
+
];
|
|
22475
|
+
for (const t of cfg.types) {
|
|
22476
|
+
out.push({
|
|
22477
|
+
uri: `sonicjs://collections/${t.typeId}/schema`,
|
|
22478
|
+
name: `${t.displayName} schema`,
|
|
22479
|
+
mimeType: "application/json"
|
|
22480
|
+
});
|
|
22481
|
+
}
|
|
22482
|
+
return out;
|
|
22483
|
+
}
|
|
22484
|
+
var SCHEMA_URI = /^sonicjs:\/\/collections\/([^/]+)\/schema$/;
|
|
22485
|
+
function readResource(uri, cfg, collections) {
|
|
22486
|
+
if (uri === "sonicjs://collections") {
|
|
22487
|
+
const list = cfg.types.map((t) => ({
|
|
22488
|
+
typeId: t.typeId,
|
|
22489
|
+
displayName: t.displayName,
|
|
22490
|
+
read: t.read,
|
|
22491
|
+
write: t.write
|
|
22492
|
+
}));
|
|
22493
|
+
return { uri, mimeType: "application/json", text: JSON.stringify(list, null, 2) };
|
|
22494
|
+
}
|
|
22495
|
+
const m = uri.match(SCHEMA_URI);
|
|
22496
|
+
if (m) {
|
|
22497
|
+
const typeId = m[1];
|
|
22498
|
+
const exposed = cfg.types.find((t) => t.typeId === typeId);
|
|
22499
|
+
const col = collections.get(typeId);
|
|
22500
|
+
if (!exposed || !col) throw new McpToolError(`Unknown collection: ${typeId}`);
|
|
22501
|
+
const schema = collectionToJsonSchema(col.schema, { redactFields: cfg.redactFields });
|
|
22502
|
+
return { uri, mimeType: "application/json", text: JSON.stringify(schema, null, 2) };
|
|
22503
|
+
}
|
|
22504
|
+
throw new McpToolError(`Unknown resource URI: ${uri}`);
|
|
22505
|
+
}
|
|
22506
|
+
|
|
22507
|
+
// src/plugins/core-plugins/mcp-plugin/routes/mcp.ts
|
|
22508
|
+
var SERVER_INFO = { name: "sonicjs-mcp", version: "1.0.0" };
|
|
22509
|
+
var PROTOCOL_VERSION = "2024-11-05";
|
|
22510
|
+
function createMcpRoutes(options = {}) {
|
|
22511
|
+
const app2 = new hono.Hono();
|
|
22512
|
+
app2.post("/", async (c) => {
|
|
22513
|
+
let body;
|
|
22514
|
+
try {
|
|
22515
|
+
body = await c.req.json();
|
|
22516
|
+
} catch {
|
|
22517
|
+
return c.json(rpcError(null, JSON_RPC.PARSE_ERROR, "Invalid JSON"));
|
|
22518
|
+
}
|
|
22519
|
+
const parsed = parseJsonRpc(body);
|
|
22520
|
+
if ("error" in parsed) {
|
|
22521
|
+
const id2 = body && typeof body === "object" ? body.id ?? null : null;
|
|
22522
|
+
return c.json(rpcError(id2, parsed.error.code, parsed.error.message));
|
|
22523
|
+
}
|
|
22524
|
+
const { id, method, params } = parsed;
|
|
22525
|
+
const user = c.get("user");
|
|
22526
|
+
if (!user) {
|
|
22527
|
+
return c.json(
|
|
22528
|
+
rpcError(id, JSON_RPC.UNAUTHORIZED, "Unauthorized: provide a valid API key via Authorization: Bearer sk_...")
|
|
22529
|
+
);
|
|
22530
|
+
}
|
|
22531
|
+
const { tenantId, principalSet, userId } = chunkI767LVN7_cjs.getDocumentRequestContext(c);
|
|
22532
|
+
const registry = chunkQCJHCSOK_cjs.getCollectionRegistry();
|
|
22533
|
+
const active = registry.listActive();
|
|
22534
|
+
const collections = new Map(active.map((col) => [col.name, col]));
|
|
22535
|
+
const cfg = resolveMcpConfig(options, active);
|
|
22536
|
+
const tools = buildToolRegistry(cfg, collections, PHASE_FLAGS);
|
|
22537
|
+
try {
|
|
22538
|
+
switch (method) {
|
|
22539
|
+
case "initialize":
|
|
22540
|
+
return c.json(
|
|
22541
|
+
rpcResult(id, {
|
|
22542
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
22543
|
+
serverInfo: SERVER_INFO,
|
|
22544
|
+
capabilities: { tools: {}, resources: {} }
|
|
22545
|
+
})
|
|
22546
|
+
);
|
|
22547
|
+
case "tools/list":
|
|
22548
|
+
return c.json(
|
|
22549
|
+
rpcResult(id, {
|
|
22550
|
+
tools: tools.map((t) => ({ name: t.name, description: t.description, inputSchema: t.inputSchema }))
|
|
22551
|
+
})
|
|
22552
|
+
);
|
|
22553
|
+
case "tools/call": {
|
|
22554
|
+
const name = typeof params.name === "string" ? params.name : "";
|
|
22555
|
+
const args = params.arguments && typeof params.arguments === "object" ? params.arguments : {};
|
|
22556
|
+
const tool = tools.find((t) => t.name === name);
|
|
22557
|
+
if (!tool) return c.json(rpcError(id, JSON_RPC.METHOD_NOT_FOUND, `Unknown tool: ${name}`));
|
|
22558
|
+
const readCtx = {
|
|
22559
|
+
db: c.env.DB,
|
|
22560
|
+
tenantId,
|
|
22561
|
+
principalSet,
|
|
22562
|
+
listLimit: cfg.listLimit,
|
|
22563
|
+
redactFields: cfg.redactFields
|
|
22564
|
+
};
|
|
22565
|
+
const writeCtx = {
|
|
22566
|
+
db: c.env.DB,
|
|
22567
|
+
tenantId,
|
|
22568
|
+
principalSet,
|
|
22569
|
+
userId: userId ?? "",
|
|
22570
|
+
redactFields: cfg.redactFields
|
|
22571
|
+
};
|
|
22572
|
+
try {
|
|
22573
|
+
let result;
|
|
22574
|
+
switch (tool.op) {
|
|
22575
|
+
case "list_collections":
|
|
22576
|
+
result = execListCollections(cfg.types);
|
|
22577
|
+
break;
|
|
22578
|
+
case "list":
|
|
22579
|
+
result = await execList(readCtx, tool.typeId, args);
|
|
22580
|
+
break;
|
|
22581
|
+
case "get":
|
|
22582
|
+
result = await execGet(readCtx, tool.typeId, args);
|
|
22583
|
+
break;
|
|
22584
|
+
case "create":
|
|
22585
|
+
result = await execCreate(writeCtx, tool.typeId, args);
|
|
22586
|
+
break;
|
|
22587
|
+
case "update":
|
|
22588
|
+
result = await execUpdate(writeCtx, tool.typeId, args);
|
|
22589
|
+
break;
|
|
22590
|
+
case "publish":
|
|
22591
|
+
result = await execPublish(writeCtx, tool.typeId, args);
|
|
22592
|
+
break;
|
|
22593
|
+
case "delete":
|
|
22594
|
+
result = await execDelete(writeCtx, tool.typeId, args);
|
|
22595
|
+
break;
|
|
22596
|
+
default:
|
|
22597
|
+
return c.json(rpcError(id, JSON_RPC.METHOD_NOT_FOUND, `Tool not available: ${name}`));
|
|
22598
|
+
}
|
|
22599
|
+
return c.json(rpcResult(id, { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }));
|
|
22600
|
+
} catch (e) {
|
|
22601
|
+
if (e instanceof McpToolError) {
|
|
22602
|
+
return c.json(rpcResult(id, { content: [{ type: "text", text: e.message }], isError: true }));
|
|
22603
|
+
}
|
|
22604
|
+
throw e;
|
|
22605
|
+
}
|
|
22606
|
+
}
|
|
22607
|
+
case "resources/list":
|
|
22608
|
+
return c.json(rpcResult(id, { resources: buildResourceList(cfg) }));
|
|
22609
|
+
case "resources/read": {
|
|
22610
|
+
const uri = typeof params.uri === "string" ? params.uri : "";
|
|
22611
|
+
if (!uri) return c.json(rpcError(id, JSON_RPC.INVALID_PARAMS, 'resources/read requires a "uri" param'));
|
|
22612
|
+
try {
|
|
22613
|
+
const contents = readResource(uri, cfg, collections);
|
|
22614
|
+
return c.json(rpcResult(id, { contents: [contents] }));
|
|
22615
|
+
} catch (e) {
|
|
22616
|
+
if (e instanceof McpToolError) return c.json(rpcError(id, JSON_RPC.INVALID_PARAMS, e.message));
|
|
22617
|
+
throw e;
|
|
22618
|
+
}
|
|
22619
|
+
}
|
|
22620
|
+
default:
|
|
22621
|
+
return c.json(rpcError(id, JSON_RPC.METHOD_NOT_FOUND, `Method not found: ${method}`));
|
|
22622
|
+
}
|
|
22623
|
+
} catch (e) {
|
|
22624
|
+
console.error("[mcp] handler error:", e);
|
|
22625
|
+
return c.json(rpcError(id, JSON_RPC.INTERNAL_ERROR, "Internal error"));
|
|
22626
|
+
}
|
|
22627
|
+
});
|
|
22628
|
+
return app2;
|
|
22629
|
+
}
|
|
22630
|
+
|
|
22631
|
+
// src/plugins/core-plugins/mcp-plugin/admin/templates.ts
|
|
22632
|
+
chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
|
|
22633
|
+
function accessBadge(ok) {
|
|
22634
|
+
return ok ? `<span class="inline-flex items-center rounded-full bg-emerald-50 dark:bg-emerald-900/20 px-2 py-0.5 text-xs font-medium text-emerald-700 dark:text-emerald-400 ring-1 ring-emerald-600/20 dark:ring-emerald-400/20">Yes</span>` : `<span class="inline-flex items-center rounded-full bg-zinc-100 dark:bg-zinc-800 px-2 py-0.5 text-xs font-medium text-zinc-500 dark:text-zinc-400 ring-1 ring-zinc-200 dark:ring-zinc-700">No</span>`;
|
|
22635
|
+
}
|
|
22636
|
+
function toolNamesForType(typeId, tools) {
|
|
22637
|
+
const names = tools.filter((t) => t.typeId === typeId).map((t) => `<code class="text-xs font-mono text-zinc-500 dark:text-zinc-400">${chunkMNWKYY5E_cjs.escapeHtml(t.name)}</code>`);
|
|
22638
|
+
return names.length ? names.join('<span class="text-zinc-300 dark:text-zinc-600 mx-1">,</span>') : "\u2014";
|
|
22639
|
+
}
|
|
22640
|
+
function buildClaudeJson(endpointUrl) {
|
|
22641
|
+
return JSON.stringify(
|
|
22642
|
+
{
|
|
22643
|
+
mcpServers: {
|
|
22644
|
+
sonicjs: {
|
|
22645
|
+
type: "http",
|
|
22646
|
+
url: endpointUrl,
|
|
22647
|
+
headers: { Authorization: "Bearer sk_YOUR_API_KEY" }
|
|
22648
|
+
}
|
|
22649
|
+
}
|
|
22650
|
+
},
|
|
22651
|
+
null,
|
|
22652
|
+
2
|
|
22653
|
+
);
|
|
22654
|
+
}
|
|
22655
|
+
function buildCursorJson(endpointUrl) {
|
|
22656
|
+
return JSON.stringify(
|
|
22657
|
+
{
|
|
22658
|
+
mcpServers: {
|
|
22659
|
+
sonicjs: {
|
|
22660
|
+
url: endpointUrl,
|
|
22661
|
+
headers: { Authorization: "Bearer sk_YOUR_API_KEY" }
|
|
22662
|
+
}
|
|
22663
|
+
}
|
|
22664
|
+
},
|
|
22665
|
+
null,
|
|
22666
|
+
2
|
|
22667
|
+
);
|
|
22668
|
+
}
|
|
22669
|
+
function renderMcpDashboardPage(data) {
|
|
22670
|
+
const { endpointUrl, types, tools, user, version, dynamicMenuItems } = data;
|
|
22671
|
+
const safeEndpoint = chunkMNWKYY5E_cjs.escapeHtml(endpointUrl);
|
|
22672
|
+
const typeCount = types.length;
|
|
22673
|
+
const toolCount = tools.length;
|
|
22674
|
+
const typeRows = types.length ? types.map(
|
|
22675
|
+
(t) => `
|
|
22676
|
+
<tr class="border-t border-zinc-950/5 dark:border-white/10">
|
|
22677
|
+
<td class="py-3 pr-4 text-sm font-mono text-zinc-950 dark:text-white">${chunkMNWKYY5E_cjs.escapeHtml(t.typeId)}</td>
|
|
22678
|
+
<td class="py-3 pr-4 text-sm text-zinc-500 dark:text-zinc-400">${chunkMNWKYY5E_cjs.escapeHtml(t.displayName)}</td>
|
|
22679
|
+
<td class="py-3 pr-4">${accessBadge(t.read)}</td>
|
|
22680
|
+
<td class="py-3 pr-4">${accessBadge(t.write)}</td>
|
|
22681
|
+
<td class="py-3 text-sm">${toolNamesForType(t.typeId, tools)}</td>
|
|
22682
|
+
</tr>`
|
|
22683
|
+
).join("") : `<tr><td colspan="5" class="py-8 text-center text-sm text-zinc-500 dark:text-zinc-400">No collections exposed. Register collections via <code class="font-mono">registerCollections()</code> in your app entry point.</td></tr>`;
|
|
22684
|
+
const claudeJson = chunkMNWKYY5E_cjs.escapeHtml(buildClaudeJson(endpointUrl));
|
|
22685
|
+
const cursorJson = chunkMNWKYY5E_cjs.escapeHtml(buildCursorJson(endpointUrl));
|
|
22686
|
+
const content2 = `
|
|
22687
|
+
<div class="space-y-8">
|
|
22688
|
+
|
|
22689
|
+
<!-- Header -->
|
|
22690
|
+
<div class="sm:flex sm:items-center sm:justify-between">
|
|
22691
|
+
<div class="sm:flex-auto">
|
|
22692
|
+
<h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">MCP Server</h1>
|
|
22693
|
+
<p class="mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400">
|
|
22694
|
+
Model Context Protocol endpoint for AI agents (Claude Code, Cursor, VS Code). Requests are authenticated with API keys.
|
|
22695
|
+
</p>
|
|
22696
|
+
</div>
|
|
22697
|
+
<div class="mt-4 sm:mt-0 sm:ml-16">
|
|
22698
|
+
<a href="/admin/plugins/api-keys"
|
|
22699
|
+
class="inline-flex items-center justify-center rounded-lg bg-cyan-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-cyan-500 transition-colors shadow-sm">
|
|
22700
|
+
Mint API Key
|
|
22701
|
+
</a>
|
|
22702
|
+
</div>
|
|
22703
|
+
</div>
|
|
22704
|
+
|
|
22705
|
+
<!-- Status -->
|
|
22706
|
+
<div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm">
|
|
22707
|
+
<h2 class="text-sm font-semibold text-zinc-950 dark:text-white mb-4">Endpoint</h2>
|
|
22708
|
+
<div class="flex items-center gap-3">
|
|
22709
|
+
<code id="endpoint-url" class="flex-1 rounded-lg bg-zinc-50 dark:bg-zinc-800 px-3 py-2 text-sm font-mono text-zinc-950 dark:text-white ring-1 ring-zinc-950/5 dark:ring-white/5 break-all">${safeEndpoint}</code>
|
|
22710
|
+
<button type="button" onclick="copyEndpoint()"
|
|
22711
|
+
class="shrink-0 rounded-lg bg-zinc-100 dark:bg-zinc-800 px-3 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-300 hover:bg-zinc-200 dark:hover:bg-zinc-700 ring-1 ring-zinc-950/5 dark:ring-white/10 transition-colors">
|
|
22712
|
+
Copy
|
|
22713
|
+
</button>
|
|
22714
|
+
</div>
|
|
22715
|
+
<div class="mt-4 flex flex-wrap gap-4 text-sm text-zinc-500 dark:text-zinc-400">
|
|
22716
|
+
<span>
|
|
22717
|
+
<span class="font-semibold text-zinc-950 dark:text-white">${typeCount}</span>
|
|
22718
|
+
collection${typeCount === 1 ? "" : "s"} exposed
|
|
22719
|
+
</span>
|
|
22720
|
+
<span class="text-zinc-300 dark:text-zinc-600">·</span>
|
|
22721
|
+
<span>
|
|
22722
|
+
<span class="font-semibold text-zinc-950 dark:text-white">${toolCount}</span>
|
|
22723
|
+
tool${toolCount === 1 ? "" : "s"} available
|
|
22724
|
+
</span>
|
|
22725
|
+
<span class="text-zinc-300 dark:text-zinc-600">·</span>
|
|
22726
|
+
<span>Auth via <a href="/admin/plugins/api-keys" class="text-cyan-600 dark:text-cyan-400 hover:underline">API Keys</a></span>
|
|
22727
|
+
</div>
|
|
22728
|
+
</div>
|
|
22729
|
+
|
|
22730
|
+
<!-- Exposed collections table -->
|
|
22731
|
+
<div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-x-auto">
|
|
22732
|
+
<h2 class="text-sm font-semibold text-zinc-950 dark:text-white mb-4">Exposed collections</h2>
|
|
22733
|
+
<table class="w-full text-left">
|
|
22734
|
+
<thead>
|
|
22735
|
+
<tr class="text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:text-zinc-400">
|
|
22736
|
+
<th class="pb-2 pr-4">ID</th>
|
|
22737
|
+
<th class="pb-2 pr-4">Display name</th>
|
|
22738
|
+
<th class="pb-2 pr-4">Read</th>
|
|
22739
|
+
<th class="pb-2 pr-4">Write</th>
|
|
22740
|
+
<th class="pb-2">Tools</th>
|
|
22741
|
+
</tr>
|
|
22742
|
+
</thead>
|
|
22743
|
+
<tbody>${typeRows}</tbody>
|
|
22744
|
+
</table>
|
|
22745
|
+
</div>
|
|
22746
|
+
|
|
22747
|
+
<!-- Integration guide -->
|
|
22748
|
+
<div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm space-y-6">
|
|
22749
|
+
<div>
|
|
22750
|
+
<h2 class="text-sm font-semibold text-zinc-950 dark:text-white mb-1">Integration guide</h2>
|
|
22751
|
+
<p class="text-sm text-zinc-500 dark:text-zinc-400">
|
|
22752
|
+
<a href="/admin/plugins/api-keys" class="text-cyan-600 dark:text-cyan-400 hover:underline">Mint an API key</a>,
|
|
22753
|
+
then paste one of the configs below into your MCP client.
|
|
22754
|
+
Replace <code class="font-mono text-xs">sk_YOUR_API_KEY</code> with the key.
|
|
22755
|
+
</p>
|
|
22756
|
+
</div>
|
|
22757
|
+
|
|
22758
|
+
<!-- Claude Code -->
|
|
22759
|
+
<div>
|
|
22760
|
+
<div class="flex items-center justify-between mb-2">
|
|
22761
|
+
<h3 class="text-sm font-medium text-zinc-700 dark:text-zinc-300">
|
|
22762
|
+
Claude Code — <code class="font-mono text-xs">~/.claude/mcp.json</code>
|
|
22763
|
+
</h3>
|
|
22764
|
+
<button type="button" onclick="copyConfig('claude-config')"
|
|
22765
|
+
class="text-xs text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 transition-colors">
|
|
22766
|
+
Copy
|
|
22767
|
+
</button>
|
|
22768
|
+
</div>
|
|
22769
|
+
<pre id="claude-config" class="rounded-lg bg-zinc-950 dark:bg-zinc-800 px-4 py-3 text-sm font-mono text-zinc-100 overflow-x-auto ring-1 ring-zinc-700 dark:ring-zinc-600 whitespace-pre">${claudeJson}</pre>
|
|
22770
|
+
</div>
|
|
22771
|
+
|
|
22772
|
+
<!-- Cursor -->
|
|
22773
|
+
<div>
|
|
22774
|
+
<div class="flex items-center justify-between mb-2">
|
|
22775
|
+
<h3 class="text-sm font-medium text-zinc-700 dark:text-zinc-300">
|
|
22776
|
+
Cursor — <code class="font-mono text-xs">~/.cursor/mcp.json</code>
|
|
22777
|
+
</h3>
|
|
22778
|
+
<button type="button" onclick="copyConfig('cursor-config')"
|
|
22779
|
+
class="text-xs text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200 transition-colors">
|
|
22780
|
+
Copy
|
|
22781
|
+
</button>
|
|
22782
|
+
</div>
|
|
22783
|
+
<pre id="cursor-config" class="rounded-lg bg-zinc-950 dark:bg-zinc-800 px-4 py-3 text-sm font-mono text-zinc-100 overflow-x-auto ring-1 ring-zinc-700 dark:ring-zinc-600 whitespace-pre">${cursorJson}</pre>
|
|
22784
|
+
</div>
|
|
22785
|
+
|
|
22786
|
+
<p class="text-xs text-zinc-400 dark:text-zinc-500">
|
|
22787
|
+
MCP v1 = HTTP POST only (no SSE stream). Clients that require stdio transport can use
|
|
22788
|
+
<code class="font-mono">npx mcp-remote ${safeEndpoint}</code> as a local bridge.
|
|
22789
|
+
</p>
|
|
22790
|
+
</div>
|
|
22791
|
+
|
|
22792
|
+
</div>
|
|
22793
|
+
|
|
22794
|
+
<script>
|
|
22795
|
+
function copyEndpoint() {
|
|
22796
|
+
navigator.clipboard.writeText(document.getElementById('endpoint-url').textContent.trim()).then(() => {
|
|
22797
|
+
window.showNotification && window.showNotification('Endpoint URL copied', 'success')
|
|
22798
|
+
})
|
|
22799
|
+
}
|
|
22800
|
+
function copyConfig(id) {
|
|
22801
|
+
navigator.clipboard.writeText(document.getElementById(id).textContent).then(() => {
|
|
22802
|
+
window.showNotification && window.showNotification('Config copied', 'success')
|
|
22803
|
+
})
|
|
22804
|
+
}
|
|
22805
|
+
</script>`;
|
|
22806
|
+
const layoutData = {
|
|
22807
|
+
title: "MCP Server",
|
|
22808
|
+
pageTitle: "MCP Server",
|
|
22809
|
+
currentPath: "/admin/mcp",
|
|
22810
|
+
user,
|
|
22811
|
+
content: content2,
|
|
22812
|
+
version,
|
|
22813
|
+
dynamicMenuItems
|
|
22814
|
+
};
|
|
22815
|
+
return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
22816
|
+
}
|
|
22817
|
+
|
|
22818
|
+
// src/plugins/core-plugins/mcp-plugin/admin/routes.ts
|
|
22819
|
+
function createMcpAdminRoutes(options = {}) {
|
|
22820
|
+
const routes2 = new hono.Hono();
|
|
22821
|
+
routes2.use("*", chunk37V3RET3_cjs.requireAuth());
|
|
22822
|
+
routes2.use("*", async (c, next) => {
|
|
22823
|
+
const user = c.get("user");
|
|
22824
|
+
if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
|
|
22825
|
+
return next();
|
|
22826
|
+
});
|
|
22827
|
+
routes2.get("/", async (c) => {
|
|
22828
|
+
const url = new URL(c.req.url);
|
|
22829
|
+
const endpointUrl = `${url.protocol}//${url.host}/mcp`;
|
|
22830
|
+
const registry = chunkQCJHCSOK_cjs.getCollectionRegistry();
|
|
22831
|
+
const active = registry.listActive();
|
|
22832
|
+
const collections = new Map(active.map((col) => [col.name, col]));
|
|
22833
|
+
const cfg = resolveMcpConfig(options, active);
|
|
22834
|
+
const tools = buildToolRegistry(cfg, collections, PHASE_FLAGS);
|
|
22835
|
+
const user = c.get("user");
|
|
22836
|
+
return c.html(
|
|
22837
|
+
renderMcpDashboardPage({
|
|
22838
|
+
endpointUrl,
|
|
22839
|
+
types: cfg.types,
|
|
22840
|
+
tools,
|
|
22841
|
+
user: { name: user.email, email: user.email, role: user.role },
|
|
22842
|
+
version: c.get("appVersion"),
|
|
22843
|
+
dynamicMenuItems: c.get("pluginMenuItems")
|
|
22844
|
+
})
|
|
22845
|
+
);
|
|
22846
|
+
});
|
|
22847
|
+
return routes2;
|
|
22848
|
+
}
|
|
22849
|
+
|
|
22850
|
+
// src/plugins/core-plugins/mcp-plugin/index.ts
|
|
22851
|
+
var MCP_ICON = `<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="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg>`;
|
|
22852
|
+
function mcpPlugin(options = {}) {
|
|
22853
|
+
return chunkBP52BFIV_cjs.definePlugin({
|
|
22854
|
+
id: "mcp",
|
|
22855
|
+
version: "1.0.0",
|
|
22856
|
+
name: "MCP Server",
|
|
22857
|
+
description: "Exposes SonicJS content as Model Context Protocol tools for AI agents (Claude Code, Cursor, \u2026).",
|
|
22858
|
+
sonicjsVersionRange: "^3.0.0",
|
|
22859
|
+
author: { name: "SonicJS Team" },
|
|
22860
|
+
register(app2) {
|
|
22861
|
+
app2.route("/mcp", createMcpRoutes(options));
|
|
22862
|
+
app2.route("/admin/mcp", createMcpAdminRoutes(options));
|
|
22863
|
+
},
|
|
22864
|
+
menu: [{ label: "MCP Server", path: "/admin/mcp", icon: MCP_ICON, order: 87 }]
|
|
22865
|
+
});
|
|
22866
|
+
}
|
|
22867
|
+
function createMcpPlugin(options) {
|
|
22868
|
+
return mcpPlugin(options);
|
|
22869
|
+
}
|
|
20611
22870
|
|
|
20612
22871
|
// src/index.ts
|
|
20613
|
-
var VERSION =
|
|
22872
|
+
var VERSION = chunkKKNEYIZJ_cjs.package_default.version;
|
|
20614
22873
|
|
|
20615
22874
|
Object.defineProperty(exports, "DocumentRepository", {
|
|
20616
22875
|
enumerable: true,
|
|
20617
|
-
get: function () { return
|
|
22876
|
+
get: function () { return chunkI767LVN7_cjs.DocumentRepository; }
|
|
20618
22877
|
});
|
|
20619
22878
|
Object.defineProperty(exports, "ROUTES_INFO", {
|
|
20620
22879
|
enumerable: true,
|
|
20621
|
-
get: function () { return
|
|
22880
|
+
get: function () { return chunkI767LVN7_cjs.ROUTES_INFO; }
|
|
20622
22881
|
});
|
|
20623
22882
|
Object.defineProperty(exports, "adminApiRoutes", {
|
|
20624
22883
|
enumerable: true,
|
|
20625
|
-
get: function () { return
|
|
22884
|
+
get: function () { return chunkI767LVN7_cjs.admin_api_default; }
|
|
20626
22885
|
});
|
|
20627
22886
|
Object.defineProperty(exports, "adminCheckboxRoutes", {
|
|
20628
22887
|
enumerable: true,
|
|
20629
|
-
get: function () { return
|
|
22888
|
+
get: function () { return chunkI767LVN7_cjs.adminCheckboxRoutes; }
|
|
20630
22889
|
});
|
|
20631
22890
|
Object.defineProperty(exports, "adminCollectionsRoutes", {
|
|
20632
22891
|
enumerable: true,
|
|
20633
|
-
get: function () { return
|
|
22892
|
+
get: function () { return chunkI767LVN7_cjs.adminCollectionsRoutes; }
|
|
20634
22893
|
});
|
|
20635
22894
|
Object.defineProperty(exports, "adminContentRoutes", {
|
|
20636
22895
|
enumerable: true,
|
|
20637
|
-
get: function () { return
|
|
22896
|
+
get: function () { return chunkI767LVN7_cjs.admin_content_default; }
|
|
20638
22897
|
});
|
|
20639
22898
|
Object.defineProperty(exports, "adminDashboardRoutes", {
|
|
20640
22899
|
enumerable: true,
|
|
20641
|
-
get: function () { return
|
|
22900
|
+
get: function () { return chunkI767LVN7_cjs.router; }
|
|
20642
22901
|
});
|
|
20643
22902
|
Object.defineProperty(exports, "adminLogsRoutes", {
|
|
20644
22903
|
enumerable: true,
|
|
20645
|
-
get: function () { return
|
|
22904
|
+
get: function () { return chunkI767LVN7_cjs.adminLogsRoutes; }
|
|
20646
22905
|
});
|
|
20647
22906
|
Object.defineProperty(exports, "adminMediaRoutes", {
|
|
20648
22907
|
enumerable: true,
|
|
20649
|
-
get: function () { return
|
|
22908
|
+
get: function () { return chunkI767LVN7_cjs.adminMediaRoutes; }
|
|
20650
22909
|
});
|
|
20651
22910
|
Object.defineProperty(exports, "adminPluginRoutes", {
|
|
20652
22911
|
enumerable: true,
|
|
20653
|
-
get: function () { return
|
|
22912
|
+
get: function () { return chunkI767LVN7_cjs.adminPluginRoutes; }
|
|
20654
22913
|
});
|
|
20655
22914
|
Object.defineProperty(exports, "adminSettingsRoutes", {
|
|
20656
22915
|
enumerable: true,
|
|
20657
|
-
get: function () { return
|
|
22916
|
+
get: function () { return chunkI767LVN7_cjs.adminSettingsRoutes; }
|
|
20658
22917
|
});
|
|
20659
22918
|
Object.defineProperty(exports, "adminUsersRoutes", {
|
|
20660
22919
|
enumerable: true,
|
|
20661
|
-
get: function () { return
|
|
22920
|
+
get: function () { return chunkI767LVN7_cjs.userRoutes; }
|
|
20662
22921
|
});
|
|
20663
22922
|
Object.defineProperty(exports, "apiContentCrudRoutes", {
|
|
20664
22923
|
enumerable: true,
|
|
20665
|
-
get: function () { return
|
|
22924
|
+
get: function () { return chunkI767LVN7_cjs.api_content_crud_default; }
|
|
20666
22925
|
});
|
|
20667
22926
|
Object.defineProperty(exports, "apiMediaRoutes", {
|
|
20668
22927
|
enumerable: true,
|
|
20669
|
-
get: function () { return
|
|
22928
|
+
get: function () { return chunkI767LVN7_cjs.api_media_default; }
|
|
20670
22929
|
});
|
|
20671
22930
|
Object.defineProperty(exports, "apiRoutes", {
|
|
20672
22931
|
enumerable: true,
|
|
20673
|
-
get: function () { return
|
|
22932
|
+
get: function () { return chunkI767LVN7_cjs.api_default; }
|
|
20674
22933
|
});
|
|
20675
22934
|
Object.defineProperty(exports, "apiSystemRoutes", {
|
|
20676
22935
|
enumerable: true,
|
|
20677
|
-
get: function () { return
|
|
22936
|
+
get: function () { return chunkI767LVN7_cjs.api_system_default; }
|
|
20678
22937
|
});
|
|
20679
22938
|
Object.defineProperty(exports, "authRoutes", {
|
|
20680
22939
|
enumerable: true,
|
|
20681
|
-
get: function () { return
|
|
22940
|
+
get: function () { return chunkI767LVN7_cjs.auth_default; }
|
|
20682
22941
|
});
|
|
20683
22942
|
Object.defineProperty(exports, "createUserProfilesPlugin", {
|
|
20684
22943
|
enumerable: true,
|
|
20685
|
-
get: function () { return
|
|
22944
|
+
get: function () { return chunkI767LVN7_cjs.createUserProfilesPlugin; }
|
|
20686
22945
|
});
|
|
20687
22946
|
Object.defineProperty(exports, "defineUserProfile", {
|
|
20688
22947
|
enumerable: true,
|
|
20689
|
-
get: function () { return
|
|
22948
|
+
get: function () { return chunkI767LVN7_cjs.defineUserProfile; }
|
|
20690
22949
|
});
|
|
20691
22950
|
Object.defineProperty(exports, "getUserProfileConfig", {
|
|
20692
22951
|
enumerable: true,
|
|
20693
|
-
get: function () { return
|
|
22952
|
+
get: function () { return chunkI767LVN7_cjs.getUserProfileConfig; }
|
|
20694
22953
|
});
|
|
20695
22954
|
Object.defineProperty(exports, "userProfilesPlugin", {
|
|
20696
22955
|
enumerable: true,
|
|
20697
|
-
get: function () { return
|
|
22956
|
+
get: function () { return chunkI767LVN7_cjs.userProfilesPlugin; }
|
|
20698
22957
|
});
|
|
20699
22958
|
Object.defineProperty(exports, "Logger", {
|
|
20700
22959
|
enumerable: true,
|
|
@@ -20850,87 +23109,87 @@ Object.defineProperty(exports, "workflowHistory", {
|
|
|
20850
23109
|
});
|
|
20851
23110
|
Object.defineProperty(exports, "AuthManager", {
|
|
20852
23111
|
enumerable: true,
|
|
20853
|
-
get: function () { return
|
|
23112
|
+
get: function () { return chunk37V3RET3_cjs.AuthManager; }
|
|
20854
23113
|
});
|
|
20855
23114
|
Object.defineProperty(exports, "PermissionManager", {
|
|
20856
23115
|
enumerable: true,
|
|
20857
|
-
get: function () { return
|
|
23116
|
+
get: function () { return chunk37V3RET3_cjs.PermissionManager; }
|
|
20858
23117
|
});
|
|
20859
23118
|
Object.defineProperty(exports, "bootstrapDocumentTypes", {
|
|
20860
23119
|
enumerable: true,
|
|
20861
|
-
get: function () { return
|
|
23120
|
+
get: function () { return chunk37V3RET3_cjs.bootstrapDocumentTypes; }
|
|
20862
23121
|
});
|
|
20863
23122
|
Object.defineProperty(exports, "bootstrapMiddleware", {
|
|
20864
23123
|
enumerable: true,
|
|
20865
|
-
get: function () { return
|
|
23124
|
+
get: function () { return chunk37V3RET3_cjs.bootstrapMiddleware; }
|
|
20866
23125
|
});
|
|
20867
23126
|
Object.defineProperty(exports, "cacheHeaders", {
|
|
20868
23127
|
enumerable: true,
|
|
20869
|
-
get: function () { return
|
|
23128
|
+
get: function () { return chunk37V3RET3_cjs.cacheHeaders; }
|
|
20870
23129
|
});
|
|
20871
23130
|
Object.defineProperty(exports, "compressionMiddleware", {
|
|
20872
23131
|
enumerable: true,
|
|
20873
|
-
get: function () { return
|
|
23132
|
+
get: function () { return chunk37V3RET3_cjs.compressionMiddleware; }
|
|
20874
23133
|
});
|
|
20875
23134
|
Object.defineProperty(exports, "detailedLoggingMiddleware", {
|
|
20876
23135
|
enumerable: true,
|
|
20877
|
-
get: function () { return
|
|
23136
|
+
get: function () { return chunk37V3RET3_cjs.detailedLoggingMiddleware; }
|
|
20878
23137
|
});
|
|
20879
23138
|
Object.defineProperty(exports, "getActivePlugins", {
|
|
20880
23139
|
enumerable: true,
|
|
20881
|
-
get: function () { return
|
|
23140
|
+
get: function () { return chunk37V3RET3_cjs.getActivePlugins; }
|
|
20882
23141
|
});
|
|
20883
23142
|
Object.defineProperty(exports, "isPluginActive", {
|
|
20884
23143
|
enumerable: true,
|
|
20885
|
-
get: function () { return
|
|
23144
|
+
get: function () { return chunk37V3RET3_cjs.isPluginActive; }
|
|
20886
23145
|
});
|
|
20887
23146
|
Object.defineProperty(exports, "logActivity", {
|
|
20888
23147
|
enumerable: true,
|
|
20889
|
-
get: function () { return
|
|
23148
|
+
get: function () { return chunk37V3RET3_cjs.logActivity; }
|
|
20890
23149
|
});
|
|
20891
23150
|
Object.defineProperty(exports, "loggingMiddleware", {
|
|
20892
23151
|
enumerable: true,
|
|
20893
|
-
get: function () { return
|
|
23152
|
+
get: function () { return chunk37V3RET3_cjs.loggingMiddleware; }
|
|
20894
23153
|
});
|
|
20895
23154
|
Object.defineProperty(exports, "optionalAuth", {
|
|
20896
23155
|
enumerable: true,
|
|
20897
|
-
get: function () { return
|
|
23156
|
+
get: function () { return chunk37V3RET3_cjs.optionalAuth; }
|
|
20898
23157
|
});
|
|
20899
23158
|
Object.defineProperty(exports, "performanceLoggingMiddleware", {
|
|
20900
23159
|
enumerable: true,
|
|
20901
|
-
get: function () { return
|
|
23160
|
+
get: function () { return chunk37V3RET3_cjs.performanceLoggingMiddleware; }
|
|
20902
23161
|
});
|
|
20903
23162
|
Object.defineProperty(exports, "requireActivePlugin", {
|
|
20904
23163
|
enumerable: true,
|
|
20905
|
-
get: function () { return
|
|
23164
|
+
get: function () { return chunk37V3RET3_cjs.requireActivePlugin; }
|
|
20906
23165
|
});
|
|
20907
23166
|
Object.defineProperty(exports, "requireActivePlugins", {
|
|
20908
23167
|
enumerable: true,
|
|
20909
|
-
get: function () { return
|
|
23168
|
+
get: function () { return chunk37V3RET3_cjs.requireActivePlugins; }
|
|
20910
23169
|
});
|
|
20911
23170
|
Object.defineProperty(exports, "requireAnyPermission", {
|
|
20912
23171
|
enumerable: true,
|
|
20913
|
-
get: function () { return
|
|
23172
|
+
get: function () { return chunk37V3RET3_cjs.requireAnyPermission; }
|
|
20914
23173
|
});
|
|
20915
23174
|
Object.defineProperty(exports, "requireAuth", {
|
|
20916
23175
|
enumerable: true,
|
|
20917
|
-
get: function () { return
|
|
23176
|
+
get: function () { return chunk37V3RET3_cjs.requireAuth; }
|
|
20918
23177
|
});
|
|
20919
23178
|
Object.defineProperty(exports, "requirePermission", {
|
|
20920
23179
|
enumerable: true,
|
|
20921
|
-
get: function () { return
|
|
23180
|
+
get: function () { return chunk37V3RET3_cjs.requirePermission; }
|
|
20922
23181
|
});
|
|
20923
23182
|
Object.defineProperty(exports, "requireRole", {
|
|
20924
23183
|
enumerable: true,
|
|
20925
|
-
get: function () { return
|
|
23184
|
+
get: function () { return chunk37V3RET3_cjs.requireRole; }
|
|
20926
23185
|
});
|
|
20927
23186
|
Object.defineProperty(exports, "securityHeaders", {
|
|
20928
23187
|
enumerable: true,
|
|
20929
|
-
get: function () { return
|
|
23188
|
+
get: function () { return chunk37V3RET3_cjs.securityHeadersMiddleware; }
|
|
20930
23189
|
});
|
|
20931
23190
|
Object.defineProperty(exports, "securityLoggingMiddleware", {
|
|
20932
23191
|
enumerable: true,
|
|
20933
|
-
get: function () { return
|
|
23192
|
+
get: function () { return chunk37V3RET3_cjs.securityLoggingMiddleware; }
|
|
20934
23193
|
});
|
|
20935
23194
|
Object.defineProperty(exports, "DocumentsService", {
|
|
20936
23195
|
enumerable: true,
|
|
@@ -20942,167 +23201,167 @@ Object.defineProperty(exports, "RbacService", {
|
|
|
20942
23201
|
});
|
|
20943
23202
|
Object.defineProperty(exports, "PluginBootstrapService", {
|
|
20944
23203
|
enumerable: true,
|
|
20945
|
-
get: function () { return
|
|
23204
|
+
get: function () { return chunkQCJHCSOK_cjs.PluginBootstrapService; }
|
|
20946
23205
|
});
|
|
20947
23206
|
Object.defineProperty(exports, "PluginServiceClass", {
|
|
20948
23207
|
enumerable: true,
|
|
20949
|
-
get: function () { return
|
|
23208
|
+
get: function () { return chunkQCJHCSOK_cjs.PluginService; }
|
|
20950
23209
|
});
|
|
20951
23210
|
Object.defineProperty(exports, "getAvailableCollectionNames", {
|
|
20952
23211
|
enumerable: true,
|
|
20953
|
-
get: function () { return
|
|
23212
|
+
get: function () { return chunkQCJHCSOK_cjs.getAvailableCollectionNames; }
|
|
20954
23213
|
});
|
|
20955
23214
|
Object.defineProperty(exports, "loadCollectionConfig", {
|
|
20956
23215
|
enumerable: true,
|
|
20957
|
-
get: function () { return
|
|
23216
|
+
get: function () { return chunkQCJHCSOK_cjs.loadCollectionConfig; }
|
|
20958
23217
|
});
|
|
20959
23218
|
Object.defineProperty(exports, "loadCollectionConfigs", {
|
|
20960
23219
|
enumerable: true,
|
|
20961
|
-
get: function () { return
|
|
23220
|
+
get: function () { return chunkQCJHCSOK_cjs.loadCollectionConfigs; }
|
|
20962
23221
|
});
|
|
20963
23222
|
Object.defineProperty(exports, "registerCollections", {
|
|
20964
23223
|
enumerable: true,
|
|
20965
|
-
get: function () { return
|
|
23224
|
+
get: function () { return chunkQCJHCSOK_cjs.registerCollections; }
|
|
20966
23225
|
});
|
|
20967
23226
|
Object.defineProperty(exports, "validateCollectionConfig", {
|
|
20968
23227
|
enumerable: true,
|
|
20969
|
-
get: function () { return
|
|
23228
|
+
get: function () { return chunkQCJHCSOK_cjs.validateCollectionConfig; }
|
|
20970
23229
|
});
|
|
20971
23230
|
Object.defineProperty(exports, "MigrationService", {
|
|
20972
23231
|
enumerable: true,
|
|
20973
|
-
get: function () { return
|
|
23232
|
+
get: function () { return chunkA2SN3RVL_cjs.MigrationService; }
|
|
20974
23233
|
});
|
|
20975
23234
|
Object.defineProperty(exports, "renderFilterBar", {
|
|
20976
23235
|
enumerable: true,
|
|
20977
|
-
get: function () { return
|
|
23236
|
+
get: function () { return chunkBBEKHLTW_cjs.renderFilterBar; }
|
|
20978
23237
|
});
|
|
20979
23238
|
Object.defineProperty(exports, "getConfirmationDialogScript", {
|
|
20980
23239
|
enumerable: true,
|
|
20981
|
-
get: function () { return
|
|
23240
|
+
get: function () { return chunkE66UVONV_cjs.getConfirmationDialogScript; }
|
|
20982
23241
|
});
|
|
20983
23242
|
Object.defineProperty(exports, "renderAlert", {
|
|
20984
23243
|
enumerable: true,
|
|
20985
|
-
get: function () { return
|
|
23244
|
+
get: function () { return chunkE66UVONV_cjs.renderAlert; }
|
|
20986
23245
|
});
|
|
20987
23246
|
Object.defineProperty(exports, "renderConfirmationDialog", {
|
|
20988
23247
|
enumerable: true,
|
|
20989
|
-
get: function () { return
|
|
23248
|
+
get: function () { return chunkE66UVONV_cjs.renderConfirmationDialog; }
|
|
20990
23249
|
});
|
|
20991
23250
|
Object.defineProperty(exports, "renderForm", {
|
|
20992
23251
|
enumerable: true,
|
|
20993
|
-
get: function () { return
|
|
23252
|
+
get: function () { return chunkE66UVONV_cjs.renderForm; }
|
|
20994
23253
|
});
|
|
20995
23254
|
Object.defineProperty(exports, "renderFormField", {
|
|
20996
23255
|
enumerable: true,
|
|
20997
|
-
get: function () { return
|
|
23256
|
+
get: function () { return chunkE66UVONV_cjs.renderFormField; }
|
|
20998
23257
|
});
|
|
20999
23258
|
Object.defineProperty(exports, "renderPagination", {
|
|
21000
23259
|
enumerable: true,
|
|
21001
|
-
get: function () { return
|
|
23260
|
+
get: function () { return chunkE66UVONV_cjs.renderPagination; }
|
|
21002
23261
|
});
|
|
21003
23262
|
Object.defineProperty(exports, "renderTable", {
|
|
21004
23263
|
enumerable: true,
|
|
21005
|
-
get: function () { return
|
|
23264
|
+
get: function () { return chunkE66UVONV_cjs.renderTable; }
|
|
21006
23265
|
});
|
|
21007
23266
|
Object.defineProperty(exports, "renderAdminLayoutCatalyst", {
|
|
21008
23267
|
enumerable: true,
|
|
21009
|
-
get: function () { return
|
|
23268
|
+
get: function () { return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst; }
|
|
21010
23269
|
});
|
|
21011
23270
|
Object.defineProperty(exports, "HookSystemImpl", {
|
|
21012
23271
|
enumerable: true,
|
|
21013
|
-
get: function () { return
|
|
23272
|
+
get: function () { return chunkQJUJNTIU_cjs.HookSystemImpl; }
|
|
21014
23273
|
});
|
|
21015
23274
|
Object.defineProperty(exports, "HookUtils", {
|
|
21016
23275
|
enumerable: true,
|
|
21017
|
-
get: function () { return
|
|
23276
|
+
get: function () { return chunkQJUJNTIU_cjs.HookUtils; }
|
|
21018
23277
|
});
|
|
21019
23278
|
Object.defineProperty(exports, "PluginDependencyCycleError", {
|
|
21020
23279
|
enumerable: true,
|
|
21021
|
-
get: function () { return
|
|
23280
|
+
get: function () { return chunkQJUJNTIU_cjs.PluginDependencyCycleError; }
|
|
21022
23281
|
});
|
|
21023
23282
|
Object.defineProperty(exports, "PluginManagerClass", {
|
|
21024
23283
|
enumerable: true,
|
|
21025
|
-
get: function () { return
|
|
23284
|
+
get: function () { return chunkQJUJNTIU_cjs.PluginManager; }
|
|
21026
23285
|
});
|
|
21027
23286
|
Object.defineProperty(exports, "PluginRegistryImpl", {
|
|
21028
23287
|
enumerable: true,
|
|
21029
|
-
get: function () { return
|
|
23288
|
+
get: function () { return chunkQJUJNTIU_cjs.PluginRegistryImpl; }
|
|
21030
23289
|
});
|
|
21031
23290
|
Object.defineProperty(exports, "PluginValidatorClass", {
|
|
21032
23291
|
enumerable: true,
|
|
21033
|
-
get: function () { return
|
|
23292
|
+
get: function () { return chunkQJUJNTIU_cjs.PluginValidator; }
|
|
21034
23293
|
});
|
|
21035
23294
|
Object.defineProperty(exports, "RegisterPluginsError", {
|
|
21036
23295
|
enumerable: true,
|
|
21037
|
-
get: function () { return
|
|
23296
|
+
get: function () { return chunkQJUJNTIU_cjs.RegisterPluginsError; }
|
|
21038
23297
|
});
|
|
21039
23298
|
Object.defineProperty(exports, "ScopedHookSystemClass", {
|
|
21040
23299
|
enumerable: true,
|
|
21041
|
-
get: function () { return
|
|
23300
|
+
get: function () { return chunkQJUJNTIU_cjs.ScopedHookSystem; }
|
|
21042
23301
|
});
|
|
21043
23302
|
Object.defineProperty(exports, "collectCronSchedules", {
|
|
21044
23303
|
enumerable: true,
|
|
21045
|
-
get: function () { return
|
|
23304
|
+
get: function () { return chunkQJUJNTIU_cjs.collectCronSchedules; }
|
|
21046
23305
|
});
|
|
21047
23306
|
Object.defineProperty(exports, "collectCrons", {
|
|
21048
23307
|
enumerable: true,
|
|
21049
|
-
get: function () { return
|
|
23308
|
+
get: function () { return chunkQJUJNTIU_cjs.collectCrons; }
|
|
21050
23309
|
});
|
|
21051
23310
|
Object.defineProperty(exports, "createScheduledHandler", {
|
|
21052
23311
|
enumerable: true,
|
|
21053
|
-
get: function () { return
|
|
23312
|
+
get: function () { return chunkQJUJNTIU_cjs.createScheduledHandler; }
|
|
21054
23313
|
});
|
|
21055
23314
|
Object.defineProperty(exports, "dispatchCronTick", {
|
|
21056
23315
|
enumerable: true,
|
|
21057
|
-
get: function () { return
|
|
21058
|
-
});
|
|
21059
|
-
Object.defineProperty(exports, "getPluginMenu", {
|
|
21060
|
-
enumerable: true,
|
|
21061
|
-
get: function () { return chunkMGHHPNJN_cjs.getPluginMenu; }
|
|
23316
|
+
get: function () { return chunkQJUJNTIU_cjs.dispatchCronTick; }
|
|
21062
23317
|
});
|
|
21063
23318
|
Object.defineProperty(exports, "registerPlugins", {
|
|
21064
23319
|
enumerable: true,
|
|
21065
|
-
get: function () { return
|
|
21066
|
-
});
|
|
21067
|
-
Object.defineProperty(exports, "resetPluginMenu", {
|
|
21068
|
-
enumerable: true,
|
|
21069
|
-
get: function () { return chunkMGHHPNJN_cjs.resetPluginMenu; }
|
|
21070
|
-
});
|
|
21071
|
-
Object.defineProperty(exports, "resolvePluginMenuItems", {
|
|
21072
|
-
enumerable: true,
|
|
21073
|
-
get: function () { return chunkMGHHPNJN_cjs.resolvePluginMenuItems; }
|
|
21074
|
-
});
|
|
21075
|
-
Object.defineProperty(exports, "setPluginMenu", {
|
|
21076
|
-
enumerable: true,
|
|
21077
|
-
get: function () { return chunkMGHHPNJN_cjs.setPluginMenu; }
|
|
23320
|
+
get: function () { return chunkQJUJNTIU_cjs.registerPlugins; }
|
|
21078
23321
|
});
|
|
21079
23322
|
Object.defineProperty(exports, "topoSort", {
|
|
21080
23323
|
enumerable: true,
|
|
21081
|
-
get: function () { return
|
|
23324
|
+
get: function () { return chunkQJUJNTIU_cjs.topoSort; }
|
|
21082
23325
|
});
|
|
21083
23326
|
Object.defineProperty(exports, "applySchemaDefaults", {
|
|
21084
23327
|
enumerable: true,
|
|
21085
|
-
get: function () { return
|
|
23328
|
+
get: function () { return chunkBP52BFIV_cjs.applySchemaDefaults; }
|
|
21086
23329
|
});
|
|
21087
23330
|
Object.defineProperty(exports, "definePlugin", {
|
|
21088
23331
|
enumerable: true,
|
|
21089
|
-
get: function () { return
|
|
23332
|
+
get: function () { return chunkBP52BFIV_cjs.definePlugin; }
|
|
23333
|
+
});
|
|
23334
|
+
Object.defineProperty(exports, "getPluginMenu", {
|
|
23335
|
+
enumerable: true,
|
|
23336
|
+
get: function () { return chunkBP52BFIV_cjs.getPluginMenu; }
|
|
21090
23337
|
});
|
|
21091
23338
|
Object.defineProperty(exports, "isDefinedPlugin", {
|
|
21092
23339
|
enumerable: true,
|
|
21093
|
-
get: function () { return
|
|
23340
|
+
get: function () { return chunkBP52BFIV_cjs.isDefinedPlugin; }
|
|
21094
23341
|
});
|
|
21095
23342
|
Object.defineProperty(exports, "parseConfigSchema", {
|
|
21096
23343
|
enumerable: true,
|
|
21097
|
-
get: function () { return
|
|
23344
|
+
get: function () { return chunkBP52BFIV_cjs.parseConfigSchema; }
|
|
21098
23345
|
});
|
|
21099
23346
|
Object.defineProperty(exports, "parseFormDataToSettings", {
|
|
21100
23347
|
enumerable: true,
|
|
21101
|
-
get: function () { return
|
|
23348
|
+
get: function () { return chunkBP52BFIV_cjs.parseFormDataToSettings; }
|
|
21102
23349
|
});
|
|
21103
23350
|
Object.defineProperty(exports, "renderSchemaFields", {
|
|
21104
23351
|
enumerable: true,
|
|
21105
|
-
get: function () { return
|
|
23352
|
+
get: function () { return chunkBP52BFIV_cjs.renderSchemaFields; }
|
|
23353
|
+
});
|
|
23354
|
+
Object.defineProperty(exports, "resetPluginMenu", {
|
|
23355
|
+
enumerable: true,
|
|
23356
|
+
get: function () { return chunkBP52BFIV_cjs.resetPluginMenu; }
|
|
23357
|
+
});
|
|
23358
|
+
Object.defineProperty(exports, "resolvePluginMenuItems", {
|
|
23359
|
+
enumerable: true,
|
|
23360
|
+
get: function () { return chunkBP52BFIV_cjs.resolvePluginMenuItems; }
|
|
23361
|
+
});
|
|
23362
|
+
Object.defineProperty(exports, "setPluginMenu", {
|
|
23363
|
+
enumerable: true,
|
|
23364
|
+
get: function () { return chunkBP52BFIV_cjs.setPluginMenu; }
|
|
21106
23365
|
});
|
|
21107
23366
|
Object.defineProperty(exports, "getHookSystem", {
|
|
21108
23367
|
enumerable: true,
|
|
@@ -21150,11 +23409,11 @@ Object.defineProperty(exports, "metricsTracker", {
|
|
|
21150
23409
|
});
|
|
21151
23410
|
Object.defineProperty(exports, "SONICJS_VERSION", {
|
|
21152
23411
|
enumerable: true,
|
|
21153
|
-
get: function () { return
|
|
23412
|
+
get: function () { return chunkKKNEYIZJ_cjs.SONICJS_VERSION; }
|
|
21154
23413
|
});
|
|
21155
23414
|
Object.defineProperty(exports, "getCoreVersion", {
|
|
21156
23415
|
enumerable: true,
|
|
21157
|
-
get: function () { return
|
|
23416
|
+
get: function () { return chunkKKNEYIZJ_cjs.getCoreVersion; }
|
|
21158
23417
|
});
|
|
21159
23418
|
Object.defineProperty(exports, "escapeHtml", {
|
|
21160
23419
|
enumerable: true,
|
|
@@ -21178,12 +23437,14 @@ exports.OAuthService = OAuthService;
|
|
|
21178
23437
|
exports.VERSION = VERSION;
|
|
21179
23438
|
exports.createDb = createDb;
|
|
21180
23439
|
exports.createHelloWorldPlugin = createHelloWorldPlugin;
|
|
23440
|
+
exports.createMcpPlugin = createMcpPlugin;
|
|
21181
23441
|
exports.createOAuthProvidersPlugin = createOAuthProvidersPlugin;
|
|
21182
23442
|
exports.createRedirectPlugin = createRedirectPlugin;
|
|
21183
23443
|
exports.createSonicJSApp = createSonicJSApp;
|
|
21184
23444
|
exports.emailReconciliationPlugin = emailReconciliationPlugin;
|
|
21185
23445
|
exports.generateTriggersComment = generateTriggersComment;
|
|
21186
23446
|
exports.helloWorldPlugin = helloWorldPlugin;
|
|
23447
|
+
exports.mcpPlugin = mcpPlugin;
|
|
21187
23448
|
exports.oauthProvidersPlugin = oauthProvidersPlugin;
|
|
21188
23449
|
exports.parseCronTriggers = parseCronTriggers;
|
|
21189
23450
|
exports.redirectPlugin = redirectPlugin;
|