@sonicjs-cms/core 3.0.0-beta.21 → 3.0.0-beta.23

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.
Files changed (106) hide show
  1. package/dist/adapters.cjs +512 -0
  2. package/dist/adapters.cjs.map +1 -0
  3. package/dist/adapters.d.cts +342 -0
  4. package/dist/adapters.d.ts +342 -0
  5. package/dist/adapters.js +501 -0
  6. package/dist/adapters.js.map +1 -0
  7. package/dist/admin-documents-form.template-55V2ZGWT.js +6 -0
  8. package/dist/{admin-documents-form.template-DDSH6ROU.js.map → admin-documents-form.template-55V2ZGWT.js.map} +1 -1
  9. package/dist/admin-documents-form.template-YNAVMJCV.cjs +19 -0
  10. package/dist/{admin-layout-catalyst.template-YQ4EMF2J.js.map → admin-documents-form.template-YNAVMJCV.cjs.map} +1 -1
  11. package/dist/admin-layout-catalyst.template-3XZXDGF7.cjs +21 -0
  12. package/dist/{admin-layout-catalyst.template-KDHKVLXR.cjs.map → admin-layout-catalyst.template-3XZXDGF7.cjs.map} +1 -1
  13. package/dist/admin-layout-catalyst.template-6UQGLCKI.js +7 -0
  14. package/dist/{admin-documents-form.template-LSZKGA5J.cjs.map → admin-layout-catalyst.template-6UQGLCKI.js.map} +1 -1
  15. package/dist/{chunk-7OTOXWEB.js → chunk-2MIYYAO4.js} +49 -4
  16. package/dist/chunk-2MIYYAO4.js.map +1 -0
  17. package/dist/{chunk-A4KUJ3LD.cjs → chunk-4WMZGHIC.cjs} +53 -4
  18. package/dist/chunk-4WMZGHIC.cjs.map +1 -0
  19. package/dist/{chunk-5U75XP74.js → chunk-A46IRC5A.js} +3 -3
  20. package/dist/chunk-A46IRC5A.js.map +1 -0
  21. package/dist/{chunk-KVBHB7QP.cjs → chunk-AT4ZQGEZ.cjs} +17 -2
  22. package/dist/chunk-AT4ZQGEZ.cjs.map +1 -0
  23. package/dist/{chunk-CRGUD4KC.cjs → chunk-BBEKHLTW.cjs} +9 -9
  24. package/dist/{chunk-CRGUD4KC.cjs.map → chunk-BBEKHLTW.cjs.map} +1 -1
  25. package/dist/{chunk-RMRJGMDE.js → chunk-BHND5PEV.js} +3 -3
  26. package/dist/{chunk-RMRJGMDE.js.map → chunk-BHND5PEV.js.map} +1 -1
  27. package/dist/{chunk-OBA2RYZN.js → chunk-BJROXF4N.js} +3 -3
  28. package/dist/{chunk-OBA2RYZN.js.map → chunk-BJROXF4N.js.map} +1 -1
  29. package/dist/{chunk-AOUVUF32.cjs → chunk-C3ZQP5NW.cjs} +12 -5
  30. package/dist/chunk-C3ZQP5NW.cjs.map +1 -0
  31. package/dist/{chunk-7RUW244J.cjs → chunk-CTYLCWMO.cjs} +487 -315
  32. package/dist/chunk-CTYLCWMO.cjs.map +1 -0
  33. package/dist/{chunk-4UYJPHSV.js → chunk-DIBCKCUE.js} +6 -6
  34. package/dist/{chunk-4UYJPHSV.js.map → chunk-DIBCKCUE.js.map} +1 -1
  35. package/dist/{chunk-JEX3UPZL.js → chunk-DPLJYTHE.js} +12 -5
  36. package/dist/chunk-DPLJYTHE.js.map +1 -0
  37. package/dist/{chunk-PXNTCCPE.cjs → chunk-E66UVONV.cjs} +8 -8
  38. package/dist/{chunk-PXNTCCPE.cjs.map → chunk-E66UVONV.cjs.map} +1 -1
  39. package/dist/{chunk-FCLKX2OS.cjs → chunk-IS54FPB7.cjs} +18 -18
  40. package/dist/{chunk-FCLKX2OS.cjs.map → chunk-IS54FPB7.cjs.map} +1 -1
  41. package/dist/{chunk-N32OWET6.cjs → chunk-JMJM7DMM.cjs} +5 -5
  42. package/dist/{chunk-N32OWET6.cjs.map → chunk-JMJM7DMM.cjs.map} +1 -1
  43. package/dist/{chunk-4LVVMVQI.js → chunk-KS24NPPL.js} +17 -2
  44. package/dist/chunk-KS24NPPL.js.map +1 -0
  45. package/dist/{chunk-5UXU3LP4.cjs → chunk-RFBW5RRH.cjs} +11 -59
  46. package/dist/chunk-RFBW5RRH.cjs.map +1 -0
  47. package/dist/{chunk-ZP77LTN4.js → chunk-SK5CHFJP.js} +193 -22
  48. package/dist/chunk-SK5CHFJP.js.map +1 -0
  49. package/dist/{chunk-5V62WT6M.js → chunk-THFZSDIU.js} +4 -2
  50. package/dist/chunk-THFZSDIU.js.map +1 -0
  51. package/dist/{chunk-JQISFW6U.js → chunk-URIBTX27.js} +3 -3
  52. package/dist/{chunk-JQISFW6U.js.map → chunk-URIBTX27.js.map} +1 -1
  53. package/dist/{chunk-K623Q6WD.cjs → chunk-UYJQDDEE.cjs} +4 -2
  54. package/dist/chunk-UYJQDDEE.cjs.map +1 -0
  55. package/dist/{chunk-OJC4G5JE.cjs → chunk-VGHEKIJL.cjs} +3 -3
  56. package/dist/chunk-VGHEKIJL.cjs.map +1 -0
  57. package/dist/{chunk-GICS5AIO.js → chunk-XXRR54AB.js} +5 -49
  58. package/dist/chunk-XXRR54AB.js.map +1 -0
  59. package/dist/{define-plugin-DsKiGu1q.d.cts → define-plugin-DMcvEy_C.d.cts} +33 -0
  60. package/dist/{define-plugin-BYIey6sp.d.ts → define-plugin-D_6D9vVZ.d.ts} +33 -0
  61. package/dist/index.cjs +1807 -332
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.d.cts +2 -2
  64. package/dist/index.d.ts +2 -2
  65. package/dist/index.js +1502 -27
  66. package/dist/index.js.map +1 -1
  67. package/dist/middleware.cjs +34 -34
  68. package/dist/middleware.js +5 -5
  69. package/dist/migrations-XQ6EX6HX.js +4 -0
  70. package/dist/{migrations-HMX5SPN2.js.map → migrations-XQ6EX6HX.js.map} +1 -1
  71. package/dist/migrations-ZD7Y5NUC.cjs +13 -0
  72. package/dist/{migrations-V73ARYV5.cjs.map → migrations-ZD7Y5NUC.cjs.map} +1 -1
  73. package/dist/plugins.cjs +40 -40
  74. package/dist/plugins.d.cts +1 -1
  75. package/dist/plugins.d.ts +1 -1
  76. package/dist/plugins.js +3 -3
  77. package/dist/routes.cjs +29 -29
  78. package/dist/routes.js +9 -9
  79. package/dist/services.cjs +18 -18
  80. package/dist/services.js +2 -2
  81. package/dist/templates.cjs +17 -17
  82. package/dist/templates.js +3 -3
  83. package/dist/utils.cjs +3 -3
  84. package/dist/utils.js +1 -1
  85. package/migrations/0001_core.sql +7 -1
  86. package/package.json +10 -3
  87. package/dist/admin-documents-form.template-DDSH6ROU.js +0 -6
  88. package/dist/admin-documents-form.template-LSZKGA5J.cjs +0 -19
  89. package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs +0 -21
  90. package/dist/admin-layout-catalyst.template-YQ4EMF2J.js +0 -7
  91. package/dist/chunk-4LVVMVQI.js.map +0 -1
  92. package/dist/chunk-5U75XP74.js.map +0 -1
  93. package/dist/chunk-5UXU3LP4.cjs.map +0 -1
  94. package/dist/chunk-5V62WT6M.js.map +0 -1
  95. package/dist/chunk-7OTOXWEB.js.map +0 -1
  96. package/dist/chunk-7RUW244J.cjs.map +0 -1
  97. package/dist/chunk-A4KUJ3LD.cjs.map +0 -1
  98. package/dist/chunk-AOUVUF32.cjs.map +0 -1
  99. package/dist/chunk-GICS5AIO.js.map +0 -1
  100. package/dist/chunk-JEX3UPZL.js.map +0 -1
  101. package/dist/chunk-K623Q6WD.cjs.map +0 -1
  102. package/dist/chunk-KVBHB7QP.cjs.map +0 -1
  103. package/dist/chunk-OJC4G5JE.cjs.map +0 -1
  104. package/dist/chunk-ZP77LTN4.js.map +0 -1
  105. package/dist/migrations-HMX5SPN2.js +0 -4
  106. package/dist/migrations-V73ARYV5.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 chunk7RUW244J_cjs = require('./chunk-7RUW244J.cjs');
4
+ var chunkCTYLCWMO_cjs = require('./chunk-CTYLCWMO.cjs');
5
5
  require('./chunk-XWVDSM2L.cjs');
6
- require('./chunk-N32OWET6.cjs');
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 chunkFCLKX2OS_cjs = require('./chunk-FCLKX2OS.cjs');
10
+ var chunkIS54FPB7_cjs = require('./chunk-IS54FPB7.cjs');
11
11
  var chunkLTZ5WYOK_cjs = require('./chunk-LTZ5WYOK.cjs');
12
12
  var chunkKIGVVO6N_cjs = require('./chunk-KIGVVO6N.cjs');
13
- var chunkKVBHB7QP_cjs = require('./chunk-KVBHB7QP.cjs');
14
- var chunkOJC4G5JE_cjs = require('./chunk-OJC4G5JE.cjs');
15
- var chunkCRGUD4KC_cjs = require('./chunk-CRGUD4KC.cjs');
16
- var chunkPXNTCCPE_cjs = require('./chunk-PXNTCCPE.cjs');
17
- var chunkK623Q6WD_cjs = require('./chunk-K623Q6WD.cjs');
18
- var chunk5UXU3LP4_cjs = require('./chunk-5UXU3LP4.cjs');
19
- var chunkA4KUJ3LD_cjs = require('./chunk-A4KUJ3LD.cjs');
13
+ var chunkAT4ZQGEZ_cjs = require('./chunk-AT4ZQGEZ.cjs');
14
+ var chunkVGHEKIJL_cjs = require('./chunk-VGHEKIJL.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 chunkRFBW5RRH_cjs = require('./chunk-RFBW5RRH.cjs');
19
+ var chunk4WMZGHIC_cjs = require('./chunk-4WMZGHIC.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 chunkAOUVUF32_cjs = require('./chunk-AOUVUF32.cjs');
24
+ var chunkC3ZQP5NW_cjs = require('./chunk-C3ZQP5NW.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
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
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 chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
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("*", chunkFCLKX2OS_cjs.requireAuth());
704
+ router3.use("*", chunkIS54FPB7_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("*", chunkFCLKX2OS_cjs.requireAuth());
1113
+ adminRoutes.use("*", chunkIS54FPB7_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 chunk7RUW244J_cjs.getEmailService().send({
1151
+ const result = await chunkCTYLCWMO_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 chunk7RUW244J_cjs.getEmailService().send({
1233
+ const result = await chunkCTYLCWMO_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 chunk7RUW244J_cjs.getEmailService().send({
1307
+ const result = await chunkCTYLCWMO_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 chunk7RUW244J_cjs.getEmailService().send({
1375
+ const result = await chunkCTYLCWMO_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 = chunkA4KUJ3LD_cjs.definePlugin({
2116
+ var emailPluginV3 = chunk4WMZGHIC_cjs.definePlugin({
2117
2117
  id: "email",
2118
2118
  version: "1.0.0",
2119
2119
  name: "Email",
@@ -2127,7 +2127,7 @@ var emailPluginV3 = chunkA4KUJ3LD_cjs.definePlugin({
2127
2127
  const db = env.DB;
2128
2128
  if (db) {
2129
2129
  try {
2130
- const typeRegistry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db);
2130
+ const typeRegistry = new chunkIS54FPB7_cjs.DocumentTypeRegistry(db);
2131
2131
  await typeRegistry.register({
2132
2132
  id: "email_log",
2133
2133
  name: "email_log",
@@ -2142,7 +2142,7 @@ var emailPluginV3 = chunkA4KUJ3LD_cjs.definePlugin({
2142
2142
  } catch {
2143
2143
  }
2144
2144
  }
2145
- if (!chunk7RUW244J_cjs.hasEmailService()) {
2145
+ if (!chunkCTYLCWMO_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 = chunkA4KUJ3LD_cjs.definePlugin({
2160
2160
  } else {
2161
2161
  provider = resolveEmailProvider({ env });
2162
2162
  }
2163
- chunk7RUW244J_cjs.setEmailService(new EmailService({ ...serviceOpts, provider }));
2163
+ chunkCTYLCWMO_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 = chunkA4KUJ3LD_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 = chunkA4KUJ3LD_cjs.definePlugin({
2174
+ var emailReconciliationPlugin = chunk4WMZGHIC_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 = chunkA4KUJ3LD_cjs.definePlugin({
2192
2192
  console.warn("[email-reconciliation] No DB binding in cron env \u2014 skipping.");
2193
2193
  return;
2194
2194
  }
2195
- if (!chunk7RUW244J_cjs.hasEmailService()) {
2195
+ if (!chunkCTYLCWMO_cjs.hasEmailService()) {
2196
2196
  console.warn("[email-reconciliation] EmailService not initialized \u2014 skipping.");
2197
2197
  return;
2198
2198
  }
2199
- const emailService = chunk7RUW244J_cjs.getEmailService();
2199
+ const emailService = chunkCTYLCWMO_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 (chunk7RUW244J_cjs.hasEmailService()) {
2687
- const sent = await chunk7RUW244J_cjs.getEmailService().send({
2686
+ if (chunkCTYLCWMO_cjs.hasEmailService()) {
2687
+ const sent = await chunkCTYLCWMO_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 chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(db, c.env);
2790
- const token = await chunkFCLKX2OS_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET, tokenTtl);
2789
+ const tokenTtl = await chunkIS54FPB7_cjs.getJwtExpirySecondsFromDb(db, c.env);
2790
+ const token = await chunkIS54FPB7_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
- chunk7RUW244J_cjs.dispatchHookEvent(
2797
+ chunkCTYLCWMO_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 chunk7RUW244J_cjs.getCustomData(db, user.id);
2803
+ const customData = await chunkCTYLCWMO_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 = chunkA4KUJ3LD_cjs.definePlugin({
2848
+ var otpLoginPlugin = chunk4WMZGHIC_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 chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
3247
- const jwt2 = await chunkFCLKX2OS_cjs.AuthManager.generateToken(
3246
+ const tokenTtl2 = await chunkIS54FPB7_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
3247
+ const jwt2 = await chunkIS54FPB7_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
- chunkFCLKX2OS_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax", maxAge: tokenTtl2 });
3254
+ chunkIS54FPB7_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 chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
3272
- const jwt2 = await chunkFCLKX2OS_cjs.AuthManager.generateToken(
3271
+ const tokenTtl2 = await chunkIS54FPB7_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
3272
+ const jwt2 = await chunkIS54FPB7_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
- chunkFCLKX2OS_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax", maxAge: tokenTtl2 });
3279
+ chunkIS54FPB7_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 chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
3293
- const jwt = await chunkFCLKX2OS_cjs.AuthManager.generateToken(
3292
+ const tokenTtl = await chunkIS54FPB7_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
3293
+ const jwt = await chunkIS54FPB7_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
- chunkFCLKX2OS_cjs.AuthManager.setAuthCookie(c, jwt, { sameSite: "Lax", maxAge: tokenTtl });
3300
+ chunkIS54FPB7_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 = chunkA4KUJ3LD_cjs.definePlugin({
3395
+ var oauthProvidersPlugin = chunk4WMZGHIC_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 = chunkKVBHB7QP_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => ({
3979
+ const allCollections = chunkAT4ZQGEZ_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 = chunkKVBHB7QP_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).sort((a, b) => a.displayName.localeCompare(b.displayName)).map((r) => ({
4031
+ const allCollections = chunkAT4ZQGEZ_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 = chunkKVBHB7QP_cjs.getCollectionRegistry();
4370
+ const registry = chunkAT4ZQGEZ_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 chunkPXNTCCPE_cjs.renderAdminLayout({
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("*", chunkFCLKX2OS_cjs.requireAuth());
4997
+ adminRoutes2.use("*", chunkIS54FPB7_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 = chunkA4KUJ3LD_cjs.definePlugin({
5238
+ var aiSearchPlugin = chunk4WMZGHIC_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
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
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 chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
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
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
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 chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
5949
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
5950
5950
  }
5951
5951
 
5952
5952
  // src/plugins/core-plugins/security-audit-plugin/components/settings-page.ts
5953
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
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 chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
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("*", chunkFCLKX2OS_cjs.requireAuth());
6111
+ adminRoutes3.use("*", chunkIS54FPB7_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 chunkKVBHB7QP_cjs.PluginService(db);
6121
+ const pluginService = new chunkAT4ZQGEZ_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 chunkKVBHB7QP_cjs.PluginService(db);
6226
+ const pluginService = new chunkAT4ZQGEZ_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("*", chunkFCLKX2OS_cjs.requireAuth());
6388
+ apiRoutes2.use("*", chunkIS54FPB7_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 chunkKVBHB7QP_cjs.PluginService(db);
6398
+ const pluginService = new chunkAT4ZQGEZ_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 chunkKVBHB7QP_cjs.PluginService(db);
6546
+ const pluginService = new chunkAT4ZQGEZ_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 = chunkA4KUJ3LD_cjs.definePlugin({
6777
+ var securityAuditPlugin = chunk4WMZGHIC_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
- chunk7RUW244J_cjs.createDocumentSchema.parse({
6853
+ chunkCTYLCWMO_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
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
6946
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
6947
6947
  function fmtDate(ms) {
6948
6948
  if (!ms) return "\u2014";
6949
6949
  try {
@@ -6995,14 +6995,18 @@ function renderApiKeysPage(data) {
6995
6995
 
6996
6996
  <!-- Newly-created secret banner (populated by JS, shown once) -->
6997
6997
  <div id="new-key-banner" class="hidden mb-6 rounded-xl bg-emerald-50 dark:bg-emerald-900/20 p-4 ring-1 ring-emerald-200 dark:ring-emerald-800">
6998
- <p class="text-sm font-medium text-emerald-800 dark:text-emerald-300 mb-2">
6999
- Copy your new key now \u2014 it will not be shown again.
7000
- </p>
6998
+ <div class="flex items-start justify-between mb-2">
6999
+ <p class="text-sm font-medium text-emerald-800 dark:text-emerald-300">
7000
+ Copy your new key now \u2014 it will not be shown again.
7001
+ </p>
7002
+ <button type="button" onclick="document.getElementById('new-key-banner').classList.add('hidden')"
7003
+ class="ml-4 text-emerald-600 dark:text-emerald-400 hover:text-emerald-800 dark:hover:text-emerald-200 text-lg leading-none">&times;</button>
7004
+ </div>
7001
7005
  <div class="flex items-center gap-2">
7002
7006
  <code id="new-key-value" class="flex-1 rounded-lg bg-white dark:bg-zinc-900 px-3 py-2 text-sm font-mono text-zinc-950 dark:text-white ring-1 ring-zinc-950/10 dark:ring-white/10 break-all"></code>
7003
7007
  <button type="button" onclick="copyNewKey()"
7004
7008
  class="rounded-lg bg-emerald-600 px-3 py-2 text-sm font-semibold text-white hover:bg-emerald-500 transition-colors">
7005
- Copy
7009
+ Copy &amp; dismiss
7006
7010
  </button>
7007
7011
  </div>
7008
7012
  </div>
@@ -7074,11 +7078,50 @@ function renderApiKeysPage(data) {
7074
7078
  document.getElementById('create-key-modal').classList.add('hidden')
7075
7079
  document.getElementById('new-key-value').textContent = apiKey.key
7076
7080
  document.getElementById('new-key-banner').classList.remove('hidden')
7077
- setTimeout(() => location.reload(), 1500)
7081
+ // Add new key row to table immediately so user can see it without reloading
7082
+ const tbody = document.getElementById('keys-tbody')
7083
+ const emptyRow = tbody.querySelector('td[colspan]')
7084
+ if (emptyRow) emptyRow.closest('tr').remove()
7085
+ const tr = document.createElement('tr')
7086
+ tr.className = 'border-t border-zinc-950/5 dark:border-white/10'
7087
+ tr.setAttribute('data-key-id', apiKey.id)
7088
+ const prefix = apiKey.prefix
7089
+ const today = new Date().toISOString().slice(0, 10)
7090
+ const expires = apiKey.expiresAt ? new Date(apiKey.expiresAt).toISOString().slice(0, 10) : 'Never'
7091
+ // Build row using DOM methods to avoid nested template-literal escaping issues
7092
+ const nameTd = document.createElement('td')
7093
+ nameTd.className = 'py-3 pr-4 text-sm font-medium text-zinc-950 dark:text-white'
7094
+ nameTd.textContent = apiKey.name
7095
+ const prefixTd = document.createElement('td')
7096
+ prefixTd.className = 'py-3 pr-4 text-sm font-mono text-zinc-500 dark:text-zinc-400'
7097
+ prefixTd.textContent = prefix + '\u2026'
7098
+ const createdTd = document.createElement('td')
7099
+ createdTd.className = 'py-3 pr-4 text-sm text-zinc-500 dark:text-zinc-400'
7100
+ createdTd.textContent = today
7101
+ const lastUsedTd = document.createElement('td')
7102
+ lastUsedTd.className = 'py-3 pr-4 text-sm text-zinc-500 dark:text-zinc-400'
7103
+ lastUsedTd.textContent = 'Never'
7104
+ const expiresTd = document.createElement('td')
7105
+ expiresTd.className = 'py-3 pr-4 text-sm text-zinc-500 dark:text-zinc-400'
7106
+ expiresTd.textContent = expires
7107
+ const actionsTd = document.createElement('td')
7108
+ actionsTd.className = 'py-3 text-right'
7109
+ const revokeBtn = document.createElement('button')
7110
+ revokeBtn.type = 'button'
7111
+ revokeBtn.className = 'rounded-lg bg-red-50 dark:bg-red-900/20 px-3 py-1.5 text-sm font-medium text-red-700 dark:text-red-400 hover:bg-red-100 dark:hover:bg-red-900/40 ring-1 ring-red-200 dark:ring-red-800 transition-colors'
7112
+ revokeBtn.textContent = 'Revoke'
7113
+ revokeBtn.addEventListener('click', () => revokeApiKey(apiKey.id, apiKey.name))
7114
+ actionsTd.appendChild(revokeBtn)
7115
+ tr.appendChild(nameTd); tr.appendChild(prefixTd); tr.appendChild(createdTd)
7116
+ tr.appendChild(lastUsedTd); tr.appendChild(expiresTd); tr.appendChild(actionsTd)
7117
+ tbody.appendChild(tr)
7078
7118
  }
7079
7119
  function copyNewKey() {
7080
7120
  const v = document.getElementById('new-key-value').textContent
7081
- navigator.clipboard.writeText(v).then(() => window.showNotification && window.showNotification('Copied', 'success'))
7121
+ navigator.clipboard.writeText(v).then(() => {
7122
+ window.showNotification && window.showNotification('Copied to clipboard', 'success')
7123
+ document.getElementById('new-key-banner').classList.add('hidden')
7124
+ })
7082
7125
  }
7083
7126
  async function revokeApiKey(id, name) {
7084
7127
  if (!confirm('Revoke "' + name + '"? This cannot be undone and will break any client using it.')) return
@@ -7101,7 +7144,7 @@ function renderApiKeysPage(data) {
7101
7144
  version,
7102
7145
  dynamicMenuItems
7103
7146
  };
7104
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
7147
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
7105
7148
  }
7106
7149
 
7107
7150
  // src/plugins/core-plugins/api-keys-plugin/types.ts
@@ -7120,7 +7163,7 @@ var createSchema = zod.z.object({
7120
7163
  });
7121
7164
  async function getSettings3(db) {
7122
7165
  try {
7123
- const plugin2 = await new chunkKVBHB7QP_cjs.PluginService(db).getPlugin("api-keys");
7166
+ const plugin2 = await new chunkAT4ZQGEZ_cjs.PluginService(db).getPlugin("api-keys");
7124
7167
  if (plugin2?.settings) {
7125
7168
  const s = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
7126
7169
  return { ...DEFAULT_SETTINGS3, ...s };
@@ -7129,7 +7172,7 @@ async function getSettings3(db) {
7129
7172
  }
7130
7173
  return DEFAULT_SETTINGS3;
7131
7174
  }
7132
- adminRoutes4.use("*", chunkFCLKX2OS_cjs.requireAuth());
7175
+ adminRoutes4.use("*", chunkIS54FPB7_cjs.requireAuth());
7133
7176
  adminRoutes4.use("*", async (c, next) => {
7134
7177
  const user = c.get("user");
7135
7178
  if (user?.role !== "admin") {
@@ -7214,7 +7257,7 @@ function apiKeyAuthMiddleware() {
7214
7257
 
7215
7258
  // src/plugins/core-plugins/api-keys-plugin/index.ts
7216
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>`;
7217
- var apiKeysPlugin = chunkA4KUJ3LD_cjs.definePlugin({
7260
+ var apiKeysPlugin = chunk4WMZGHIC_cjs.definePlugin({
7218
7261
  id: "api-keys",
7219
7262
  version: "1.0.0-beta.1",
7220
7263
  name: "API Keys",
@@ -7600,7 +7643,7 @@ var StripeEventService = class {
7600
7643
  };
7601
7644
 
7602
7645
  // src/plugins/core-plugins/stripe-plugin/components/subscriptions-page.ts
7603
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
7646
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
7604
7647
 
7605
7648
  // src/plugins/core-plugins/stripe-plugin/components/tab-bar.ts
7606
7649
  var TABS = [
@@ -7733,7 +7776,7 @@ function renderSubscriptionsPage(data) {
7733
7776
  version,
7734
7777
  dynamicMenuItems
7735
7778
  };
7736
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
7779
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
7737
7780
  }
7738
7781
  function statsCard(label, value, colorClass) {
7739
7782
  return `
@@ -7813,7 +7856,7 @@ function renderPagination2(page, totalPages, status) {
7813
7856
  }
7814
7857
 
7815
7858
  // src/plugins/core-plugins/stripe-plugin/components/events-page.ts
7816
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
7859
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
7817
7860
  function renderEventsPage(data) {
7818
7861
  const { events, stats, types, filters, user, version, dynamicMenuItems } = data;
7819
7862
  const content2 = `
@@ -7886,7 +7929,7 @@ function renderEventsPage(data) {
7886
7929
  version,
7887
7930
  dynamicMenuItems
7888
7931
  };
7889
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
7932
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
7890
7933
  }
7891
7934
  function eventStatsCard(label, value, colorClass) {
7892
7935
  return `
@@ -7985,7 +8028,7 @@ var DEFAULT_SETTINGS4 = {
7985
8028
 
7986
8029
  // src/plugins/core-plugins/stripe-plugin/routes/admin.ts
7987
8030
  var adminRoutes5 = new hono.Hono();
7988
- adminRoutes5.use("*", chunkFCLKX2OS_cjs.requireAuth());
8031
+ adminRoutes5.use("*", chunkIS54FPB7_cjs.requireAuth());
7989
8032
  adminRoutes5.use("*", async (c, next) => {
7990
8033
  const user = c.get("user");
7991
8034
  if (user?.role !== "admin") {
@@ -7995,7 +8038,7 @@ adminRoutes5.use("*", async (c, next) => {
7995
8038
  });
7996
8039
  async function getSettings4(db) {
7997
8040
  try {
7998
- const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
8041
+ const pluginService = new chunkAT4ZQGEZ_cjs.PluginService(db);
7999
8042
  const plugin2 = await pluginService.getPlugin("stripe");
8000
8043
  if (plugin2?.settings) {
8001
8044
  const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
@@ -8058,7 +8101,7 @@ adminRoutes5.get("/settings", async (c) => {
8058
8101
  const db = c.env.DB;
8059
8102
  const user = c.get("user");
8060
8103
  const settings = await getSettings4(db);
8061
- const { renderAdminLayoutCatalyst: renderAdminLayoutCatalyst2 } = await import('./admin-layout-catalyst.template-KDHKVLXR.cjs');
8104
+ const { renderAdminLayoutCatalyst: renderAdminLayoutCatalyst2 } = await import('./admin-layout-catalyst.template-3XZXDGF7.cjs');
8062
8105
  const content2 = `
8063
8106
  <div>
8064
8107
  <div class="mb-6">
@@ -8318,7 +8361,7 @@ function timingSafeEqual(a, b) {
8318
8361
  var apiRoutes3 = new hono.Hono();
8319
8362
  async function getSettings5(db) {
8320
8363
  try {
8321
- const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
8364
+ const pluginService = new chunkAT4ZQGEZ_cjs.PluginService(db);
8322
8365
  const plugin2 = await pluginService.getPlugin("stripe");
8323
8366
  if (plugin2?.settings) {
8324
8367
  const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
@@ -8469,7 +8512,7 @@ apiRoutes3.post("/webhook", async (c) => {
8469
8512
  }
8470
8513
  return c.json({ received: true });
8471
8514
  });
8472
- apiRoutes3.post("/create-checkout-session", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
8515
+ apiRoutes3.post("/create-checkout-session", chunkIS54FPB7_cjs.requireAuth(), async (c) => {
8473
8516
  const db = c.env.DB;
8474
8517
  const user = c.get("user");
8475
8518
  if (!user) return c.json({ error: "Unauthorized" }, 401);
@@ -8509,7 +8552,7 @@ apiRoutes3.post("/create-checkout-session", chunkFCLKX2OS_cjs.requireAuth(), asy
8509
8552
  });
8510
8553
  return c.json({ sessionId: session.id, url: session.url });
8511
8554
  });
8512
- apiRoutes3.get("/subscription", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
8555
+ apiRoutes3.get("/subscription", chunkIS54FPB7_cjs.requireAuth(), async (c) => {
8513
8556
  const user = c.get("user");
8514
8557
  if (!user) return c.json({ error: "Unauthorized" }, 401);
8515
8558
  const db = c.env.DB;
@@ -8521,7 +8564,7 @@ apiRoutes3.get("/subscription", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
8521
8564
  }
8522
8565
  return c.json({ subscription });
8523
8566
  });
8524
- apiRoutes3.get("/subscriptions", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
8567
+ apiRoutes3.get("/subscriptions", chunkIS54FPB7_cjs.requireAuth(), async (c) => {
8525
8568
  const user = c.get("user");
8526
8569
  if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
8527
8570
  const db = c.env.DB;
@@ -8537,7 +8580,7 @@ apiRoutes3.get("/subscriptions", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
8537
8580
  const result = await subscriptionService.list(filters);
8538
8581
  return c.json(result);
8539
8582
  });
8540
- apiRoutes3.get("/stats", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
8583
+ apiRoutes3.get("/stats", chunkIS54FPB7_cjs.requireAuth(), async (c) => {
8541
8584
  const user = c.get("user");
8542
8585
  if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
8543
8586
  const db = c.env.DB;
@@ -8546,7 +8589,7 @@ apiRoutes3.get("/stats", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
8546
8589
  const stats = await subscriptionService.getStats();
8547
8590
  return c.json(stats);
8548
8591
  });
8549
- apiRoutes3.post("/sync-subscriptions", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
8592
+ apiRoutes3.post("/sync-subscriptions", chunkIS54FPB7_cjs.requireAuth(), async (c) => {
8550
8593
  const user = c.get("user");
8551
8594
  if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
8552
8595
  const db = c.env.DB;
@@ -8594,7 +8637,7 @@ apiRoutes3.post("/sync-subscriptions", chunkFCLKX2OS_cjs.requireAuth(), async (c
8594
8637
  }, 500);
8595
8638
  }
8596
8639
  });
8597
- apiRoutes3.get("/events", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
8640
+ apiRoutes3.get("/events", chunkIS54FPB7_cjs.requireAuth(), async (c) => {
8598
8641
  const user = c.get("user");
8599
8642
  if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
8600
8643
  const db = c.env.DB;
@@ -8617,7 +8660,7 @@ apiRoutes3.get("/events", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
8617
8660
 
8618
8661
  // src/plugins/core-plugins/stripe-plugin/index.ts
8619
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>`;
8620
- var stripePlugin = chunkA4KUJ3LD_cjs.definePlugin({
8663
+ var stripePlugin = chunk4WMZGHIC_cjs.definePlugin({
8621
8664
  id: "stripe",
8622
8665
  version: "1.0.0",
8623
8666
  name: "Stripe",
@@ -8638,7 +8681,7 @@ var stripePlugin = chunkA4KUJ3LD_cjs.definePlugin({
8638
8681
  });
8639
8682
 
8640
8683
  // src/templates/pages/admin-forms-list.template.ts
8641
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
8684
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
8642
8685
  function renderFormsListPage(data) {
8643
8686
  const tableData = {
8644
8687
  tableId: "forms-table",
@@ -8890,7 +8933,7 @@ function renderFormsListPage(data) {
8890
8933
 
8891
8934
  <!-- Forms Table -->
8892
8935
  <div class="bg-white dark:bg-zinc-900 rounded-lg border border-zinc-950/5 dark:border-white/10 overflow-hidden">
8893
- ${chunk7RUW244J_cjs.renderTable(tableData)}
8936
+ ${chunkCTYLCWMO_cjs.renderTable(tableData)}
8894
8937
  </div>
8895
8938
  </div>
8896
8939
  `;
@@ -8900,11 +8943,11 @@ function renderFormsListPage(data) {
8900
8943
  user: data.user,
8901
8944
  version: data.version
8902
8945
  };
8903
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
8946
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
8904
8947
  }
8905
8948
 
8906
8949
  // src/templates/pages/admin-forms-builder.template.ts
8907
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
8950
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
8908
8951
  function getTurnstileComponentScript() {
8909
8952
  return `
8910
8953
  (function() {
@@ -10117,11 +10160,11 @@ ${getTurnstileComponentScript()}
10117
10160
  user: data.user,
10118
10161
  version: data.version
10119
10162
  };
10120
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
10163
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
10121
10164
  }
10122
10165
 
10123
10166
  // src/templates/pages/admin-forms-create.template.ts
10124
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
10167
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
10125
10168
  function renderFormCreatePage(data) {
10126
10169
  const pageContent = `
10127
10170
  <div class="max-w-3xl mx-auto">
@@ -10314,13 +10357,13 @@ function renderFormCreatePage(data) {
10314
10357
  user: data.user,
10315
10358
  version: data.version
10316
10359
  };
10317
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
10360
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
10318
10361
  }
10319
10362
 
10320
10363
  // src/routes/admin-forms.ts
10321
10364
  var isTableMissing = (err) => String(err?.message ?? err?.cause?.message ?? "").includes("no such table: forms");
10322
10365
  var adminFormsRoutes = new hono.Hono();
10323
- adminFormsRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
10366
+ adminFormsRoutes.use("*", chunkIS54FPB7_cjs.requireAuth());
10324
10367
  adminFormsRoutes.get("/", async (c) => {
10325
10368
  try {
10326
10369
  const user = c.get("user");
@@ -10493,7 +10536,7 @@ adminFormsRoutes.get("/:id/builder", async (c) => {
10493
10536
  if (!form) {
10494
10537
  return c.html("<p>Form not found</p>", 404);
10495
10538
  }
10496
- const turnstileService = new chunk5UXU3LP4_cjs.TurnstileService(db);
10539
+ const turnstileService = new chunkRFBW5RRH_cjs.TurnstileService(db);
10497
10540
  const turnstileSettings = await turnstileService.getSettings();
10498
10541
  const pageData = {
10499
10542
  id: form.id,
@@ -10662,7 +10705,7 @@ publicFormsRoutes.get("/:identifier/turnstile-config", async (c) => {
10662
10705
  if (!form) {
10663
10706
  return c.json({ error: "Form not found" }, 404);
10664
10707
  }
10665
- const turnstileService = new chunk5UXU3LP4_cjs.TurnstileService(db);
10708
+ const turnstileService = new chunkRFBW5RRH_cjs.TurnstileService(db);
10666
10709
  const globalSettings = await turnstileService.getSettings();
10667
10710
  const formSettings = form.turnstile_settings ? JSON.parse(form.turnstile_settings) : { inherit: true };
10668
10711
  const enabled = form.turnstile_enabled === 1 || formSettings.inherit && globalSettings?.enabled;
@@ -11092,7 +11135,7 @@ publicFormsRoutes.post("/:identifier/submit", async (c) => {
11092
11135
  const turnstileEnabled = form.turnstile_enabled === 1;
11093
11136
  const turnstileSettings = form.turnstile_settings ? JSON.parse(form.turnstile_settings) : { inherit: true };
11094
11137
  if (turnstileEnabled || turnstileSettings.inherit) {
11095
- const turnstileService = new chunk5UXU3LP4_cjs.TurnstileService(db);
11138
+ const turnstileService = new chunkRFBW5RRH_cjs.TurnstileService(db);
11096
11139
  const globalEnabled = await turnstileService.isEnabled();
11097
11140
  if (globalEnabled || turnstileEnabled) {
11098
11141
  const turnstileToken = body.data?.turnstile || body.turnstile;
@@ -11154,7 +11197,7 @@ publicFormsRoutes.post("/:identifier/submit", async (c) => {
11154
11197
  });
11155
11198
 
11156
11199
  // src/plugins/core-plugins/forms-plugin/index.ts
11157
- var formsPlugin = chunkA4KUJ3LD_cjs.definePlugin({
11200
+ var formsPlugin = chunk4WMZGHIC_cjs.definePlugin({
11158
11201
  id: "forms",
11159
11202
  version: "1.0.0",
11160
11203
  name: "Forms",
@@ -11172,9 +11215,9 @@ var formsPlugin = chunkA4KUJ3LD_cjs.definePlugin({
11172
11215
  activate: async () => console.info("\u2705 Forms plugin activated"),
11173
11216
  deactivate: async () => console.info("\u274C Forms plugin deactivated")
11174
11217
  });
11175
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
11218
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
11176
11219
  var adminRbacRoutes = new hono.Hono();
11177
- adminRbacRoutes.use("*", chunkFCLKX2OS_cjs.requireRbac("rbac", "manage"));
11220
+ adminRbacRoutes.use("*", chunkIS54FPB7_cjs.requireRbac("rbac", "manage"));
11178
11221
  var esc = (s) => String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
11179
11222
  var TABS2 = `
11180
11223
  <div class="border-b border-zinc-950/10 dark:border-white/10 mb-6">
@@ -11478,11 +11521,11 @@ adminRbacRoutes.get("/", async (c) => {
11478
11521
  </script>`;
11479
11522
  const u = c.get("user");
11480
11523
  return c.html(
11481
- chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
11524
+ chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
11482
11525
  title: "Roles & Permissions",
11483
11526
  pageTitle: "Roles & Permissions",
11484
11527
  currentPath: "/admin/users",
11485
- version: chunkAOUVUF32_cjs.getCoreVersion(),
11528
+ version: chunkC3ZQP5NW_cjs.getCoreVersion(),
11486
11529
  user: u ? { name: u.email || "Admin", email: u.email || "", role: u.role || "admin" } : void 0,
11487
11530
  content: content2
11488
11531
  })
@@ -11619,7 +11662,7 @@ adminRbacRoutes.get("/check", async (c) => {
11619
11662
  });
11620
11663
 
11621
11664
  // src/middleware/plugin-menu.ts
11622
- var REGISTRY_MENU_PLUGINS = Object.values(chunkKVBHB7QP_cjs.PLUGIN_REGISTRY).filter((p) => p.adminMenu !== null).map((p) => ({
11665
+ var REGISTRY_MENU_PLUGINS = Object.values(chunkAT4ZQGEZ_cjs.PLUGIN_REGISTRY).filter((p) => p.adminMenu !== null).map((p) => ({
11623
11666
  id: p.id,
11624
11667
  label: p.adminMenu.label,
11625
11668
  path: p.adminMenu.path,
@@ -11698,7 +11741,7 @@ function pluginMenuMiddleware() {
11698
11741
  } catch {
11699
11742
  }
11700
11743
  const user = c.get("user");
11701
- const singletonItems = chunk5UXU3LP4_cjs.resolvePluginMenuItems(user ? { role: user.role } : void 0);
11744
+ const singletonItems = chunk4WMZGHIC_cjs.resolvePluginMenuItems(user ? { role: user.role } : void 0);
11702
11745
  const existingPaths = new Set(activeMenuItems.map((i) => i.path));
11703
11746
  for (const item of singletonItems) {
11704
11747
  if (!existingPaths.has(item.path)) {
@@ -11723,9 +11766,1439 @@ function pluginMenuMiddleware() {
11723
11766
  }
11724
11767
  };
11725
11768
  }
11726
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
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("*", chunkIS54FPB7_cjs.requireAuth());
12917
+ adminMenuRoutes.use("*", chunkIS54FPB7_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 = chunk4WMZGHIC_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 chunkIS54FPB7_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 chunkCTYLCWMO_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();
11727
13200
  var adminRoutes6 = new hono.Hono();
11728
- adminRoutes6.use("*", chunkFCLKX2OS_cjs.requireAuth());
13201
+ adminRoutes6.use("*", chunkIS54FPB7_cjs.requireAuth());
11729
13202
  adminRoutes6.use("*", async (c, next) => {
11730
13203
  const user = c.get("user");
11731
13204
  if (user?.role !== "admin") {
@@ -11841,7 +13314,7 @@ adminRoutes6.get("/", async (c) => {
11841
13314
  </div>
11842
13315
  </div>
11843
13316
  `;
11844
- return c.html(chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
13317
+ return c.html(chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
11845
13318
  title: "Analytics",
11846
13319
  pageTitle: "Analytics Dashboard",
11847
13320
  currentPath: "/admin/analytics",
@@ -12081,7 +13554,7 @@ apiRoutes4.get("/stats", async (c) => {
12081
13554
  });
12082
13555
 
12083
13556
  // src/plugins/core-plugins/analytics/index.ts
12084
- var analyticsPlugin = chunkA4KUJ3LD_cjs.definePlugin({
13557
+ var analyticsPlugin = chunk4WMZGHIC_cjs.definePlugin({
12085
13558
  id: "core-analytics",
12086
13559
  version: "1.0.0",
12087
13560
  name: "Analytics",
@@ -12228,7 +13701,7 @@ function esc2(s) {
12228
13701
  return (s || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
12229
13702
  }
12230
13703
  async function getVariablesMap(db) {
12231
- let variables = chunk7RUW244J_cjs.getVariablesCached();
13704
+ let variables = chunkCTYLCWMO_cjs.getVariablesCached();
12232
13705
  if (variables) return variables;
12233
13706
  try {
12234
13707
  const { results } = await db.prepare(
@@ -12238,7 +13711,7 @@ async function getVariablesMap(db) {
12238
13711
  for (const row of results || []) {
12239
13712
  variables.set(row.key, row.value);
12240
13713
  }
12241
- chunk7RUW244J_cjs.setVariablesCache(variables);
13714
+ chunkCTYLCWMO_cjs.setVariablesCache(variables);
12242
13715
  return variables;
12243
13716
  } catch {
12244
13717
  return /* @__PURE__ */ new Map();
@@ -12307,7 +13780,7 @@ apiRoutes5.post("/", async (c) => {
12307
13780
  await db.prepare(
12308
13781
  "INSERT INTO global_variables (key, value, description, category, is_active) VALUES (?, ?, ?, ?, ?)"
12309
13782
  ).bind(key, value || "", description || "", category || "general", isActive !== false ? 1 : 0).run();
12310
- chunk7RUW244J_cjs.invalidateVariablesCache();
13783
+ chunkCTYLCWMO_cjs.invalidateVariablesCache();
12311
13784
  const created = await db.prepare("SELECT * FROM global_variables WHERE key = ?").bind(key).first();
12312
13785
  return c.json({ success: true, data: formatVariable(created) }, 201);
12313
13786
  } catch {
@@ -12352,7 +13825,7 @@ apiRoutes5.put("/:id", async (c) => {
12352
13825
  updates.push("updated_at = strftime('%s', 'now')");
12353
13826
  params.push(id);
12354
13827
  await db.prepare(`UPDATE global_variables SET ${updates.join(", ")} WHERE id = ?`).bind(...params).run();
12355
- chunk7RUW244J_cjs.invalidateVariablesCache();
13828
+ chunkCTYLCWMO_cjs.invalidateVariablesCache();
12356
13829
  const updated = await db.prepare("SELECT * FROM global_variables WHERE id = ?").bind(id).first();
12357
13830
  return c.json({ success: true, data: formatVariable(updated) });
12358
13831
  } catch {
@@ -12366,7 +13839,7 @@ apiRoutes5.delete("/:id", async (c) => {
12366
13839
  const existing = await db.prepare("SELECT id FROM global_variables WHERE id = ?").bind(id).first();
12367
13840
  if (!existing) return c.json({ error: "Variable not found" }, 404);
12368
13841
  await db.prepare("DELETE FROM global_variables WHERE id = ?").bind(id).run();
12369
- chunk7RUW244J_cjs.invalidateVariablesCache();
13842
+ chunkCTYLCWMO_cjs.invalidateVariablesCache();
12370
13843
  return c.json({ success: true });
12371
13844
  } catch {
12372
13845
  return c.json({ success: false, error: "Failed to delete variable" }, 500);
@@ -12426,7 +13899,7 @@ adminRoutes7.put("/:id", async (c) => {
12426
13899
  const value = body.value;
12427
13900
  if (value !== void 0) {
12428
13901
  await db.prepare("UPDATE global_variables SET value = ?, updated_at = strftime('%s', 'now') WHERE id = ?").bind(value, id).run();
12429
- chunk7RUW244J_cjs.invalidateVariablesCache();
13902
+ chunkCTYLCWMO_cjs.invalidateVariablesCache();
12430
13903
  }
12431
13904
  return c.html('<span class="text-green-400 text-xs">Saved</span>');
12432
13905
  });
@@ -12434,7 +13907,7 @@ adminRoutes7.post("/:id/toggle", async (c) => {
12434
13907
  const db = c.env.DB;
12435
13908
  const id = c.req.param("id");
12436
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();
12437
- chunk7RUW244J_cjs.invalidateVariablesCache();
13910
+ chunkCTYLCWMO_cjs.invalidateVariablesCache();
12438
13911
  c.header("HX-Redirect", "/admin/global-variables");
12439
13912
  return c.body(null, 204);
12440
13913
  });
@@ -12455,7 +13928,7 @@ adminRoutes7.post("/", async (c) => {
12455
13928
  await db.prepare(
12456
13929
  "INSERT INTO global_variables (key, value, description, category) VALUES (?, ?, ?, ?)"
12457
13930
  ).bind(key, value, description, category).run();
12458
- chunk7RUW244J_cjs.invalidateVariablesCache();
13931
+ chunkCTYLCWMO_cjs.invalidateVariablesCache();
12459
13932
  c.header("HX-Redirect", "/admin/global-variables");
12460
13933
  return c.body(null, 204);
12461
13934
  });
@@ -12474,7 +13947,7 @@ adminRoutes7.post("/settings/editor-integration", async (c) => {
12474
13947
  adminRoutes7.delete("/:id", async (c) => {
12475
13948
  const db = c.env.DB;
12476
13949
  await db.prepare("DELETE FROM global_variables WHERE id = ?").bind(c.req.param("id")).run();
12477
- chunk7RUW244J_cjs.invalidateVariablesCache();
13950
+ chunkCTYLCWMO_cjs.invalidateVariablesCache();
12478
13951
  return c.html("");
12479
13952
  });
12480
13953
  function renderAdminPage(variables, editorStatus = { editorActive: false, activeEditorName: "", enableEditorIntegration: true }) {
@@ -12792,7 +14265,7 @@ function renderAdminPage(variables, editorStatus = { editorActive: false, active
12792
14265
  </div>
12793
14266
  ` });
12794
14267
  }
12795
- var globalVariablesPlugin = chunkA4KUJ3LD_cjs.definePlugin({
14268
+ var globalVariablesPlugin = chunk4WMZGHIC_cjs.definePlugin({
12796
14269
  id: "global-variables",
12797
14270
  version: "1.1.0",
12798
14271
  name: "Global Variables",
@@ -12815,7 +14288,7 @@ var globalVariablesPlugin = chunkA4KUJ3LD_cjs.definePlugin({
12815
14288
  if (!db || !data) return data;
12816
14289
  const variables = await getVariablesMap(db);
12817
14290
  if (variables.size === 0) return data;
12818
- return chunk7RUW244J_cjs.resolveVariablesInObject(data, variables);
14291
+ return chunkCTYLCWMO_cjs.resolveVariablesInObject(data, variables);
12819
14292
  } catch {
12820
14293
  return data;
12821
14294
  }
@@ -12833,7 +14306,7 @@ var globalVariablesPlugin = chunkA4KUJ3LD_cjs.definePlugin({
12833
14306
  },
12834
14307
  activate: async () => console.info("[GlobalVariables] Plugin activated"),
12835
14308
  deactivate: async () => {
12836
- chunk7RUW244J_cjs.invalidateVariablesCache();
14309
+ chunkCTYLCWMO_cjs.invalidateVariablesCache();
12837
14310
  console.info("[GlobalVariables] Plugin deactivated, cache cleared");
12838
14311
  },
12839
14312
  uninstall: async (ctx) => {
@@ -13399,7 +14872,7 @@ function renderAdminPage2(shortcodes, editorStatus = { editorActive: false, acti
13399
14872
  </div>
13400
14873
  ` });
13401
14874
  }
13402
- var shortcodesPlugin = chunkA4KUJ3LD_cjs.definePlugin({
14875
+ var shortcodesPlugin = chunk4WMZGHIC_cjs.definePlugin({
13403
14876
  id: "shortcodes",
13404
14877
  version: "1.0.0",
13405
14878
  name: "Shortcodes",
@@ -13483,7 +14956,7 @@ helloWorldRoutes.get("/", async (c) => {
13483
14956
  </html>
13484
14957
  `);
13485
14958
  });
13486
- var helloWorldPlugin = chunkA4KUJ3LD_cjs.definePlugin({
14959
+ var helloWorldPlugin = chunk4WMZGHIC_cjs.definePlugin({
13487
14960
  id: "hello-world",
13488
14961
  version: "1.0.0",
13489
14962
  name: "Hello World",
@@ -13530,7 +15003,7 @@ var manifest_default2 = {
13530
15003
  author: "SonicJS Team"};
13531
15004
 
13532
15005
  // src/plugins/core-plugins/multi-tenant-plugin/templates/tenants-list.template.ts
13533
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
15006
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
13534
15007
  function statusBadge2(status) {
13535
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>';
13536
15009
  }
@@ -13603,7 +15076,7 @@ function renderTenantsList(data) {
13603
15076
  </table>
13604
15077
  </div>
13605
15078
  </div>`;
13606
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
15079
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
13607
15080
  title: "Tenants - SonicJS",
13608
15081
  pageTitle: "Tenants",
13609
15082
  currentPath: "/admin/tenants",
@@ -13622,7 +15095,7 @@ function renderTenantsInactive(data) {
13622
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>
13623
15096
  </div>
13624
15097
  </div>`;
13625
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
15098
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
13626
15099
  title: "Tenants - SonicJS",
13627
15100
  pageTitle: "Tenants",
13628
15101
  currentPath: "/admin/tenants",
@@ -13633,7 +15106,7 @@ function renderTenantsInactive(data) {
13633
15106
  }
13634
15107
 
13635
15108
  // src/plugins/core-plugins/multi-tenant-plugin/templates/tenant-form.template.ts
13636
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
15109
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
13637
15110
  function fieldErrors(errors, field) {
13638
15111
  const list = errors?.[field];
13639
15112
  if (!list || list.length === 0) return "";
@@ -13701,7 +15174,7 @@ function renderTenantForm(data) {
13701
15174
  </form>
13702
15175
  </div>
13703
15176
  </div>`;
13704
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
15177
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
13705
15178
  title: `${data.isEdit ? "Edit Tenant" : "New Tenant"} - SonicJS`,
13706
15179
  pageTitle: data.isEdit ? "Edit Tenant" : "New Tenant",
13707
15180
  currentPath: "/admin/tenants",
@@ -13712,9 +15185,9 @@ function renderTenantForm(data) {
13712
15185
  }
13713
15186
 
13714
15187
  // src/plugins/core-plugins/multi-tenant-plugin/templates/tenant-members.template.ts
13715
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
15188
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
13716
15189
  function roleOptions(selected) {
13717
- return chunk7RUW244J_cjs.VALID_MEMBER_ROLES.map(
15190
+ return chunkCTYLCWMO_cjs.VALID_MEMBER_ROLES.map(
13718
15191
  (r) => `<option value="${r}" ${r === selected ? "selected" : ""}>${r}</option>`
13719
15192
  ).join("");
13720
15193
  }
@@ -13776,7 +15249,7 @@ function renderInvitations(slug, invitations) {
13776
15249
  <div>
13777
15250
  <label for="invite-role" class="mb-1 block text-xs font-medium text-zinc-500 dark:text-zinc-400">Role</label>
13778
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">
13779
- ${chunk7RUW244J_cjs.VALID_MEMBER_ROLES.map((r) => `<option value="${r}" ${r === "viewer" ? "selected" : ""}>${r}</option>`).join("")}
15252
+ ${chunkCTYLCWMO_cjs.VALID_MEMBER_ROLES.map((r) => `<option value="${r}" ${r === "viewer" ? "selected" : ""}>${r}</option>`).join("")}
13780
15253
  </select>
13781
15254
  </div>
13782
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>
@@ -13859,7 +15332,7 @@ function renderTenantMembers(data) {
13859
15332
 
13860
15333
  ${renderInvitations(data.slug, data.invitations)}
13861
15334
  </div>`;
13862
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
15335
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
13863
15336
  title: `Members - ${data.tenantName} - SonicJS`,
13864
15337
  pageTitle: "Tenant Members",
13865
15338
  currentPath: "/admin/tenants",
@@ -13870,9 +15343,9 @@ function renderTenantMembers(data) {
13870
15343
  }
13871
15344
 
13872
15345
  // src/plugins/core-plugins/multi-tenant-plugin/templates/user-memberships.template.ts
13873
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
15346
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
13874
15347
  function roleOptions2(selected) {
13875
- return chunk7RUW244J_cjs.VALID_MEMBER_ROLES.map(
15348
+ return chunkCTYLCWMO_cjs.VALID_MEMBER_ROLES.map(
13876
15349
  (r) => `<option value="${r}" ${r === selected ? "selected" : ""}>${r}</option>`
13877
15350
  ).join("");
13878
15351
  }
@@ -13945,7 +15418,7 @@ function renderUserMemberships(data) {
13945
15418
  </table>
13946
15419
  </div>
13947
15420
  </div>`;
13948
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
15421
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
13949
15422
  title: `Tenant memberships - ${data.userEmail} - SonicJS`,
13950
15423
  pageTitle: "Tenant memberships",
13951
15424
  currentPath: "/admin/users",
@@ -13956,7 +15429,7 @@ function renderUserMemberships(data) {
13956
15429
  }
13957
15430
 
13958
15431
  // src/plugins/core-plugins/multi-tenant-plugin/templates/role-usage.template.ts
13959
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
15432
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
13960
15433
  function renderRoleUsage(data) {
13961
15434
  const role = chunkMNWKYY5E_cjs.escapeHtml(data.roleName);
13962
15435
  const rows = data.assignments.length ? data.assignments.map((a) => `
@@ -13991,7 +15464,7 @@ function renderRoleUsage(data) {
13991
15464
  </table>
13992
15465
  </div>
13993
15466
  </div>`;
13994
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
15467
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
13995
15468
  title: `Role usage - ${data.roleName} - SonicJS`,
13996
15469
  pageTitle: "Role usage",
13997
15470
  currentPath: "/admin/tenants",
@@ -14034,7 +15507,7 @@ function zodToFieldErrors(error) {
14034
15507
  }
14035
15508
  async function isMultiTenantActive(db) {
14036
15509
  try {
14037
- const plugin2 = await new chunkKVBHB7QP_cjs.PluginService(db).getPlugin(chunkKVBHB7QP_cjs.MULTI_TENANT_PLUGIN_ID);
15510
+ const plugin2 = await new chunkAT4ZQGEZ_cjs.PluginService(db).getPlugin(chunkAT4ZQGEZ_cjs.MULTI_TENANT_PLUGIN_ID);
14038
15511
  return plugin2?.status === "active";
14039
15512
  } catch {
14040
15513
  return false;
@@ -14042,7 +15515,7 @@ async function isMultiTenantActive(db) {
14042
15515
  }
14043
15516
  function createTenantAdminRoutes() {
14044
15517
  const routes2 = new hono.Hono();
14045
- routes2.use("*", chunkFCLKX2OS_cjs.requireAuth());
15518
+ routes2.use("*", chunkIS54FPB7_cjs.requireAuth());
14046
15519
  routes2.use("*", async (c, next) => {
14047
15520
  const user = c.get("user");
14048
15521
  if (user?.role !== "admin") {
@@ -14056,7 +15529,7 @@ function createTenantAdminRoutes() {
14056
15529
  const form = await c.req.formData();
14057
15530
  const slug = String(form.get("tenant") ?? "").trim().toLowerCase();
14058
15531
  const redirect = String(form.get("redirect") ?? "");
14059
- const svc = new chunk7RUW244J_cjs.TenantService(db);
15532
+ const svc = new chunkCTYLCWMO_cjs.TenantService(db);
14060
15533
  const tenant = await svc.getTenantBySlug(slug);
14061
15534
  if (!tenant || tenant.status !== "active") {
14062
15535
  return c.json({ error: "Unknown or inactive tenant" }, 400);
@@ -14066,7 +15539,7 @@ function createTenantAdminRoutes() {
14066
15539
  if (!user.isSuperAdmin && !await svc.isMember(user.userId, slug)) {
14067
15540
  return c.json({ error: "You are not a member of this tenant" }, 403);
14068
15541
  }
14069
- cookie.setCookie(c, chunkKVBHB7QP_cjs.TENANT_COOKIE, slug, {
15542
+ cookie.setCookie(c, chunkAT4ZQGEZ_cjs.TENANT_COOKIE, slug, {
14070
15543
  path: "/",
14071
15544
  httpOnly: true,
14072
15545
  sameSite: "Lax",
@@ -14083,7 +15556,7 @@ function createTenantAdminRoutes() {
14083
15556
  if (!user) return c.redirect("/auth/login");
14084
15557
  const token = c.req.query("token") ?? "";
14085
15558
  try {
14086
- const { slug } = await new chunk7RUW244J_cjs.TenantService(db).acceptInvitation(token, user.userId, user.email);
15559
+ const { slug } = await new chunkCTYLCWMO_cjs.TenantService(db).acceptInvitation(token, user.userId, user.email);
14087
15560
  return c.redirect(`/admin/tenants/${slug}/members?message=Invitation accepted`);
14088
15561
  } catch (error) {
14089
15562
  const message = error instanceof Error ? error.message : "Failed to accept invitation";
@@ -14111,7 +15584,7 @@ function createTenantAdminRoutes() {
14111
15584
  const userId = c.req.param("userId");
14112
15585
  const target = await db.prepare("SELECT id, email FROM auth_user WHERE id = ?").bind(userId).first();
14113
15586
  if (!target?.id) return c.redirect("/admin/users?message=User not found&type=error");
14114
- const svc = new chunk7RUW244J_cjs.TenantService(db);
15587
+ const svc = new chunkCTYLCWMO_cjs.TenantService(db);
14115
15588
  const [memberships, allTenants] = await Promise.all([svc.listUserMemberships(userId), svc.listTenants()]);
14116
15589
  const memberSlugs = new Set(memberships.map((m) => m.slug));
14117
15590
  const availableTenants = allTenants.filter((t) => t.status === "active" && !memberSlugs.has(t.slug)).map((t) => ({ slug: t.slug, name: t.name }));
@@ -14136,10 +15609,10 @@ function createTenantAdminRoutes() {
14136
15609
  const slug = String(form.get("slug") ?? "").trim().toLowerCase();
14137
15610
  const role = String(form.get("role") ?? "viewer");
14138
15611
  const redirectTo = String(form.get("_redirect") ?? "") || `/admin/tenants/users/${userId}`;
14139
- if (!chunk7RUW244J_cjs.isValidMemberRole(role)) throw new Error(`Invalid role '${role}'`);
15612
+ if (!chunkCTYLCWMO_cjs.isValidMemberRole(role)) throw new Error(`Invalid role '${role}'`);
14140
15613
  const target = await db.prepare("SELECT email FROM auth_user WHERE id = ?").bind(userId).first();
14141
15614
  if (!target) throw new Error("User not found");
14142
- const svc = new chunk7RUW244J_cjs.TenantService(db);
15615
+ const svc = new chunkCTYLCWMO_cjs.TenantService(db);
14143
15616
  if (!await svc.getTenantBySlug(slug)) throw new Error("Tenant not found");
14144
15617
  if (await svc.isMember(userId, slug)) throw new Error(`Already a member of '${slug}'`);
14145
15618
  await svc.addMember(slug, userId, role, target.email ?? null);
@@ -14158,7 +15631,7 @@ function createTenantAdminRoutes() {
14158
15631
  const form = await c.req.formData();
14159
15632
  const role = String(form.get("role") ?? "");
14160
15633
  const redirectTo = String(form.get("_redirect") ?? "") || `/admin/tenants/users/${userId}`;
14161
- await new chunk7RUW244J_cjs.TenantService(db).setMemberRole(slug, userId, role);
15634
+ await new chunkCTYLCWMO_cjs.TenantService(db).setMemberRole(slug, userId, role);
14162
15635
  return c.redirect(`${redirectTo}?message=Role updated`);
14163
15636
  } catch (error) {
14164
15637
  const message = error instanceof Error ? error.message : "Failed to update role";
@@ -14173,7 +15646,7 @@ function createTenantAdminRoutes() {
14173
15646
  try {
14174
15647
  const form = await c.req.formData();
14175
15648
  const redirectTo = String(form.get("_redirect") ?? "") || `/admin/tenants/users/${userId}`;
14176
- await new chunk7RUW244J_cjs.TenantService(db).removeMember(slug, userId);
15649
+ await new chunkCTYLCWMO_cjs.TenantService(db).removeMember(slug, userId);
14177
15650
  return c.redirect(`${redirectTo}?message=Removed from ${encodeURIComponent(slug)}`);
14178
15651
  } catch (error) {
14179
15652
  const message = error instanceof Error ? error.message : "Failed to remove membership";
@@ -14188,7 +15661,7 @@ function createTenantAdminRoutes() {
14188
15661
  return c.html(renderTenantsInactive({ user: userShape(cur), version }));
14189
15662
  }
14190
15663
  const roleName = c.req.param("roleName");
14191
- const assignments = await new chunk7RUW244J_cjs.TenantService(db).listAssignmentsByRole(roleName);
15664
+ const assignments = await new chunkCTYLCWMO_cjs.TenantService(db).listAssignmentsByRole(roleName);
14192
15665
  return c.html(renderRoleUsage({ roleName, assignments, user: userShape(cur), version }));
14193
15666
  });
14194
15667
  routes2.get("/", async (c) => {
@@ -14198,7 +15671,7 @@ function createTenantAdminRoutes() {
14198
15671
  if (!await isMultiTenantActive(db)) {
14199
15672
  return c.html(renderTenantsInactive({ user: userShape(user), version }));
14200
15673
  }
14201
- const svc = new chunk7RUW244J_cjs.TenantService(db);
15674
+ const svc = new chunkCTYLCWMO_cjs.TenantService(db);
14202
15675
  await svc.ensureDefaultTenant();
14203
15676
  const tenants = await svc.listTenants();
14204
15677
  const [docRes, memberRes] = await db.batch([
@@ -14237,7 +15710,7 @@ function createTenantAdminRoutes() {
14237
15710
  formEntries = Object.fromEntries(form.entries());
14238
15711
  const validated = tenantFormSchema.parse(formEntries);
14239
15712
  if (!validated.slug) throw new zod.z.ZodError([{ code: "custom", message: "Slug is required", path: ["slug"] }]);
14240
- const svc = new chunk7RUW244J_cjs.TenantService(db);
15713
+ const svc = new chunkCTYLCWMO_cjs.TenantService(db);
14241
15714
  await svc.createTenant({
14242
15715
  name: validated.name,
14243
15716
  slug: validated.slug,
@@ -14262,7 +15735,7 @@ function createTenantAdminRoutes() {
14262
15735
  if (!await isMultiTenantActive(db)) {
14263
15736
  return c.html(renderTenantsInactive({ user: userShape(user), version }));
14264
15737
  }
14265
- const tenant = await new chunk7RUW244J_cjs.TenantService(db).getTenantBySlug(c.req.param("slug"));
15738
+ const tenant = await new chunkCTYLCWMO_cjs.TenantService(db).getTenantBySlug(c.req.param("slug"));
14266
15739
  if (!tenant) return c.redirect("/admin/tenants?message=Tenant not found&type=error");
14267
15740
  return c.html(renderTenantForm({ tenant, isEdit: true, user: userShape(user), version }));
14268
15741
  });
@@ -14272,7 +15745,7 @@ function createTenantAdminRoutes() {
14272
15745
  const version = c.get("appVersion");
14273
15746
  const slug = c.req.param("slug");
14274
15747
  if (!await isMultiTenantActive(db)) return c.json({ error: "Multi-tenant plugin is not active" }, 403);
14275
- const svc = new chunk7RUW244J_cjs.TenantService(db);
15748
+ const svc = new chunkCTYLCWMO_cjs.TenantService(db);
14276
15749
  try {
14277
15750
  const form = await c.req.formData();
14278
15751
  const validated = tenantFormSchema.parse(Object.fromEntries(form.entries()));
@@ -14297,7 +15770,7 @@ function createTenantAdminRoutes() {
14297
15770
  const slug = c.req.param("slug");
14298
15771
  if (!await isMultiTenantActive(db)) return c.json({ error: "Multi-tenant plugin is not active" }, 403);
14299
15772
  try {
14300
- await new chunk7RUW244J_cjs.TenantService(db).deleteTenant(slug);
15773
+ await new chunkCTYLCWMO_cjs.TenantService(db).deleteTenant(slug);
14301
15774
  return c.redirect("/admin/tenants?message=Tenant deleted successfully");
14302
15775
  } catch (error) {
14303
15776
  const message = error instanceof Error ? error.message : "Failed to delete tenant";
@@ -14312,7 +15785,7 @@ function createTenantAdminRoutes() {
14312
15785
  return c.html(renderTenantsInactive({ user: userShape(user), version }));
14313
15786
  }
14314
15787
  const slug = c.req.param("slug");
14315
- const svc = new chunk7RUW244J_cjs.TenantService(db);
15788
+ const svc = new chunkCTYLCWMO_cjs.TenantService(db);
14316
15789
  const tenant = await svc.getTenantBySlug(slug);
14317
15790
  if (!tenant) return c.redirect("/admin/tenants?message=Tenant not found&type=error");
14318
15791
  const [members, invitations] = await Promise.all([svc.listMembers(slug), svc.listInvitations(slug)]);
@@ -14338,7 +15811,7 @@ function createTenantAdminRoutes() {
14338
15811
  const form = await c.req.formData();
14339
15812
  const email = String(form.get("email") ?? "");
14340
15813
  const role = String(form.get("role") ?? "viewer");
14341
- await new chunk7RUW244J_cjs.TenantService(db).addMemberByEmail(slug, email, role);
15814
+ await new chunkCTYLCWMO_cjs.TenantService(db).addMemberByEmail(slug, email, role);
14342
15815
  return c.redirect(`/admin/tenants/${slug}/members?message=Member added`);
14343
15816
  } catch (error) {
14344
15817
  const message = error instanceof Error ? error.message : "Failed to add member";
@@ -14353,7 +15826,7 @@ function createTenantAdminRoutes() {
14353
15826
  try {
14354
15827
  const form = await c.req.formData();
14355
15828
  const role = String(form.get("role") ?? "");
14356
- await new chunk7RUW244J_cjs.TenantService(db).setMemberRole(slug, userId, role);
15829
+ await new chunkCTYLCWMO_cjs.TenantService(db).setMemberRole(slug, userId, role);
14357
15830
  return c.redirect(`/admin/tenants/${slug}/members?message=Role updated`);
14358
15831
  } catch (error) {
14359
15832
  const message = error instanceof Error ? error.message : "Failed to update role";
@@ -14366,7 +15839,7 @@ function createTenantAdminRoutes() {
14366
15839
  const userId = c.req.param("userId");
14367
15840
  if (!await isMultiTenantActive(db)) return c.json({ error: "Multi-tenant plugin is not active" }, 403);
14368
15841
  try {
14369
- await new chunk7RUW244J_cjs.TenantService(db).removeMember(slug, userId);
15842
+ await new chunkCTYLCWMO_cjs.TenantService(db).removeMember(slug, userId);
14370
15843
  return c.redirect(`/admin/tenants/${slug}/members?message=Member removed`);
14371
15844
  } catch (error) {
14372
15845
  const message = error instanceof Error ? error.message : "Failed to remove member";
@@ -14382,12 +15855,12 @@ function createTenantAdminRoutes() {
14382
15855
  const form = await c.req.formData();
14383
15856
  const email = String(form.get("email") ?? "");
14384
15857
  const role = String(form.get("role") ?? "viewer");
14385
- const token = await new chunk7RUW244J_cjs.TenantService(db).createInvitation(slug, email, role, user?.userId ?? null);
15858
+ const token = await new chunkCTYLCWMO_cjs.TenantService(db).createInvitation(slug, email, role, user?.userId ?? null);
14386
15859
  const origin = c.req.header("origin") || new URL(c.req.url).origin;
14387
15860
  const acceptUrl = `${origin}/join/invite?token=${encodeURIComponent(token)}`;
14388
15861
  let note;
14389
15862
  let noteType = "";
14390
- const svc2 = chunk7RUW244J_cjs.hasEmailService() ? chunk7RUW244J_cjs.getEmailService() : null;
15863
+ const svc2 = chunkCTYLCWMO_cjs.hasEmailService() ? chunkCTYLCWMO_cjs.getEmailService() : null;
14391
15864
  const hasRealProvider = !!svc2 && svc2.getProviderName() !== "console";
14392
15865
  if (hasRealProvider) {
14393
15866
  const result = await svc2.send({
@@ -14428,7 +15901,7 @@ function createTenantAdminRoutes() {
14428
15901
  WHERE i.id = ? AND t.slug = ? AND i.status = 'pending'`
14429
15902
  ).bind(id, slug).first();
14430
15903
  if (!inv) throw new Error("Invitation not found or already used");
14431
- const svc2 = chunk7RUW244J_cjs.hasEmailService() ? chunk7RUW244J_cjs.getEmailService() : null;
15904
+ const svc2 = chunkCTYLCWMO_cjs.hasEmailService() ? chunkCTYLCWMO_cjs.getEmailService() : null;
14432
15905
  const hasRealProvider = !!svc2 && svc2.getProviderName() !== "console";
14433
15906
  if (!hasRealProvider) throw new Error("No email plugin active");
14434
15907
  const origin = c.req.header("origin") || new URL(c.req.url).origin;
@@ -14453,7 +15926,7 @@ function createTenantAdminRoutes() {
14453
15926
  const id = c.req.param("id");
14454
15927
  if (!await isMultiTenantActive(db)) return c.json({ error: "Multi-tenant plugin is not active" }, 403);
14455
15928
  try {
14456
- await new chunk7RUW244J_cjs.TenantService(db).revokeInvitation(slug, id);
15929
+ await new chunkCTYLCWMO_cjs.TenantService(db).revokeInvitation(slug, id);
14457
15930
  return c.redirect(`/admin/tenants/${slug}/members?message=Invitation revoked`);
14458
15931
  } catch (error) {
14459
15932
  const message = error instanceof Error ? error.message : "Failed to revoke invitation";
@@ -14683,7 +16156,7 @@ function createJoinRoutes() {
14683
16156
  if (existing) return rerender("An account with this email already exists. Please sign in instead.");
14684
16157
  try {
14685
16158
  const userId = crypto.randomUUID();
14686
- const passwordHash = await chunkFCLKX2OS_cjs.AuthManager.hashPassword(password);
16159
+ const passwordHash = await chunkIS54FPB7_cjs.AuthManager.hashPassword(password);
14687
16160
  const now = Date.now();
14688
16161
  const nowSec = Math.floor(now / 1e3);
14689
16162
  await db.batch([
@@ -14696,7 +16169,7 @@ function createJoinRoutes() {
14696
16169
  VALUES (?, ?, ?, 'credential', ?, ?, ?)`
14697
16170
  ).bind(`cred-${userId}`, userId, userId, passwordHash, nowSec, nowSec)
14698
16171
  ]);
14699
- await new chunk7RUW244J_cjs.TenantService(db).acceptInvitation(token, userId, inv.email);
16172
+ await new chunkCTYLCWMO_cjs.TenantService(db).acceptInvitation(token, userId, inv.email);
14700
16173
  const auth = chunkGMMCCIQO_cjs.createAuth(c.env);
14701
16174
  const origin = new URL(c.req.url).origin;
14702
16175
  const baReq = new Request(`${origin}/auth/sign-in/email`, {
@@ -14764,7 +16237,7 @@ function createJoinRoutes() {
14764
16237
  const baBody = await baRes.json();
14765
16238
  const userId = baBody?.user?.id;
14766
16239
  if (!userId) return rerender("Sign-in succeeded but could not read user ID.");
14767
- await new chunk7RUW244J_cjs.TenantService(db).acceptInvitation(token, userId, inv.email);
16240
+ await new chunkCTYLCWMO_cjs.TenantService(db).acceptInvitation(token, userId, inv.email);
14768
16241
  const headers = new Headers({ Location: "/admin?message=Welcome! You have joined " + encodeURIComponent(inv.tenantName) });
14769
16242
  copyBaCookies(baRes, headers);
14770
16243
  return new Response(null, { status: 302, headers });
@@ -14778,7 +16251,7 @@ function createJoinRoutes() {
14778
16251
 
14779
16252
  // src/plugins/core-plugins/multi-tenant-plugin/index.ts
14780
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>`;
14781
- var multiTenantPlugin = chunkA4KUJ3LD_cjs.definePlugin({
16254
+ var multiTenantPlugin = chunk4WMZGHIC_cjs.definePlugin({
14782
16255
  id: manifest_default2.id,
14783
16256
  version: "1.0.0",
14784
16257
  name: manifest_default2.name,
@@ -14793,30 +16266,30 @@ var multiTenantPlugin = chunkA4KUJ3LD_cjs.definePlugin({
14793
16266
  { label: "Tenants", path: "/admin/tenants", icon: TENANT_ICON, order: 80 }
14794
16267
  ],
14795
16268
  activate: async () => {
14796
- chunkKVBHB7QP_cjs.invalidateTenantCache();
16269
+ chunkAT4ZQGEZ_cjs.invalidateTenantCache();
14797
16270
  console.info("\u2705 Multi-Tenant plugin activated");
14798
16271
  },
14799
16272
  deactivate: async () => {
14800
- chunkKVBHB7QP_cjs.invalidateTenantCache();
16273
+ chunkAT4ZQGEZ_cjs.invalidateTenantCache();
14801
16274
  console.info("\u274C Multi-Tenant plugin deactivated");
14802
16275
  }
14803
16276
  });
14804
16277
  var routes = new hono.Hono();
14805
- routes.use("*", chunkFCLKX2OS_cjs.requireAuth());
14806
- routes.use("*", chunkFCLKX2OS_cjs.requireRole(["admin", "editor"]));
16278
+ routes.use("*", chunkIS54FPB7_cjs.requireAuth());
16279
+ routes.use("*", chunkIS54FPB7_cjs.requireRole(["admin", "editor"]));
14807
16280
  routes.get("/:rootId", async (c) => {
14808
16281
  const { rootId } = c.req.param();
14809
16282
  const db = c.env.DB;
14810
- const scope = await chunk7RUW244J_cjs.resolveDocScope(c, db, { rootId });
16283
+ const scope = await chunkCTYLCWMO_cjs.resolveDocScope(c, db, { rootId });
14811
16284
  if (!scope) {
14812
16285
  return c.html('<p class="text-zinc-500 dark:text-zinc-400 p-4">Document not found.</p>', 404);
14813
16286
  }
14814
16287
  if (!scope.docType?.settings?.versioning) {
14815
16288
  return c.html('<p class="text-zinc-500 dark:text-zinc-400 p-4">Versioning not enabled for this type.</p>', 404);
14816
16289
  }
14817
- const denied = await chunk7RUW244J_cjs.denyIfNotAllowed(c, db, rootId, "read", scope.docType?.settings, scope.tenantId);
16290
+ const denied = await chunkCTYLCWMO_cjs.denyIfNotAllowed(c, db, rootId, "read", scope.docType?.settings, scope.tenantId);
14818
16291
  if (denied) return denied;
14819
- const repo = new chunk7RUW244J_cjs.DocumentRepository(db, scope.tenantId);
16292
+ const repo = new chunkCTYLCWMO_cjs.DocumentRepository(db, scope.tenantId);
14820
16293
  const versions = await repo.getVersionHistory(rootId);
14821
16294
  const safeRootIdAttr = chunkMNWKYY5E_cjs.escapeHtml(rootId);
14822
16295
  const rows = versions.map((v) => {
@@ -14909,14 +16382,14 @@ routes.post("/:rootId/restore/:versionNumber", async (c) => {
14909
16382
  const { rootId, versionNumber } = c.req.param();
14910
16383
  const db = c.env.DB;
14911
16384
  const user = c.get("user");
14912
- const scope = await chunk7RUW244J_cjs.resolveDocScope(c, db, { rootId });
16385
+ const scope = await chunkCTYLCWMO_cjs.resolveDocScope(c, db, { rootId });
14913
16386
  if (!scope) {
14914
16387
  return c.json({ error: "Document not found" }, 404);
14915
16388
  }
14916
16389
  if (!scope.docType?.settings?.versioning) {
14917
16390
  return c.json({ error: "Versioning not enabled for this type" }, 404);
14918
16391
  }
14919
- const denied = await chunk7RUW244J_cjs.denyIfNotAllowed(c, db, rootId, "update", scope.docType?.settings, scope.tenantId);
16392
+ const denied = await chunkCTYLCWMO_cjs.denyIfNotAllowed(c, db, rootId, "update", scope.docType?.settings, scope.tenantId);
14920
16393
  if (denied) return denied;
14921
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();
14922
16395
  if (!row) {
@@ -14939,7 +16412,7 @@ routes.post("/:rootId/restore/:versionNumber", async (c) => {
14939
16412
  var routes_default = routes;
14940
16413
 
14941
16414
  // src/plugins/core-plugins/versioning-plugin/index.ts
14942
- var versioningPlugin = chunkA4KUJ3LD_cjs.definePlugin({
16415
+ var versioningPlugin = chunk4WMZGHIC_cjs.definePlugin({
14943
16416
  id: "versioning",
14944
16417
  version: "1.0.0",
14945
16418
  name: "Versioning",
@@ -15016,8 +16489,8 @@ function createMagicLinkAuthPlugin() {
15016
16489
  const baseUrl = new URL(c.req.url).origin;
15017
16490
  const magicLink = `${baseUrl}/auth/magic-link/verify?token=${token}`;
15018
16491
  try {
15019
- if (chunk7RUW244J_cjs.hasEmailService()) {
15020
- await chunk7RUW244J_cjs.getEmailService().send({
16492
+ if (chunkCTYLCWMO_cjs.hasEmailService()) {
16493
+ await chunkCTYLCWMO_cjs.getEmailService().send({
15021
16494
  to: normalizedEmail,
15022
16495
  subject: "Your Magic Link to Sign In",
15023
16496
  flow: "magic-link",
@@ -15094,19 +16567,19 @@ function createMagicLinkAuthPlugin() {
15094
16567
  SET used = 1, used_at = ?
15095
16568
  WHERE id = ?
15096
16569
  `).bind(Date.now(), magicLink.id).run();
15097
- const tokenTtl = await chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
15098
- const jwtToken = await chunkFCLKX2OS_cjs.AuthManager.generateToken(
16570
+ const tokenTtl = await chunkIS54FPB7_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
16571
+ const jwtToken = await chunkIS54FPB7_cjs.AuthManager.generateToken(
15099
16572
  user.id,
15100
16573
  user.email,
15101
16574
  user.role,
15102
16575
  c.env.JWT_SECRET,
15103
16576
  tokenTtl
15104
16577
  );
15105
- chunkFCLKX2OS_cjs.AuthManager.setAuthCookie(c, jwtToken, { maxAge: tokenTtl });
16578
+ chunkIS54FPB7_cjs.AuthManager.setAuthCookie(c, jwtToken, { maxAge: tokenTtl });
15106
16579
  await db.prepare(`
15107
16580
  UPDATE auth_user SET last_login_at = ? WHERE id = ?
15108
16581
  `).bind(Date.now(), user.id).run();
15109
- chunk7RUW244J_cjs.dispatchHookEvent(
16582
+ chunkCTYLCWMO_cjs.dispatchHookEvent(
15110
16583
  c,
15111
16584
  "auth:magic-link:consumed",
15112
16585
  { user: { id: user.id, email: user.email, role: user.role } },
@@ -15591,7 +17064,7 @@ async function warmCollections(db) {
15591
17064
  const collectionCache = chunkYA3TJ65D_cjs.getCacheService(config);
15592
17065
  let count = 0;
15593
17066
  try {
15594
- const results = chunkKVBHB7QP_cjs.getCollectionRegistry().listActive().map(chunkKVBHB7QP_cjs.collectionRecordToRow);
17067
+ const results = chunkAT4ZQGEZ_cjs.getCollectionRegistry().listActive().map(chunkAT4ZQGEZ_cjs.collectionRecordToRow);
15595
17068
  for (const collection of results) {
15596
17069
  const key = collectionCache.generateKey("item", collection.id);
15597
17070
  await collectionCache.set(key, collection);
@@ -15658,7 +17131,7 @@ async function warmNamespace(namespace, entries) {
15658
17131
  }
15659
17132
 
15660
17133
  // src/templates/pages/admin-cache.template.ts
15661
- chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
17134
+ chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
15662
17135
  function renderCacheDashboard(data) {
15663
17136
  const pageContent = `
15664
17137
  <div class="space-y-6">
@@ -15862,7 +17335,7 @@ function renderCacheDashboard(data) {
15862
17335
  </script>
15863
17336
 
15864
17337
  <!-- Confirmation Dialogs -->
15865
- ${chunk7RUW244J_cjs.renderConfirmationDialog({
17338
+ ${chunkCTYLCWMO_cjs.renderConfirmationDialog({
15866
17339
  id: "clear-all-cache-confirm",
15867
17340
  title: "Clear All Cache",
15868
17341
  message: "Are you sure you want to clear all cache entries? This cannot be undone.",
@@ -15873,7 +17346,7 @@ function renderCacheDashboard(data) {
15873
17346
  onConfirm: "performClearAllCaches()"
15874
17347
  })}
15875
17348
 
15876
- ${chunk7RUW244J_cjs.renderConfirmationDialog({
17349
+ ${chunkCTYLCWMO_cjs.renderConfirmationDialog({
15877
17350
  id: "clear-namespace-cache-confirm",
15878
17351
  title: "Clear Namespace Cache",
15879
17352
  message: "Clear cache for this namespace?",
@@ -15884,7 +17357,7 @@ function renderCacheDashboard(data) {
15884
17357
  onConfirm: "performClearNamespaceCache()"
15885
17358
  })}
15886
17359
 
15887
- ${chunk7RUW244J_cjs.getConfirmationDialogScript()}
17360
+ ${chunkCTYLCWMO_cjs.getConfirmationDialogScript()}
15888
17361
  `;
15889
17362
  const layoutData = {
15890
17363
  title: "Cache System",
@@ -15894,7 +17367,7 @@ function renderCacheDashboard(data) {
15894
17367
  version: data.version,
15895
17368
  content: pageContent
15896
17369
  };
15897
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
17370
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
15898
17371
  }
15899
17372
  function renderCollectionSettingsTab(collections) {
15900
17373
  if (collections.length === 0) {
@@ -16150,7 +17623,7 @@ app.get("/", async (c) => {
16150
17623
  const totalRequests = totalHits + totalMisses;
16151
17624
  const overallHitRate = totalRequests > 0 ? totalHits / totalRequests * 100 : 0;
16152
17625
  const DEFAULT_TTL = chunkYA3TJ65D_cjs.CACHE_CONFIGS.api?.ttl ?? 300;
16153
- const collections = chunkKVBHB7QP_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => {
17626
+ const collections = chunkAT4ZQGEZ_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => {
16154
17627
  const cacheOverride = r.cache;
16155
17628
  const cacheEnabled = cacheOverride?.enabled !== false;
16156
17629
  const hasCustomTtl = typeof cacheOverride?.ttl === "number";
@@ -16687,9 +18160,9 @@ var faviconSvg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
16687
18160
  // src/app.ts
16688
18161
  function createSonicJSApp(config = {}) {
16689
18162
  const app2 = new hono.Hono();
16690
- const appVersion = config.version || chunkAOUVUF32_cjs.getCoreVersion();
18163
+ const appVersion = config.version || chunkC3ZQP5NW_cjs.getCoreVersion();
16691
18164
  const appName = config.name || "SonicJS AI";
16692
- const hookSystem = new chunk5UXU3LP4_cjs.HookSystemImpl();
18165
+ const hookSystem = new chunkRFBW5RRH_cjs.HookSystemImpl();
16693
18166
  chunkJ6JTWD2A_cjs.setHookSystem(hookSystem);
16694
18167
  const magicLinkPlugin = createMagicLinkAuthPlugin();
16695
18168
  const corePluginsBeforeCatchAll = [
@@ -16697,7 +18170,7 @@ function createSonicJSApp(config = {}) {
16697
18170
  apiKeysPlugin,
16698
18171
  aiSearchPlugin,
16699
18172
  oauthProvidersPlugin,
16700
- chunk7RUW244J_cjs.userProfilesPlugin,
18173
+ chunkCTYLCWMO_cjs.userProfilesPlugin,
16701
18174
  otpLoginPlugin,
16702
18175
  analyticsPlugin,
16703
18176
  stripePlugin,
@@ -16707,23 +18180,24 @@ function createSonicJSApp(config = {}) {
16707
18180
  shortcodesPlugin,
16708
18181
  helloWorldPlugin,
16709
18182
  multiTenantPlugin,
16710
- chunk7RUW244J_cjs.lexicalEditorPlugin,
16711
- versioningPlugin
18183
+ chunkCTYLCWMO_cjs.lexicalEditorPlugin,
18184
+ versioningPlugin,
18185
+ menuPlugin
16712
18186
  ];
16713
18187
  const corePluginsAfterCatchAll = [emailPluginV3, magicLinkPlugin, emailReconciliationPlugin];
16714
- const wirePlugins = chunk5UXU3LP4_cjs.createPluginWirer(
18188
+ const wirePlugins = chunkRFBW5RRH_cjs.createPluginWirer(
16715
18189
  () => [...corePluginsBeforeCatchAll, ...corePluginsAfterCatchAll, ...config.plugins?.register ?? []],
16716
18190
  // The capability-gated `ctx.cap.email` resolves to the app EmailService, which
16717
18191
  // is initialized (below) just before wiring on the first request.
16718
18192
  () => ({
16719
18193
  hooks: hookSystem,
16720
18194
  env: firstRequestEnv,
16721
- providers: { email: () => chunk7RUW244J_cjs.getEmailService() }
18195
+ providers: { email: () => chunkCTYLCWMO_cjs.getEmailService() }
16722
18196
  })
16723
18197
  );
16724
18198
  let firstRequestEnv;
16725
18199
  const initEmailService = async (env = {}) => {
16726
- if (chunk7RUW244J_cjs.hasEmailService()) return;
18200
+ if (chunkCTYLCWMO_cjs.hasEmailService()) return;
16727
18201
  let provider;
16728
18202
  let defaultFrom = config.email?.from;
16729
18203
  let defaultReplyTo;
@@ -16758,14 +18232,14 @@ function createSonicJSApp(config = {}) {
16758
18232
  }
16759
18233
  }
16760
18234
  defaultFrom = defaultFrom || env.DEFAULT_FROM_EMAIL || "noreply@sonicjs.local";
16761
- chunk7RUW244J_cjs.setEmailService(new EmailService({ provider, defaultFrom, defaultReplyTo, db: env.DB }));
18235
+ chunkCTYLCWMO_cjs.setEmailService(new EmailService({ provider, defaultFrom, defaultReplyTo, db: env.DB }));
16762
18236
  };
16763
18237
  app2.use("*", async (c, next) => {
16764
18238
  c.set("appVersion", appVersion);
16765
18239
  await next();
16766
18240
  });
16767
- app2.use("*", chunkFCLKX2OS_cjs.metricsMiddleware());
16768
- app2.use("*", chunkFCLKX2OS_cjs.bootstrapMiddleware(config));
18241
+ app2.use("*", chunkIS54FPB7_cjs.metricsMiddleware());
18242
+ app2.use("*", chunkIS54FPB7_cjs.bootstrapMiddleware(config));
16769
18243
  const boot = async (env) => {
16770
18244
  if (config.plugins?.disableAll) return;
16771
18245
  firstRequestEnv = env;
@@ -16803,8 +18277,8 @@ function createSonicJSApp(config = {}) {
16803
18277
  allowHeaders: ["Content-Type", "Authorization", "X-API-Key"],
16804
18278
  credentials: true
16805
18279
  }));
16806
- app2.use("*", chunkFCLKX2OS_cjs.securityHeadersMiddleware());
16807
- app2.use("*", chunkFCLKX2OS_cjs.csrfProtection());
18280
+ app2.use("*", chunkIS54FPB7_cjs.securityHeadersMiddleware());
18281
+ app2.use("*", chunkIS54FPB7_cjs.csrfProtection());
16808
18282
  app2.use("*", async (c, next) => {
16809
18283
  try {
16810
18284
  const reqUrl = new URL(c.req.url);
@@ -16842,10 +18316,11 @@ function createSonicJSApp(config = {}) {
16842
18316
  app2.use("*", middleware);
16843
18317
  }
16844
18318
  }
16845
- app2.use("*", chunkKVBHB7QP_cjs.tenantMiddleware());
16846
- app2.use("/admin/*", chunkFCLKX2OS_cjs.requireAuth());
16847
- app2.use("/admin/*", chunkFCLKX2OS_cjs.requireRbac("portal", "access"));
18319
+ app2.use("*", chunkAT4ZQGEZ_cjs.tenantMiddleware());
18320
+ app2.use("/admin/*", chunkIS54FPB7_cjs.requireAuth());
18321
+ app2.use("/admin/*", chunkIS54FPB7_cjs.requireRbac("portal", "access"));
16848
18322
  app2.use("/admin/*", pluginMenuMiddleware());
18323
+ app2.use("/admin/*", menuMiddleware());
16849
18324
  const NAV_LANDING = [
16850
18325
  { path: "/admin/content", perm: "content:read" },
16851
18326
  { path: "/admin/media", perm: "media:read" },
@@ -16890,43 +18365,43 @@ function createSonicJSApp(config = {}) {
16890
18365
  });
16891
18366
  app2.route("/api/security-audit", apiRoutes2);
16892
18367
  app2.route("/admin/plugins/security-audit", adminRoutes3);
16893
- app2.route("/api/media", chunk7RUW244J_cjs.api_media_default);
16894
- app2.route("/api/system", chunk7RUW244J_cjs.api_system_default);
16895
- app2.route("/api/documents", chunk7RUW244J_cjs.apiDocumentsRoutes);
16896
- app2.route("/api", chunk7RUW244J_cjs.api_default);
16897
- app2.route("/admin/documents", chunk7RUW244J_cjs.adminDocumentsRoutes);
16898
- chunk5UXU3LP4_cjs.registerPluginRoutes(app2, [formsPlugin], { source: "core" });
16899
- app2.route("/admin/api", chunk7RUW244J_cjs.admin_api_default);
16900
- app2.route("/admin/collections", chunk7RUW244J_cjs.adminCollectionsRoutes);
16901
- app2.route("/admin/settings", chunk7RUW244J_cjs.adminSettingsRoutes);
16902
- app2.route("/admin/api-reference", chunk7RUW244J_cjs.router2);
18368
+ app2.route("/api/media", chunkCTYLCWMO_cjs.api_media_default);
18369
+ app2.route("/api/system", chunkCTYLCWMO_cjs.api_system_default);
18370
+ app2.route("/api/documents", chunkCTYLCWMO_cjs.apiDocumentsRoutes);
18371
+ app2.route("/api", chunkCTYLCWMO_cjs.api_default);
18372
+ app2.route("/admin/documents", chunkCTYLCWMO_cjs.adminDocumentsRoutes);
18373
+ chunkRFBW5RRH_cjs.registerPluginRoutes(app2, [formsPlugin], { source: "core" });
18374
+ app2.route("/admin/api", chunkCTYLCWMO_cjs.admin_api_default);
18375
+ app2.route("/admin/collections", chunkCTYLCWMO_cjs.adminCollectionsRoutes);
18376
+ app2.route("/admin/settings", chunkCTYLCWMO_cjs.adminSettingsRoutes);
18377
+ app2.route("/admin/api-reference", chunkCTYLCWMO_cjs.router2);
16903
18378
  app2.route("/admin/database-tools", createDatabaseToolsAdminRoutes());
16904
- app2.route("/admin/content", chunk7RUW244J_cjs.admin_content_default);
16905
- app2.route("/admin/media", chunk7RUW244J_cjs.adminMediaRoutes);
18379
+ app2.route("/admin/content", chunkCTYLCWMO_cjs.admin_content_default);
18380
+ app2.route("/admin/media", chunkCTYLCWMO_cjs.adminMediaRoutes);
16906
18381
  app2.use("/auth/*", securityAuditMiddleware());
16907
18382
  if (!config.plugins?.disableAll) {
16908
- chunk5UXU3LP4_cjs.registerPluginRoutes(app2, corePluginsBeforeCatchAll, { source: "core" });
18383
+ chunkRFBW5RRH_cjs.registerPluginRoutes(app2, corePluginsBeforeCatchAll, { source: "core" });
16909
18384
  app2.route("/admin/cache", cache_default.getRoutes());
16910
18385
  if (config.plugins?.register && config.plugins.register.length > 0) {
16911
- chunk5UXU3LP4_cjs.registerPluginRoutes(app2, config.plugins.register, { source: "user" });
18386
+ chunkRFBW5RRH_cjs.registerPluginRoutes(app2, config.plugins.register, { source: "user" });
16912
18387
  }
16913
18388
  }
16914
18389
  app2.route("/api/events", apiRoutes4);
16915
- app2.route("/admin/dashboard", chunk7RUW244J_cjs.router);
16916
- app2.route("/admin/plugins", chunk7RUW244J_cjs.adminPluginRoutes);
16917
- app2.route("/admin/logs", chunk7RUW244J_cjs.adminLogsRoutes);
18390
+ app2.route("/admin/dashboard", chunkCTYLCWMO_cjs.router);
18391
+ app2.route("/admin/plugins", chunkCTYLCWMO_cjs.adminPluginRoutes);
18392
+ app2.route("/admin/logs", chunkCTYLCWMO_cjs.adminLogsRoutes);
16918
18393
  app2.route("/admin/rbac", adminRbacRoutes);
16919
- app2.route("/admin", chunk7RUW244J_cjs.userRoutes);
16920
- app2.route("/auth", chunk7RUW244J_cjs.auth_default);
18394
+ app2.route("/admin", chunkCTYLCWMO_cjs.userRoutes);
18395
+ app2.route("/auth", chunkCTYLCWMO_cjs.auth_default);
16921
18396
  app2.on(["GET", "POST"], "/auth/*", (c) => {
16922
18397
  const reqUrl = new URL(c.req.url);
16923
18398
  const requestBaseURL = `${reqUrl.protocol}//${reqUrl.host}`;
16924
18399
  const auth = chunkGMMCCIQO_cjs.createAuth(c.env, config.auth?.extendBetterAuth, requestBaseURL);
16925
18400
  return auth.handler(c.req.raw);
16926
18401
  });
16927
- app2.route("/", chunk7RUW244J_cjs.test_cleanup_default);
18402
+ app2.route("/", chunkCTYLCWMO_cjs.test_cleanup_default);
16928
18403
  if (!config.plugins?.disableAll) {
16929
- chunk5UXU3LP4_cjs.registerPluginRoutes(app2, corePluginsAfterCatchAll, { source: "core" });
18404
+ chunkRFBW5RRH_cjs.registerPluginRoutes(app2, corePluginsAfterCatchAll, { source: "core" });
16930
18405
  }
16931
18406
  if (!config.plugins?.disableAll) {
16932
18407
  const allMountedPlugins = [
@@ -16936,10 +18411,10 @@ function createSonicJSApp(config = {}) {
16936
18411
  ...config.plugins?.register ?? []
16937
18412
  ];
16938
18413
  const userPlugins = (config.plugins?.register ?? []).filter(
16939
- (p) => !chunkKVBHB7QP_cjs.PLUGIN_REGISTRY[p.id]
18414
+ (p) => !chunkAT4ZQGEZ_cjs.PLUGIN_REGISTRY[p.id]
16940
18415
  );
16941
- chunk5UXU3LP4_cjs.setPluginMenu(userPlugins.flatMap((p) => p.menu ?? []));
16942
- chunkA4KUJ3LD_cjs.setPluginDefinitions(allMountedPlugins);
18416
+ chunk4WMZGHIC_cjs.setPluginMenu(userPlugins.flatMap((p) => p.menu ?? []));
18417
+ chunk4WMZGHIC_cjs.setPluginDefinitions(allMountedPlugins);
16943
18418
  }
16944
18419
  app2.get("/favicon.svg", (c) => {
16945
18420
  return new Response(faviconSvg, {
@@ -19110,7 +20585,7 @@ function renderLayout(title, content2) {
19110
20585
  }
19111
20586
  </style>
19112
20587
  `;
19113
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
20588
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
19114
20589
  title,
19115
20590
  currentPath: "/admin/redirects",
19116
20591
  content: customStyles + content2.toString()
@@ -19475,7 +20950,7 @@ function getFormScripts() {
19475
20950
  `;
19476
20951
  }
19477
20952
  function renderLayout2(title, content2) {
19478
- return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
20953
+ return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
19479
20954
  title,
19480
20955
  currentPath: "/admin/redirects",
19481
20956
  content: content2.toString()
@@ -20433,7 +21908,7 @@ function createRedirectApiRoutes() {
20433
21908
  });
20434
21909
  return api;
20435
21910
  }
20436
- var redirectPlugin = chunkA4KUJ3LD_cjs.definePlugin({
21911
+ var redirectPlugin = chunk4WMZGHIC_cjs.definePlugin({
20437
21912
  id: manifest_default3.id,
20438
21913
  version: manifest_default3.version,
20439
21914
  name: manifest_default3.name,
@@ -20451,7 +21926,7 @@ var redirectPlugin = chunkA4KUJ3LD_cjs.definePlugin({
20451
21926
  async onBoot(ctx) {
20452
21927
  const db = ctx.env?.DB;
20453
21928
  if (!db) return;
20454
- const registry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db);
21929
+ const registry = new chunkIS54FPB7_cjs.DocumentTypeRegistry(db);
20455
21930
  await registry.register({
20456
21931
  id: "redirect",
20457
21932
  name: "redirect",
@@ -20567,91 +22042,91 @@ function createDb(d1$1) {
20567
22042
  }
20568
22043
 
20569
22044
  // src/index.ts
20570
- var VERSION = chunkAOUVUF32_cjs.package_default.version;
22045
+ var VERSION = chunkC3ZQP5NW_cjs.package_default.version;
20571
22046
 
20572
22047
  Object.defineProperty(exports, "DocumentRepository", {
20573
22048
  enumerable: true,
20574
- get: function () { return chunk7RUW244J_cjs.DocumentRepository; }
22049
+ get: function () { return chunkCTYLCWMO_cjs.DocumentRepository; }
20575
22050
  });
20576
22051
  Object.defineProperty(exports, "ROUTES_INFO", {
20577
22052
  enumerable: true,
20578
- get: function () { return chunk7RUW244J_cjs.ROUTES_INFO; }
22053
+ get: function () { return chunkCTYLCWMO_cjs.ROUTES_INFO; }
20579
22054
  });
20580
22055
  Object.defineProperty(exports, "adminApiRoutes", {
20581
22056
  enumerable: true,
20582
- get: function () { return chunk7RUW244J_cjs.admin_api_default; }
22057
+ get: function () { return chunkCTYLCWMO_cjs.admin_api_default; }
20583
22058
  });
20584
22059
  Object.defineProperty(exports, "adminCheckboxRoutes", {
20585
22060
  enumerable: true,
20586
- get: function () { return chunk7RUW244J_cjs.adminCheckboxRoutes; }
22061
+ get: function () { return chunkCTYLCWMO_cjs.adminCheckboxRoutes; }
20587
22062
  });
20588
22063
  Object.defineProperty(exports, "adminCollectionsRoutes", {
20589
22064
  enumerable: true,
20590
- get: function () { return chunk7RUW244J_cjs.adminCollectionsRoutes; }
22065
+ get: function () { return chunkCTYLCWMO_cjs.adminCollectionsRoutes; }
20591
22066
  });
20592
22067
  Object.defineProperty(exports, "adminContentRoutes", {
20593
22068
  enumerable: true,
20594
- get: function () { return chunk7RUW244J_cjs.admin_content_default; }
22069
+ get: function () { return chunkCTYLCWMO_cjs.admin_content_default; }
20595
22070
  });
20596
22071
  Object.defineProperty(exports, "adminDashboardRoutes", {
20597
22072
  enumerable: true,
20598
- get: function () { return chunk7RUW244J_cjs.router; }
22073
+ get: function () { return chunkCTYLCWMO_cjs.router; }
20599
22074
  });
20600
22075
  Object.defineProperty(exports, "adminLogsRoutes", {
20601
22076
  enumerable: true,
20602
- get: function () { return chunk7RUW244J_cjs.adminLogsRoutes; }
22077
+ get: function () { return chunkCTYLCWMO_cjs.adminLogsRoutes; }
20603
22078
  });
20604
22079
  Object.defineProperty(exports, "adminMediaRoutes", {
20605
22080
  enumerable: true,
20606
- get: function () { return chunk7RUW244J_cjs.adminMediaRoutes; }
22081
+ get: function () { return chunkCTYLCWMO_cjs.adminMediaRoutes; }
20607
22082
  });
20608
22083
  Object.defineProperty(exports, "adminPluginRoutes", {
20609
22084
  enumerable: true,
20610
- get: function () { return chunk7RUW244J_cjs.adminPluginRoutes; }
22085
+ get: function () { return chunkCTYLCWMO_cjs.adminPluginRoutes; }
20611
22086
  });
20612
22087
  Object.defineProperty(exports, "adminSettingsRoutes", {
20613
22088
  enumerable: true,
20614
- get: function () { return chunk7RUW244J_cjs.adminSettingsRoutes; }
22089
+ get: function () { return chunkCTYLCWMO_cjs.adminSettingsRoutes; }
20615
22090
  });
20616
22091
  Object.defineProperty(exports, "adminUsersRoutes", {
20617
22092
  enumerable: true,
20618
- get: function () { return chunk7RUW244J_cjs.userRoutes; }
22093
+ get: function () { return chunkCTYLCWMO_cjs.userRoutes; }
20619
22094
  });
20620
22095
  Object.defineProperty(exports, "apiContentCrudRoutes", {
20621
22096
  enumerable: true,
20622
- get: function () { return chunk7RUW244J_cjs.api_content_crud_default; }
22097
+ get: function () { return chunkCTYLCWMO_cjs.api_content_crud_default; }
20623
22098
  });
20624
22099
  Object.defineProperty(exports, "apiMediaRoutes", {
20625
22100
  enumerable: true,
20626
- get: function () { return chunk7RUW244J_cjs.api_media_default; }
22101
+ get: function () { return chunkCTYLCWMO_cjs.api_media_default; }
20627
22102
  });
20628
22103
  Object.defineProperty(exports, "apiRoutes", {
20629
22104
  enumerable: true,
20630
- get: function () { return chunk7RUW244J_cjs.api_default; }
22105
+ get: function () { return chunkCTYLCWMO_cjs.api_default; }
20631
22106
  });
20632
22107
  Object.defineProperty(exports, "apiSystemRoutes", {
20633
22108
  enumerable: true,
20634
- get: function () { return chunk7RUW244J_cjs.api_system_default; }
22109
+ get: function () { return chunkCTYLCWMO_cjs.api_system_default; }
20635
22110
  });
20636
22111
  Object.defineProperty(exports, "authRoutes", {
20637
22112
  enumerable: true,
20638
- get: function () { return chunk7RUW244J_cjs.auth_default; }
22113
+ get: function () { return chunkCTYLCWMO_cjs.auth_default; }
20639
22114
  });
20640
22115
  Object.defineProperty(exports, "createUserProfilesPlugin", {
20641
22116
  enumerable: true,
20642
- get: function () { return chunk7RUW244J_cjs.createUserProfilesPlugin; }
22117
+ get: function () { return chunkCTYLCWMO_cjs.createUserProfilesPlugin; }
20643
22118
  });
20644
22119
  Object.defineProperty(exports, "defineUserProfile", {
20645
22120
  enumerable: true,
20646
- get: function () { return chunk7RUW244J_cjs.defineUserProfile; }
22121
+ get: function () { return chunkCTYLCWMO_cjs.defineUserProfile; }
20647
22122
  });
20648
22123
  Object.defineProperty(exports, "getUserProfileConfig", {
20649
22124
  enumerable: true,
20650
- get: function () { return chunk7RUW244J_cjs.getUserProfileConfig; }
22125
+ get: function () { return chunkCTYLCWMO_cjs.getUserProfileConfig; }
20651
22126
  });
20652
22127
  Object.defineProperty(exports, "userProfilesPlugin", {
20653
22128
  enumerable: true,
20654
- get: function () { return chunk7RUW244J_cjs.userProfilesPlugin; }
22129
+ get: function () { return chunkCTYLCWMO_cjs.userProfilesPlugin; }
20655
22130
  });
20656
22131
  Object.defineProperty(exports, "Logger", {
20657
22132
  enumerable: true,
@@ -20807,87 +22282,87 @@ Object.defineProperty(exports, "workflowHistory", {
20807
22282
  });
20808
22283
  Object.defineProperty(exports, "AuthManager", {
20809
22284
  enumerable: true,
20810
- get: function () { return chunkFCLKX2OS_cjs.AuthManager; }
22285
+ get: function () { return chunkIS54FPB7_cjs.AuthManager; }
20811
22286
  });
20812
22287
  Object.defineProperty(exports, "PermissionManager", {
20813
22288
  enumerable: true,
20814
- get: function () { return chunkFCLKX2OS_cjs.PermissionManager; }
22289
+ get: function () { return chunkIS54FPB7_cjs.PermissionManager; }
20815
22290
  });
20816
22291
  Object.defineProperty(exports, "bootstrapDocumentTypes", {
20817
22292
  enumerable: true,
20818
- get: function () { return chunkFCLKX2OS_cjs.bootstrapDocumentTypes; }
22293
+ get: function () { return chunkIS54FPB7_cjs.bootstrapDocumentTypes; }
20819
22294
  });
20820
22295
  Object.defineProperty(exports, "bootstrapMiddleware", {
20821
22296
  enumerable: true,
20822
- get: function () { return chunkFCLKX2OS_cjs.bootstrapMiddleware; }
22297
+ get: function () { return chunkIS54FPB7_cjs.bootstrapMiddleware; }
20823
22298
  });
20824
22299
  Object.defineProperty(exports, "cacheHeaders", {
20825
22300
  enumerable: true,
20826
- get: function () { return chunkFCLKX2OS_cjs.cacheHeaders; }
22301
+ get: function () { return chunkIS54FPB7_cjs.cacheHeaders; }
20827
22302
  });
20828
22303
  Object.defineProperty(exports, "compressionMiddleware", {
20829
22304
  enumerable: true,
20830
- get: function () { return chunkFCLKX2OS_cjs.compressionMiddleware; }
22305
+ get: function () { return chunkIS54FPB7_cjs.compressionMiddleware; }
20831
22306
  });
20832
22307
  Object.defineProperty(exports, "detailedLoggingMiddleware", {
20833
22308
  enumerable: true,
20834
- get: function () { return chunkFCLKX2OS_cjs.detailedLoggingMiddleware; }
22309
+ get: function () { return chunkIS54FPB7_cjs.detailedLoggingMiddleware; }
20835
22310
  });
20836
22311
  Object.defineProperty(exports, "getActivePlugins", {
20837
22312
  enumerable: true,
20838
- get: function () { return chunkFCLKX2OS_cjs.getActivePlugins; }
22313
+ get: function () { return chunkIS54FPB7_cjs.getActivePlugins; }
20839
22314
  });
20840
22315
  Object.defineProperty(exports, "isPluginActive", {
20841
22316
  enumerable: true,
20842
- get: function () { return chunkFCLKX2OS_cjs.isPluginActive; }
22317
+ get: function () { return chunkIS54FPB7_cjs.isPluginActive; }
20843
22318
  });
20844
22319
  Object.defineProperty(exports, "logActivity", {
20845
22320
  enumerable: true,
20846
- get: function () { return chunkFCLKX2OS_cjs.logActivity; }
22321
+ get: function () { return chunkIS54FPB7_cjs.logActivity; }
20847
22322
  });
20848
22323
  Object.defineProperty(exports, "loggingMiddleware", {
20849
22324
  enumerable: true,
20850
- get: function () { return chunkFCLKX2OS_cjs.loggingMiddleware; }
22325
+ get: function () { return chunkIS54FPB7_cjs.loggingMiddleware; }
20851
22326
  });
20852
22327
  Object.defineProperty(exports, "optionalAuth", {
20853
22328
  enumerable: true,
20854
- get: function () { return chunkFCLKX2OS_cjs.optionalAuth; }
22329
+ get: function () { return chunkIS54FPB7_cjs.optionalAuth; }
20855
22330
  });
20856
22331
  Object.defineProperty(exports, "performanceLoggingMiddleware", {
20857
22332
  enumerable: true,
20858
- get: function () { return chunkFCLKX2OS_cjs.performanceLoggingMiddleware; }
22333
+ get: function () { return chunkIS54FPB7_cjs.performanceLoggingMiddleware; }
20859
22334
  });
20860
22335
  Object.defineProperty(exports, "requireActivePlugin", {
20861
22336
  enumerable: true,
20862
- get: function () { return chunkFCLKX2OS_cjs.requireActivePlugin; }
22337
+ get: function () { return chunkIS54FPB7_cjs.requireActivePlugin; }
20863
22338
  });
20864
22339
  Object.defineProperty(exports, "requireActivePlugins", {
20865
22340
  enumerable: true,
20866
- get: function () { return chunkFCLKX2OS_cjs.requireActivePlugins; }
22341
+ get: function () { return chunkIS54FPB7_cjs.requireActivePlugins; }
20867
22342
  });
20868
22343
  Object.defineProperty(exports, "requireAnyPermission", {
20869
22344
  enumerable: true,
20870
- get: function () { return chunkFCLKX2OS_cjs.requireAnyPermission; }
22345
+ get: function () { return chunkIS54FPB7_cjs.requireAnyPermission; }
20871
22346
  });
20872
22347
  Object.defineProperty(exports, "requireAuth", {
20873
22348
  enumerable: true,
20874
- get: function () { return chunkFCLKX2OS_cjs.requireAuth; }
22349
+ get: function () { return chunkIS54FPB7_cjs.requireAuth; }
20875
22350
  });
20876
22351
  Object.defineProperty(exports, "requirePermission", {
20877
22352
  enumerable: true,
20878
- get: function () { return chunkFCLKX2OS_cjs.requirePermission; }
22353
+ get: function () { return chunkIS54FPB7_cjs.requirePermission; }
20879
22354
  });
20880
22355
  Object.defineProperty(exports, "requireRole", {
20881
22356
  enumerable: true,
20882
- get: function () { return chunkFCLKX2OS_cjs.requireRole; }
22357
+ get: function () { return chunkIS54FPB7_cjs.requireRole; }
20883
22358
  });
20884
22359
  Object.defineProperty(exports, "securityHeaders", {
20885
22360
  enumerable: true,
20886
- get: function () { return chunkFCLKX2OS_cjs.securityHeadersMiddleware; }
22361
+ get: function () { return chunkIS54FPB7_cjs.securityHeadersMiddleware; }
20887
22362
  });
20888
22363
  Object.defineProperty(exports, "securityLoggingMiddleware", {
20889
22364
  enumerable: true,
20890
- get: function () { return chunkFCLKX2OS_cjs.securityLoggingMiddleware; }
22365
+ get: function () { return chunkIS54FPB7_cjs.securityLoggingMiddleware; }
20891
22366
  });
20892
22367
  Object.defineProperty(exports, "DocumentsService", {
20893
22368
  enumerable: true,
@@ -20899,167 +22374,167 @@ Object.defineProperty(exports, "RbacService", {
20899
22374
  });
20900
22375
  Object.defineProperty(exports, "PluginBootstrapService", {
20901
22376
  enumerable: true,
20902
- get: function () { return chunkKVBHB7QP_cjs.PluginBootstrapService; }
22377
+ get: function () { return chunkAT4ZQGEZ_cjs.PluginBootstrapService; }
20903
22378
  });
20904
22379
  Object.defineProperty(exports, "PluginServiceClass", {
20905
22380
  enumerable: true,
20906
- get: function () { return chunkKVBHB7QP_cjs.PluginService; }
22381
+ get: function () { return chunkAT4ZQGEZ_cjs.PluginService; }
20907
22382
  });
20908
22383
  Object.defineProperty(exports, "getAvailableCollectionNames", {
20909
22384
  enumerable: true,
20910
- get: function () { return chunkKVBHB7QP_cjs.getAvailableCollectionNames; }
22385
+ get: function () { return chunkAT4ZQGEZ_cjs.getAvailableCollectionNames; }
20911
22386
  });
20912
22387
  Object.defineProperty(exports, "loadCollectionConfig", {
20913
22388
  enumerable: true,
20914
- get: function () { return chunkKVBHB7QP_cjs.loadCollectionConfig; }
22389
+ get: function () { return chunkAT4ZQGEZ_cjs.loadCollectionConfig; }
20915
22390
  });
20916
22391
  Object.defineProperty(exports, "loadCollectionConfigs", {
20917
22392
  enumerable: true,
20918
- get: function () { return chunkKVBHB7QP_cjs.loadCollectionConfigs; }
22393
+ get: function () { return chunkAT4ZQGEZ_cjs.loadCollectionConfigs; }
20919
22394
  });
20920
22395
  Object.defineProperty(exports, "registerCollections", {
20921
22396
  enumerable: true,
20922
- get: function () { return chunkKVBHB7QP_cjs.registerCollections; }
22397
+ get: function () { return chunkAT4ZQGEZ_cjs.registerCollections; }
20923
22398
  });
20924
22399
  Object.defineProperty(exports, "validateCollectionConfig", {
20925
22400
  enumerable: true,
20926
- get: function () { return chunkKVBHB7QP_cjs.validateCollectionConfig; }
22401
+ get: function () { return chunkAT4ZQGEZ_cjs.validateCollectionConfig; }
20927
22402
  });
20928
22403
  Object.defineProperty(exports, "MigrationService", {
20929
22404
  enumerable: true,
20930
- get: function () { return chunkOJC4G5JE_cjs.MigrationService; }
22405
+ get: function () { return chunkVGHEKIJL_cjs.MigrationService; }
20931
22406
  });
20932
22407
  Object.defineProperty(exports, "renderFilterBar", {
20933
22408
  enumerable: true,
20934
- get: function () { return chunkCRGUD4KC_cjs.renderFilterBar; }
22409
+ get: function () { return chunkBBEKHLTW_cjs.renderFilterBar; }
20935
22410
  });
20936
22411
  Object.defineProperty(exports, "getConfirmationDialogScript", {
20937
22412
  enumerable: true,
20938
- get: function () { return chunkPXNTCCPE_cjs.getConfirmationDialogScript; }
22413
+ get: function () { return chunkE66UVONV_cjs.getConfirmationDialogScript; }
20939
22414
  });
20940
22415
  Object.defineProperty(exports, "renderAlert", {
20941
22416
  enumerable: true,
20942
- get: function () { return chunkPXNTCCPE_cjs.renderAlert; }
22417
+ get: function () { return chunkE66UVONV_cjs.renderAlert; }
20943
22418
  });
20944
22419
  Object.defineProperty(exports, "renderConfirmationDialog", {
20945
22420
  enumerable: true,
20946
- get: function () { return chunkPXNTCCPE_cjs.renderConfirmationDialog; }
22421
+ get: function () { return chunkE66UVONV_cjs.renderConfirmationDialog; }
20947
22422
  });
20948
22423
  Object.defineProperty(exports, "renderForm", {
20949
22424
  enumerable: true,
20950
- get: function () { return chunkPXNTCCPE_cjs.renderForm; }
22425
+ get: function () { return chunkE66UVONV_cjs.renderForm; }
20951
22426
  });
20952
22427
  Object.defineProperty(exports, "renderFormField", {
20953
22428
  enumerable: true,
20954
- get: function () { return chunkPXNTCCPE_cjs.renderFormField; }
22429
+ get: function () { return chunkE66UVONV_cjs.renderFormField; }
20955
22430
  });
20956
22431
  Object.defineProperty(exports, "renderPagination", {
20957
22432
  enumerable: true,
20958
- get: function () { return chunkPXNTCCPE_cjs.renderPagination; }
22433
+ get: function () { return chunkE66UVONV_cjs.renderPagination; }
20959
22434
  });
20960
22435
  Object.defineProperty(exports, "renderTable", {
20961
22436
  enumerable: true,
20962
- get: function () { return chunkPXNTCCPE_cjs.renderTable; }
22437
+ get: function () { return chunkE66UVONV_cjs.renderTable; }
20963
22438
  });
20964
22439
  Object.defineProperty(exports, "renderAdminLayoutCatalyst", {
20965
22440
  enumerable: true,
20966
- get: function () { return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst; }
22441
+ get: function () { return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst; }
20967
22442
  });
20968
22443
  Object.defineProperty(exports, "HookSystemImpl", {
20969
22444
  enumerable: true,
20970
- get: function () { return chunk5UXU3LP4_cjs.HookSystemImpl; }
22445
+ get: function () { return chunkRFBW5RRH_cjs.HookSystemImpl; }
20971
22446
  });
20972
22447
  Object.defineProperty(exports, "HookUtils", {
20973
22448
  enumerable: true,
20974
- get: function () { return chunk5UXU3LP4_cjs.HookUtils; }
22449
+ get: function () { return chunkRFBW5RRH_cjs.HookUtils; }
20975
22450
  });
20976
22451
  Object.defineProperty(exports, "PluginDependencyCycleError", {
20977
22452
  enumerable: true,
20978
- get: function () { return chunk5UXU3LP4_cjs.PluginDependencyCycleError; }
22453
+ get: function () { return chunkRFBW5RRH_cjs.PluginDependencyCycleError; }
20979
22454
  });
20980
22455
  Object.defineProperty(exports, "PluginManagerClass", {
20981
22456
  enumerable: true,
20982
- get: function () { return chunk5UXU3LP4_cjs.PluginManager; }
22457
+ get: function () { return chunkRFBW5RRH_cjs.PluginManager; }
20983
22458
  });
20984
22459
  Object.defineProperty(exports, "PluginRegistryImpl", {
20985
22460
  enumerable: true,
20986
- get: function () { return chunk5UXU3LP4_cjs.PluginRegistryImpl; }
22461
+ get: function () { return chunkRFBW5RRH_cjs.PluginRegistryImpl; }
20987
22462
  });
20988
22463
  Object.defineProperty(exports, "PluginValidatorClass", {
20989
22464
  enumerable: true,
20990
- get: function () { return chunk5UXU3LP4_cjs.PluginValidator; }
22465
+ get: function () { return chunkRFBW5RRH_cjs.PluginValidator; }
20991
22466
  });
20992
22467
  Object.defineProperty(exports, "RegisterPluginsError", {
20993
22468
  enumerable: true,
20994
- get: function () { return chunk5UXU3LP4_cjs.RegisterPluginsError; }
22469
+ get: function () { return chunkRFBW5RRH_cjs.RegisterPluginsError; }
20995
22470
  });
20996
22471
  Object.defineProperty(exports, "ScopedHookSystemClass", {
20997
22472
  enumerable: true,
20998
- get: function () { return chunk5UXU3LP4_cjs.ScopedHookSystem; }
22473
+ get: function () { return chunkRFBW5RRH_cjs.ScopedHookSystem; }
20999
22474
  });
21000
22475
  Object.defineProperty(exports, "collectCronSchedules", {
21001
22476
  enumerable: true,
21002
- get: function () { return chunk5UXU3LP4_cjs.collectCronSchedules; }
22477
+ get: function () { return chunkRFBW5RRH_cjs.collectCronSchedules; }
21003
22478
  });
21004
22479
  Object.defineProperty(exports, "collectCrons", {
21005
22480
  enumerable: true,
21006
- get: function () { return chunk5UXU3LP4_cjs.collectCrons; }
22481
+ get: function () { return chunkRFBW5RRH_cjs.collectCrons; }
21007
22482
  });
21008
22483
  Object.defineProperty(exports, "createScheduledHandler", {
21009
22484
  enumerable: true,
21010
- get: function () { return chunk5UXU3LP4_cjs.createScheduledHandler; }
22485
+ get: function () { return chunkRFBW5RRH_cjs.createScheduledHandler; }
21011
22486
  });
21012
22487
  Object.defineProperty(exports, "dispatchCronTick", {
21013
22488
  enumerable: true,
21014
- get: function () { return chunk5UXU3LP4_cjs.dispatchCronTick; }
21015
- });
21016
- Object.defineProperty(exports, "getPluginMenu", {
21017
- enumerable: true,
21018
- get: function () { return chunk5UXU3LP4_cjs.getPluginMenu; }
22489
+ get: function () { return chunkRFBW5RRH_cjs.dispatchCronTick; }
21019
22490
  });
21020
22491
  Object.defineProperty(exports, "registerPlugins", {
21021
22492
  enumerable: true,
21022
- get: function () { return chunk5UXU3LP4_cjs.registerPlugins; }
21023
- });
21024
- Object.defineProperty(exports, "resetPluginMenu", {
21025
- enumerable: true,
21026
- get: function () { return chunk5UXU3LP4_cjs.resetPluginMenu; }
21027
- });
21028
- Object.defineProperty(exports, "resolvePluginMenuItems", {
21029
- enumerable: true,
21030
- get: function () { return chunk5UXU3LP4_cjs.resolvePluginMenuItems; }
21031
- });
21032
- Object.defineProperty(exports, "setPluginMenu", {
21033
- enumerable: true,
21034
- get: function () { return chunk5UXU3LP4_cjs.setPluginMenu; }
22493
+ get: function () { return chunkRFBW5RRH_cjs.registerPlugins; }
21035
22494
  });
21036
22495
  Object.defineProperty(exports, "topoSort", {
21037
22496
  enumerable: true,
21038
- get: function () { return chunk5UXU3LP4_cjs.topoSort; }
22497
+ get: function () { return chunkRFBW5RRH_cjs.topoSort; }
21039
22498
  });
21040
22499
  Object.defineProperty(exports, "applySchemaDefaults", {
21041
22500
  enumerable: true,
21042
- get: function () { return chunkA4KUJ3LD_cjs.applySchemaDefaults; }
22501
+ get: function () { return chunk4WMZGHIC_cjs.applySchemaDefaults; }
21043
22502
  });
21044
22503
  Object.defineProperty(exports, "definePlugin", {
21045
22504
  enumerable: true,
21046
- get: function () { return chunkA4KUJ3LD_cjs.definePlugin; }
22505
+ get: function () { return chunk4WMZGHIC_cjs.definePlugin; }
22506
+ });
22507
+ Object.defineProperty(exports, "getPluginMenu", {
22508
+ enumerable: true,
22509
+ get: function () { return chunk4WMZGHIC_cjs.getPluginMenu; }
21047
22510
  });
21048
22511
  Object.defineProperty(exports, "isDefinedPlugin", {
21049
22512
  enumerable: true,
21050
- get: function () { return chunkA4KUJ3LD_cjs.isDefinedPlugin; }
22513
+ get: function () { return chunk4WMZGHIC_cjs.isDefinedPlugin; }
21051
22514
  });
21052
22515
  Object.defineProperty(exports, "parseConfigSchema", {
21053
22516
  enumerable: true,
21054
- get: function () { return chunkA4KUJ3LD_cjs.parseConfigSchema; }
22517
+ get: function () { return chunk4WMZGHIC_cjs.parseConfigSchema; }
21055
22518
  });
21056
22519
  Object.defineProperty(exports, "parseFormDataToSettings", {
21057
22520
  enumerable: true,
21058
- get: function () { return chunkA4KUJ3LD_cjs.parseFormDataToSettings; }
22521
+ get: function () { return chunk4WMZGHIC_cjs.parseFormDataToSettings; }
21059
22522
  });
21060
22523
  Object.defineProperty(exports, "renderSchemaFields", {
21061
22524
  enumerable: true,
21062
- get: function () { return chunkA4KUJ3LD_cjs.renderSchemaFields; }
22525
+ get: function () { return chunk4WMZGHIC_cjs.renderSchemaFields; }
22526
+ });
22527
+ Object.defineProperty(exports, "resetPluginMenu", {
22528
+ enumerable: true,
22529
+ get: function () { return chunk4WMZGHIC_cjs.resetPluginMenu; }
22530
+ });
22531
+ Object.defineProperty(exports, "resolvePluginMenuItems", {
22532
+ enumerable: true,
22533
+ get: function () { return chunk4WMZGHIC_cjs.resolvePluginMenuItems; }
22534
+ });
22535
+ Object.defineProperty(exports, "setPluginMenu", {
22536
+ enumerable: true,
22537
+ get: function () { return chunk4WMZGHIC_cjs.setPluginMenu; }
21063
22538
  });
21064
22539
  Object.defineProperty(exports, "getHookSystem", {
21065
22540
  enumerable: true,
@@ -21107,11 +22582,11 @@ Object.defineProperty(exports, "metricsTracker", {
21107
22582
  });
21108
22583
  Object.defineProperty(exports, "SONICJS_VERSION", {
21109
22584
  enumerable: true,
21110
- get: function () { return chunkAOUVUF32_cjs.SONICJS_VERSION; }
22585
+ get: function () { return chunkC3ZQP5NW_cjs.SONICJS_VERSION; }
21111
22586
  });
21112
22587
  Object.defineProperty(exports, "getCoreVersion", {
21113
22588
  enumerable: true,
21114
- get: function () { return chunkAOUVUF32_cjs.getCoreVersion; }
22589
+ get: function () { return chunkC3ZQP5NW_cjs.getCoreVersion; }
21115
22590
  });
21116
22591
  Object.defineProperty(exports, "escapeHtml", {
21117
22592
  enumerable: true,