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

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 (170) hide show
  1. package/README.md +48 -49
  2. package/dist/admin-documents-form.template-DDSH6ROU.js +6 -0
  3. package/dist/{admin-documents-form.template-NLSI6Z42.js.map → admin-documents-form.template-DDSH6ROU.js.map} +1 -1
  4. package/dist/admin-documents-form.template-LSZKGA5J.cjs +19 -0
  5. package/dist/{admin-layout-catalyst.template-WHJGSWWD.js.map → admin-documents-form.template-LSZKGA5J.cjs.map} +1 -1
  6. package/dist/{filter-bar.template-DlVYMk-T.d.ts → admin-layout-catalyst.template-DrwDUfsE.d.cts} +25 -1
  7. package/dist/{filter-bar.template-DlVYMk-T.d.cts → admin-layout-catalyst.template-DrwDUfsE.d.ts} +25 -1
  8. package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs +21 -0
  9. package/dist/{admin-layout-catalyst.template-ZK5HD545.cjs.map → admin-layout-catalyst.template-KDHKVLXR.cjs.map} +1 -1
  10. package/dist/admin-layout-catalyst.template-YQ4EMF2J.js +7 -0
  11. package/dist/{admin-documents-form.template-KN7JF66Q.cjs.map → admin-layout-catalyst.template-YQ4EMF2J.js.map} +1 -1
  12. package/dist/{app-Bo0X1OWX.d.ts → app-01M0dIwt.d.ts} +1 -1
  13. package/dist/{app-Do66yCcV.d.cts → app-aj39TGHB.d.cts} +1 -1
  14. package/dist/{chunk-ZEZ245PW.js → chunk-2XAQTPAE.js} +4 -236
  15. package/dist/chunk-2XAQTPAE.js.map +1 -0
  16. package/dist/{chunk-BDDABDAB.cjs → chunk-36Z3AKX3.cjs} +3 -239
  17. package/dist/chunk-36Z3AKX3.cjs.map +1 -0
  18. package/dist/{chunk-BLMTL57B.js → chunk-3TMTYJAJ.js} +26 -4
  19. package/dist/chunk-3TMTYJAJ.js.map +1 -0
  20. package/dist/{chunk-ZGGXCFR6.js → chunk-4LVVMVQI.js} +282 -4
  21. package/dist/chunk-4LVVMVQI.js.map +1 -0
  22. package/dist/{chunk-RZ6H7OZK.js → chunk-4UYJPHSV.js} +87 -12
  23. package/dist/chunk-4UYJPHSV.js.map +1 -0
  24. package/dist/{chunk-NLJVSER2.js → chunk-5U75XP74.js} +3 -2
  25. package/dist/chunk-5U75XP74.js.map +1 -0
  26. package/dist/{chunk-H2AXVCLS.cjs → chunk-5UXU3LP4.cjs} +141 -74
  27. package/dist/chunk-5UXU3LP4.cjs.map +1 -0
  28. package/dist/{chunk-3TB6AT6X.js → chunk-5V62WT6M.js} +35 -4
  29. package/dist/chunk-5V62WT6M.js.map +1 -0
  30. package/dist/{chunk-6OUHGKFD.js → chunk-7OTOXWEB.js} +3 -3
  31. package/dist/{chunk-6OUHGKFD.js.map → chunk-7OTOXWEB.js.map} +1 -1
  32. package/dist/{chunk-VXE42MYF.cjs → chunk-7RUW244J.cjs} +710 -434
  33. package/dist/chunk-7RUW244J.cjs.map +1 -0
  34. package/dist/{chunk-XW56B23A.cjs → chunk-A4KUJ3LD.cjs} +4 -4
  35. package/dist/{chunk-XW56B23A.cjs.map → chunk-A4KUJ3LD.cjs.map} +1 -1
  36. package/dist/{chunk-LRZIAW7U.cjs → chunk-AOUVUF32.cjs} +3 -3
  37. package/dist/chunk-AOUVUF32.cjs.map +1 -0
  38. package/dist/{chunk-WULONYGB.cjs → chunk-CRGUD4KC.cjs} +9 -9
  39. package/dist/{chunk-WULONYGB.cjs.map → chunk-CRGUD4KC.cjs.map} +1 -1
  40. package/dist/{chunk-AAWNRBRB.cjs → chunk-FCLKX2OS.cjs} +95 -20
  41. package/dist/chunk-FCLKX2OS.cjs.map +1 -0
  42. package/dist/{chunk-YHSQVQXX.js → chunk-GICS5AIO.js} +135 -68
  43. package/dist/chunk-GICS5AIO.js.map +1 -0
  44. package/dist/{chunk-NUKJ54GA.cjs → chunk-GMMCCIQO.cjs} +6 -6
  45. package/dist/{chunk-NUKJ54GA.cjs.map → chunk-GMMCCIQO.cjs.map} +1 -1
  46. package/dist/{chunk-NMPEMSU4.js → chunk-JEX3UPZL.js} +3 -3
  47. package/dist/chunk-JEX3UPZL.js.map +1 -0
  48. package/dist/{chunk-6JQOUUOB.js → chunk-JQISFW6U.js} +3 -3
  49. package/dist/{chunk-6JQOUUOB.js.map → chunk-JQISFW6U.js.map} +1 -1
  50. package/dist/{chunk-NAVPFIG5.cjs → chunk-K623Q6WD.cjs} +35 -3
  51. package/dist/chunk-K623Q6WD.cjs.map +1 -0
  52. package/dist/{chunk-JEQ7FLOD.cjs → chunk-KIGVVO6N.cjs} +16 -10
  53. package/dist/chunk-KIGVVO6N.cjs.map +1 -0
  54. package/dist/{chunk-QAYFOER6.cjs → chunk-KVBHB7QP.cjs} +285 -3
  55. package/dist/chunk-KVBHB7QP.cjs.map +1 -0
  56. package/dist/{chunk-2CB4KY7I.cjs → chunk-LTZ5WYOK.cjs} +29 -7
  57. package/dist/chunk-LTZ5WYOK.cjs.map +1 -0
  58. package/dist/{chunk-DNQCEKUK.cjs → chunk-N32OWET6.cjs} +5 -5
  59. package/dist/{chunk-DNQCEKUK.cjs.map → chunk-N32OWET6.cjs.map} +1 -1
  60. package/dist/{chunk-HDWE5FRJ.js → chunk-OBA2RYZN.js} +3 -3
  61. package/dist/{chunk-HDWE5FRJ.js.map → chunk-OBA2RYZN.js.map} +1 -1
  62. package/dist/{chunk-DSA4UX5B.cjs → chunk-OJC4G5JE.cjs} +3 -2
  63. package/dist/chunk-OJC4G5JE.cjs.map +1 -0
  64. package/dist/{chunk-MVIZJOO5.cjs → chunk-PXNTCCPE.cjs} +8 -8
  65. package/dist/{chunk-MVIZJOO5.cjs.map → chunk-PXNTCCPE.cjs.map} +1 -1
  66. package/dist/{chunk-EF2NQUIQ.js → chunk-RMRJGMDE.js} +3 -3
  67. package/dist/{chunk-EF2NQUIQ.js.map → chunk-RMRJGMDE.js.map} +1 -1
  68. package/dist/{chunk-IVPRUGTY.js → chunk-SOZUG52O.js} +4 -4
  69. package/dist/{chunk-IVPRUGTY.js.map → chunk-SOZUG52O.js.map} +1 -1
  70. package/dist/{chunk-GCDZZNIN.js → chunk-UWUP2VMT.js} +16 -10
  71. package/dist/chunk-UWUP2VMT.js.map +1 -0
  72. package/dist/{chunk-IESEVHXL.js → chunk-VVYVFCML.js} +12 -3
  73. package/dist/chunk-VVYVFCML.js.map +1 -0
  74. package/dist/{chunk-HIKBY7MS.cjs → chunk-XWVDSM2L.cjs} +12 -3
  75. package/dist/chunk-XWVDSM2L.cjs.map +1 -0
  76. package/dist/{chunk-VD2EA3WT.js → chunk-ZP77LTN4.js} +343 -68
  77. package/dist/chunk-ZP77LTN4.js.map +1 -0
  78. package/dist/{collection-config-JgHOpFCG.d.ts → collection-config-BTzAvKt2.d.cts} +25 -0
  79. package/dist/{collection-config-JgHOpFCG.d.cts → collection-config-BTzAvKt2.d.ts} +25 -0
  80. package/dist/config-6FB2BXMP.js +6 -0
  81. package/dist/{config-HFXANXCC.js.map → config-6FB2BXMP.js.map} +1 -1
  82. package/dist/config-OCH7S4WK.cjs +19 -0
  83. package/dist/{config-ON6FNMYX.cjs.map → config-OCH7S4WK.cjs.map} +1 -1
  84. package/dist/{define-plugin-BzNHc1ZI.d.ts → define-plugin-BYIey6sp.d.ts} +1 -1
  85. package/dist/{define-plugin-IWDKYaVm.d.cts → define-plugin-DsKiGu1q.d.cts} +1 -1
  86. package/dist/document-projection-4HG75S5S.js +4 -0
  87. package/dist/{document-projection-YYMC6I4U.js.map → document-projection-4HG75S5S.js.map} +1 -1
  88. package/dist/document-projection-JQHSTSFD.cjs +13 -0
  89. package/dist/{document-projection-TDWRJX3Z.cjs.map → document-projection-JQHSTSFD.cjs.map} +1 -1
  90. package/dist/index.cjs +1119 -440
  91. package/dist/index.cjs.map +1 -1
  92. package/dist/index.d.cts +200 -12
  93. package/dist/index.d.ts +200 -12
  94. package/dist/index.js +803 -137
  95. package/dist/index.js.map +1 -1
  96. package/dist/middleware.cjs +37 -34
  97. package/dist/middleware.d.cts +2 -2
  98. package/dist/middleware.d.ts +2 -2
  99. package/dist/middleware.js +8 -5
  100. package/dist/migrations-HMX5SPN2.js +4 -0
  101. package/dist/{migrations-WCAVBD7C.js.map → migrations-HMX5SPN2.js.map} +1 -1
  102. package/dist/migrations-V73ARYV5.cjs +13 -0
  103. package/dist/{migrations-NJJWQUKK.cjs.map → migrations-V73ARYV5.cjs.map} +1 -1
  104. package/dist/{plugin-bootstrap-B8ThJU21.d.cts → plugin-bootstrap-BHWQ2df8.d.cts} +1 -1
  105. package/dist/{plugin-bootstrap-qu8hJgUt.d.ts → plugin-bootstrap-Bj4fxX1q.d.ts} +1 -1
  106. package/dist/plugins.cjs +40 -40
  107. package/dist/plugins.d.cts +2 -2
  108. package/dist/plugins.d.ts +2 -2
  109. package/dist/plugins.js +3 -3
  110. package/dist/rbac-7QZ4JZ2E.cjs +14 -0
  111. package/dist/{rbac-VONLJJKB.cjs.map → rbac-7QZ4JZ2E.cjs.map} +1 -1
  112. package/dist/rbac-Y43IEQOP.js +5 -0
  113. package/dist/{rbac-O73MFKDA.js.map → rbac-Y43IEQOP.js.map} +1 -1
  114. package/dist/routes.cjs +34 -34
  115. package/dist/routes.d.cts +2 -2
  116. package/dist/routes.d.ts +2 -2
  117. package/dist/routes.js +14 -14
  118. package/dist/services.cjs +42 -42
  119. package/dist/services.d.cts +16 -3
  120. package/dist/services.d.ts +16 -3
  121. package/dist/services.js +3 -3
  122. package/dist/{telemetry-B9vIV4wh.d.cts → telemetry-Cku1ax74.d.cts} +1 -1
  123. package/dist/{telemetry-B9vIV4wh.d.ts → telemetry-Cku1ax74.d.ts} +1 -1
  124. package/dist/templates.cjs +17 -17
  125. package/dist/templates.d.cts +2 -24
  126. package/dist/templates.d.ts +2 -24
  127. package/dist/templates.js +3 -3
  128. package/dist/{types-Dea1eNxU.d.ts → types-DT7XN5TX.d.cts} +1 -1
  129. package/dist/{types-Dea1eNxU.d.cts → types-DT7XN5TX.d.ts} +1 -1
  130. package/dist/types.d.cts +2 -2
  131. package/dist/types.d.ts +2 -2
  132. package/dist/utils.cjs +8 -8
  133. package/dist/utils.d.cts +2 -2
  134. package/dist/utils.d.ts +2 -2
  135. package/dist/utils.js +2 -2
  136. package/package.json +1 -1
  137. package/dist/admin-documents-form.template-KN7JF66Q.cjs +0 -19
  138. package/dist/admin-documents-form.template-NLSI6Z42.js +0 -6
  139. package/dist/admin-layout-catalyst.template-WHJGSWWD.js +0 -7
  140. package/dist/admin-layout-catalyst.template-ZK5HD545.cjs +0 -17
  141. package/dist/chunk-2CB4KY7I.cjs.map +0 -1
  142. package/dist/chunk-3TB6AT6X.js.map +0 -1
  143. package/dist/chunk-AAWNRBRB.cjs.map +0 -1
  144. package/dist/chunk-BDDABDAB.cjs.map +0 -1
  145. package/dist/chunk-BLMTL57B.js.map +0 -1
  146. package/dist/chunk-DSA4UX5B.cjs.map +0 -1
  147. package/dist/chunk-GCDZZNIN.js.map +0 -1
  148. package/dist/chunk-H2AXVCLS.cjs.map +0 -1
  149. package/dist/chunk-HIKBY7MS.cjs.map +0 -1
  150. package/dist/chunk-IESEVHXL.js.map +0 -1
  151. package/dist/chunk-JEQ7FLOD.cjs.map +0 -1
  152. package/dist/chunk-LRZIAW7U.cjs.map +0 -1
  153. package/dist/chunk-NAVPFIG5.cjs.map +0 -1
  154. package/dist/chunk-NLJVSER2.js.map +0 -1
  155. package/dist/chunk-NMPEMSU4.js.map +0 -1
  156. package/dist/chunk-QAYFOER6.cjs.map +0 -1
  157. package/dist/chunk-RZ6H7OZK.js.map +0 -1
  158. package/dist/chunk-VD2EA3WT.js.map +0 -1
  159. package/dist/chunk-VXE42MYF.cjs.map +0 -1
  160. package/dist/chunk-YHSQVQXX.js.map +0 -1
  161. package/dist/chunk-ZEZ245PW.js.map +0 -1
  162. package/dist/chunk-ZGGXCFR6.js.map +0 -1
  163. package/dist/config-HFXANXCC.js +0 -6
  164. package/dist/config-ON6FNMYX.cjs +0 -19
  165. package/dist/document-projection-TDWRJX3Z.cjs +0 -13
  166. package/dist/document-projection-YYMC6I4U.js +0 -4
  167. package/dist/migrations-NJJWQUKK.cjs +0 -13
  168. package/dist/migrations-WCAVBD7C.js +0 -4
  169. package/dist/rbac-O73MFKDA.js +0 -5
  170. package/dist/rbac-VONLJJKB.cjs +0 -14
package/dist/index.cjs CHANGED
@@ -1,31 +1,32 @@
1
1
  'use strict';
2
2
 
3
- var chunkNUKJ54GA_cjs = require('./chunk-NUKJ54GA.cjs');
4
- var chunkVXE42MYF_cjs = require('./chunk-VXE42MYF.cjs');
5
- require('./chunk-HIKBY7MS.cjs');
6
- require('./chunk-DNQCEKUK.cjs');
7
- var chunkBDDABDAB_cjs = require('./chunk-BDDABDAB.cjs');
3
+ var chunkGMMCCIQO_cjs = require('./chunk-GMMCCIQO.cjs');
4
+ var chunk7RUW244J_cjs = require('./chunk-7RUW244J.cjs');
5
+ require('./chunk-XWVDSM2L.cjs');
6
+ require('./chunk-N32OWET6.cjs');
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 chunkAAWNRBRB_cjs = require('./chunk-AAWNRBRB.cjs');
11
- var chunk2CB4KY7I_cjs = require('./chunk-2CB4KY7I.cjs');
12
- var chunkJEQ7FLOD_cjs = require('./chunk-JEQ7FLOD.cjs');
13
- var chunkQAYFOER6_cjs = require('./chunk-QAYFOER6.cjs');
14
- var chunkDSA4UX5B_cjs = require('./chunk-DSA4UX5B.cjs');
15
- var chunkWULONYGB_cjs = require('./chunk-WULONYGB.cjs');
16
- var chunkMVIZJOO5_cjs = require('./chunk-MVIZJOO5.cjs');
17
- var chunkNAVPFIG5_cjs = require('./chunk-NAVPFIG5.cjs');
18
- var chunkH2AXVCLS_cjs = require('./chunk-H2AXVCLS.cjs');
19
- var chunkXW56B23A_cjs = require('./chunk-XW56B23A.cjs');
10
+ var chunkFCLKX2OS_cjs = require('./chunk-FCLKX2OS.cjs');
11
+ var chunkLTZ5WYOK_cjs = require('./chunk-LTZ5WYOK.cjs');
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');
20
20
  var chunkJ6JTWD2A_cjs = require('./chunk-J6JTWD2A.cjs');
21
21
  var chunkIXUHXTHW_cjs = require('./chunk-IXUHXTHW.cjs');
22
- require('./chunk-P3XDZL6Q.cjs');
23
22
  var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
24
- var chunkLRZIAW7U_cjs = require('./chunk-LRZIAW7U.cjs');
23
+ require('./chunk-P3XDZL6Q.cjs');
24
+ var chunkAOUVUF32_cjs = require('./chunk-AOUVUF32.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');
28
28
  var hono = require('hono');
29
+ var cors = require('hono/cors');
29
30
  var zod = require('zod');
30
31
  var cookie = require('hono/cookie');
31
32
  var html = require('hono/html');
@@ -39,6 +40,7 @@ var DatabaseToolsService = class {
39
40
  constructor(db) {
40
41
  this.db = db;
41
42
  }
43
+ db;
42
44
  /**
43
45
  * Get database statistics
44
46
  */
@@ -180,9 +182,9 @@ var DatabaseToolsService = class {
180
182
  }
181
183
  }
182
184
  /**
183
- * Get table data with optional pagination and sorting
185
+ * Get table data with optional pagination, sorting, and search
184
186
  */
185
- async getTableData(tableName, limit = 100, offset = 0, sortColumn, sortDirection = "asc") {
187
+ async getTableData(tableName, limit = 100, offset = 0, sortColumn, sortDirection = "asc", search) {
186
188
  try {
187
189
  const tables = await this.getTables();
188
190
  if (!tables.includes(tableName)) {
@@ -193,14 +195,26 @@ var DatabaseToolsService = class {
193
195
  if (sortColumn && !columns.includes(sortColumn)) {
194
196
  sortColumn = void 0;
195
197
  }
196
- const countResult = await this.db.prepare(`SELECT COUNT(*) as count FROM ${tableName}`).first();
198
+ const searchTerm = search?.trim();
199
+ let whereClause = "";
200
+ let bindings = [];
201
+ if (searchTerm) {
202
+ const conditions = columns.map(() => `CAST(? AS TEXT) IS NOT NULL AND CAST(? AS TEXT) LIKE ?`).join(" OR ");
203
+ const colConditions = columns.map((col) => `CAST("${col}" AS TEXT) LIKE ?`).join(" OR ");
204
+ whereClause = ` WHERE (${colConditions})`;
205
+ bindings = columns.map(() => `%${searchTerm}%`);
206
+ }
207
+ const countQuery = `SELECT COUNT(*) as count FROM "${tableName}"${whereClause}`;
208
+ const countStmt = this.db.prepare(countQuery);
209
+ const countResult = bindings.length > 0 ? await countStmt.bind(...bindings).first() : await countStmt.first();
197
210
  const totalRows = countResult?.count || 0;
198
- let query = `SELECT * FROM ${tableName}`;
211
+ let query = `SELECT * FROM "${tableName}"${whereClause}`;
199
212
  if (sortColumn) {
200
- query += ` ORDER BY ${sortColumn} ${sortDirection.toUpperCase()}`;
213
+ query += ` ORDER BY "${sortColumn}" ${sortDirection.toUpperCase()}`;
201
214
  }
202
215
  query += ` LIMIT ${limit} OFFSET ${offset}`;
203
- const dataResult = await this.db.prepare(query).all();
216
+ const dataStmt = this.db.prepare(query);
217
+ const dataResult = bindings.length > 0 ? await dataStmt.bind(...bindings).all() : await dataStmt.all();
204
218
  return {
205
219
  tableName,
206
220
  columns,
@@ -249,7 +263,7 @@ var DatabaseToolsService = class {
249
263
  };
250
264
 
251
265
  // src/templates/pages/admin-database-table.template.ts
252
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
266
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
253
267
  function renderDatabaseTablePage(data) {
254
268
  const totalPages = Math.ceil(data.totalRows / data.pageSize);
255
269
  const startRow = (data.currentPage - 1) * data.pageSize + 1;
@@ -304,6 +318,43 @@ function renderDatabaseTablePage(data) {
304
318
  </div>
305
319
  </div>
306
320
 
321
+ <!-- Search bar -->
322
+ <div class="flex items-center gap-3">
323
+ <div class="relative flex-1 max-w-xl">
324
+ <div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
325
+ <svg class="h-4 w-4 text-zinc-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
326
+ <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 0"/>
327
+ </svg>
328
+ </div>
329
+ <input
330
+ id="searchInput"
331
+ type="text"
332
+ placeholder="Search all columns including JSON data..."
333
+ value="${escapeHtml2(data.search || "")}"
334
+ class="block w-full rounded-lg border-0 py-2.5 pl-10 pr-10 text-sm text-zinc-900 dark:text-white bg-white dark:bg-zinc-800 ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600"
335
+ onkeydown="if(event.key==='Enter') doSearch()"
336
+ />
337
+ ${data.search ? `
338
+ <button
339
+ onclick="clearSearch()"
340
+ class="absolute inset-y-0 right-0 flex items-center pr-3 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-200"
341
+ title="Clear search"
342
+ >
343
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
344
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
345
+ </svg>
346
+ </button>
347
+ ` : ""}
348
+ </div>
349
+ <button
350
+ onclick="doSearch()"
351
+ class="inline-flex items-center justify-center rounded-lg bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-indigo-500 transition-colors shadow-sm"
352
+ >
353
+ Search
354
+ </button>
355
+ ${data.search ? `<span class="text-sm text-zinc-500 dark:text-zinc-400">Filtered: <strong class="text-zinc-900 dark:text-white">${escapeHtml2(data.search)}</strong></span>` : ""}
356
+ </div>
357
+
307
358
  <!-- Table Card -->
308
359
  <div class="rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden">
309
360
  <!-- Table -->
@@ -338,7 +389,7 @@ function renderDatabaseTablePage(data) {
338
389
  <tr class="${idx % 2 === 0 ? "bg-white dark:bg-zinc-900" : "bg-zinc-50 dark:bg-zinc-900/50"}">
339
390
  ${data.columns.map((col) => `
340
391
  <td class="px-4 py-3 text-sm text-zinc-700 dark:text-zinc-300 whitespace-nowrap max-w-xs overflow-hidden text-ellipsis" title="${escapeHtml2(String(row[col] ?? ""))}">
341
- ${formatCellValue(row[col])}
392
+ ${formatCellValue(row[col], col)}
342
393
  </td>
343
394
  `).join("")}
344
395
  </tr>
@@ -414,79 +465,143 @@ function renderDatabaseTablePage(data) {
414
465
  </div>
415
466
  </div>
416
467
 
468
+ <!-- JSON Viewer Modal -->
469
+ <div id="jsonModal" class="fixed inset-0 z-50 hidden" role="dialog" aria-modal="true">
470
+ <div class="fixed inset-0 bg-black/60 backdrop-blur-sm" onclick="closeJsonModal()"></div>
471
+ <div class="fixed inset-0 flex items-center justify-center p-4 pointer-events-none">
472
+ <div class="pointer-events-auto relative w-full max-w-4xl max-h-[85vh] flex flex-col rounded-xl bg-white dark:bg-zinc-900 shadow-2xl ring-1 ring-zinc-950/10 dark:ring-white/10">
473
+ <div class="flex items-center justify-between px-6 py-4 border-b border-zinc-200 dark:border-zinc-700">
474
+ <div>
475
+ <h3 id="jsonModalTitle" class="text-base font-semibold text-zinc-900 dark:text-white">Field Value</h3>
476
+ <p id="jsonModalSubtitle" class="text-xs text-zinc-500 dark:text-zinc-400 mt-0.5"></p>
477
+ </div>
478
+ <div class="flex items-center gap-2">
479
+ <button onclick="copyJsonValue()" class="inline-flex items-center gap-1.5 rounded-lg bg-zinc-100 dark:bg-zinc-800 px-3 py-1.5 text-xs font-medium text-zinc-700 dark:text-zinc-300 hover:bg-zinc-200 dark:hover:bg-zinc-700 transition-colors">
480
+ <svg class="h-3.5 w-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
481
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/>
482
+ </svg>
483
+ Copy
484
+ </button>
485
+ <button onclick="closeJsonModal()" class="rounded-lg p-1.5 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-200 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors">
486
+ <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
487
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
488
+ </svg>
489
+ </button>
490
+ </div>
491
+ </div>
492
+ <div class="flex-1 overflow-auto p-6">
493
+ <pre id="jsonModalContent" class="text-sm font-mono text-zinc-800 dark:text-zinc-200 whitespace-pre-wrap break-words leading-relaxed"></pre>
494
+ </div>
495
+ </div>
496
+ </div>
497
+ </div>
498
+
417
499
  <script>
418
500
  const currentTableName = '${data.tableName}';
419
501
  let currentPage = ${data.currentPage};
420
502
  let currentPageSize = ${data.pageSize};
421
503
  let currentSort = '${data.sortColumn || ""}';
422
504
  let currentSortDir = '${data.sortDirection || "asc"}';
505
+ let currentSearch = ${JSON.stringify(data.search || "")};
506
+
507
+ function buildParams(overrides = {}) {
508
+ const params = new URLSearchParams();
509
+ const p = { page: currentPage, pageSize: currentPageSize, sort: currentSort, dir: currentSortDir, search: currentSearch, ...overrides };
510
+ if (p.page) params.set('page', p.page);
511
+ if (p.pageSize) params.set('pageSize', p.pageSize);
512
+ if (p.sort) { params.set('sort', p.sort); params.set('dir', p.dir || 'asc'); }
513
+ if (p.search) params.set('search', p.search);
514
+ return params;
515
+ }
423
516
 
424
517
  function goToPage(page) {
425
518
  if (page < 1 || page > ${totalPages}) return;
426
- const params = new URLSearchParams();
427
- params.set('page', page);
428
- params.set('pageSize', currentPageSize);
429
- if (currentSort) {
430
- params.set('sort', currentSort);
431
- params.set('dir', currentSortDir);
432
- }
433
- window.location.href = \`/admin/database-tools/tables/\${currentTableName}?\${params}\`;
519
+ window.location.href = \`/admin/database-tools/tables/\${currentTableName}?\${buildParams({ page })}\`;
434
520
  }
435
521
 
436
522
  function sortTable(column) {
437
- let newDir = 'asc';
438
- if (currentSort === column && currentSortDir === 'asc') {
439
- newDir = 'desc';
440
- }
441
-
442
- const params = new URLSearchParams();
443
- params.set('page', '1');
444
- params.set('pageSize', currentPageSize);
445
- params.set('sort', column);
446
- params.set('dir', newDir);
447
- window.location.href = \`/admin/database-tools/tables/\${currentTableName}?\${params}\`;
523
+ const newDir = (currentSort === column && currentSortDir === 'asc') ? 'desc' : 'asc';
524
+ window.location.href = \`/admin/database-tools/tables/\${currentTableName}?\${buildParams({ page: 1, sort: column, dir: newDir })}\`;
448
525
  }
449
526
 
450
527
  function changePageSize(newSize) {
451
- const params = new URLSearchParams();
452
- params.set('page', '1');
453
- params.set('pageSize', newSize);
454
- if (currentSort) {
455
- params.set('sort', currentSort);
456
- params.set('dir', currentSortDir);
457
- }
458
- window.location.href = \`/admin/database-tools/tables/\${currentTableName}?\${params}\`;
528
+ window.location.href = \`/admin/database-tools/tables/\${currentTableName}?\${buildParams({ page: 1, pageSize: newSize })}\`;
459
529
  }
460
530
 
461
531
  function refreshTableData() {
462
532
  window.location.reload();
463
533
  }
464
534
 
465
- function formatCellValue(value) {
466
- if (value === null || value === undefined) {
467
- return '<span class="text-zinc-400 dark:text-zinc-500 italic">null</span>';
468
- }
469
- if (typeof value === 'boolean') {
470
- return \`<span class="px-2 py-0.5 rounded text-xs font-medium \${value ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400' : 'bg-zinc-100 text-zinc-800 dark:bg-zinc-800 dark:text-zinc-400'}">\${value}</span>\`;
471
- }
472
- if (typeof value === 'object') {
473
- return '<span class="text-xs font-mono text-zinc-600 dark:text-zinc-400">' + JSON.stringify(value).substring(0, 50) + (JSON.stringify(value).length > 50 ? '...' : '') + '</span>';
474
- }
475
- const str = String(value);
476
- if (str.length > 100) {
477
- return escapeHtml(str.substring(0, 100)) + '...';
535
+ function doSearch() {
536
+ const val = document.getElementById('searchInput').value.trim();
537
+ window.location.href = \`/admin/database-tools/tables/\${currentTableName}?\${buildParams({ page: 1, search: val })}\`;
538
+ }
539
+
540
+ function clearSearch() {
541
+ window.location.href = \`/admin/database-tools/tables/\${currentTableName}?\${buildParams({ page: 1, search: '' })}\`;
542
+ }
543
+
544
+ // JSON viewer modal
545
+ let _jsonModalValue = '';
546
+
547
+ function openJsonModal(rawValue, colName) {
548
+ // rawValue comes from dataset \u2014 browser already decoded HTML entities, so it's the original string
549
+ _jsonModalValue = rawValue;
550
+ document.getElementById('jsonModalTitle').textContent = colName;
551
+ const el = document.getElementById('jsonModalContent');
552
+ const subtitle = document.getElementById('jsonModalSubtitle');
553
+ try {
554
+ const parsed = JSON.parse(rawValue);
555
+ const pretty = JSON.stringify(parsed, null, 2);
556
+ subtitle.textContent = 'JSON \u2022 ' + rawValue.length + ' chars';
557
+ el.innerHTML = syntaxHighlight(pretty);
558
+ } catch {
559
+ el.textContent = rawValue;
560
+ subtitle.textContent = rawValue.length + ' chars';
478
561
  }
479
- return escapeHtml(str);
562
+ document.getElementById('jsonModal').classList.remove('hidden');
563
+ document.body.style.overflow = 'hidden';
480
564
  }
481
565
 
566
+ function closeJsonModal() {
567
+ document.getElementById('jsonModal').classList.add('hidden');
568
+ document.body.style.overflow = '';
569
+ }
570
+
571
+ function copyJsonValue() {
572
+ navigator.clipboard.writeText(_jsonModalValue).then(() => {
573
+ const btn = event.currentTarget;
574
+ const orig = btn.innerHTML;
575
+ btn.textContent = 'Copied!';
576
+ setTimeout(() => { btn.innerHTML = orig; }, 1500);
577
+ });
578
+ }
579
+
580
+ function syntaxHighlight(json) {
581
+ json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
582
+ return json.replace(/("(\\\\u[a-zA-Z0-9]{4}|\\\\[^u]|[^\\\\"])*"(\\s*:)?|\\b(true|false|null)\\b|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)/g, function(match) {
583
+ let cls = 'text-purple-600 dark:text-purple-400'; // number
584
+ if (/^"/.test(match)) {
585
+ if (/:$/.test(match)) {
586
+ cls = 'text-blue-600 dark:text-blue-400 font-medium'; // key
587
+ } else {
588
+ cls = 'text-green-700 dark:text-green-400'; // string value
589
+ }
590
+ } else if (/true|false/.test(match)) {
591
+ cls = 'text-orange-600 dark:text-orange-400';
592
+ } else if (/null/.test(match)) {
593
+ cls = 'text-zinc-400 italic';
594
+ }
595
+ return \`<span class="\${cls}">\${match}</span>\`;
596
+ });
597
+ }
598
+
599
+ document.addEventListener('keydown', (e) => {
600
+ if (e.key === 'Escape') closeJsonModal();
601
+ });
602
+
482
603
  function escapeHtml(text) {
483
- const map = {
484
- '&': '&amp;',
485
- '<': '&lt;',
486
- '>': '&gt;',
487
- '"': '&quot;',
488
- "'": '&#039;'
489
- };
604
+ const map = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;' };
490
605
  return String(text).replace(/[&<>"']/g, m => map[m]);
491
606
  }
492
607
  </script>
@@ -498,7 +613,7 @@ function renderDatabaseTablePage(data) {
498
613
  user: data.user,
499
614
  content: pageContent
500
615
  };
501
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst(layoutData);
616
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
502
617
  }
503
618
  function generatePageNumbers(currentPage, totalPages) {
504
619
  const pages = [];
@@ -553,7 +668,16 @@ function escapeHtml2(text) {
553
668
  };
554
669
  return String(text).replace(/[&<>"']/g, (m) => map[m] || m);
555
670
  }
556
- function formatCellValue(value) {
671
+ function isJsonString(str2) {
672
+ const s = str2.trim();
673
+ return (s.startsWith("{") || s.startsWith("[")) && (s.endsWith("}") || s.endsWith("]"));
674
+ }
675
+ function jsonButton(raw, colName) {
676
+ const preview = raw.length > 60 ? escapeHtml2(raw.substring(0, 60)) + "\u2026" : escapeHtml2(raw);
677
+ return `<button data-json-val="${escapeHtml2(raw)}" data-col-name="${escapeHtml2(colName)}" onclick="openJsonModal(this.dataset.jsonVal, this.dataset.colName)" class="text-left text-xs font-mono text-indigo-600 dark:text-indigo-400 hover:underline">${preview}</button>`;
678
+ }
679
+ function formatCellValue(value, colName) {
680
+ const col = colName || "value";
557
681
  if (value === null || value === void 0) {
558
682
  return '<span class="text-zinc-400 dark:text-zinc-500 italic">null</span>';
559
683
  }
@@ -561,11 +685,15 @@ function formatCellValue(value) {
561
685
  return `<span class="px-2 py-0.5 rounded text-xs font-medium ${value ? "bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400" : "bg-zinc-100 text-zinc-800 dark:bg-zinc-800 dark:text-zinc-400"}">${value}</span>`;
562
686
  }
563
687
  if (typeof value === "object") {
564
- return '<span class="text-xs font-mono text-zinc-600 dark:text-zinc-400">' + JSON.stringify(value).substring(0, 50) + (JSON.stringify(value).length > 50 ? "..." : "") + "</span>";
688
+ return jsonButton(JSON.stringify(value), col);
565
689
  }
566
690
  const str2 = String(value);
567
- if (str2.length > 100) {
568
- return escapeHtml2(str2.substring(0, 100)) + "...";
691
+ if (isJsonString(str2)) {
692
+ return jsonButton(str2, col);
693
+ }
694
+ if (str2.length > 120) {
695
+ const preview = escapeHtml2(str2.substring(0, 120)) + "\u2026";
696
+ return `<button data-json-val="${escapeHtml2(str2)}" data-col-name="${escapeHtml2(col)}" onclick="openJsonModal(this.dataset.jsonVal, this.dataset.colName)" class="text-left text-sm text-zinc-700 dark:text-zinc-300 hover:underline">${preview}</button>`;
569
697
  }
570
698
  return escapeHtml2(str2);
571
699
  }
@@ -573,7 +701,7 @@ function formatCellValue(value) {
573
701
  // src/plugins/core-plugins/database-tools-plugin/admin-routes.ts
574
702
  function createDatabaseToolsAdminRoutes() {
575
703
  const router3 = new hono.Hono();
576
- router3.use("*", chunkAAWNRBRB_cjs.requireAuth());
704
+ router3.use("*", chunkFCLKX2OS_cjs.requireAuth());
577
705
  router3.get("/api/stats", async (c) => {
578
706
  try {
579
707
  const user = c.get("user");
@@ -700,9 +828,10 @@ function createDatabaseToolsAdminRoutes() {
700
828
  const offset = parseInt(c.req.query("offset") || "0");
701
829
  const sortColumn = c.req.query("sort");
702
830
  const sortDirection = c.req.query("dir") || "asc";
831
+ const search = c.req.query("search");
703
832
  const db = c.env.DB;
704
833
  const service = new DatabaseToolsService(db);
705
- const tableData = await service.getTableData(tableName, limit, offset, sortColumn, sortDirection);
834
+ const tableData = await service.getTableData(tableName, limit, offset, sortColumn, sortDirection, search);
706
835
  return c.json({
707
836
  success: true,
708
837
  data: tableData
@@ -726,10 +855,11 @@ function createDatabaseToolsAdminRoutes() {
726
855
  const pageSize = parseInt(c.req.query("pageSize") || "20");
727
856
  const sortColumn = c.req.query("sort");
728
857
  const sortDirection = c.req.query("dir") || "asc";
858
+ const search = c.req.query("search");
729
859
  const offset = (page - 1) * pageSize;
730
860
  const db = c.env.DB;
731
861
  const service = new DatabaseToolsService(db);
732
- const tableData = await service.getTableData(tableName, pageSize, offset, sortColumn, sortDirection);
862
+ const tableData = await service.getTableData(tableName, pageSize, offset, sortColumn, sortDirection, search);
733
863
  const pageData = {
734
864
  user: {
735
865
  name: user.email.split("@")[0] || "Unknown",
@@ -743,7 +873,8 @@ function createDatabaseToolsAdminRoutes() {
743
873
  currentPage: page,
744
874
  pageSize,
745
875
  sortColumn,
746
- sortDirection
876
+ sortDirection,
877
+ search
747
878
  };
748
879
  return c.html(renderDatabaseTablePage(pageData));
749
880
  } catch (error) {
@@ -897,6 +1028,7 @@ var EmailSettingsService = class {
897
1028
  constructor(db) {
898
1029
  this.db = db;
899
1030
  }
1031
+ db;
900
1032
  async load() {
901
1033
  let row = null;
902
1034
  try {
@@ -925,8 +1057,10 @@ var SiteConfigService = class {
925
1057
  this.db = db;
926
1058
  this.env = env;
927
1059
  }
1060
+ db;
1061
+ env;
928
1062
  async load() {
929
- const settings = new chunkBDDABDAB_cjs.SettingsService(this.db);
1063
+ const settings = new chunk36Z3AKX3_cjs.SettingsService(this.db);
930
1064
  const general = await settings.getGeneralSettings();
931
1065
  const siteUrl = this.env.PUBLIC_URL || "http://localhost:8787";
932
1066
  return {
@@ -976,7 +1110,7 @@ var SiteConfigService = class {
976
1110
 
977
1111
  // src/plugins/core-plugins/email-plugin/routes/admin.ts
978
1112
  var adminRoutes = new hono.Hono();
979
- adminRoutes.use("*", chunkAAWNRBRB_cjs.requireAuth());
1113
+ adminRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
980
1114
  adminRoutes.post("/settings", async (c) => {
981
1115
  if (c.get("user")?.role !== "admin") {
982
1116
  return c.json({ error: "admin role required" }, 403);
@@ -1014,7 +1148,7 @@ adminRoutes.post("/test", async (c) => {
1014
1148
  const { subject, html: html4, text } = renderTestEmail({ siteName });
1015
1149
  try {
1016
1150
  const settingsLoaded = await settings.load();
1017
- const result = await chunkVXE42MYF_cjs.getEmailService().send({
1151
+ const result = await chunk7RUW244J_cjs.getEmailService().send({
1018
1152
  to,
1019
1153
  subject,
1020
1154
  html: html4,
@@ -1096,7 +1230,7 @@ function makeOnRegistrationCompleted(env) {
1096
1230
  siteName,
1097
1231
  loginUrl: siteConfig.buildLoginUrl(siteUrl)
1098
1232
  });
1099
- const result = await chunkVXE42MYF_cjs.getEmailService().send({
1233
+ const result = await chunk7RUW244J_cjs.getEmailService().send({
1100
1234
  to: user.email,
1101
1235
  subject,
1102
1236
  html: html4,
@@ -1170,7 +1304,7 @@ function makeOnPasswordResetRequested(env) {
1170
1304
  expiresAt: Date.now() + DEFAULT_EXPIRY_MS,
1171
1305
  siteName
1172
1306
  });
1173
- const result = await chunkVXE42MYF_cjs.getEmailService().send({
1307
+ const result = await chunk7RUW244J_cjs.getEmailService().send({
1174
1308
  to: user.email,
1175
1309
  subject,
1176
1310
  html: html4,
@@ -1238,7 +1372,7 @@ function makeOnPasswordResetCompleted(env) {
1238
1372
  supportEmail,
1239
1373
  when: Date.now()
1240
1374
  });
1241
- const result = await chunkVXE42MYF_cjs.getEmailService().send({
1375
+ const result = await chunk7RUW244J_cjs.getEmailService().send({
1242
1376
  to: user.email,
1243
1377
  subject,
1244
1378
  html: html4,
@@ -1262,6 +1396,8 @@ var EmailValidationError = class extends Error {
1262
1396
  this.reason = reason;
1263
1397
  this.name = "EmailValidationError";
1264
1398
  }
1399
+ field;
1400
+ reason;
1265
1401
  code = "EMAIL_VALIDATION_FAILED";
1266
1402
  };
1267
1403
 
@@ -1297,6 +1433,9 @@ var CfGraphqlClient = class {
1297
1433
  throw new EmailValidationError("apiToken", "EMAIL_API_TOKEN is required for GraphQL queries");
1298
1434
  }
1299
1435
  }
1436
+ zoneId;
1437
+ apiToken;
1438
+ fetchImpl;
1300
1439
  async queryEmailSends(input) {
1301
1440
  const startIso = new Date(input.startSeconds * 1e3).toISOString();
1302
1441
  const endIso = new Date(input.endSeconds * 1e3).toISOString();
@@ -1359,6 +1498,7 @@ var EmailLogService = class {
1359
1498
  constructor(db) {
1360
1499
  this.db = db;
1361
1500
  }
1501
+ db;
1362
1502
  /**
1363
1503
  * Records a successful submission to CF Email Service. `status` =
1364
1504
  * `'submitted'`, `delivery_state` remains NULL until reconciliation runs.
@@ -1532,6 +1672,8 @@ var ReconciliationService = class {
1532
1672
  this.graphql = graphql;
1533
1673
  this.emailLog = emailLog;
1534
1674
  }
1675
+ graphql;
1676
+ emailLog;
1535
1677
  async run(input = {}) {
1536
1678
  const windowHours = input.windowHours ?? 24;
1537
1679
  const nowMs = input.now ?? Date.now();
@@ -1940,6 +2082,7 @@ var CloudflareEmailProvider = class {
1940
2082
  constructor(binding) {
1941
2083
  this.binding = binding;
1942
2084
  }
2085
+ binding;
1943
2086
  name = "cloudflare";
1944
2087
  isConfigured() {
1945
2088
  return !!this.binding;
@@ -1970,7 +2113,7 @@ var CloudflareEmailProvider = class {
1970
2113
  }
1971
2114
  }
1972
2115
  };
1973
- var emailPluginV3 = chunkXW56B23A_cjs.definePlugin({
2116
+ var emailPluginV3 = chunkA4KUJ3LD_cjs.definePlugin({
1974
2117
  id: "email",
1975
2118
  version: "1.0.0",
1976
2119
  name: "Email",
@@ -1984,7 +2127,7 @@ var emailPluginV3 = chunkXW56B23A_cjs.definePlugin({
1984
2127
  const db = env.DB;
1985
2128
  if (db) {
1986
2129
  try {
1987
- const typeRegistry = new chunkAAWNRBRB_cjs.DocumentTypeRegistry(db);
2130
+ const typeRegistry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db);
1988
2131
  await typeRegistry.register({
1989
2132
  id: "email_log",
1990
2133
  name: "email_log",
@@ -1999,7 +2142,7 @@ var emailPluginV3 = chunkXW56B23A_cjs.definePlugin({
1999
2142
  } catch {
2000
2143
  }
2001
2144
  }
2002
- if (!chunkVXE42MYF_cjs.hasEmailService()) {
2145
+ if (!chunk7RUW244J_cjs.hasEmailService()) {
2003
2146
  const settings = db ? await new EmailSettingsService(db).load() : {};
2004
2147
  const envResendKey = typeof env.RESEND_API_KEY === "string" && env.RESEND_API_KEY ? env.RESEND_API_KEY : void 0;
2005
2148
  const cfEmailBinding = env.EMAIL;
@@ -2017,7 +2160,7 @@ var emailPluginV3 = chunkXW56B23A_cjs.definePlugin({
2017
2160
  } else {
2018
2161
  provider = resolveEmailProvider({ env });
2019
2162
  }
2020
- chunkVXE42MYF_cjs.setEmailService(new EmailService({ ...serviceOpts, provider }));
2163
+ chunk7RUW244J_cjs.setEmailService(new EmailService({ ...serviceOpts, provider }));
2021
2164
  }
2022
2165
  ctx.hooks.on("auth:registration:completed", makeOnRegistrationCompleted(env));
2023
2166
  ctx.hooks.on("auth:password-reset:requested", makeOnPasswordResetRequested(env));
@@ -2028,7 +2171,7 @@ var emailPluginV3 = chunkXW56B23A_cjs.definePlugin({
2028
2171
  var BATCH_SIZE = 100;
2029
2172
  ({
2030
2173
  schema: zod.z.record(zod.z.string(), zod.z.unknown())});
2031
- var emailReconciliationPlugin = chunkXW56B23A_cjs.definePlugin({
2174
+ var emailReconciliationPlugin = chunkA4KUJ3LD_cjs.definePlugin({
2032
2175
  id: "email-reconciliation",
2033
2176
  version: "1.0.0",
2034
2177
  description: "Hourly cron that backfills email delivery state from provider status APIs. Only active for providers that implement EmailProvider.reconcile().",
@@ -2049,11 +2192,11 @@ var emailReconciliationPlugin = chunkXW56B23A_cjs.definePlugin({
2049
2192
  console.warn("[email-reconciliation] No DB binding in cron env \u2014 skipping.");
2050
2193
  return;
2051
2194
  }
2052
- if (!chunkVXE42MYF_cjs.hasEmailService()) {
2195
+ if (!chunk7RUW244J_cjs.hasEmailService()) {
2053
2196
  console.warn("[email-reconciliation] EmailService not initialized \u2014 skipping.");
2054
2197
  return;
2055
2198
  }
2056
- const emailService = chunkVXE42MYF_cjs.getEmailService();
2199
+ const emailService = chunk7RUW244J_cjs.getEmailService();
2057
2200
  let rows = [];
2058
2201
  try {
2059
2202
  const result = await db.prepare(
@@ -2122,6 +2265,7 @@ var OTPService = class {
2122
2265
  constructor(db) {
2123
2266
  this.db = db;
2124
2267
  }
2268
+ db;
2125
2269
  /**
2126
2270
  * Generate a secure random OTP code
2127
2271
  */
@@ -2485,7 +2629,7 @@ function buildOtpApi() {
2485
2629
  console.warn("Failed to parse OTP plugin settings, using defaults");
2486
2630
  }
2487
2631
  }
2488
- const settingsService = new chunkBDDABDAB_cjs.SettingsService(db);
2632
+ const settingsService = new chunk36Z3AKX3_cjs.SettingsService(db);
2489
2633
  const generalSettings = await settingsService.getGeneralSettings();
2490
2634
  const siteName = generalSettings.siteName;
2491
2635
  const canRequest = await otpService.checkRateLimit(normalizedEmail, settings);
@@ -2539,8 +2683,8 @@ function buildOtpApi() {
2539
2683
  loginUrl: settings.loginUrl || "",
2540
2684
  loginButtonText: settings.loginButtonText || ""
2541
2685
  });
2542
- if (chunkVXE42MYF_cjs.hasEmailService()) {
2543
- const sent = await chunkVXE42MYF_cjs.getEmailService().send({
2686
+ if (chunk7RUW244J_cjs.hasEmailService()) {
2687
+ const sent = await chunk7RUW244J_cjs.getEmailService().send({
2544
2688
  to: normalizedEmail,
2545
2689
  subject: `Your login code for ${siteName}`,
2546
2690
  flow: "otp",
@@ -2642,21 +2786,21 @@ function buildOtpApi() {
2642
2786
  error: "Account is deactivated"
2643
2787
  }, 403);
2644
2788
  }
2645
- const tokenTtl = await chunkAAWNRBRB_cjs.getJwtExpirySecondsFromDb(db, c.env);
2646
- const token = await chunkAAWNRBRB_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET, tokenTtl);
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);
2647
2791
  cookie.setCookie(c, "auth_token", token, {
2648
2792
  httpOnly: true,
2649
2793
  secure: true,
2650
2794
  sameSite: "Strict",
2651
2795
  maxAge: tokenTtl
2652
2796
  });
2653
- chunkVXE42MYF_cjs.dispatchHookEvent(
2797
+ chunk7RUW244J_cjs.dispatchHookEvent(
2654
2798
  c,
2655
2799
  "auth:otp:verified",
2656
2800
  { user: { id: user.id, email: user.email, role: user.role } },
2657
2801
  "fire-and-forget"
2658
2802
  );
2659
- const customData = await chunkVXE42MYF_cjs.getCustomData(db, user.id);
2803
+ const customData = await chunk7RUW244J_cjs.getCustomData(db, user.id);
2660
2804
  const { is_active: _isActive, ...publicUser } = user;
2661
2805
  return c.json({
2662
2806
  success: true,
@@ -2701,7 +2845,7 @@ function buildOtpApi() {
2701
2845
  });
2702
2846
  return otpAPI;
2703
2847
  }
2704
- var otpLoginPlugin = chunkXW56B23A_cjs.definePlugin({
2848
+ var otpLoginPlugin = chunkA4KUJ3LD_cjs.definePlugin({
2705
2849
  id: "otp-login",
2706
2850
  version: "1.0.0",
2707
2851
  name: "OTP Login",
@@ -2756,6 +2900,7 @@ var OAuthService = class {
2756
2900
  constructor(db) {
2757
2901
  this.db = db;
2758
2902
  }
2903
+ db;
2759
2904
  /**
2760
2905
  * Build the authorization redirect URL for a provider.
2761
2906
  */
@@ -3098,15 +3243,15 @@ function buildOauthApi() {
3098
3243
  if (!user || !user.is_active) {
3099
3244
  return c.redirect("/auth/login?error=Account is deactivated");
3100
3245
  }
3101
- const tokenTtl2 = await chunkAAWNRBRB_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
3102
- const jwt2 = await chunkAAWNRBRB_cjs.AuthManager.generateToken(
3246
+ const tokenTtl2 = await chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
3247
+ const jwt2 = await chunkFCLKX2OS_cjs.AuthManager.generateToken(
3103
3248
  user.id,
3104
3249
  user.email,
3105
3250
  user.role,
3106
3251
  c.env.JWT_SECRET,
3107
3252
  tokenTtl2
3108
3253
  );
3109
- chunkAAWNRBRB_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax", maxAge: tokenTtl2 });
3254
+ chunkFCLKX2OS_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax", maxAge: tokenTtl2 });
3110
3255
  return c.redirect("/admin");
3111
3256
  }
3112
3257
  const existingUser = await oauthService.findUserByEmail(profile.email);
@@ -3123,15 +3268,15 @@ function buildOauthApi() {
3123
3268
  tokenExpiresAt: tokenExpiresAt ?? void 0,
3124
3269
  profileData: JSON.stringify(profile)
3125
3270
  });
3126
- const tokenTtl2 = await chunkAAWNRBRB_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
3127
- const jwt2 = await chunkAAWNRBRB_cjs.AuthManager.generateToken(
3271
+ const tokenTtl2 = await chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
3272
+ const jwt2 = await chunkFCLKX2OS_cjs.AuthManager.generateToken(
3128
3273
  existingUser.id,
3129
3274
  existingUser.email,
3130
3275
  existingUser.role,
3131
3276
  c.env.JWT_SECRET,
3132
3277
  tokenTtl2
3133
3278
  );
3134
- chunkAAWNRBRB_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax", maxAge: tokenTtl2 });
3279
+ chunkFCLKX2OS_cjs.AuthManager.setAuthCookie(c, jwt2, { sameSite: "Lax", maxAge: tokenTtl2 });
3135
3280
  return c.redirect("/admin");
3136
3281
  }
3137
3282
  const newUserId = await oauthService.createUserFromOAuth(profile);
@@ -3144,15 +3289,15 @@ function buildOauthApi() {
3144
3289
  tokenExpiresAt: tokenExpiresAt ?? void 0,
3145
3290
  profileData: JSON.stringify(profile)
3146
3291
  });
3147
- const tokenTtl = await chunkAAWNRBRB_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
3148
- const jwt = await chunkAAWNRBRB_cjs.AuthManager.generateToken(
3292
+ const tokenTtl = await chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
3293
+ const jwt = await chunkFCLKX2OS_cjs.AuthManager.generateToken(
3149
3294
  newUserId,
3150
3295
  profile.email.toLowerCase(),
3151
3296
  "viewer",
3152
3297
  c.env.JWT_SECRET,
3153
3298
  tokenTtl
3154
3299
  );
3155
- chunkAAWNRBRB_cjs.AuthManager.setAuthCookie(c, jwt, { sameSite: "Lax", maxAge: tokenTtl });
3300
+ chunkFCLKX2OS_cjs.AuthManager.setAuthCookie(c, jwt, { sameSite: "Lax", maxAge: tokenTtl });
3156
3301
  return c.redirect("/admin");
3157
3302
  } catch (error) {
3158
3303
  console.error("OAuth callback error:", error);
@@ -3247,7 +3392,7 @@ function buildOauthApi() {
3247
3392
  });
3248
3393
  return oauthAPI;
3249
3394
  }
3250
- var oauthProvidersPlugin = chunkXW56B23A_cjs.definePlugin({
3395
+ var oauthProvidersPlugin = chunkA4KUJ3LD_cjs.definePlugin({
3251
3396
  id: "oauth-providers",
3252
3397
  version: "1.0.0",
3253
3398
  name: "OAuth Providers",
@@ -3272,6 +3417,7 @@ var EmbeddingService = class {
3272
3417
  constructor(ai) {
3273
3418
  this.ai = ai;
3274
3419
  }
3420
+ ai;
3275
3421
  /**
3276
3422
  * Generate embedding for a single text
3277
3423
  */
@@ -3476,6 +3622,9 @@ var CustomRAGService = class {
3476
3622
  this.embeddingService = new EmbeddingService(ai);
3477
3623
  this.chunkingService = new ChunkingService();
3478
3624
  }
3625
+ db;
3626
+ ai;
3627
+ vectorize;
3479
3628
  embeddingService;
3480
3629
  chunkingService;
3481
3630
  /**
@@ -3766,6 +3915,9 @@ var AISearchService = class {
3766
3915
  console.log("[AISearchService] Custom RAG not available, using keyword search only");
3767
3916
  }
3768
3917
  }
3918
+ db;
3919
+ ai;
3920
+ vectorize;
3769
3921
  customRAG;
3770
3922
  /**
3771
3923
  * Get plugin settings
@@ -3824,7 +3976,7 @@ var AISearchService = class {
3824
3976
  */
3825
3977
  async detectNewCollections() {
3826
3978
  try {
3827
- const allCollections = chunkQAYFOER6_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => ({
3979
+ const allCollections = chunkKVBHB7QP_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => ({
3828
3980
  id: r.id,
3829
3981
  name: r.name,
3830
3982
  display_name: r.displayName,
@@ -3876,7 +4028,7 @@ var AISearchService = class {
3876
4028
  */
3877
4029
  async getAllCollections() {
3878
4030
  try {
3879
- const allCollections = chunkQAYFOER6_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).sort((a, b) => a.displayName.localeCompare(b.displayName)).map((r) => ({
4031
+ const allCollections = chunkKVBHB7QP_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).sort((a, b) => a.displayName.localeCompare(b.displayName)).map((r) => ({
3880
4032
  id: r.id,
3881
4033
  name: r.name,
3882
4034
  display_name: r.displayName,
@@ -4206,13 +4358,16 @@ var IndexManager = class {
4206
4358
  console.log("[IndexManager] Custom RAG initialized");
4207
4359
  }
4208
4360
  }
4361
+ db;
4362
+ ai;
4363
+ vectorize;
4209
4364
  customRAG;
4210
4365
  /**
4211
4366
  * Index all content items within a collection using Custom RAG
4212
4367
  */
4213
4368
  async indexCollection(collectionId) {
4214
4369
  try {
4215
- const registry = chunkQAYFOER6_cjs.getCollectionRegistry();
4370
+ const registry = chunkKVBHB7QP_cjs.getCollectionRegistry();
4216
4371
  const record = registry.getById(collectionId) ?? registry.getByName(collectionId);
4217
4372
  if (!record) {
4218
4373
  throw new Error(`Collection ${collectionId} not found`);
@@ -4828,7 +4983,7 @@ function renderSettingsPage(data) {
4828
4983
  }, 30000);
4829
4984
  </script>
4830
4985
  `;
4831
- return chunkMVIZJOO5_cjs.renderAdminLayout({
4986
+ return chunkPXNTCCPE_cjs.renderAdminLayout({
4832
4987
  title: "AI Search Settings",
4833
4988
  pageTitle: "AI Search Settings",
4834
4989
  currentPath: "/admin/plugins/ai-search/settings",
@@ -4839,7 +4994,7 @@ function renderSettingsPage(data) {
4839
4994
 
4840
4995
  // src/plugins/core-plugins/ai-search-plugin/routes/admin.ts
4841
4996
  var adminRoutes2 = new hono.Hono();
4842
- adminRoutes2.use("*", chunkAAWNRBRB_cjs.requireAuth());
4997
+ adminRoutes2.use("*", chunkFCLKX2OS_cjs.requireAuth());
4843
4998
  adminRoutes2.get("/", async (c) => {
4844
4999
  try {
4845
5000
  const user = c.get("user");
@@ -5080,7 +5235,7 @@ var manifest_default = {
5080
5235
  author: "SonicJS"};
5081
5236
 
5082
5237
  // src/plugins/core-plugins/ai-search-plugin/index.ts
5083
- var aiSearchPlugin = chunkXW56B23A_cjs.definePlugin({
5238
+ var aiSearchPlugin = chunkA4KUJ3LD_cjs.definePlugin({
5084
5239
  id: manifest_default.id,
5085
5240
  version: manifest_default.version,
5086
5241
  name: manifest_default.name,
@@ -5133,12 +5288,14 @@ var SecurityAuditService = class {
5133
5288
  constructor(db, settings = DEFAULT_SETTINGS2) {
5134
5289
  this.db = db;
5135
5290
  this.settings = settings;
5136
- this.docsService = new chunk2CB4KY7I_cjs.DocumentsService(db, {
5291
+ this.docsService = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
5137
5292
  queryableFields: QUERYABLE_FIELDS,
5138
5293
  maxVersionsPerRoot: 1,
5139
5294
  tenantId: TENANT
5140
5295
  });
5141
5296
  }
5297
+ db;
5298
+ settings;
5142
5299
  docsService;
5143
5300
  async logEvent(event) {
5144
5301
  const doc = await this.docsService.create({
@@ -5379,7 +5536,7 @@ function rowToEvent(row) {
5379
5536
  }
5380
5537
 
5381
5538
  // src/plugins/core-plugins/security-audit-plugin/components/dashboard-page.ts
5382
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
5539
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
5383
5540
  function formatTimestamp(ts) {
5384
5541
  const date = new Date(ts);
5385
5542
  const now = Date.now();
@@ -5578,11 +5735,11 @@ function renderSecurityDashboard(data) {
5578
5735
  version,
5579
5736
  dynamicMenuItems
5580
5737
  };
5581
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst(layoutData);
5738
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
5582
5739
  }
5583
5740
 
5584
5741
  // src/plugins/core-plugins/security-audit-plugin/components/event-log-page.ts
5585
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
5742
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
5586
5743
  function formatTimestamp2(ts) {
5587
5744
  const date = new Date(ts);
5588
5745
  return date.toLocaleDateString("en-US", {
@@ -5789,11 +5946,11 @@ function renderEventLogPage(data) {
5789
5946
  version,
5790
5947
  dynamicMenuItems
5791
5948
  };
5792
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst(layoutData);
5949
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
5793
5950
  }
5794
5951
 
5795
5952
  // src/plugins/core-plugins/security-audit-plugin/components/settings-page.ts
5796
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
5953
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
5797
5954
  function renderSecuritySettingsPage(data) {
5798
5955
  const { settings, user, version, message, dynamicMenuItems } = data;
5799
5956
  const content2 = `
@@ -5946,12 +6103,12 @@ function renderSecuritySettingsPage(data) {
5946
6103
  version,
5947
6104
  dynamicMenuItems
5948
6105
  };
5949
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst(layoutData);
6106
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
5950
6107
  }
5951
6108
 
5952
6109
  // src/plugins/core-plugins/security-audit-plugin/routes/admin.ts
5953
6110
  var adminRoutes3 = new hono.Hono();
5954
- adminRoutes3.use("*", chunkAAWNRBRB_cjs.requireAuth());
6111
+ adminRoutes3.use("*", chunkFCLKX2OS_cjs.requireAuth());
5955
6112
  adminRoutes3.use("*", async (c, next) => {
5956
6113
  const user = c.get("user");
5957
6114
  if (user?.role !== "admin") {
@@ -5961,7 +6118,7 @@ adminRoutes3.use("*", async (c, next) => {
5961
6118
  });
5962
6119
  async function getSettings(db) {
5963
6120
  try {
5964
- const pluginService = new chunkQAYFOER6_cjs.PluginService(db);
6121
+ const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
5965
6122
  const plugin2 = await pluginService.getPlugin("security-audit");
5966
6123
  if (plugin2?.settings) {
5967
6124
  const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
@@ -6066,7 +6223,7 @@ adminRoutes3.post("/settings", async (c) => {
6066
6223
  autoPurge: body["retention.autoPurge"] === "true"
6067
6224
  }
6068
6225
  };
6069
- const pluginService = new chunkQAYFOER6_cjs.PluginService(db);
6226
+ const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
6070
6227
  await pluginService.updatePluginSettings("security-audit", settings);
6071
6228
  if (c.req.header("HX-Request")) {
6072
6229
  return c.json({ success: true });
@@ -6082,6 +6239,7 @@ var BruteForceDetector = class {
6082
6239
  this.kv = kv;
6083
6240
  this.settings = settings || DEFAULT_SETTINGS2.bruteForce;
6084
6241
  }
6242
+ kv;
6085
6243
  settings;
6086
6244
  async recordFailedAttempt(ip, email) {
6087
6245
  if (!this.settings.enabled || !this.kv) {
@@ -6227,7 +6385,7 @@ var BruteForceDetector = class {
6227
6385
 
6228
6386
  // src/plugins/core-plugins/security-audit-plugin/routes/api.ts
6229
6387
  var apiRoutes2 = new hono.Hono();
6230
- apiRoutes2.use("*", chunkAAWNRBRB_cjs.requireAuth());
6388
+ apiRoutes2.use("*", chunkFCLKX2OS_cjs.requireAuth());
6231
6389
  apiRoutes2.use("*", async (c, next) => {
6232
6390
  const user = c.get("user");
6233
6391
  if (user?.role !== "admin") {
@@ -6237,7 +6395,7 @@ apiRoutes2.use("*", async (c, next) => {
6237
6395
  });
6238
6396
  async function getSettings2(db) {
6239
6397
  try {
6240
- const pluginService = new chunkQAYFOER6_cjs.PluginService(db);
6398
+ const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
6241
6399
  const plugin2 = await pluginService.getPlugin("security-audit");
6242
6400
  if (plugin2?.settings) {
6243
6401
  const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
@@ -6385,7 +6543,7 @@ function generateFingerprint(ip, userAgent) {
6385
6543
  }
6386
6544
  async function getPluginSettings(db) {
6387
6545
  try {
6388
- const pluginService = new chunkQAYFOER6_cjs.PluginService(db);
6546
+ const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
6389
6547
  const plugin2 = await pluginService.getPlugin("security-audit");
6390
6548
  if (plugin2?.settings) {
6391
6549
  const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
@@ -6616,7 +6774,7 @@ async function logAuthEvent(c, db, settings, ip, userAgent, countryCode, fingerp
6616
6774
 
6617
6775
  // src/plugins/core-plugins/security-audit-plugin/index.ts
6618
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>`;
6619
- var securityAuditPlugin = chunkXW56B23A_cjs.definePlugin({
6777
+ var securityAuditPlugin = chunkA4KUJ3LD_cjs.definePlugin({
6620
6778
  id: "security-audit",
6621
6779
  version: "1.0.0",
6622
6780
  name: "Security Audit",
@@ -6634,11 +6792,465 @@ var securityAuditPlugin = chunkXW56B23A_cjs.definePlugin({
6634
6792
  deactivate: async () => console.log("[SecurityAudit] Plugin deactivated")
6635
6793
  });
6636
6794
 
6795
+ // src/plugins/core-plugins/api-keys-plugin/services/api-key-service.ts
6796
+ var API_KEY_QUERYABLE = [
6797
+ { name: "keyHash", kind: "scalar", type: "text", column: "q_apikey_hash" },
6798
+ { name: "userId", kind: "scalar", type: "text", column: "q_apikey_user_id" },
6799
+ { name: "revoked", kind: "scalar", type: "integer", column: "q_apikey_revoked" }
6800
+ ];
6801
+ var KEY_PREFIX = "sk_";
6802
+ var KEY_BYTES = 24;
6803
+ var DISPLAY_PREFIX_LEN = KEY_PREFIX.length + 8;
6804
+ function generateApiKeySecret() {
6805
+ const bytes = new Uint8Array(KEY_BYTES);
6806
+ crypto.getRandomValues(bytes);
6807
+ let hex = "";
6808
+ for (const b of bytes) hex += b.toString(16).padStart(2, "0");
6809
+ return KEY_PREFIX + hex;
6810
+ }
6811
+ async function hashApiKey(secret) {
6812
+ const data = new TextEncoder().encode(secret);
6813
+ const digest = await crypto.subtle.digest("SHA-256", data);
6814
+ const view = new Uint8Array(digest);
6815
+ let hex = "";
6816
+ for (const b of view) hex += b.toString(16).padStart(2, "0");
6817
+ return hex;
6818
+ }
6819
+ var ApiKeyService = class {
6820
+ constructor(db, tenantId = "default") {
6821
+ this.db = db;
6822
+ this.tenantId = tenantId;
6823
+ }
6824
+ db;
6825
+ tenantId;
6826
+ docService() {
6827
+ return new chunkLTZ5WYOK_cjs.DocumentsService(this.db, {
6828
+ queryableFields: API_KEY_QUERYABLE,
6829
+ tenantId: this.tenantId,
6830
+ maxVersionsPerRoot: 1
6831
+ });
6832
+ }
6833
+ /** Count a user's active (non-revoked) keys — used to enforce the per-user cap. */
6834
+ async countForUser(userId) {
6835
+ const row = await this.db.prepare(
6836
+ `SELECT COUNT(*) AS c FROM documents
6837
+ WHERE type_id = 'api_key' AND tenant_id = ? AND is_current_draft = 1
6838
+ AND deleted_at IS NULL AND q_apikey_user_id = ? AND q_apikey_revoked = 0`
6839
+ ).bind(this.tenantId, userId).first();
6840
+ return row?.c ?? 0;
6841
+ }
6842
+ /**
6843
+ * Mint a new key for a user. The returned `key` is the only time the plaintext
6844
+ * exists outside the caller — it is hashed before storage.
6845
+ */
6846
+ async create(input) {
6847
+ const name = input.name.trim() || "API Key";
6848
+ const secret = generateApiKeySecret();
6849
+ const keyHash = await hashApiKey(secret);
6850
+ const prefix = secret.slice(0, DISPLAY_PREFIX_LEN);
6851
+ const expiresAt = input.expiresAt ?? null;
6852
+ const doc = await this.docService().create(
6853
+ chunk7RUW244J_cjs.createDocumentSchema.parse({
6854
+ typeId: "api_key",
6855
+ tenantId: this.tenantId,
6856
+ title: name,
6857
+ ownerId: input.userId,
6858
+ publishOnCreate: true,
6859
+ data: {
6860
+ name,
6861
+ userId: input.userId,
6862
+ keyHash,
6863
+ keyPrefix: prefix,
6864
+ revoked: 0,
6865
+ lastUsedAt: null,
6866
+ expiresAt
6867
+ }
6868
+ }),
6869
+ input.userId
6870
+ );
6871
+ return { id: doc.rootId, key: secret, name, prefix, expiresAt };
6872
+ }
6873
+ /** List a user's non-revoked keys (metadata only — never the secret or hash). */
6874
+ async list(userId) {
6875
+ const res = await this.db.prepare(
6876
+ `SELECT root_id, data, created_at FROM documents
6877
+ WHERE type_id = 'api_key' AND tenant_id = ? AND is_current_draft = 1
6878
+ AND deleted_at IS NULL AND q_apikey_user_id = ? AND q_apikey_revoked = 0
6879
+ ORDER BY created_at DESC`
6880
+ ).bind(this.tenantId, userId).all();
6881
+ return (res.results ?? []).map((row) => {
6882
+ const d = JSON.parse(row.data);
6883
+ return {
6884
+ id: row.root_id,
6885
+ name: d.name ?? "API Key",
6886
+ prefix: d.keyPrefix ?? "",
6887
+ createdAt: row.created_at,
6888
+ lastUsedAt: d.lastUsedAt ?? null,
6889
+ expiresAt: d.expiresAt ?? null
6890
+ };
6891
+ });
6892
+ }
6893
+ /**
6894
+ * Revoke (hard-delete) a key owned by `userId`. Credentials are erased, not
6895
+ * soft-flagged. Returns false if the key does not exist or is not owned by
6896
+ * the caller (no information leak about other users' keys).
6897
+ */
6898
+ async revoke(rootId, userId) {
6899
+ const row = await this.db.prepare(
6900
+ `SELECT q_apikey_user_id AS owner FROM documents
6901
+ WHERE root_id = ? AND tenant_id = ? AND type_id = 'api_key' AND is_current_draft = 1 AND deleted_at IS NULL`
6902
+ ).bind(rootId, this.tenantId).first();
6903
+ if (!row || row.owner !== userId) return false;
6904
+ await this.docService().erase(rootId, this.tenantId);
6905
+ return true;
6906
+ }
6907
+ /**
6908
+ * Resolve a presented secret to its owning user, or null. Rejects unknown,
6909
+ * revoked, expired keys and inactive users. Best-effort updates lastUsedAt.
6910
+ */
6911
+ async resolve(secret) {
6912
+ if (!secret || !secret.startsWith(KEY_PREFIX)) return null;
6913
+ const keyHash = await hashApiKey(secret);
6914
+ const keyRow2 = await this.db.prepare(
6915
+ `SELECT root_id, data FROM documents
6916
+ WHERE type_id = 'api_key' AND tenant_id = ? AND is_current_draft = 1 AND deleted_at IS NULL
6917
+ AND q_apikey_hash = ? AND q_apikey_revoked = 0
6918
+ LIMIT 1`
6919
+ ).bind(this.tenantId, keyHash).first();
6920
+ if (!keyRow2) return null;
6921
+ const d = JSON.parse(keyRow2.data);
6922
+ if (d.expiresAt != null && Date.now() > Number(d.expiresAt)) return null;
6923
+ const user = await this.db.prepare(`SELECT id, email, role, is_active, is_super_admin FROM auth_user WHERE id = ?`).bind(d.userId).first();
6924
+ if (!user || user.is_active !== 1) return null;
6925
+ try {
6926
+ await this.touchLastUsed(keyRow2.root_id, d);
6927
+ } catch {
6928
+ }
6929
+ return {
6930
+ userId: user.id,
6931
+ email: user.email,
6932
+ role: user.role ?? "viewer",
6933
+ isSuperAdmin: user.is_super_admin === 1
6934
+ };
6935
+ }
6936
+ /** Update lastUsedAt in-place (single-version type, no history churn). */
6937
+ async touchLastUsed(rootId, data) {
6938
+ const next = JSON.stringify({ ...data, lastUsedAt: Date.now() });
6939
+ await this.db.prepare(
6940
+ `UPDATE documents SET data = ? WHERE root_id = ? AND tenant_id = ? AND type_id = 'api_key' AND is_current_draft = 1`
6941
+ ).bind(next, rootId, this.tenantId).run();
6942
+ }
6943
+ };
6944
+
6945
+ // src/plugins/core-plugins/api-keys-plugin/components/keys-page.ts
6946
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
6947
+ function fmtDate(ms) {
6948
+ if (!ms) return "\u2014";
6949
+ try {
6950
+ return new Date(ms).toISOString().slice(0, 10);
6951
+ } catch {
6952
+ return "\u2014";
6953
+ }
6954
+ }
6955
+ function keyRow(k) {
6956
+ const name = chunkMNWKYY5E_cjs.escapeHtml(k.name);
6957
+ const prefix = chunkMNWKYY5E_cjs.escapeHtml(k.prefix);
6958
+ const id = chunkMNWKYY5E_cjs.escapeHtml(k.id);
6959
+ return `
6960
+ <tr class="border-t border-zinc-950/5 dark:border-white/10" data-key-id="${id}">
6961
+ <td class="py-3 pr-4 text-sm font-medium text-zinc-950 dark:text-white">${name}</td>
6962
+ <td class="py-3 pr-4 text-sm font-mono text-zinc-500 dark:text-zinc-400">${prefix}\u2026</td>
6963
+ <td class="py-3 pr-4 text-sm text-zinc-500 dark:text-zinc-400">${fmtDate(k.createdAt ? k.createdAt * 1e3 : null)}</td>
6964
+ <td class="py-3 pr-4 text-sm text-zinc-500 dark:text-zinc-400">${k.lastUsedAt ? fmtDate(k.lastUsedAt) : "Never"}</td>
6965
+ <td class="py-3 pr-4 text-sm text-zinc-500 dark:text-zinc-400">${k.expiresAt ? fmtDate(k.expiresAt) : "Never"}</td>
6966
+ <td class="py-3 text-right">
6967
+ <button type="button" onclick="revokeApiKey('${id}', '${name.replace(/'/g, "\\'")}')"
6968
+ class="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">
6969
+ Revoke
6970
+ </button>
6971
+ </td>
6972
+ </tr>`;
6973
+ }
6974
+ function renderApiKeysPage(data) {
6975
+ const { keys, user, version, dynamicMenuItems } = data;
6976
+ const rows = keys.length ? keys.map(keyRow).join("") : `<tr><td colspan="6" class="py-8 text-center text-sm text-zinc-500 dark:text-zinc-400">No API keys yet. Create one to enable programmatic access.</td></tr>`;
6977
+ const content2 = `
6978
+ <div>
6979
+ <div class="sm:flex sm:items-center sm:justify-between mb-6">
6980
+ <div class="sm:flex-auto">
6981
+ <h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">API Keys</h1>
6982
+ <p class="mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400">
6983
+ Long-lived secrets for headless / server-to-server REST access. Send a key as the
6984
+ <code class="font-mono">x-api-key</code> header or <code class="font-mono">Authorization: Bearer &lt;key&gt;</code>.
6985
+ The secret is shown once at creation \u2014 store it now.
6986
+ </p>
6987
+ </div>
6988
+ <div class="mt-4 sm:mt-0 sm:ml-16">
6989
+ <button type="button" onclick="document.getElementById('create-key-modal').classList.remove('hidden')"
6990
+ class="inline-flex items-center justify-center rounded-lg bg-cyan-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-cyan-500 transition-colors shadow-sm">
6991
+ Create API key
6992
+ </button>
6993
+ </div>
6994
+ </div>
6995
+
6996
+ <!-- Newly-created secret banner (populated by JS, shown once) -->
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>
7001
+ <div class="flex items-center gap-2">
7002
+ <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
+ <button type="button" onclick="copyNewKey()"
7004
+ class="rounded-lg bg-emerald-600 px-3 py-2 text-sm font-semibold text-white hover:bg-emerald-500 transition-colors">
7005
+ Copy
7006
+ </button>
7007
+ </div>
7008
+ </div>
7009
+
7010
+ <div class="rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-x-auto">
7011
+ <table class="w-full text-left">
7012
+ <thead>
7013
+ <tr class="text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:text-zinc-400">
7014
+ <th class="pb-2 pr-4">Name</th>
7015
+ <th class="pb-2 pr-4">Prefix</th>
7016
+ <th class="pb-2 pr-4">Created</th>
7017
+ <th class="pb-2 pr-4">Last used</th>
7018
+ <th class="pb-2 pr-4">Expires</th>
7019
+ <th class="pb-2 text-right">Actions</th>
7020
+ </tr>
7021
+ </thead>
7022
+ <tbody id="keys-tbody">${rows}</tbody>
7023
+ </table>
7024
+ </div>
7025
+ </div>
7026
+
7027
+ <!-- Create modal -->
7028
+ <div id="create-key-modal" class="hidden fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
7029
+ <div class="w-full max-w-md rounded-xl bg-white dark:bg-zinc-900 p-6 ring-1 ring-zinc-950/10 dark:ring-white/10 shadow-xl">
7030
+ <h2 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Create API key</h2>
7031
+ <label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1">Name</label>
7032
+ <input id="new-key-name" type="text" placeholder="e.g. CI deploy token"
7033
+ class="w-full rounded-lg border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white mb-4 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10">
7034
+ <label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1">Expires in (days, optional)</label>
7035
+ <input id="new-key-expiry" type="number" min="1" max="3650" placeholder="Never"
7036
+ class="w-full rounded-lg border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white mb-4 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10">
7037
+ <div class="flex justify-end gap-2">
7038
+ <button type="button" onclick="document.getElementById('create-key-modal').classList.add('hidden')"
7039
+ class="rounded-lg bg-white dark:bg-zinc-800 px-4 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10">
7040
+ Cancel
7041
+ </button>
7042
+ <button type="button" onclick="createApiKey()"
7043
+ class="rounded-lg bg-cyan-600 px-4 py-2 text-sm font-semibold text-white hover:bg-cyan-500 transition-colors">
7044
+ Create
7045
+ </button>
7046
+ </div>
7047
+ </div>
7048
+ </div>
7049
+
7050
+ <script>
7051
+ // CSRF: the csrf_token cookie is JS-readable (httpOnly:false); echo it back
7052
+ // as X-CSRF-Token on state-changing requests (signed double-submit).
7053
+ function csrfHeader() {
7054
+ const m = document.cookie.match(/(?:^|; )csrf_token=([^;]+)/)
7055
+ return m ? { 'X-CSRF-Token': decodeURIComponent(m[1]) } : {}
7056
+ }
7057
+ async function createApiKey() {
7058
+ const name = document.getElementById('new-key-name').value.trim()
7059
+ if (!name) { window.showNotification && window.showNotification('Name is required', 'error'); return }
7060
+ const expiry = parseInt(document.getElementById('new-key-expiry').value, 10)
7061
+ const body = { name }
7062
+ if (Number.isFinite(expiry) && expiry > 0) body.expiresInDays = expiry
7063
+ const res = await fetch('/admin/plugins/api-keys/api/keys', {
7064
+ method: 'POST',
7065
+ headers: { 'Content-Type': 'application/json', ...csrfHeader() },
7066
+ body: JSON.stringify(body),
7067
+ })
7068
+ if (!res.ok) {
7069
+ const e = await res.json().catch(() => ({}))
7070
+ window.showNotification && window.showNotification(e.error || 'Failed to create key', 'error')
7071
+ return
7072
+ }
7073
+ const { apiKey } = await res.json()
7074
+ document.getElementById('create-key-modal').classList.add('hidden')
7075
+ document.getElementById('new-key-value').textContent = apiKey.key
7076
+ document.getElementById('new-key-banner').classList.remove('hidden')
7077
+ setTimeout(() => location.reload(), 1500)
7078
+ }
7079
+ function copyNewKey() {
7080
+ const v = document.getElementById('new-key-value').textContent
7081
+ navigator.clipboard.writeText(v).then(() => window.showNotification && window.showNotification('Copied', 'success'))
7082
+ }
7083
+ async function revokeApiKey(id, name) {
7084
+ if (!confirm('Revoke "' + name + '"? This cannot be undone and will break any client using it.')) return
7085
+ const res = await fetch('/admin/plugins/api-keys/api/keys/' + id, { method: 'DELETE', headers: { ...csrfHeader() } })
7086
+ if (res.ok) {
7087
+ const row = document.querySelector('[data-key-id="' + id + '"]')
7088
+ if (row) row.remove()
7089
+ window.showNotification && window.showNotification('Key revoked', 'success')
7090
+ } else {
7091
+ window.showNotification && window.showNotification('Failed to revoke', 'error')
7092
+ }
7093
+ }
7094
+ </script>`;
7095
+ const layoutData = {
7096
+ title: "API Keys",
7097
+ pageTitle: "API Keys",
7098
+ currentPath: "/admin/plugins/api-keys",
7099
+ user,
7100
+ content: content2,
7101
+ version,
7102
+ dynamicMenuItems
7103
+ };
7104
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
7105
+ }
7106
+
7107
+ // src/plugins/core-plugins/api-keys-plugin/types.ts
7108
+ var DEFAULT_SETTINGS3 = {
7109
+ maxKeysPerUser: 50,
7110
+ defaultExpiryDays: 0
7111
+ };
7112
+
7113
+ // src/plugins/core-plugins/api-keys-plugin/routes/admin.ts
7114
+ var adminRoutes4 = new hono.Hono();
7115
+ var DAY_MS = 24 * 60 * 60 * 1e3;
7116
+ var createSchema = zod.z.object({
7117
+ name: zod.z.string().min(1).max(100),
7118
+ // Optional lifetime in days; omitted/null → plugin default (which may be "never").
7119
+ expiresInDays: zod.z.number().int().positive().max(3650).nullish()
7120
+ });
7121
+ async function getSettings3(db) {
7122
+ try {
7123
+ const plugin2 = await new chunkKVBHB7QP_cjs.PluginService(db).getPlugin("api-keys");
7124
+ if (plugin2?.settings) {
7125
+ const s = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
7126
+ return { ...DEFAULT_SETTINGS3, ...s };
7127
+ }
7128
+ } catch {
7129
+ }
7130
+ return DEFAULT_SETTINGS3;
7131
+ }
7132
+ adminRoutes4.use("*", chunkFCLKX2OS_cjs.requireAuth());
7133
+ adminRoutes4.use("*", async (c, next) => {
7134
+ const user = c.get("user");
7135
+ if (user?.role !== "admin") {
7136
+ return c.json({ error: "Access denied" }, 403);
7137
+ }
7138
+ return next();
7139
+ });
7140
+ adminRoutes4.get("/", async (c) => {
7141
+ const user = c.get("user");
7142
+ const tenantId = c.get("tenantId") || "default";
7143
+ const keys = await new ApiKeyService(c.env.DB, tenantId).list(user.userId);
7144
+ return c.html(
7145
+ renderApiKeysPage({
7146
+ keys,
7147
+ user: { name: user.email, email: user.email, role: user.role },
7148
+ version: c.get("appVersion"),
7149
+ dynamicMenuItems: c.get("pluginMenuItems")
7150
+ })
7151
+ );
7152
+ });
7153
+ adminRoutes4.get("/api/keys", async (c) => {
7154
+ const user = c.get("user");
7155
+ const tenantId = c.get("tenantId") || "default";
7156
+ const keys = await new ApiKeyService(c.env.DB, tenantId).list(user.userId);
7157
+ return c.json({ keys });
7158
+ });
7159
+ adminRoutes4.post("/api/keys", async (c) => {
7160
+ const user = c.get("user");
7161
+ const tenantId = c.get("tenantId") || "default";
7162
+ const body = await c.req.json().catch(() => ({}));
7163
+ const parsed = createSchema.safeParse(body);
7164
+ if (!parsed.success) {
7165
+ return c.json({ error: "Invalid request", details: parsed.error.flatten() }, 400);
7166
+ }
7167
+ const settings = await getSettings3(c.env.DB);
7168
+ const svc = new ApiKeyService(c.env.DB, tenantId);
7169
+ if (await svc.countForUser(user.userId) >= settings.maxKeysPerUser) {
7170
+ return c.json({ error: `API key limit reached (max ${settings.maxKeysPerUser})` }, 409);
7171
+ }
7172
+ const days = parsed.data.expiresInDays ?? (settings.defaultExpiryDays > 0 ? settings.defaultExpiryDays : null);
7173
+ const expiresAt = days ? Date.now() + days * DAY_MS : null;
7174
+ const created = await svc.create({ userId: user.userId, name: parsed.data.name, expiresAt });
7175
+ return c.json({ apiKey: created }, 201);
7176
+ });
7177
+ adminRoutes4.delete("/api/keys/:id", async (c) => {
7178
+ const user = c.get("user");
7179
+ const tenantId = c.get("tenantId") || "default";
7180
+ const ok = await new ApiKeyService(c.env.DB, tenantId).revoke(c.req.param("id") ?? "", user.userId);
7181
+ if (!ok) return c.json({ error: "API key not found" }, 404);
7182
+ return c.json({ success: true });
7183
+ });
7184
+
7185
+ // src/plugins/core-plugins/api-keys-plugin/middleware/api-key-auth.ts
7186
+ function apiKeyAuthMiddleware() {
7187
+ return async (c, next) => {
7188
+ if (!c.get("user")) {
7189
+ const authz = c.req.header("authorization") || "";
7190
+ const bearer = authz.toLowerCase().startsWith("bearer ") ? authz.slice(7).trim() : "";
7191
+ const presented = c.req.header("x-api-key") || (bearer.startsWith("sk_") ? bearer : "");
7192
+ if (presented) {
7193
+ try {
7194
+ const tenantId = c.get("tenantId") || "default";
7195
+ const resolved = await new ApiKeyService(c.env.DB, tenantId).resolve(presented);
7196
+ if (resolved) {
7197
+ c.set("user", {
7198
+ userId: resolved.userId,
7199
+ email: resolved.email,
7200
+ role: resolved.role,
7201
+ isSuperAdmin: resolved.isSuperAdmin,
7202
+ // API keys are stateless bearer creds — no session window.
7203
+ exp: 0,
7204
+ iat: 0
7205
+ });
7206
+ }
7207
+ } catch {
7208
+ }
7209
+ }
7210
+ }
7211
+ await next();
7212
+ };
7213
+ }
7214
+
7215
+ // src/plugins/core-plugins/api-keys-plugin/index.ts
7216
+ 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({
7218
+ id: "api-keys",
7219
+ version: "1.0.0-beta.1",
7220
+ name: "API Keys",
7221
+ description: "Programmatic API access keys for headless / server-to-server REST access.",
7222
+ sonicjsVersionRange: "^3.0.0",
7223
+ author: { name: "SonicJS Team" },
7224
+ register(app2) {
7225
+ app2.route("/admin/plugins/api-keys", adminRoutes4);
7226
+ },
7227
+ menu: [
7228
+ { label: "API Keys", path: "/admin/plugins/api-keys", icon: KEY_ICON, order: 86 }
7229
+ ],
7230
+ configSchema: {
7231
+ maxKeysPerUser: {
7232
+ type: "number",
7233
+ label: "Max keys per user",
7234
+ description: "Hard cap on active keys a single user may hold.",
7235
+ default: 50
7236
+ },
7237
+ defaultExpiryDays: {
7238
+ type: "number",
7239
+ label: "Default expiry (days)",
7240
+ description: "Lifetime applied to new keys when no explicit expiry is given. 0 = never expires.",
7241
+ default: 0
7242
+ }
7243
+ },
7244
+ activate: async () => console.log("[ApiKeys] Plugin activated"),
7245
+ deactivate: async () => console.log("[ApiKeys] Plugin deactivated")
7246
+ });
7247
+
6637
7248
  // src/plugins/core-plugins/stripe-plugin/services/subscription-service.ts
6638
7249
  var SubscriptionService = class {
6639
7250
  constructor(db) {
6640
7251
  this.db = db;
6641
7252
  }
7253
+ db;
6642
7254
  /**
6643
7255
  * Ensure the subscriptions table exists
6644
7256
  */
@@ -6877,6 +7489,7 @@ var StripeEventService = class {
6877
7489
  constructor(db) {
6878
7490
  this.db = db;
6879
7491
  }
7492
+ db;
6880
7493
  async ensureTable() {
6881
7494
  await this.db.prepare(`
6882
7495
  CREATE TABLE IF NOT EXISTS stripe_events (
@@ -6987,7 +7600,7 @@ var StripeEventService = class {
6987
7600
  };
6988
7601
 
6989
7602
  // src/plugins/core-plugins/stripe-plugin/components/subscriptions-page.ts
6990
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
7603
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
6991
7604
 
6992
7605
  // src/plugins/core-plugins/stripe-plugin/components/tab-bar.ts
6993
7606
  var TABS = [
@@ -7120,7 +7733,7 @@ function renderSubscriptionsPage(data) {
7120
7733
  version,
7121
7734
  dynamicMenuItems
7122
7735
  };
7123
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst(layoutData);
7736
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
7124
7737
  }
7125
7738
  function statsCard(label, value, colorClass) {
7126
7739
  return `
@@ -7200,7 +7813,7 @@ function renderPagination2(page, totalPages, status) {
7200
7813
  }
7201
7814
 
7202
7815
  // src/plugins/core-plugins/stripe-plugin/components/events-page.ts
7203
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
7816
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
7204
7817
  function renderEventsPage(data) {
7205
7818
  const { events, stats, types, filters, user, version, dynamicMenuItems } = data;
7206
7819
  const content2 = `
@@ -7273,7 +7886,7 @@ function renderEventsPage(data) {
7273
7886
  version,
7274
7887
  dynamicMenuItems
7275
7888
  };
7276
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst(layoutData);
7889
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
7277
7890
  }
7278
7891
  function eventStatsCard(label, value, colorClass) {
7279
7892
  return `
@@ -7361,7 +7974,7 @@ function renderEventPagination(page, totalPages, type, status) {
7361
7974
  }
7362
7975
 
7363
7976
  // src/plugins/core-plugins/stripe-plugin/types.ts
7364
- var DEFAULT_SETTINGS3 = {
7977
+ var DEFAULT_SETTINGS4 = {
7365
7978
  stripePublishableKey: "",
7366
7979
  stripeSecretKey: "",
7367
7980
  stripeWebhookSecret: "",
@@ -7371,28 +7984,28 @@ var DEFAULT_SETTINGS3 = {
7371
7984
  };
7372
7985
 
7373
7986
  // src/plugins/core-plugins/stripe-plugin/routes/admin.ts
7374
- var adminRoutes4 = new hono.Hono();
7375
- adminRoutes4.use("*", chunkAAWNRBRB_cjs.requireAuth());
7376
- adminRoutes4.use("*", async (c, next) => {
7987
+ var adminRoutes5 = new hono.Hono();
7988
+ adminRoutes5.use("*", chunkFCLKX2OS_cjs.requireAuth());
7989
+ adminRoutes5.use("*", async (c, next) => {
7377
7990
  const user = c.get("user");
7378
7991
  if (user?.role !== "admin") {
7379
7992
  return c.text("Access denied", 403);
7380
7993
  }
7381
7994
  return next();
7382
7995
  });
7383
- async function getSettings3(db) {
7996
+ async function getSettings4(db) {
7384
7997
  try {
7385
- const pluginService = new chunkQAYFOER6_cjs.PluginService(db);
7998
+ const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
7386
7999
  const plugin2 = await pluginService.getPlugin("stripe");
7387
8000
  if (plugin2?.settings) {
7388
8001
  const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
7389
- return { ...DEFAULT_SETTINGS3, ...settings };
8002
+ return { ...DEFAULT_SETTINGS4, ...settings };
7390
8003
  }
7391
8004
  } catch {
7392
8005
  }
7393
- return DEFAULT_SETTINGS3;
8006
+ return DEFAULT_SETTINGS4;
7394
8007
  }
7395
- adminRoutes4.get("/", async (c) => {
8008
+ adminRoutes5.get("/", async (c) => {
7396
8009
  const db = c.env.DB;
7397
8010
  const user = c.get("user");
7398
8011
  const subscriptionService = new SubscriptionService(db);
@@ -7415,7 +8028,7 @@ adminRoutes4.get("/", async (c) => {
7415
8028
  });
7416
8029
  return c.html(html4);
7417
8030
  });
7418
- adminRoutes4.get("/events", async (c) => {
8031
+ adminRoutes5.get("/events", async (c) => {
7419
8032
  const db = c.env.DB;
7420
8033
  const user = c.get("user");
7421
8034
  const eventService = new StripeEventService(db);
@@ -7441,11 +8054,11 @@ adminRoutes4.get("/events", async (c) => {
7441
8054
  });
7442
8055
  return c.html(html4);
7443
8056
  });
7444
- adminRoutes4.get("/settings", async (c) => {
8057
+ adminRoutes5.get("/settings", async (c) => {
7445
8058
  const db = c.env.DB;
7446
8059
  const user = c.get("user");
7447
- const settings = await getSettings3(db);
7448
- const { renderAdminLayoutCatalyst: renderAdminLayoutCatalyst2 } = await import('./admin-layout-catalyst.template-ZK5HD545.cjs');
8060
+ const settings = await getSettings4(db);
8061
+ const { renderAdminLayoutCatalyst: renderAdminLayoutCatalyst2 } = await import('./admin-layout-catalyst.template-KDHKVLXR.cjs');
7449
8062
  const content2 = `
7450
8063
  <div>
7451
8064
  <div class="mb-6">
@@ -7551,7 +8164,7 @@ adminRoutes4.get("/settings", async (c) => {
7551
8164
  dynamicMenuItems: c.get("pluginMenuItems")
7552
8165
  }));
7553
8166
  });
7554
- adminRoutes4.post("/settings", async (c) => {
8167
+ adminRoutes5.post("/settings", async (c) => {
7555
8168
  try {
7556
8169
  const body = await c.req.json();
7557
8170
  const db = c.env.DB;
@@ -7573,6 +8186,7 @@ var StripeAPI = class {
7573
8186
  constructor(secretKey) {
7574
8187
  this.secretKey = secretKey;
7575
8188
  }
8189
+ secretKey;
7576
8190
  baseUrl = "https://api.stripe.com/v1";
7577
8191
  /**
7578
8192
  * Verify a webhook signature
@@ -7702,17 +8316,17 @@ function timingSafeEqual(a, b) {
7702
8316
 
7703
8317
  // src/plugins/core-plugins/stripe-plugin/routes/api.ts
7704
8318
  var apiRoutes3 = new hono.Hono();
7705
- async function getSettings4(db) {
8319
+ async function getSettings5(db) {
7706
8320
  try {
7707
- const pluginService = new chunkQAYFOER6_cjs.PluginService(db);
8321
+ const pluginService = new chunkKVBHB7QP_cjs.PluginService(db);
7708
8322
  const plugin2 = await pluginService.getPlugin("stripe");
7709
8323
  if (plugin2?.settings) {
7710
8324
  const settings = typeof plugin2.settings === "string" ? JSON.parse(plugin2.settings) : plugin2.settings;
7711
- return { ...DEFAULT_SETTINGS3, ...settings };
8325
+ return { ...DEFAULT_SETTINGS4, ...settings };
7712
8326
  }
7713
8327
  } catch {
7714
8328
  }
7715
- return DEFAULT_SETTINGS3;
8329
+ return DEFAULT_SETTINGS4;
7716
8330
  }
7717
8331
  function mapStripeStatus(status) {
7718
8332
  const map = {
@@ -7729,7 +8343,7 @@ function mapStripeStatus(status) {
7729
8343
  }
7730
8344
  apiRoutes3.post("/webhook", async (c) => {
7731
8345
  const db = c.env.DB;
7732
- const settings = await getSettings4(db);
8346
+ const settings = await getSettings5(db);
7733
8347
  if (!settings.stripeWebhookSecret) {
7734
8348
  return c.json({ error: "Webhook secret not configured" }, 500);
7735
8349
  }
@@ -7855,11 +8469,11 @@ apiRoutes3.post("/webhook", async (c) => {
7855
8469
  }
7856
8470
  return c.json({ received: true });
7857
8471
  });
7858
- apiRoutes3.post("/create-checkout-session", chunkAAWNRBRB_cjs.requireAuth(), async (c) => {
8472
+ apiRoutes3.post("/create-checkout-session", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
7859
8473
  const db = c.env.DB;
7860
8474
  const user = c.get("user");
7861
8475
  if (!user) return c.json({ error: "Unauthorized" }, 401);
7862
- const settings = await getSettings4(db);
8476
+ const settings = await getSettings5(db);
7863
8477
  if (!settings.stripeSecretKey) {
7864
8478
  return c.json({ error: "Stripe not configured" }, 500);
7865
8479
  }
@@ -7895,7 +8509,7 @@ apiRoutes3.post("/create-checkout-session", chunkAAWNRBRB_cjs.requireAuth(), asy
7895
8509
  });
7896
8510
  return c.json({ sessionId: session.id, url: session.url });
7897
8511
  });
7898
- apiRoutes3.get("/subscription", chunkAAWNRBRB_cjs.requireAuth(), async (c) => {
8512
+ apiRoutes3.get("/subscription", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
7899
8513
  const user = c.get("user");
7900
8514
  if (!user) return c.json({ error: "Unauthorized" }, 401);
7901
8515
  const db = c.env.DB;
@@ -7907,7 +8521,7 @@ apiRoutes3.get("/subscription", chunkAAWNRBRB_cjs.requireAuth(), async (c) => {
7907
8521
  }
7908
8522
  return c.json({ subscription });
7909
8523
  });
7910
- apiRoutes3.get("/subscriptions", chunkAAWNRBRB_cjs.requireAuth(), async (c) => {
8524
+ apiRoutes3.get("/subscriptions", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
7911
8525
  const user = c.get("user");
7912
8526
  if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
7913
8527
  const db = c.env.DB;
@@ -7923,7 +8537,7 @@ apiRoutes3.get("/subscriptions", chunkAAWNRBRB_cjs.requireAuth(), async (c) => {
7923
8537
  const result = await subscriptionService.list(filters);
7924
8538
  return c.json(result);
7925
8539
  });
7926
- apiRoutes3.get("/stats", chunkAAWNRBRB_cjs.requireAuth(), async (c) => {
8540
+ apiRoutes3.get("/stats", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
7927
8541
  const user = c.get("user");
7928
8542
  if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
7929
8543
  const db = c.env.DB;
@@ -7932,11 +8546,11 @@ apiRoutes3.get("/stats", chunkAAWNRBRB_cjs.requireAuth(), async (c) => {
7932
8546
  const stats = await subscriptionService.getStats();
7933
8547
  return c.json(stats);
7934
8548
  });
7935
- apiRoutes3.post("/sync-subscriptions", chunkAAWNRBRB_cjs.requireAuth(), async (c) => {
8549
+ apiRoutes3.post("/sync-subscriptions", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
7936
8550
  const user = c.get("user");
7937
8551
  if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
7938
8552
  const db = c.env.DB;
7939
- const settings = await getSettings4(db);
8553
+ const settings = await getSettings5(db);
7940
8554
  if (!settings.stripeSecretKey) {
7941
8555
  return c.json({ error: "Stripe secret key not configured" }, 400);
7942
8556
  }
@@ -7980,7 +8594,7 @@ apiRoutes3.post("/sync-subscriptions", chunkAAWNRBRB_cjs.requireAuth(), async (c
7980
8594
  }, 500);
7981
8595
  }
7982
8596
  });
7983
- apiRoutes3.get("/events", chunkAAWNRBRB_cjs.requireAuth(), async (c) => {
8597
+ apiRoutes3.get("/events", chunkFCLKX2OS_cjs.requireAuth(), async (c) => {
7984
8598
  const user = c.get("user");
7985
8599
  if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
7986
8600
  const db = c.env.DB;
@@ -8003,7 +8617,7 @@ apiRoutes3.get("/events", chunkAAWNRBRB_cjs.requireAuth(), async (c) => {
8003
8617
 
8004
8618
  // src/plugins/core-plugins/stripe-plugin/index.ts
8005
8619
  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>`;
8006
- var stripePlugin = chunkXW56B23A_cjs.definePlugin({
8620
+ var stripePlugin = chunkA4KUJ3LD_cjs.definePlugin({
8007
8621
  id: "stripe",
8008
8622
  version: "1.0.0",
8009
8623
  name: "Stripe",
@@ -8011,7 +8625,7 @@ var stripePlugin = chunkXW56B23A_cjs.definePlugin({
8011
8625
  sonicjsVersionRange: "^3.0.0",
8012
8626
  author: { name: "SonicJS Team" },
8013
8627
  register(app2) {
8014
- app2.route("/admin/plugins/stripe", adminRoutes4);
8628
+ app2.route("/admin/plugins/stripe", adminRoutes5);
8015
8629
  app2.route("/api/stripe", apiRoutes3);
8016
8630
  },
8017
8631
  menu: [
@@ -8024,7 +8638,7 @@ var stripePlugin = chunkXW56B23A_cjs.definePlugin({
8024
8638
  });
8025
8639
 
8026
8640
  // src/templates/pages/admin-forms-list.template.ts
8027
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
8641
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
8028
8642
  function renderFormsListPage(data) {
8029
8643
  const tableData = {
8030
8644
  tableId: "forms-table",
@@ -8276,7 +8890,7 @@ function renderFormsListPage(data) {
8276
8890
 
8277
8891
  <!-- Forms Table -->
8278
8892
  <div class="bg-white dark:bg-zinc-900 rounded-lg border border-zinc-950/5 dark:border-white/10 overflow-hidden">
8279
- ${chunkVXE42MYF_cjs.renderTable(tableData)}
8893
+ ${chunk7RUW244J_cjs.renderTable(tableData)}
8280
8894
  </div>
8281
8895
  </div>
8282
8896
  `;
@@ -8286,11 +8900,11 @@ function renderFormsListPage(data) {
8286
8900
  user: data.user,
8287
8901
  version: data.version
8288
8902
  };
8289
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst(layoutData);
8903
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
8290
8904
  }
8291
8905
 
8292
8906
  // src/templates/pages/admin-forms-builder.template.ts
8293
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
8907
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
8294
8908
  function getTurnstileComponentScript() {
8295
8909
  return `
8296
8910
  (function() {
@@ -9503,11 +10117,11 @@ ${getTurnstileComponentScript()}
9503
10117
  user: data.user,
9504
10118
  version: data.version
9505
10119
  };
9506
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst(layoutData);
10120
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
9507
10121
  }
9508
10122
 
9509
10123
  // src/templates/pages/admin-forms-create.template.ts
9510
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
10124
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
9511
10125
  function renderFormCreatePage(data) {
9512
10126
  const pageContent = `
9513
10127
  <div class="max-w-3xl mx-auto">
@@ -9700,12 +10314,13 @@ function renderFormCreatePage(data) {
9700
10314
  user: data.user,
9701
10315
  version: data.version
9702
10316
  };
9703
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst(layoutData);
10317
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
9704
10318
  }
9705
10319
 
9706
10320
  // src/routes/admin-forms.ts
10321
+ var isTableMissing = (err) => String(err?.message ?? err?.cause?.message ?? "").includes("no such table: forms");
9707
10322
  var adminFormsRoutes = new hono.Hono();
9708
- adminFormsRoutes.use("*", chunkAAWNRBRB_cjs.requireAuth());
10323
+ adminFormsRoutes.use("*", chunkFCLKX2OS_cjs.requireAuth());
9709
10324
  adminFormsRoutes.get("/", async (c) => {
9710
10325
  try {
9711
10326
  const user = c.get("user");
@@ -9745,6 +10360,14 @@ adminFormsRoutes.get("/", async (c) => {
9745
10360
  };
9746
10361
  return c.html(renderFormsListPage(pageData));
9747
10362
  } catch (error) {
10363
+ if (isTableMissing(error)) {
10364
+ const user = c.get("user");
10365
+ return c.html(renderFormsListPage({
10366
+ forms: [],
10367
+ user: user ? { name: user.email, email: user.email, role: user.role } : void 0,
10368
+ version: c.get("appVersion")
10369
+ }));
10370
+ }
9748
10371
  console.error("Error listing forms:", error);
9749
10372
  return c.html("<p>Error loading forms</p>", 500);
9750
10373
  }
@@ -9855,6 +10478,7 @@ adminFormsRoutes.post("/", async (c) => {
9855
10478
  ).run();
9856
10479
  return c.redirect(`/admin/forms/${formId}/builder`);
9857
10480
  } catch (error) {
10481
+ if (isTableMissing(error)) return c.json({ error: "Forms storage not configured \u2014 run database migrations" }, 503);
9858
10482
  console.error("Error creating form:", error);
9859
10483
  return c.json({ error: "Failed to create form" }, 500);
9860
10484
  }
@@ -9869,7 +10493,7 @@ adminFormsRoutes.get("/:id/builder", async (c) => {
9869
10493
  if (!form) {
9870
10494
  return c.html("<p>Form not found</p>", 404);
9871
10495
  }
9872
- const turnstileService = new chunkH2AXVCLS_cjs.TurnstileService(db);
10496
+ const turnstileService = new chunk5UXU3LP4_cjs.TurnstileService(db);
9873
10497
  const turnstileSettings = await turnstileService.getSettings();
9874
10498
  const pageData = {
9875
10499
  id: form.id,
@@ -9892,6 +10516,7 @@ adminFormsRoutes.get("/:id/builder", async (c) => {
9892
10516
  };
9893
10517
  return c.html(renderFormBuilderPage(pageData));
9894
10518
  } catch (error) {
10519
+ if (isTableMissing(error)) return c.html("<p>Forms storage not configured \u2014 run database migrations</p>", 503);
9895
10520
  console.error("Error showing form builder:", error);
9896
10521
  return c.html("<p>Error loading form builder</p>", 500);
9897
10522
  }
@@ -9921,6 +10546,7 @@ adminFormsRoutes.put("/:id", async (c) => {
9921
10546
  ).run();
9922
10547
  return c.json({ success: true, message: "Form saved successfully" });
9923
10548
  } catch (error) {
10549
+ if (isTableMissing(error)) return c.json({ error: "Forms storage not configured \u2014 run database migrations" }, 503);
9924
10550
  console.error("Error updating form:", error);
9925
10551
  return c.json({ error: "Failed to save form" }, 500);
9926
10552
  }
@@ -9942,6 +10568,7 @@ adminFormsRoutes.delete("/:id", async (c) => {
9942
10568
  await db.prepare("DELETE FROM forms WHERE id = ?").bind(formId).run();
9943
10569
  return c.json({ success: true, message: "Form deleted successfully" });
9944
10570
  } catch (error) {
10571
+ if (isTableMissing(error)) return c.json({ error: "Forms storage not configured \u2014 run database migrations" }, 503);
9945
10572
  console.error("Error deleting form:", error);
9946
10573
  return c.json({ error: "Failed to delete form" }, 500);
9947
10574
  }
@@ -10002,6 +10629,7 @@ adminFormsRoutes.get("/:id/submissions", async (c) => {
10002
10629
  `;
10003
10630
  return c.html(html4);
10004
10631
  } catch (error) {
10632
+ if (isTableMissing(error)) return c.html("<p>Forms storage not configured \u2014 run database migrations</p>", 503);
10005
10633
  console.error("Error loading submissions:", error);
10006
10634
  return c.html("<p>Error loading submissions</p>", 500);
10007
10635
  }
@@ -10022,6 +10650,7 @@ function sanitizeDeep(value) {
10022
10650
  }
10023
10651
  return value;
10024
10652
  }
10653
+ var isTableMissing2 = (err) => String(err?.message ?? err?.cause?.message ?? "").includes("no such table: form");
10025
10654
  var publicFormsRoutes = new hono.Hono();
10026
10655
  publicFormsRoutes.get("/:identifier/turnstile-config", async (c) => {
10027
10656
  try {
@@ -10033,7 +10662,7 @@ publicFormsRoutes.get("/:identifier/turnstile-config", async (c) => {
10033
10662
  if (!form) {
10034
10663
  return c.json({ error: "Form not found" }, 404);
10035
10664
  }
10036
- const turnstileService = new chunkH2AXVCLS_cjs.TurnstileService(db);
10665
+ const turnstileService = new chunk5UXU3LP4_cjs.TurnstileService(db);
10037
10666
  const globalSettings = await turnstileService.getSettings();
10038
10667
  const formSettings = form.turnstile_settings ? JSON.parse(form.turnstile_settings) : { inherit: true };
10039
10668
  const enabled = form.turnstile_enabled === 1 || formSettings.inherit && globalSettings?.enabled;
@@ -10049,6 +10678,7 @@ publicFormsRoutes.get("/:identifier/turnstile-config", async (c) => {
10049
10678
  appearance: formSettings.appearance || globalSettings.appearance || "always"
10050
10679
  });
10051
10680
  } catch (error) {
10681
+ if (isTableMissing2(error)) return c.json({ enabled: false });
10052
10682
  console.error("Error fetching Turnstile config:", error);
10053
10683
  return c.json({ error: "Failed to fetch config" }, 500);
10054
10684
  }
@@ -10076,6 +10706,7 @@ publicFormsRoutes.get("/:identifier/schema", async (c) => {
10076
10706
  submitUrl: `/api/forms/${form.id}/submit`
10077
10707
  });
10078
10708
  } catch (error) {
10709
+ if (isTableMissing2(error)) return c.json({ error: "Form not found" }, 404);
10079
10710
  console.error("Error fetching form schema:", error);
10080
10711
  return c.json({ error: "Failed to fetch form schema" }, 500);
10081
10712
  }
@@ -10442,6 +11073,7 @@ publicFormsRoutes.get("/:name", async (c) => {
10442
11073
  `;
10443
11074
  return c.html(html4);
10444
11075
  } catch (error) {
11076
+ if (isTableMissing2(error)) return c.html("<h1>Form not found</h1><p>This form does not exist or is not publicly available.</p>", 404);
10445
11077
  console.error("Error rendering form:", error);
10446
11078
  return c.html("<p>Error loading form</p>", 500);
10447
11079
  }
@@ -10460,7 +11092,7 @@ publicFormsRoutes.post("/:identifier/submit", async (c) => {
10460
11092
  const turnstileEnabled = form.turnstile_enabled === 1;
10461
11093
  const turnstileSettings = form.turnstile_settings ? JSON.parse(form.turnstile_settings) : { inherit: true };
10462
11094
  if (turnstileEnabled || turnstileSettings.inherit) {
10463
- const turnstileService = new chunkH2AXVCLS_cjs.TurnstileService(db);
11095
+ const turnstileService = new chunk5UXU3LP4_cjs.TurnstileService(db);
10464
11096
  const globalEnabled = await turnstileService.isEnabled();
10465
11097
  if (globalEnabled || turnstileEnabled) {
10466
11098
  const turnstileToken = body.data?.turnstile || body.turnstile;
@@ -10515,13 +11147,14 @@ publicFormsRoutes.post("/:identifier/submit", async (c) => {
10515
11147
  message: "Form submitted successfully"
10516
11148
  });
10517
11149
  } catch (error) {
11150
+ if (isTableMissing2(error)) return c.json({ error: "Form not found" }, 404);
10518
11151
  console.error("Error submitting form:", error);
10519
11152
  return c.json({ error: "Failed to submit form" }, 500);
10520
11153
  }
10521
11154
  });
10522
11155
 
10523
11156
  // src/plugins/core-plugins/forms-plugin/index.ts
10524
- var formsPlugin = chunkXW56B23A_cjs.definePlugin({
11157
+ var formsPlugin = chunkA4KUJ3LD_cjs.definePlugin({
10525
11158
  id: "forms",
10526
11159
  version: "1.0.0",
10527
11160
  name: "Forms",
@@ -10539,9 +11172,9 @@ var formsPlugin = chunkXW56B23A_cjs.definePlugin({
10539
11172
  activate: async () => console.info("\u2705 Forms plugin activated"),
10540
11173
  deactivate: async () => console.info("\u274C Forms plugin deactivated")
10541
11174
  });
10542
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
11175
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
10543
11176
  var adminRbacRoutes = new hono.Hono();
10544
- adminRbacRoutes.use("*", chunkAAWNRBRB_cjs.requireRbac("rbac", "manage"));
11177
+ adminRbacRoutes.use("*", chunkFCLKX2OS_cjs.requireRbac("rbac", "manage"));
10545
11178
  var esc = (s) => String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
10546
11179
  var TABS2 = `
10547
11180
  <div class="border-b border-zinc-950/10 dark:border-white/10 mb-6">
@@ -10551,7 +11184,7 @@ var TABS2 = `
10551
11184
  </nav>
10552
11185
  </div>`;
10553
11186
  adminRbacRoutes.get("/", async (c) => {
10554
- const rbac = new chunk2CB4KY7I_cjs.RbacService(c.env.DB);
11187
+ const rbac = new chunkLTZ5WYOK_cjs.RbacService(c.env.DB);
10555
11188
  const [roles, verbs, resources, grants] = await Promise.all([
10556
11189
  rbac.getRoles(),
10557
11190
  rbac.getVerbs(),
@@ -10662,7 +11295,7 @@ adminRbacRoutes.get("/", async (c) => {
10662
11295
  ${r.is_system ? `<code class="text-xs text-zinc-500 dark:text-zinc-400">${esc(r.name)}</code><span class="rounded-full bg-zinc-100 dark:bg-white/10 px-2 py-0.5 text-[11px] text-zinc-500 dark:text-zinc-400">system</span>` : `<input form="roles-bulk-form" class="${inpSm} w-28" name="name_${esc(r.id)}" value="${esc(r.name)}" required>`}
10663
11296
  <label class="ml-auto inline-flex items-center gap-2 rounded-md bg-white/5 px-2.5 py-1 text-xs font-medium text-zinc-700 dark:text-zinc-300 ring-1 ring-inset ring-zinc-500/20">
10664
11297
  <input form="roles-bulk-form" type="checkbox" name="portal_${esc(r.id)}" value="1" ${portalChecked ? "checked" : ""} ${portalDisabled ? "disabled" : ""} class="h-3.5 w-3.5 rounded border-zinc-400 text-cyan-600 focus:ring-cyan-500">
10665
- Access portal
11298
+ Admin Panel
10666
11299
  </label>
10667
11300
  <a href="/admin/tenants/roles/${esc(r.name)}" data-role-tenants="${esc(r.name)}" class="text-xs text-cyan-600 dark:text-cyan-400 hover:underline" title="Per-tenant assignments of this role">tenants</a>
10668
11301
  ${r.is_system ? "" : `<button form="delete-role-${esc(r.id)}" type="submit" onclick="return confirm('Delete role ${esc(r.name)}?')" class="text-xs text-red-600 dark:text-red-400 hover:underline">delete</button>`}
@@ -10766,7 +11399,7 @@ adminRbacRoutes.get("/", async (c) => {
10766
11399
  <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
10767
11400
  <div class="${card}">
10768
11401
  <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-3">Roles</h3>
10769
- <p class="mb-3 text-xs text-zinc-500 dark:text-zinc-400">Use <strong>Access portal</strong> to allow a role into the admin backend. Resource permissions are configured in the <strong>Matrix</strong> tab.</p>
11402
+ <p class="mb-3 text-xs text-zinc-500 dark:text-zinc-400">Use <strong>Admin Panel</strong> to allow a role into the admin backend. Resource permissions are configured in the <strong>Matrix</strong> tab.</p>
10770
11403
  ${roleList}
10771
11404
  </div>
10772
11405
  <div class="${card}">
@@ -10845,11 +11478,11 @@ adminRbacRoutes.get("/", async (c) => {
10845
11478
  </script>`;
10846
11479
  const u = c.get("user");
10847
11480
  return c.html(
10848
- chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst({
11481
+ chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
10849
11482
  title: "Roles & Permissions",
10850
11483
  pageTitle: "Roles & Permissions",
10851
11484
  currentPath: "/admin/users",
10852
- version: chunkLRZIAW7U_cjs.getCoreVersion(),
11485
+ version: chunkAOUVUF32_cjs.getCoreVersion(),
10853
11486
  user: u ? { name: u.email || "Admin", email: u.email || "", role: u.role || "admin" } : void 0,
10854
11487
  content: content2
10855
11488
  })
@@ -10873,7 +11506,7 @@ adminRbacRoutes.post("/grants", async (c) => {
10873
11506
  pairsByRole.get(roleId).push({ resource, verb, scope });
10874
11507
  }
10875
11508
  }
10876
- const rbac = new chunk2CB4KY7I_cjs.RbacService(c.env.DB);
11509
+ const rbac = new chunkLTZ5WYOK_cjs.RbacService(c.env.DB);
10877
11510
  for (const id of saveRoleIds) {
10878
11511
  await rbac.setRoleGrants(id, pairsByRole.get(id) || []);
10879
11512
  }
@@ -10894,7 +11527,7 @@ adminRbacRoutes.post("/grants", async (c) => {
10894
11527
  adminRbacRoutes.post("/roles/bulk", async (c) => {
10895
11528
  const form = await c.req.formData();
10896
11529
  const roleIds = String(form.get("role_ids") || "").split(",").filter(Boolean);
10897
- const rbac = new chunk2CB4KY7I_cjs.RbacService(c.env.DB);
11530
+ const rbac = new chunkLTZ5WYOK_cjs.RbacService(c.env.DB);
10898
11531
  for (const roleId of roleIds) {
10899
11532
  const displayName = String(form.get(`display_name_${roleId}`) || "").trim();
10900
11533
  const nameVal = form.get(`name_${roleId}`) ? String(form.get(`name_${roleId}`)).trim() : void 0;
@@ -10919,7 +11552,7 @@ adminRbacRoutes.post("/roles", async (c) => {
10919
11552
  const displayName = String(form.get("display_name") || "").trim();
10920
11553
  if (name && displayName) {
10921
11554
  try {
10922
- await new chunk2CB4KY7I_cjs.RbacService(c.env.DB).createRole(name, displayName);
11555
+ await new chunkLTZ5WYOK_cjs.RbacService(c.env.DB).createRole(name, displayName);
10923
11556
  } catch {
10924
11557
  }
10925
11558
  }
@@ -10934,7 +11567,7 @@ adminRbacRoutes.post("/roles/:id", async (c) => {
10934
11567
  const portalAccess = form.get("portal_access") === "1";
10935
11568
  if (displayName) {
10936
11569
  try {
10937
- const rbac = new chunk2CB4KY7I_cjs.RbacService(c.env.DB);
11570
+ const rbac = new chunkLTZ5WYOK_cjs.RbacService(c.env.DB);
10938
11571
  if (roleId !== "role-admin") {
10939
11572
  await rbac.updateRoleAndPortalAccess(roleId, displayName, name, portalAccess, description);
10940
11573
  } else {
@@ -10946,7 +11579,7 @@ adminRbacRoutes.post("/roles/:id", async (c) => {
10946
11579
  return c.redirect(`/admin/rbac#roles-verbs`);
10947
11580
  });
10948
11581
  adminRbacRoutes.post("/roles/:id/delete", async (c) => {
10949
- await new chunk2CB4KY7I_cjs.RbacService(c.env.DB).deleteRole(c.req.param("id"));
11582
+ await new chunkLTZ5WYOK_cjs.RbacService(c.env.DB).deleteRole(c.req.param("id"));
10950
11583
  return c.redirect("/admin/rbac#roles-verbs");
10951
11584
  });
10952
11585
  adminRbacRoutes.post("/verbs", async (c) => {
@@ -10954,18 +11587,18 @@ adminRbacRoutes.post("/verbs", async (c) => {
10954
11587
  const name = String(form.get("name") || "").trim();
10955
11588
  if (name) {
10956
11589
  try {
10957
- await new chunk2CB4KY7I_cjs.RbacService(c.env.DB).createVerb(name);
11590
+ await new chunkLTZ5WYOK_cjs.RbacService(c.env.DB).createVerb(name);
10958
11591
  } catch {
10959
11592
  }
10960
11593
  }
10961
11594
  return c.redirect("/admin/rbac#roles-verbs");
10962
11595
  });
10963
11596
  adminRbacRoutes.post("/verbs/:id/delete", async (c) => {
10964
- await new chunk2CB4KY7I_cjs.RbacService(c.env.DB).deleteVerb(c.req.param("id"));
11597
+ await new chunkLTZ5WYOK_cjs.RbacService(c.env.DB).deleteVerb(c.req.param("id"));
10965
11598
  return c.redirect("/admin/rbac#roles-verbs");
10966
11599
  });
10967
11600
  adminRbacRoutes.get("/check", async (c) => {
10968
- const rbac = new chunk2CB4KY7I_cjs.RbacService(c.env.DB);
11601
+ const rbac = new chunkLTZ5WYOK_cjs.RbacService(c.env.DB);
10969
11602
  const resource = c.req.query("resource") || "";
10970
11603
  const verb = c.req.query("verb") || "";
10971
11604
  const roleId = c.req.query("role");
@@ -10986,7 +11619,7 @@ adminRbacRoutes.get("/check", async (c) => {
10986
11619
  });
10987
11620
 
10988
11621
  // src/middleware/plugin-menu.ts
10989
- var REGISTRY_MENU_PLUGINS = Object.values(chunkQAYFOER6_cjs.PLUGIN_REGISTRY).filter((p) => p.adminMenu !== null).map((p) => ({
11622
+ var REGISTRY_MENU_PLUGINS = Object.values(chunkKVBHB7QP_cjs.PLUGIN_REGISTRY).filter((p) => p.adminMenu !== null).map((p) => ({
10990
11623
  id: p.id,
10991
11624
  label: p.adminMenu.label,
10992
11625
  path: p.adminMenu.path,
@@ -11064,14 +11697,24 @@ function pluginMenuMiddleware() {
11064
11697
  }
11065
11698
  } catch {
11066
11699
  }
11067
- c.set("pluginMenuItems", activeMenuItems.map((m) => ({ label: m.label, path: m.path, icon: resolveIcon(m.icon) || "" })));
11700
+ const user = c.get("user");
11701
+ const singletonItems = chunk5UXU3LP4_cjs.resolvePluginMenuItems(user ? { role: user.role } : void 0);
11702
+ const existingPaths = new Set(activeMenuItems.map((i) => i.path));
11703
+ for (const item of singletonItems) {
11704
+ if (!existingPaths.has(item.path)) {
11705
+ activeMenuItems.push({ label: item.label, path: item.path, icon: item.icon, order: item.order });
11706
+ }
11707
+ }
11708
+ activeMenuItems.sort((a, b) => a.order - b.order);
11709
+ c.set("pluginMenuItems", activeMenuItems.map((m) => ({ label: m.label, path: m.path, icon: resolveIcon(m.icon) || m.icon || "" })));
11068
11710
  await next();
11069
- if (activeMenuItems.length > 0 && c.res.headers.get("content-type")?.includes("text/html")) {
11711
+ const finalItems = c.get("pluginMenuItems") ?? [];
11712
+ if (finalItems.length > 0 && c.res.headers.get("content-type")?.includes("text/html")) {
11070
11713
  const status = c.res.status;
11071
11714
  const headers = new Headers(c.res.headers);
11072
11715
  const html4 = await c.res.text();
11073
11716
  if (html4.includes(MARKER)) {
11074
- const renderedItems = activeMenuItems.map((item) => renderMenuItem(item, path)).join("");
11717
+ const renderedItems = finalItems.map((item) => renderMenuItem(item, path)).join("");
11075
11718
  const newHtml = html4.split(MARKER).join(renderedItems);
11076
11719
  c.res = new Response(newHtml, { status, headers });
11077
11720
  } else {
@@ -11080,17 +11723,17 @@ function pluginMenuMiddleware() {
11080
11723
  }
11081
11724
  };
11082
11725
  }
11083
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
11084
- var adminRoutes5 = new hono.Hono();
11085
- adminRoutes5.use("*", chunkAAWNRBRB_cjs.requireAuth());
11086
- adminRoutes5.use("*", async (c, next) => {
11726
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
11727
+ var adminRoutes6 = new hono.Hono();
11728
+ adminRoutes6.use("*", chunkFCLKX2OS_cjs.requireAuth());
11729
+ adminRoutes6.use("*", async (c, next) => {
11087
11730
  const user = c.get("user");
11088
11731
  if (user?.role !== "admin") {
11089
11732
  return c.text("Access denied", 403);
11090
11733
  }
11091
11734
  return next();
11092
11735
  });
11093
- adminRoutes5.get("/", async (c) => {
11736
+ adminRoutes6.get("/", async (c) => {
11094
11737
  const user = c.get("user");
11095
11738
  const db = c.env.DB;
11096
11739
  let totalRequests = 0;
@@ -11198,7 +11841,7 @@ adminRoutes5.get("/", async (c) => {
11198
11841
  </div>
11199
11842
  </div>
11200
11843
  `;
11201
- return c.html(chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst({
11844
+ return c.html(chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
11202
11845
  title: "Analytics",
11203
11846
  pageTitle: "Analytics Dashboard",
11204
11847
  currentPath: "/admin/analytics",
@@ -11229,12 +11872,13 @@ var QUERYABLE_FIELDS2 = [
11229
11872
  var EventTrackingService = class {
11230
11873
  constructor(db) {
11231
11874
  this.db = db;
11232
- this.docsService = new chunk2CB4KY7I_cjs.DocumentsService(db, {
11875
+ this.docsService = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
11233
11876
  queryableFields: QUERYABLE_FIELDS2,
11234
11877
  maxVersionsPerRoot: 1,
11235
11878
  tenantId: TENANT2
11236
11879
  });
11237
11880
  }
11881
+ db;
11238
11882
  docsService;
11239
11883
  async trackEvent(input) {
11240
11884
  const doc = await this.docsService.create({
@@ -11437,7 +12081,7 @@ apiRoutes4.get("/stats", async (c) => {
11437
12081
  });
11438
12082
 
11439
12083
  // src/plugins/core-plugins/analytics/index.ts
11440
- var analyticsPlugin = chunkXW56B23A_cjs.definePlugin({
12084
+ var analyticsPlugin = chunkA4KUJ3LD_cjs.definePlugin({
11441
12085
  id: "core-analytics",
11442
12086
  version: "1.0.0",
11443
12087
  name: "Analytics",
@@ -11446,7 +12090,7 @@ var analyticsPlugin = chunkXW56B23A_cjs.definePlugin({
11446
12090
  author: { name: "SonicJS Team", email: "team@sonicjs.com" },
11447
12091
  register(app2) {
11448
12092
  app2.route("/api/events", apiRoutes4);
11449
- app2.route("/admin/analytics", adminRoutes5);
12093
+ app2.route("/admin/analytics", adminRoutes6);
11450
12094
  },
11451
12095
  menu: [
11452
12096
  {
@@ -11584,7 +12228,7 @@ function esc2(s) {
11584
12228
  return (s || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
11585
12229
  }
11586
12230
  async function getVariablesMap(db) {
11587
- let variables = chunkVXE42MYF_cjs.getVariablesCached();
12231
+ let variables = chunk7RUW244J_cjs.getVariablesCached();
11588
12232
  if (variables) return variables;
11589
12233
  try {
11590
12234
  const { results } = await db.prepare(
@@ -11594,7 +12238,7 @@ async function getVariablesMap(db) {
11594
12238
  for (const row of results || []) {
11595
12239
  variables.set(row.key, row.value);
11596
12240
  }
11597
- chunkVXE42MYF_cjs.setVariablesCache(variables);
12241
+ chunk7RUW244J_cjs.setVariablesCache(variables);
11598
12242
  return variables;
11599
12243
  } catch {
11600
12244
  return /* @__PURE__ */ new Map();
@@ -11663,7 +12307,7 @@ apiRoutes5.post("/", async (c) => {
11663
12307
  await db.prepare(
11664
12308
  "INSERT INTO global_variables (key, value, description, category, is_active) VALUES (?, ?, ?, ?, ?)"
11665
12309
  ).bind(key, value || "", description || "", category || "general", isActive !== false ? 1 : 0).run();
11666
- chunkVXE42MYF_cjs.invalidateVariablesCache();
12310
+ chunk7RUW244J_cjs.invalidateVariablesCache();
11667
12311
  const created = await db.prepare("SELECT * FROM global_variables WHERE key = ?").bind(key).first();
11668
12312
  return c.json({ success: true, data: formatVariable(created) }, 201);
11669
12313
  } catch {
@@ -11708,7 +12352,7 @@ apiRoutes5.put("/:id", async (c) => {
11708
12352
  updates.push("updated_at = strftime('%s', 'now')");
11709
12353
  params.push(id);
11710
12354
  await db.prepare(`UPDATE global_variables SET ${updates.join(", ")} WHERE id = ?`).bind(...params).run();
11711
- chunkVXE42MYF_cjs.invalidateVariablesCache();
12355
+ chunk7RUW244J_cjs.invalidateVariablesCache();
11712
12356
  const updated = await db.prepare("SELECT * FROM global_variables WHERE id = ?").bind(id).first();
11713
12357
  return c.json({ success: true, data: formatVariable(updated) });
11714
12358
  } catch {
@@ -11722,14 +12366,14 @@ apiRoutes5.delete("/:id", async (c) => {
11722
12366
  const existing = await db.prepare("SELECT id FROM global_variables WHERE id = ?").bind(id).first();
11723
12367
  if (!existing) return c.json({ error: "Variable not found" }, 404);
11724
12368
  await db.prepare("DELETE FROM global_variables WHERE id = ?").bind(id).run();
11725
- chunkVXE42MYF_cjs.invalidateVariablesCache();
12369
+ chunk7RUW244J_cjs.invalidateVariablesCache();
11726
12370
  return c.json({ success: true });
11727
12371
  } catch {
11728
12372
  return c.json({ success: false, error: "Failed to delete variable" }, 500);
11729
12373
  }
11730
12374
  });
11731
- var adminRoutes6 = new hono.Hono();
11732
- adminRoutes6.use("*", async (c, next) => {
12375
+ var adminRoutes7 = new hono.Hono();
12376
+ adminRoutes7.use("*", async (c, next) => {
11733
12377
  try {
11734
12378
  const db = c.env?.DB;
11735
12379
  if (db) {
@@ -11740,7 +12384,7 @@ adminRoutes6.use("*", async (c, next) => {
11740
12384
  }
11741
12385
  await next();
11742
12386
  });
11743
- adminRoutes6.get("/", async (c) => {
12387
+ adminRoutes7.get("/", async (c) => {
11744
12388
  const db = c.env.DB;
11745
12389
  let variables = [];
11746
12390
  try {
@@ -11770,7 +12414,7 @@ adminRoutes6.get("/", async (c) => {
11770
12414
  }
11771
12415
  return c.html(renderAdminPage(variables, { editorActive, activeEditorName, enableEditorIntegration }));
11772
12416
  });
11773
- adminRoutes6.put("/:id", async (c) => {
12417
+ adminRoutes7.put("/:id", async (c) => {
11774
12418
  const db = c.env.DB;
11775
12419
  const id = c.req.param("id");
11776
12420
  let body;
@@ -11782,19 +12426,19 @@ adminRoutes6.put("/:id", async (c) => {
11782
12426
  const value = body.value;
11783
12427
  if (value !== void 0) {
11784
12428
  await db.prepare("UPDATE global_variables SET value = ?, updated_at = strftime('%s', 'now') WHERE id = ?").bind(value, id).run();
11785
- chunkVXE42MYF_cjs.invalidateVariablesCache();
12429
+ chunk7RUW244J_cjs.invalidateVariablesCache();
11786
12430
  }
11787
12431
  return c.html('<span class="text-green-400 text-xs">Saved</span>');
11788
12432
  });
11789
- adminRoutes6.post("/:id/toggle", async (c) => {
12433
+ adminRoutes7.post("/:id/toggle", async (c) => {
11790
12434
  const db = c.env.DB;
11791
12435
  const id = c.req.param("id");
11792
12436
  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();
11793
- chunkVXE42MYF_cjs.invalidateVariablesCache();
12437
+ chunk7RUW244J_cjs.invalidateVariablesCache();
11794
12438
  c.header("HX-Redirect", "/admin/global-variables");
11795
12439
  return c.body(null, 204);
11796
12440
  });
11797
- adminRoutes6.post("/", async (c) => {
12441
+ adminRoutes7.post("/", async (c) => {
11798
12442
  const db = c.env.DB;
11799
12443
  const form = await c.req.parseBody();
11800
12444
  const key = (form.key || "").trim();
@@ -11811,11 +12455,11 @@ adminRoutes6.post("/", async (c) => {
11811
12455
  await db.prepare(
11812
12456
  "INSERT INTO global_variables (key, value, description, category) VALUES (?, ?, ?, ?)"
11813
12457
  ).bind(key, value, description, category).run();
11814
- chunkVXE42MYF_cjs.invalidateVariablesCache();
12458
+ chunk7RUW244J_cjs.invalidateVariablesCache();
11815
12459
  c.header("HX-Redirect", "/admin/global-variables");
11816
12460
  return c.body(null, 204);
11817
12461
  });
11818
- adminRoutes6.post("/settings/editor-integration", async (c) => {
12462
+ adminRoutes7.post("/settings/editor-integration", async (c) => {
11819
12463
  const db = c.env.DB;
11820
12464
  try {
11821
12465
  const row = await db.prepare("SELECT settings FROM plugins WHERE id = 'global-variables'").first();
@@ -11827,10 +12471,10 @@ adminRoutes6.post("/settings/editor-integration", async (c) => {
11827
12471
  return c.json({ success: false, error: "Failed to update setting" }, 500);
11828
12472
  }
11829
12473
  });
11830
- adminRoutes6.delete("/:id", async (c) => {
12474
+ adminRoutes7.delete("/:id", async (c) => {
11831
12475
  const db = c.env.DB;
11832
12476
  await db.prepare("DELETE FROM global_variables WHERE id = ?").bind(c.req.param("id")).run();
11833
- chunkVXE42MYF_cjs.invalidateVariablesCache();
12477
+ chunk7RUW244J_cjs.invalidateVariablesCache();
11834
12478
  return c.html("");
11835
12479
  });
11836
12480
  function renderAdminPage(variables, editorStatus = { editorActive: false, activeEditorName: "", enableEditorIntegration: true }) {
@@ -12148,7 +12792,7 @@ function renderAdminPage(variables, editorStatus = { editorActive: false, active
12148
12792
  </div>
12149
12793
  ` });
12150
12794
  }
12151
- var globalVariablesPlugin = chunkXW56B23A_cjs.definePlugin({
12795
+ var globalVariablesPlugin = chunkA4KUJ3LD_cjs.definePlugin({
12152
12796
  id: "global-variables",
12153
12797
  version: "1.1.0",
12154
12798
  name: "Global Variables",
@@ -12158,7 +12802,7 @@ var globalVariablesPlugin = chunkXW56B23A_cjs.definePlugin({
12158
12802
  capabilities: ["hooks.content:subscribe"],
12159
12803
  register(app2) {
12160
12804
  app2.route("/api/global-variables", apiRoutes5);
12161
- app2.route("/admin/global-variables", adminRoutes6);
12805
+ app2.route("/admin/global-variables", adminRoutes7);
12162
12806
  },
12163
12807
  menu: [
12164
12808
  { label: "Global Variables", path: "/admin/global-variables", icon: "bolt", order: 45, permissions: ["global-variables:view"] }
@@ -12171,7 +12815,7 @@ var globalVariablesPlugin = chunkXW56B23A_cjs.definePlugin({
12171
12815
  if (!db || !data) return data;
12172
12816
  const variables = await getVariablesMap(db);
12173
12817
  if (variables.size === 0) return data;
12174
- return chunkVXE42MYF_cjs.resolveVariablesInObject(data, variables);
12818
+ return chunk7RUW244J_cjs.resolveVariablesInObject(data, variables);
12175
12819
  } catch {
12176
12820
  return data;
12177
12821
  }
@@ -12189,7 +12833,7 @@ var globalVariablesPlugin = chunkXW56B23A_cjs.definePlugin({
12189
12833
  },
12190
12834
  activate: async () => console.info("[GlobalVariables] Plugin activated"),
12191
12835
  deactivate: async () => {
12192
- chunkVXE42MYF_cjs.invalidateVariablesCache();
12836
+ chunk7RUW244J_cjs.invalidateVariablesCache();
12193
12837
  console.info("[GlobalVariables] Plugin deactivated, cache cleared");
12194
12838
  },
12195
12839
  uninstall: async (ctx) => {
@@ -12479,8 +13123,8 @@ apiRoutes6.delete("/:id", async (c) => {
12479
13123
  return c.json({ success: false, error: "Failed to delete shortcode" }, 500);
12480
13124
  }
12481
13125
  });
12482
- var adminRoutes7 = new hono.Hono();
12483
- adminRoutes7.use("*", async (c, next) => {
13126
+ var adminRoutes8 = new hono.Hono();
13127
+ adminRoutes8.use("*", async (c, next) => {
12484
13128
  try {
12485
13129
  const db = c.env?.DB;
12486
13130
  if (db) {
@@ -12491,7 +13135,7 @@ adminRoutes7.use("*", async (c, next) => {
12491
13135
  }
12492
13136
  await next();
12493
13137
  });
12494
- adminRoutes7.get("/", async (c) => {
13138
+ adminRoutes8.get("/", async (c) => {
12495
13139
  const db = c.env.DB;
12496
13140
  let shortcodes = [];
12497
13141
  try {
@@ -12521,7 +13165,7 @@ adminRoutes7.get("/", async (c) => {
12521
13165
  }
12522
13166
  return c.html(renderAdminPage2(shortcodes, { editorActive, activeEditorName, enableEditorIntegration }));
12523
13167
  });
12524
- adminRoutes7.post("/", async (c) => {
13168
+ adminRoutes8.post("/", async (c) => {
12525
13169
  const db = c.env.DB;
12526
13170
  const form = await c.req.parseBody();
12527
13171
  const name = (form.name || "").trim();
@@ -12542,7 +13186,7 @@ adminRoutes7.post("/", async (c) => {
12542
13186
  c.header("HX-Redirect", "/admin/shortcodes");
12543
13187
  return c.body(null, 204);
12544
13188
  });
12545
- adminRoutes7.post("/settings/editor-integration", async (c) => {
13189
+ adminRoutes8.post("/settings/editor-integration", async (c) => {
12546
13190
  const db = c.env.DB;
12547
13191
  try {
12548
13192
  const row = await db.prepare("SELECT settings FROM plugins WHERE id = 'shortcodes'").first();
@@ -12554,7 +13198,7 @@ adminRoutes7.post("/settings/editor-integration", async (c) => {
12554
13198
  return c.json({ success: false, error: "Failed to update setting" }, 500);
12555
13199
  }
12556
13200
  });
12557
- adminRoutes7.delete("/:id", async (c) => {
13201
+ adminRoutes8.delete("/:id", async (c) => {
12558
13202
  await c.env.DB.prepare("DELETE FROM shortcodes WHERE id = ?").bind(c.req.param("id")).run();
12559
13203
  return c.html("");
12560
13204
  });
@@ -12755,7 +13399,7 @@ function renderAdminPage2(shortcodes, editorStatus = { editorActive: false, acti
12755
13399
  </div>
12756
13400
  ` });
12757
13401
  }
12758
- var shortcodesPlugin = chunkXW56B23A_cjs.definePlugin({
13402
+ var shortcodesPlugin = chunkA4KUJ3LD_cjs.definePlugin({
12759
13403
  id: "shortcodes",
12760
13404
  version: "1.0.0",
12761
13405
  name: "Shortcodes",
@@ -12765,7 +13409,7 @@ var shortcodesPlugin = chunkXW56B23A_cjs.definePlugin({
12765
13409
  capabilities: ["hooks.content:subscribe"],
12766
13410
  register(app2) {
12767
13411
  app2.route("/api/shortcodes", apiRoutes6);
12768
- app2.route("/admin/shortcodes", adminRoutes7);
13412
+ app2.route("/admin/shortcodes", adminRoutes8);
12769
13413
  },
12770
13414
  menu: [
12771
13415
  { label: "Shortcodes", path: "/admin/shortcodes", icon: "bolt", order: 46, permissions: ["shortcodes:view"] }
@@ -12839,7 +13483,7 @@ helloWorldRoutes.get("/", async (c) => {
12839
13483
  </html>
12840
13484
  `);
12841
13485
  });
12842
- var helloWorldPlugin = chunkXW56B23A_cjs.definePlugin({
13486
+ var helloWorldPlugin = chunkA4KUJ3LD_cjs.definePlugin({
12843
13487
  id: "hello-world",
12844
13488
  version: "1.0.0",
12845
13489
  name: "Hello World",
@@ -12874,6 +13518,9 @@ var helloWorldPlugin = chunkXW56B23A_cjs.definePlugin({
12874
13518
  console.info("\u274C Hello World plugin deactivated");
12875
13519
  }
12876
13520
  });
13521
+ function createHelloWorldPlugin() {
13522
+ return helloWorldPlugin;
13523
+ }
12877
13524
 
12878
13525
  // src/plugins/core-plugins/multi-tenant-plugin/manifest.json
12879
13526
  var manifest_default2 = {
@@ -12883,7 +13530,7 @@ var manifest_default2 = {
12883
13530
  author: "SonicJS Team"};
12884
13531
 
12885
13532
  // src/plugins/core-plugins/multi-tenant-plugin/templates/tenants-list.template.ts
12886
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
13533
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
12887
13534
  function statusBadge2(status) {
12888
13535
  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>';
12889
13536
  }
@@ -12956,7 +13603,7 @@ function renderTenantsList(data) {
12956
13603
  </table>
12957
13604
  </div>
12958
13605
  </div>`;
12959
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst({
13606
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
12960
13607
  title: "Tenants - SonicJS",
12961
13608
  pageTitle: "Tenants",
12962
13609
  currentPath: "/admin/tenants",
@@ -12975,7 +13622,7 @@ function renderTenantsInactive(data) {
12975
13622
  <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>
12976
13623
  </div>
12977
13624
  </div>`;
12978
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst({
13625
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
12979
13626
  title: "Tenants - SonicJS",
12980
13627
  pageTitle: "Tenants",
12981
13628
  currentPath: "/admin/tenants",
@@ -12986,7 +13633,7 @@ function renderTenantsInactive(data) {
12986
13633
  }
12987
13634
 
12988
13635
  // src/plugins/core-plugins/multi-tenant-plugin/templates/tenant-form.template.ts
12989
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
13636
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
12990
13637
  function fieldErrors(errors, field) {
12991
13638
  const list = errors?.[field];
12992
13639
  if (!list || list.length === 0) return "";
@@ -13054,7 +13701,7 @@ function renderTenantForm(data) {
13054
13701
  </form>
13055
13702
  </div>
13056
13703
  </div>`;
13057
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst({
13704
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
13058
13705
  title: `${data.isEdit ? "Edit Tenant" : "New Tenant"} - SonicJS`,
13059
13706
  pageTitle: data.isEdit ? "Edit Tenant" : "New Tenant",
13060
13707
  currentPath: "/admin/tenants",
@@ -13065,9 +13712,9 @@ function renderTenantForm(data) {
13065
13712
  }
13066
13713
 
13067
13714
  // src/plugins/core-plugins/multi-tenant-plugin/templates/tenant-members.template.ts
13068
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
13715
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
13069
13716
  function roleOptions(selected) {
13070
- return chunkVXE42MYF_cjs.VALID_MEMBER_ROLES.map(
13717
+ return chunk7RUW244J_cjs.VALID_MEMBER_ROLES.map(
13071
13718
  (r) => `<option value="${r}" ${r === selected ? "selected" : ""}>${r}</option>`
13072
13719
  ).join("");
13073
13720
  }
@@ -13129,7 +13776,7 @@ function renderInvitations(slug, invitations) {
13129
13776
  <div>
13130
13777
  <label for="invite-role" class="mb-1 block text-xs font-medium text-zinc-500 dark:text-zinc-400">Role</label>
13131
13778
  <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">
13132
- ${chunkVXE42MYF_cjs.VALID_MEMBER_ROLES.map((r) => `<option value="${r}" ${r === "viewer" ? "selected" : ""}>${r}</option>`).join("")}
13779
+ ${chunk7RUW244J_cjs.VALID_MEMBER_ROLES.map((r) => `<option value="${r}" ${r === "viewer" ? "selected" : ""}>${r}</option>`).join("")}
13133
13780
  </select>
13134
13781
  </div>
13135
13782
  <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>
@@ -13212,7 +13859,7 @@ function renderTenantMembers(data) {
13212
13859
 
13213
13860
  ${renderInvitations(data.slug, data.invitations)}
13214
13861
  </div>`;
13215
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst({
13862
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
13216
13863
  title: `Members - ${data.tenantName} - SonicJS`,
13217
13864
  pageTitle: "Tenant Members",
13218
13865
  currentPath: "/admin/tenants",
@@ -13223,9 +13870,9 @@ function renderTenantMembers(data) {
13223
13870
  }
13224
13871
 
13225
13872
  // src/plugins/core-plugins/multi-tenant-plugin/templates/user-memberships.template.ts
13226
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
13873
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
13227
13874
  function roleOptions2(selected) {
13228
- return chunkVXE42MYF_cjs.VALID_MEMBER_ROLES.map(
13875
+ return chunk7RUW244J_cjs.VALID_MEMBER_ROLES.map(
13229
13876
  (r) => `<option value="${r}" ${r === selected ? "selected" : ""}>${r}</option>`
13230
13877
  ).join("");
13231
13878
  }
@@ -13298,7 +13945,7 @@ function renderUserMemberships(data) {
13298
13945
  </table>
13299
13946
  </div>
13300
13947
  </div>`;
13301
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst({
13948
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
13302
13949
  title: `Tenant memberships - ${data.userEmail} - SonicJS`,
13303
13950
  pageTitle: "Tenant memberships",
13304
13951
  currentPath: "/admin/users",
@@ -13309,7 +13956,7 @@ function renderUserMemberships(data) {
13309
13956
  }
13310
13957
 
13311
13958
  // src/plugins/core-plugins/multi-tenant-plugin/templates/role-usage.template.ts
13312
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
13959
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
13313
13960
  function renderRoleUsage(data) {
13314
13961
  const role = chunkMNWKYY5E_cjs.escapeHtml(data.roleName);
13315
13962
  const rows = data.assignments.length ? data.assignments.map((a) => `
@@ -13344,7 +13991,7 @@ function renderRoleUsage(data) {
13344
13991
  </table>
13345
13992
  </div>
13346
13993
  </div>`;
13347
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst({
13994
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
13348
13995
  title: `Role usage - ${data.roleName} - SonicJS`,
13349
13996
  pageTitle: "Role usage",
13350
13997
  currentPath: "/admin/tenants",
@@ -13387,7 +14034,7 @@ function zodToFieldErrors(error) {
13387
14034
  }
13388
14035
  async function isMultiTenantActive(db) {
13389
14036
  try {
13390
- const plugin2 = await new chunkQAYFOER6_cjs.PluginService(db).getPlugin(chunkQAYFOER6_cjs.MULTI_TENANT_PLUGIN_ID);
14037
+ const plugin2 = await new chunkKVBHB7QP_cjs.PluginService(db).getPlugin(chunkKVBHB7QP_cjs.MULTI_TENANT_PLUGIN_ID);
13391
14038
  return plugin2?.status === "active";
13392
14039
  } catch {
13393
14040
  return false;
@@ -13395,7 +14042,7 @@ async function isMultiTenantActive(db) {
13395
14042
  }
13396
14043
  function createTenantAdminRoutes() {
13397
14044
  const routes2 = new hono.Hono();
13398
- routes2.use("*", chunkAAWNRBRB_cjs.requireAuth());
14045
+ routes2.use("*", chunkFCLKX2OS_cjs.requireAuth());
13399
14046
  routes2.use("*", async (c, next) => {
13400
14047
  const user = c.get("user");
13401
14048
  if (user?.role !== "admin") {
@@ -13409,7 +14056,7 @@ function createTenantAdminRoutes() {
13409
14056
  const form = await c.req.formData();
13410
14057
  const slug = String(form.get("tenant") ?? "").trim().toLowerCase();
13411
14058
  const redirect = String(form.get("redirect") ?? "");
13412
- const svc = new chunkVXE42MYF_cjs.TenantService(db);
14059
+ const svc = new chunk7RUW244J_cjs.TenantService(db);
13413
14060
  const tenant = await svc.getTenantBySlug(slug);
13414
14061
  if (!tenant || tenant.status !== "active") {
13415
14062
  return c.json({ error: "Unknown or inactive tenant" }, 400);
@@ -13419,7 +14066,7 @@ function createTenantAdminRoutes() {
13419
14066
  if (!user.isSuperAdmin && !await svc.isMember(user.userId, slug)) {
13420
14067
  return c.json({ error: "You are not a member of this tenant" }, 403);
13421
14068
  }
13422
- cookie.setCookie(c, chunkQAYFOER6_cjs.TENANT_COOKIE, slug, {
14069
+ cookie.setCookie(c, chunkKVBHB7QP_cjs.TENANT_COOKIE, slug, {
13423
14070
  path: "/",
13424
14071
  httpOnly: true,
13425
14072
  sameSite: "Lax",
@@ -13436,7 +14083,7 @@ function createTenantAdminRoutes() {
13436
14083
  if (!user) return c.redirect("/auth/login");
13437
14084
  const token = c.req.query("token") ?? "";
13438
14085
  try {
13439
- const { slug } = await new chunkVXE42MYF_cjs.TenantService(db).acceptInvitation(token, user.userId, user.email);
14086
+ const { slug } = await new chunk7RUW244J_cjs.TenantService(db).acceptInvitation(token, user.userId, user.email);
13440
14087
  return c.redirect(`/admin/tenants/${slug}/members?message=Invitation accepted`);
13441
14088
  } catch (error) {
13442
14089
  const message = error instanceof Error ? error.message : "Failed to accept invitation";
@@ -13464,7 +14111,7 @@ function createTenantAdminRoutes() {
13464
14111
  const userId = c.req.param("userId");
13465
14112
  const target = await db.prepare("SELECT id, email FROM auth_user WHERE id = ?").bind(userId).first();
13466
14113
  if (!target?.id) return c.redirect("/admin/users?message=User not found&type=error");
13467
- const svc = new chunkVXE42MYF_cjs.TenantService(db);
14114
+ const svc = new chunk7RUW244J_cjs.TenantService(db);
13468
14115
  const [memberships, allTenants] = await Promise.all([svc.listUserMemberships(userId), svc.listTenants()]);
13469
14116
  const memberSlugs = new Set(memberships.map((m) => m.slug));
13470
14117
  const availableTenants = allTenants.filter((t) => t.status === "active" && !memberSlugs.has(t.slug)).map((t) => ({ slug: t.slug, name: t.name }));
@@ -13489,10 +14136,10 @@ function createTenantAdminRoutes() {
13489
14136
  const slug = String(form.get("slug") ?? "").trim().toLowerCase();
13490
14137
  const role = String(form.get("role") ?? "viewer");
13491
14138
  const redirectTo = String(form.get("_redirect") ?? "") || `/admin/tenants/users/${userId}`;
13492
- if (!chunkVXE42MYF_cjs.isValidMemberRole(role)) throw new Error(`Invalid role '${role}'`);
14139
+ if (!chunk7RUW244J_cjs.isValidMemberRole(role)) throw new Error(`Invalid role '${role}'`);
13493
14140
  const target = await db.prepare("SELECT email FROM auth_user WHERE id = ?").bind(userId).first();
13494
14141
  if (!target) throw new Error("User not found");
13495
- const svc = new chunkVXE42MYF_cjs.TenantService(db);
14142
+ const svc = new chunk7RUW244J_cjs.TenantService(db);
13496
14143
  if (!await svc.getTenantBySlug(slug)) throw new Error("Tenant not found");
13497
14144
  if (await svc.isMember(userId, slug)) throw new Error(`Already a member of '${slug}'`);
13498
14145
  await svc.addMember(slug, userId, role, target.email ?? null);
@@ -13511,7 +14158,7 @@ function createTenantAdminRoutes() {
13511
14158
  const form = await c.req.formData();
13512
14159
  const role = String(form.get("role") ?? "");
13513
14160
  const redirectTo = String(form.get("_redirect") ?? "") || `/admin/tenants/users/${userId}`;
13514
- await new chunkVXE42MYF_cjs.TenantService(db).setMemberRole(slug, userId, role);
14161
+ await new chunk7RUW244J_cjs.TenantService(db).setMemberRole(slug, userId, role);
13515
14162
  return c.redirect(`${redirectTo}?message=Role updated`);
13516
14163
  } catch (error) {
13517
14164
  const message = error instanceof Error ? error.message : "Failed to update role";
@@ -13526,7 +14173,7 @@ function createTenantAdminRoutes() {
13526
14173
  try {
13527
14174
  const form = await c.req.formData();
13528
14175
  const redirectTo = String(form.get("_redirect") ?? "") || `/admin/tenants/users/${userId}`;
13529
- await new chunkVXE42MYF_cjs.TenantService(db).removeMember(slug, userId);
14176
+ await new chunk7RUW244J_cjs.TenantService(db).removeMember(slug, userId);
13530
14177
  return c.redirect(`${redirectTo}?message=Removed from ${encodeURIComponent(slug)}`);
13531
14178
  } catch (error) {
13532
14179
  const message = error instanceof Error ? error.message : "Failed to remove membership";
@@ -13541,7 +14188,7 @@ function createTenantAdminRoutes() {
13541
14188
  return c.html(renderTenantsInactive({ user: userShape(cur), version }));
13542
14189
  }
13543
14190
  const roleName = c.req.param("roleName");
13544
- const assignments = await new chunkVXE42MYF_cjs.TenantService(db).listAssignmentsByRole(roleName);
14191
+ const assignments = await new chunk7RUW244J_cjs.TenantService(db).listAssignmentsByRole(roleName);
13545
14192
  return c.html(renderRoleUsage({ roleName, assignments, user: userShape(cur), version }));
13546
14193
  });
13547
14194
  routes2.get("/", async (c) => {
@@ -13551,7 +14198,7 @@ function createTenantAdminRoutes() {
13551
14198
  if (!await isMultiTenantActive(db)) {
13552
14199
  return c.html(renderTenantsInactive({ user: userShape(user), version }));
13553
14200
  }
13554
- const svc = new chunkVXE42MYF_cjs.TenantService(db);
14201
+ const svc = new chunk7RUW244J_cjs.TenantService(db);
13555
14202
  await svc.ensureDefaultTenant();
13556
14203
  const tenants = await svc.listTenants();
13557
14204
  const [docRes, memberRes] = await db.batch([
@@ -13590,7 +14237,7 @@ function createTenantAdminRoutes() {
13590
14237
  formEntries = Object.fromEntries(form.entries());
13591
14238
  const validated = tenantFormSchema.parse(formEntries);
13592
14239
  if (!validated.slug) throw new zod.z.ZodError([{ code: "custom", message: "Slug is required", path: ["slug"] }]);
13593
- const svc = new chunkVXE42MYF_cjs.TenantService(db);
14240
+ const svc = new chunk7RUW244J_cjs.TenantService(db);
13594
14241
  await svc.createTenant({
13595
14242
  name: validated.name,
13596
14243
  slug: validated.slug,
@@ -13615,7 +14262,7 @@ function createTenantAdminRoutes() {
13615
14262
  if (!await isMultiTenantActive(db)) {
13616
14263
  return c.html(renderTenantsInactive({ user: userShape(user), version }));
13617
14264
  }
13618
- const tenant = await new chunkVXE42MYF_cjs.TenantService(db).getTenantBySlug(c.req.param("slug"));
14265
+ const tenant = await new chunk7RUW244J_cjs.TenantService(db).getTenantBySlug(c.req.param("slug"));
13619
14266
  if (!tenant) return c.redirect("/admin/tenants?message=Tenant not found&type=error");
13620
14267
  return c.html(renderTenantForm({ tenant, isEdit: true, user: userShape(user), version }));
13621
14268
  });
@@ -13625,7 +14272,7 @@ function createTenantAdminRoutes() {
13625
14272
  const version = c.get("appVersion");
13626
14273
  const slug = c.req.param("slug");
13627
14274
  if (!await isMultiTenantActive(db)) return c.json({ error: "Multi-tenant plugin is not active" }, 403);
13628
- const svc = new chunkVXE42MYF_cjs.TenantService(db);
14275
+ const svc = new chunk7RUW244J_cjs.TenantService(db);
13629
14276
  try {
13630
14277
  const form = await c.req.formData();
13631
14278
  const validated = tenantFormSchema.parse(Object.fromEntries(form.entries()));
@@ -13650,7 +14297,7 @@ function createTenantAdminRoutes() {
13650
14297
  const slug = c.req.param("slug");
13651
14298
  if (!await isMultiTenantActive(db)) return c.json({ error: "Multi-tenant plugin is not active" }, 403);
13652
14299
  try {
13653
- await new chunkVXE42MYF_cjs.TenantService(db).deleteTenant(slug);
14300
+ await new chunk7RUW244J_cjs.TenantService(db).deleteTenant(slug);
13654
14301
  return c.redirect("/admin/tenants?message=Tenant deleted successfully");
13655
14302
  } catch (error) {
13656
14303
  const message = error instanceof Error ? error.message : "Failed to delete tenant";
@@ -13665,7 +14312,7 @@ function createTenantAdminRoutes() {
13665
14312
  return c.html(renderTenantsInactive({ user: userShape(user), version }));
13666
14313
  }
13667
14314
  const slug = c.req.param("slug");
13668
- const svc = new chunkVXE42MYF_cjs.TenantService(db);
14315
+ const svc = new chunk7RUW244J_cjs.TenantService(db);
13669
14316
  const tenant = await svc.getTenantBySlug(slug);
13670
14317
  if (!tenant) return c.redirect("/admin/tenants?message=Tenant not found&type=error");
13671
14318
  const [members, invitations] = await Promise.all([svc.listMembers(slug), svc.listInvitations(slug)]);
@@ -13691,7 +14338,7 @@ function createTenantAdminRoutes() {
13691
14338
  const form = await c.req.formData();
13692
14339
  const email = String(form.get("email") ?? "");
13693
14340
  const role = String(form.get("role") ?? "viewer");
13694
- await new chunkVXE42MYF_cjs.TenantService(db).addMemberByEmail(slug, email, role);
14341
+ await new chunk7RUW244J_cjs.TenantService(db).addMemberByEmail(slug, email, role);
13695
14342
  return c.redirect(`/admin/tenants/${slug}/members?message=Member added`);
13696
14343
  } catch (error) {
13697
14344
  const message = error instanceof Error ? error.message : "Failed to add member";
@@ -13706,7 +14353,7 @@ function createTenantAdminRoutes() {
13706
14353
  try {
13707
14354
  const form = await c.req.formData();
13708
14355
  const role = String(form.get("role") ?? "");
13709
- await new chunkVXE42MYF_cjs.TenantService(db).setMemberRole(slug, userId, role);
14356
+ await new chunk7RUW244J_cjs.TenantService(db).setMemberRole(slug, userId, role);
13710
14357
  return c.redirect(`/admin/tenants/${slug}/members?message=Role updated`);
13711
14358
  } catch (error) {
13712
14359
  const message = error instanceof Error ? error.message : "Failed to update role";
@@ -13719,7 +14366,7 @@ function createTenantAdminRoutes() {
13719
14366
  const userId = c.req.param("userId");
13720
14367
  if (!await isMultiTenantActive(db)) return c.json({ error: "Multi-tenant plugin is not active" }, 403);
13721
14368
  try {
13722
- await new chunkVXE42MYF_cjs.TenantService(db).removeMember(slug, userId);
14369
+ await new chunk7RUW244J_cjs.TenantService(db).removeMember(slug, userId);
13723
14370
  return c.redirect(`/admin/tenants/${slug}/members?message=Member removed`);
13724
14371
  } catch (error) {
13725
14372
  const message = error instanceof Error ? error.message : "Failed to remove member";
@@ -13735,12 +14382,12 @@ function createTenantAdminRoutes() {
13735
14382
  const form = await c.req.formData();
13736
14383
  const email = String(form.get("email") ?? "");
13737
14384
  const role = String(form.get("role") ?? "viewer");
13738
- const token = await new chunkVXE42MYF_cjs.TenantService(db).createInvitation(slug, email, role, user?.userId ?? null);
14385
+ const token = await new chunk7RUW244J_cjs.TenantService(db).createInvitation(slug, email, role, user?.userId ?? null);
13739
14386
  const origin = c.req.header("origin") || new URL(c.req.url).origin;
13740
14387
  const acceptUrl = `${origin}/join/invite?token=${encodeURIComponent(token)}`;
13741
14388
  let note;
13742
14389
  let noteType = "";
13743
- const svc2 = chunkVXE42MYF_cjs.hasEmailService() ? chunkVXE42MYF_cjs.getEmailService() : null;
14390
+ const svc2 = chunk7RUW244J_cjs.hasEmailService() ? chunk7RUW244J_cjs.getEmailService() : null;
13744
14391
  const hasRealProvider = !!svc2 && svc2.getProviderName() !== "console";
13745
14392
  if (hasRealProvider) {
13746
14393
  const result = await svc2.send({
@@ -13781,7 +14428,7 @@ function createTenantAdminRoutes() {
13781
14428
  WHERE i.id = ? AND t.slug = ? AND i.status = 'pending'`
13782
14429
  ).bind(id, slug).first();
13783
14430
  if (!inv) throw new Error("Invitation not found or already used");
13784
- const svc2 = chunkVXE42MYF_cjs.hasEmailService() ? chunkVXE42MYF_cjs.getEmailService() : null;
14431
+ const svc2 = chunk7RUW244J_cjs.hasEmailService() ? chunk7RUW244J_cjs.getEmailService() : null;
13785
14432
  const hasRealProvider = !!svc2 && svc2.getProviderName() !== "console";
13786
14433
  if (!hasRealProvider) throw new Error("No email plugin active");
13787
14434
  const origin = c.req.header("origin") || new URL(c.req.url).origin;
@@ -13806,7 +14453,7 @@ function createTenantAdminRoutes() {
13806
14453
  const id = c.req.param("id");
13807
14454
  if (!await isMultiTenantActive(db)) return c.json({ error: "Multi-tenant plugin is not active" }, 403);
13808
14455
  try {
13809
- await new chunkVXE42MYF_cjs.TenantService(db).revokeInvitation(slug, id);
14456
+ await new chunk7RUW244J_cjs.TenantService(db).revokeInvitation(slug, id);
13810
14457
  return c.redirect(`/admin/tenants/${slug}/members?message=Invitation revoked`);
13811
14458
  } catch (error) {
13812
14459
  const message = error instanceof Error ? error.message : "Failed to revoke invitation";
@@ -14036,7 +14683,7 @@ function createJoinRoutes() {
14036
14683
  if (existing) return rerender("An account with this email already exists. Please sign in instead.");
14037
14684
  try {
14038
14685
  const userId = crypto.randomUUID();
14039
- const passwordHash = await chunkAAWNRBRB_cjs.AuthManager.hashPassword(password);
14686
+ const passwordHash = await chunkFCLKX2OS_cjs.AuthManager.hashPassword(password);
14040
14687
  const now = Date.now();
14041
14688
  const nowSec = Math.floor(now / 1e3);
14042
14689
  await db.batch([
@@ -14049,8 +14696,8 @@ function createJoinRoutes() {
14049
14696
  VALUES (?, ?, ?, 'credential', ?, ?, ?)`
14050
14697
  ).bind(`cred-${userId}`, userId, userId, passwordHash, nowSec, nowSec)
14051
14698
  ]);
14052
- await new chunkVXE42MYF_cjs.TenantService(db).acceptInvitation(token, userId, inv.email);
14053
- const auth = chunkNUKJ54GA_cjs.createAuth(c.env);
14699
+ await new chunk7RUW244J_cjs.TenantService(db).acceptInvitation(token, userId, inv.email);
14700
+ const auth = chunkGMMCCIQO_cjs.createAuth(c.env);
14054
14701
  const origin = new URL(c.req.url).origin;
14055
14702
  const baReq = new Request(`${origin}/auth/sign-in/email`, {
14056
14703
  method: "POST",
@@ -14105,7 +14752,7 @@ function createJoinRoutes() {
14105
14752
  version
14106
14753
  }), 400);
14107
14754
  try {
14108
- const auth = chunkNUKJ54GA_cjs.createAuth(c.env);
14755
+ const auth = chunkGMMCCIQO_cjs.createAuth(c.env);
14109
14756
  const origin = new URL(c.req.url).origin;
14110
14757
  const baReq = new Request(`${origin}/auth/sign-in/email`, {
14111
14758
  method: "POST",
@@ -14117,7 +14764,7 @@ function createJoinRoutes() {
14117
14764
  const baBody = await baRes.json();
14118
14765
  const userId = baBody?.user?.id;
14119
14766
  if (!userId) return rerender("Sign-in succeeded but could not read user ID.");
14120
- await new chunkVXE42MYF_cjs.TenantService(db).acceptInvitation(token, userId, inv.email);
14767
+ await new chunk7RUW244J_cjs.TenantService(db).acceptInvitation(token, userId, inv.email);
14121
14768
  const headers = new Headers({ Location: "/admin?message=Welcome! You have joined " + encodeURIComponent(inv.tenantName) });
14122
14769
  copyBaCookies(baRes, headers);
14123
14770
  return new Response(null, { status: 302, headers });
@@ -14131,7 +14778,7 @@ function createJoinRoutes() {
14131
14778
 
14132
14779
  // src/plugins/core-plugins/multi-tenant-plugin/index.ts
14133
14780
  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>`;
14134
- var multiTenantPlugin = chunkXW56B23A_cjs.definePlugin({
14781
+ var multiTenantPlugin = chunkA4KUJ3LD_cjs.definePlugin({
14135
14782
  id: manifest_default2.id,
14136
14783
  version: "1.0.0",
14137
14784
  name: manifest_default2.name,
@@ -14146,30 +14793,30 @@ var multiTenantPlugin = chunkXW56B23A_cjs.definePlugin({
14146
14793
  { label: "Tenants", path: "/admin/tenants", icon: TENANT_ICON, order: 80 }
14147
14794
  ],
14148
14795
  activate: async () => {
14149
- chunkQAYFOER6_cjs.invalidateTenantCache();
14796
+ chunkKVBHB7QP_cjs.invalidateTenantCache();
14150
14797
  console.info("\u2705 Multi-Tenant plugin activated");
14151
14798
  },
14152
14799
  deactivate: async () => {
14153
- chunkQAYFOER6_cjs.invalidateTenantCache();
14800
+ chunkKVBHB7QP_cjs.invalidateTenantCache();
14154
14801
  console.info("\u274C Multi-Tenant plugin deactivated");
14155
14802
  }
14156
14803
  });
14157
14804
  var routes = new hono.Hono();
14158
- routes.use("*", chunkAAWNRBRB_cjs.requireAuth());
14159
- routes.use("*", chunkAAWNRBRB_cjs.requireRole(["admin", "editor"]));
14805
+ routes.use("*", chunkFCLKX2OS_cjs.requireAuth());
14806
+ routes.use("*", chunkFCLKX2OS_cjs.requireRole(["admin", "editor"]));
14160
14807
  routes.get("/:rootId", async (c) => {
14161
14808
  const { rootId } = c.req.param();
14162
14809
  const db = c.env.DB;
14163
- const scope = await chunkVXE42MYF_cjs.resolveDocScope(c, db, { rootId });
14810
+ const scope = await chunk7RUW244J_cjs.resolveDocScope(c, db, { rootId });
14164
14811
  if (!scope) {
14165
14812
  return c.html('<p class="text-zinc-500 dark:text-zinc-400 p-4">Document not found.</p>', 404);
14166
14813
  }
14167
14814
  if (!scope.docType?.settings?.versioning) {
14168
14815
  return c.html('<p class="text-zinc-500 dark:text-zinc-400 p-4">Versioning not enabled for this type.</p>', 404);
14169
14816
  }
14170
- const denied = await chunkVXE42MYF_cjs.denyIfNotAllowed(c, db, rootId, "read", scope.docType?.settings, scope.tenantId);
14817
+ const denied = await chunk7RUW244J_cjs.denyIfNotAllowed(c, db, rootId, "read", scope.docType?.settings, scope.tenantId);
14171
14818
  if (denied) return denied;
14172
- const repo = new chunkVXE42MYF_cjs.DocumentRepository(db, scope.tenantId);
14819
+ const repo = new chunk7RUW244J_cjs.DocumentRepository(db, scope.tenantId);
14173
14820
  const versions = await repo.getVersionHistory(rootId);
14174
14821
  const safeRootIdAttr = chunkMNWKYY5E_cjs.escapeHtml(rootId);
14175
14822
  const rows = versions.map((v) => {
@@ -14262,14 +14909,14 @@ routes.post("/:rootId/restore/:versionNumber", async (c) => {
14262
14909
  const { rootId, versionNumber } = c.req.param();
14263
14910
  const db = c.env.DB;
14264
14911
  const user = c.get("user");
14265
- const scope = await chunkVXE42MYF_cjs.resolveDocScope(c, db, { rootId });
14912
+ const scope = await chunk7RUW244J_cjs.resolveDocScope(c, db, { rootId });
14266
14913
  if (!scope) {
14267
14914
  return c.json({ error: "Document not found" }, 404);
14268
14915
  }
14269
14916
  if (!scope.docType?.settings?.versioning) {
14270
14917
  return c.json({ error: "Versioning not enabled for this type" }, 404);
14271
14918
  }
14272
- const denied = await chunkVXE42MYF_cjs.denyIfNotAllowed(c, db, rootId, "update", scope.docType?.settings, scope.tenantId);
14919
+ const denied = await chunk7RUW244J_cjs.denyIfNotAllowed(c, db, rootId, "update", scope.docType?.settings, scope.tenantId);
14273
14920
  if (denied) return denied;
14274
14921
  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();
14275
14922
  if (!row) {
@@ -14279,7 +14926,7 @@ routes.post("/:rootId/restore/:versionNumber", async (c) => {
14279
14926
  const title = row.title ?? null;
14280
14927
  const slug = row.slug ?? null;
14281
14928
  const docType = scope.docType;
14282
- const svc = new chunk2CB4KY7I_cjs.DocumentsService(db, {
14929
+ const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
14283
14930
  queryableFields: docType?.queryableFields ?? [],
14284
14931
  typeSchemaVersion: docType?.schemaVersion ?? 1,
14285
14932
  maxVersionsPerRoot: docType?.settings?.maxVersionsPerRoot ?? 50,
@@ -14292,7 +14939,7 @@ routes.post("/:rootId/restore/:versionNumber", async (c) => {
14292
14939
  var routes_default = routes;
14293
14940
 
14294
14941
  // src/plugins/core-plugins/versioning-plugin/index.ts
14295
- var versioningPlugin = chunkXW56B23A_cjs.definePlugin({
14942
+ var versioningPlugin = chunkA4KUJ3LD_cjs.definePlugin({
14296
14943
  id: "versioning",
14297
14944
  version: "1.0.0",
14298
14945
  name: "Versioning",
@@ -14369,8 +15016,8 @@ function createMagicLinkAuthPlugin() {
14369
15016
  const baseUrl = new URL(c.req.url).origin;
14370
15017
  const magicLink = `${baseUrl}/auth/magic-link/verify?token=${token}`;
14371
15018
  try {
14372
- if (chunkVXE42MYF_cjs.hasEmailService()) {
14373
- await chunkVXE42MYF_cjs.getEmailService().send({
15019
+ if (chunk7RUW244J_cjs.hasEmailService()) {
15020
+ await chunk7RUW244J_cjs.getEmailService().send({
14374
15021
  to: normalizedEmail,
14375
15022
  subject: "Your Magic Link to Sign In",
14376
15023
  flow: "magic-link",
@@ -14447,19 +15094,19 @@ function createMagicLinkAuthPlugin() {
14447
15094
  SET used = 1, used_at = ?
14448
15095
  WHERE id = ?
14449
15096
  `).bind(Date.now(), magicLink.id).run();
14450
- const tokenTtl = await chunkAAWNRBRB_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
14451
- const jwtToken = await chunkAAWNRBRB_cjs.AuthManager.generateToken(
15097
+ const tokenTtl = await chunkFCLKX2OS_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
15098
+ const jwtToken = await chunkFCLKX2OS_cjs.AuthManager.generateToken(
14452
15099
  user.id,
14453
15100
  user.email,
14454
15101
  user.role,
14455
15102
  c.env.JWT_SECRET,
14456
15103
  tokenTtl
14457
15104
  );
14458
- chunkAAWNRBRB_cjs.AuthManager.setAuthCookie(c, jwtToken, { maxAge: tokenTtl });
15105
+ chunkFCLKX2OS_cjs.AuthManager.setAuthCookie(c, jwtToken, { maxAge: tokenTtl });
14459
15106
  await db.prepare(`
14460
15107
  UPDATE auth_user SET last_login_at = ? WHERE id = ?
14461
15108
  `).bind(Date.now(), user.id).run();
14462
- chunkVXE42MYF_cjs.dispatchHookEvent(
15109
+ chunk7RUW244J_cjs.dispatchHookEvent(
14463
15110
  c,
14464
15111
  "auth:magic-link:consumed",
14465
15112
  { user: { id: user.id, email: user.email, role: user.role } },
@@ -14944,7 +15591,7 @@ async function warmCollections(db) {
14944
15591
  const collectionCache = chunkYA3TJ65D_cjs.getCacheService(config);
14945
15592
  let count = 0;
14946
15593
  try {
14947
- const results = chunkQAYFOER6_cjs.getCollectionRegistry().listActive().map(chunkQAYFOER6_cjs.collectionRecordToRow);
15594
+ const results = chunkKVBHB7QP_cjs.getCollectionRegistry().listActive().map(chunkKVBHB7QP_cjs.collectionRecordToRow);
14948
15595
  for (const collection of results) {
14949
15596
  const key = collectionCache.generateKey("item", collection.id);
14950
15597
  await collectionCache.set(key, collection);
@@ -15011,7 +15658,7 @@ async function warmNamespace(namespace, entries) {
15011
15658
  }
15012
15659
 
15013
15660
  // src/templates/pages/admin-cache.template.ts
15014
- chunkNAVPFIG5_cjs.init_admin_layout_catalyst_template();
15661
+ chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
15015
15662
  function renderCacheDashboard(data) {
15016
15663
  const pageContent = `
15017
15664
  <div class="space-y-6">
@@ -15215,7 +15862,7 @@ function renderCacheDashboard(data) {
15215
15862
  </script>
15216
15863
 
15217
15864
  <!-- Confirmation Dialogs -->
15218
- ${chunkVXE42MYF_cjs.renderConfirmationDialog({
15865
+ ${chunk7RUW244J_cjs.renderConfirmationDialog({
15219
15866
  id: "clear-all-cache-confirm",
15220
15867
  title: "Clear All Cache",
15221
15868
  message: "Are you sure you want to clear all cache entries? This cannot be undone.",
@@ -15226,7 +15873,7 @@ function renderCacheDashboard(data) {
15226
15873
  onConfirm: "performClearAllCaches()"
15227
15874
  })}
15228
15875
 
15229
- ${chunkVXE42MYF_cjs.renderConfirmationDialog({
15876
+ ${chunk7RUW244J_cjs.renderConfirmationDialog({
15230
15877
  id: "clear-namespace-cache-confirm",
15231
15878
  title: "Clear Namespace Cache",
15232
15879
  message: "Clear cache for this namespace?",
@@ -15237,7 +15884,7 @@ function renderCacheDashboard(data) {
15237
15884
  onConfirm: "performClearNamespaceCache()"
15238
15885
  })}
15239
15886
 
15240
- ${chunkVXE42MYF_cjs.getConfirmationDialogScript()}
15887
+ ${chunk7RUW244J_cjs.getConfirmationDialogScript()}
15241
15888
  `;
15242
15889
  const layoutData = {
15243
15890
  title: "Cache System",
@@ -15247,7 +15894,7 @@ function renderCacheDashboard(data) {
15247
15894
  version: data.version,
15248
15895
  content: pageContent
15249
15896
  };
15250
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst(layoutData);
15897
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst(layoutData);
15251
15898
  }
15252
15899
  function renderCollectionSettingsTab(collections) {
15253
15900
  if (collections.length === 0) {
@@ -15503,7 +16150,7 @@ app.get("/", async (c) => {
15503
16150
  const totalRequests = totalHits + totalMisses;
15504
16151
  const overallHitRate = totalRequests > 0 ? totalHits / totalRequests * 100 : 0;
15505
16152
  const DEFAULT_TTL = chunkYA3TJ65D_cjs.CACHE_CONFIGS.api?.ttl ?? 300;
15506
- const collections = chunkQAYFOER6_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => {
16153
+ const collections = chunkKVBHB7QP_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => {
15507
16154
  const cacheOverride = r.cache;
15508
16155
  const cacheEnabled = cacheOverride?.enabled !== false;
15509
16156
  const hasCustomTtl = typeof cacheOverride?.ttl === "number";
@@ -16040,16 +16687,17 @@ var faviconSvg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
16040
16687
  // src/app.ts
16041
16688
  function createSonicJSApp(config = {}) {
16042
16689
  const app2 = new hono.Hono();
16043
- const appVersion = config.version || chunkLRZIAW7U_cjs.getCoreVersion();
16690
+ const appVersion = config.version || chunkAOUVUF32_cjs.getCoreVersion();
16044
16691
  const appName = config.name || "SonicJS AI";
16045
- const hookSystem = new chunkH2AXVCLS_cjs.HookSystemImpl();
16692
+ const hookSystem = new chunk5UXU3LP4_cjs.HookSystemImpl();
16046
16693
  chunkJ6JTWD2A_cjs.setHookSystem(hookSystem);
16047
16694
  const magicLinkPlugin = createMagicLinkAuthPlugin();
16048
16695
  const corePluginsBeforeCatchAll = [
16049
16696
  securityAuditPlugin,
16697
+ apiKeysPlugin,
16050
16698
  aiSearchPlugin,
16051
16699
  oauthProvidersPlugin,
16052
- chunkVXE42MYF_cjs.userProfilesPlugin,
16700
+ chunk7RUW244J_cjs.userProfilesPlugin,
16053
16701
  otpLoginPlugin,
16054
16702
  analyticsPlugin,
16055
16703
  stripePlugin,
@@ -16059,23 +16707,23 @@ function createSonicJSApp(config = {}) {
16059
16707
  shortcodesPlugin,
16060
16708
  helloWorldPlugin,
16061
16709
  multiTenantPlugin,
16062
- chunkVXE42MYF_cjs.lexicalEditorPlugin,
16710
+ chunk7RUW244J_cjs.lexicalEditorPlugin,
16063
16711
  versioningPlugin
16064
16712
  ];
16065
16713
  const corePluginsAfterCatchAll = [emailPluginV3, magicLinkPlugin, emailReconciliationPlugin];
16066
- const wirePlugins = chunkH2AXVCLS_cjs.createPluginWirer(
16714
+ const wirePlugins = chunk5UXU3LP4_cjs.createPluginWirer(
16067
16715
  () => [...corePluginsBeforeCatchAll, ...corePluginsAfterCatchAll, ...config.plugins?.register ?? []],
16068
16716
  // The capability-gated `ctx.cap.email` resolves to the app EmailService, which
16069
16717
  // is initialized (below) just before wiring on the first request.
16070
16718
  () => ({
16071
16719
  hooks: hookSystem,
16072
16720
  env: firstRequestEnv,
16073
- providers: { email: () => chunkVXE42MYF_cjs.getEmailService() }
16721
+ providers: { email: () => chunk7RUW244J_cjs.getEmailService() }
16074
16722
  })
16075
16723
  );
16076
16724
  let firstRequestEnv;
16077
16725
  const initEmailService = async (env = {}) => {
16078
- if (chunkVXE42MYF_cjs.hasEmailService()) return;
16726
+ if (chunk7RUW244J_cjs.hasEmailService()) return;
16079
16727
  let provider;
16080
16728
  let defaultFrom = config.email?.from;
16081
16729
  let defaultReplyTo;
@@ -16110,14 +16758,14 @@ function createSonicJSApp(config = {}) {
16110
16758
  }
16111
16759
  }
16112
16760
  defaultFrom = defaultFrom || env.DEFAULT_FROM_EMAIL || "noreply@sonicjs.local";
16113
- chunkVXE42MYF_cjs.setEmailService(new EmailService({ provider, defaultFrom, defaultReplyTo, db: env.DB }));
16761
+ chunk7RUW244J_cjs.setEmailService(new EmailService({ provider, defaultFrom, defaultReplyTo, db: env.DB }));
16114
16762
  };
16115
16763
  app2.use("*", async (c, next) => {
16116
16764
  c.set("appVersion", appVersion);
16117
16765
  await next();
16118
16766
  });
16119
- app2.use("*", chunkAAWNRBRB_cjs.metricsMiddleware());
16120
- app2.use("*", chunkAAWNRBRB_cjs.bootstrapMiddleware(config));
16767
+ app2.use("*", chunkFCLKX2OS_cjs.metricsMiddleware());
16768
+ app2.use("*", chunkFCLKX2OS_cjs.bootstrapMiddleware(config));
16121
16769
  const boot = async (env) => {
16122
16770
  if (config.plugins?.disableAll) return;
16123
16771
  firstRequestEnv = env;
@@ -16144,13 +16792,24 @@ function createSonicJSApp(config = {}) {
16144
16792
  app2.use("*", async (_c, next) => {
16145
16793
  await next();
16146
16794
  });
16147
- app2.use("*", chunkAAWNRBRB_cjs.securityHeadersMiddleware());
16148
- app2.use("*", chunkAAWNRBRB_cjs.csrfProtection());
16795
+ app2.use("*", cors.cors({
16796
+ origin: (origin, c) => {
16797
+ const allowed = c.env?.CORS_ORIGINS;
16798
+ if (!allowed) return null;
16799
+ const list = allowed.split(",").map((s) => s.trim());
16800
+ return list.includes(origin) ? origin : null;
16801
+ },
16802
+ allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
16803
+ allowHeaders: ["Content-Type", "Authorization", "X-API-Key"],
16804
+ credentials: true
16805
+ }));
16806
+ app2.use("*", chunkFCLKX2OS_cjs.securityHeadersMiddleware());
16807
+ app2.use("*", chunkFCLKX2OS_cjs.csrfProtection());
16149
16808
  app2.use("*", async (c, next) => {
16150
16809
  try {
16151
16810
  const reqUrl = new URL(c.req.url);
16152
16811
  const requestBaseURL = `${reqUrl.protocol}//${reqUrl.host}`;
16153
- const auth = chunkNUKJ54GA_cjs.createAuth(c.env, config.auth?.extendBetterAuth, requestBaseURL);
16812
+ const auth = chunkGMMCCIQO_cjs.createAuth(c.env, config.auth?.extendBetterAuth, requestBaseURL);
16154
16813
  const session = await auth.api.getSession({ headers: c.req.raw.headers });
16155
16814
  if (session?.user) {
16156
16815
  const u = session.user;
@@ -16177,14 +16836,15 @@ function createSonicJSApp(config = {}) {
16177
16836
  }
16178
16837
  await next();
16179
16838
  });
16839
+ app2.use("*", apiKeyAuthMiddleware());
16180
16840
  if (config.middleware?.afterAuth) {
16181
16841
  for (const middleware of config.middleware.afterAuth) {
16182
16842
  app2.use("*", middleware);
16183
16843
  }
16184
16844
  }
16185
- app2.use("*", chunkQAYFOER6_cjs.tenantMiddleware());
16186
- app2.use("/admin/*", chunkAAWNRBRB_cjs.requireAuth());
16187
- app2.use("/admin/*", chunkAAWNRBRB_cjs.requireRbac("portal", "access"));
16845
+ app2.use("*", chunkKVBHB7QP_cjs.tenantMiddleware());
16846
+ app2.use("/admin/*", chunkFCLKX2OS_cjs.requireAuth());
16847
+ app2.use("/admin/*", chunkFCLKX2OS_cjs.requireRbac("portal", "access"));
16188
16848
  app2.use("/admin/*", pluginMenuMiddleware());
16189
16849
  const NAV_LANDING = [
16190
16850
  { path: "/admin/content", perm: "content:read" },
@@ -16201,7 +16861,7 @@ function createSonicJSApp(config = {}) {
16201
16861
  if (!user?.userId) return next();
16202
16862
  let perms = [];
16203
16863
  try {
16204
- const { RbacService: RbacService2 } = await import('./rbac-VONLJJKB.cjs');
16864
+ const { RbacService: RbacService2 } = await import('./rbac-7QZ4JZ2E.cjs');
16205
16865
  perms = await new RbacService2(c.env.DB, c.env.CACHE_KV).permissionsForUser(user.userId);
16206
16866
  } catch {
16207
16867
  return next();
@@ -16230,43 +16890,43 @@ function createSonicJSApp(config = {}) {
16230
16890
  });
16231
16891
  app2.route("/api/security-audit", apiRoutes2);
16232
16892
  app2.route("/admin/plugins/security-audit", adminRoutes3);
16233
- app2.route("/api/media", chunkVXE42MYF_cjs.api_media_default);
16234
- app2.route("/api/system", chunkVXE42MYF_cjs.api_system_default);
16235
- app2.route("/api/documents", chunkVXE42MYF_cjs.apiDocumentsRoutes);
16236
- app2.route("/api", chunkVXE42MYF_cjs.api_default);
16237
- app2.route("/admin/documents", chunkVXE42MYF_cjs.adminDocumentsRoutes);
16238
- chunkH2AXVCLS_cjs.registerPluginRoutes(app2, [formsPlugin], { source: "core" });
16239
- app2.route("/admin/api", chunkVXE42MYF_cjs.admin_api_default);
16240
- app2.route("/admin/collections", chunkVXE42MYF_cjs.adminCollectionsRoutes);
16241
- app2.route("/admin/settings", chunkVXE42MYF_cjs.adminSettingsRoutes);
16242
- app2.route("/admin/api-reference", chunkVXE42MYF_cjs.router2);
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);
16243
16903
  app2.route("/admin/database-tools", createDatabaseToolsAdminRoutes());
16244
- app2.route("/admin/content", chunkVXE42MYF_cjs.admin_content_default);
16245
- app2.route("/admin/media", chunkVXE42MYF_cjs.adminMediaRoutes);
16904
+ app2.route("/admin/content", chunk7RUW244J_cjs.admin_content_default);
16905
+ app2.route("/admin/media", chunk7RUW244J_cjs.adminMediaRoutes);
16246
16906
  app2.use("/auth/*", securityAuditMiddleware());
16247
16907
  if (!config.plugins?.disableAll) {
16248
- chunkH2AXVCLS_cjs.registerPluginRoutes(app2, corePluginsBeforeCatchAll, { source: "core" });
16908
+ chunk5UXU3LP4_cjs.registerPluginRoutes(app2, corePluginsBeforeCatchAll, { source: "core" });
16249
16909
  app2.route("/admin/cache", cache_default.getRoutes());
16250
16910
  if (config.plugins?.register && config.plugins.register.length > 0) {
16251
- chunkH2AXVCLS_cjs.registerPluginRoutes(app2, config.plugins.register, { source: "user" });
16911
+ chunk5UXU3LP4_cjs.registerPluginRoutes(app2, config.plugins.register, { source: "user" });
16252
16912
  }
16253
16913
  }
16254
16914
  app2.route("/api/events", apiRoutes4);
16255
- app2.route("/admin/dashboard", chunkVXE42MYF_cjs.router);
16256
- app2.route("/admin/plugins", chunkVXE42MYF_cjs.adminPluginRoutes);
16257
- app2.route("/admin/logs", chunkVXE42MYF_cjs.adminLogsRoutes);
16915
+ app2.route("/admin/dashboard", chunk7RUW244J_cjs.router);
16916
+ app2.route("/admin/plugins", chunk7RUW244J_cjs.adminPluginRoutes);
16917
+ app2.route("/admin/logs", chunk7RUW244J_cjs.adminLogsRoutes);
16258
16918
  app2.route("/admin/rbac", adminRbacRoutes);
16259
- app2.route("/admin", chunkVXE42MYF_cjs.userRoutes);
16260
- app2.route("/auth", chunkVXE42MYF_cjs.auth_default);
16919
+ app2.route("/admin", chunk7RUW244J_cjs.userRoutes);
16920
+ app2.route("/auth", chunk7RUW244J_cjs.auth_default);
16261
16921
  app2.on(["GET", "POST"], "/auth/*", (c) => {
16262
16922
  const reqUrl = new URL(c.req.url);
16263
16923
  const requestBaseURL = `${reqUrl.protocol}//${reqUrl.host}`;
16264
- const auth = chunkNUKJ54GA_cjs.createAuth(c.env, config.auth?.extendBetterAuth, requestBaseURL);
16924
+ const auth = chunkGMMCCIQO_cjs.createAuth(c.env, config.auth?.extendBetterAuth, requestBaseURL);
16265
16925
  return auth.handler(c.req.raw);
16266
16926
  });
16267
- app2.route("/", chunkVXE42MYF_cjs.test_cleanup_default);
16927
+ app2.route("/", chunk7RUW244J_cjs.test_cleanup_default);
16268
16928
  if (!config.plugins?.disableAll) {
16269
- chunkH2AXVCLS_cjs.registerPluginRoutes(app2, corePluginsAfterCatchAll, { source: "core" });
16929
+ chunk5UXU3LP4_cjs.registerPluginRoutes(app2, corePluginsAfterCatchAll, { source: "core" });
16270
16930
  }
16271
16931
  if (!config.plugins?.disableAll) {
16272
16932
  const allMountedPlugins = [
@@ -16275,8 +16935,11 @@ function createSonicJSApp(config = {}) {
16275
16935
  ...corePluginsAfterCatchAll,
16276
16936
  ...config.plugins?.register ?? []
16277
16937
  ];
16278
- chunkH2AXVCLS_cjs.setPluginMenu(allMountedPlugins.flatMap((p) => p.menu ?? []));
16279
- chunkXW56B23A_cjs.setPluginDefinitions(allMountedPlugins);
16938
+ const userPlugins = (config.plugins?.register ?? []).filter(
16939
+ (p) => !chunkKVBHB7QP_cjs.PLUGIN_REGISTRY[p.id]
16940
+ );
16941
+ chunk5UXU3LP4_cjs.setPluginMenu(userPlugins.flatMap((p) => p.menu ?? []));
16942
+ chunkA4KUJ3LD_cjs.setPluginDefinitions(allMountedPlugins);
16280
16943
  }
16281
16944
  app2.get("/favicon.svg", (c) => {
16282
16945
  return new Response(faviconSvg, {
@@ -16329,7 +16992,7 @@ function createSonicJSApp(config = {}) {
16329
16992
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
16330
16993
  });
16331
16994
  });
16332
- chunkBDDABDAB_cjs.setAppInstance(app2);
16995
+ chunk36Z3AKX3_cjs.setAppInstance(app2);
16333
16996
  app2.notFound((c) => {
16334
16997
  return c.json({ error: "Not Found", status: 404 }, 404);
16335
16998
  });
@@ -17140,9 +17803,11 @@ var RedirectService = class {
17140
17803
  this.cloudflareService = new CloudflareBulkService(env);
17141
17804
  }
17142
17805
  }
17806
+ db;
17807
+ env;
17143
17808
  cloudflareService = null;
17144
17809
  getDocService() {
17145
- return new chunk2CB4KY7I_cjs.DocumentsService(this.db, {
17810
+ return new chunkLTZ5WYOK_cjs.DocumentsService(this.db, {
17146
17811
  queryableFields: REDIRECT_QUERYABLE_FIELDS,
17147
17812
  maxVersionsPerRoot: 1,
17148
17813
  tenantId: TENANT3
@@ -17258,7 +17923,7 @@ var RedirectService = class {
17258
17923
  async batchCreate(rows, userId) {
17259
17924
  const now = Math.floor(Date.now() / 1e3);
17260
17925
  const statements = rows.map((r) => {
17261
- const id = chunkJEQ7FLOD_cjs.nanoid();
17926
+ const id = chunkKIGVVO6N_cjs.nanoid();
17262
17927
  const data = JSON.stringify({
17263
17928
  source: r.source,
17264
17929
  destination: r.destination,
@@ -18445,7 +19110,7 @@ function renderLayout(title, content2) {
18445
19110
  }
18446
19111
  </style>
18447
19112
  `;
18448
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst({
19113
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
18449
19114
  title,
18450
19115
  currentPath: "/admin/redirects",
18451
19116
  content: customStyles + content2.toString()
@@ -18810,7 +19475,7 @@ function getFormScripts() {
18810
19475
  `;
18811
19476
  }
18812
19477
  function renderLayout2(title, content2) {
18813
- return chunkNAVPFIG5_cjs.renderAdminLayoutCatalyst({
19478
+ return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst({
18814
19479
  title,
18815
19480
  currentPath: "/admin/redirects",
18816
19481
  content: content2.toString()
@@ -19768,7 +20433,7 @@ function createRedirectApiRoutes() {
19768
20433
  });
19769
20434
  return api;
19770
20435
  }
19771
- var redirectPlugin = chunkXW56B23A_cjs.definePlugin({
20436
+ var redirectPlugin = chunkA4KUJ3LD_cjs.definePlugin({
19772
20437
  id: manifest_default3.id,
19773
20438
  version: manifest_default3.version,
19774
20439
  name: manifest_default3.name,
@@ -19786,7 +20451,7 @@ var redirectPlugin = chunkXW56B23A_cjs.definePlugin({
19786
20451
  async onBoot(ctx) {
19787
20452
  const db = ctx.env?.DB;
19788
20453
  if (!db) return;
19789
- const registry = new chunkAAWNRBRB_cjs.DocumentTypeRegistry(db);
20454
+ const registry = new chunkFCLKX2OS_cjs.DocumentTypeRegistry(db);
19790
20455
  await registry.register({
19791
20456
  id: "redirect",
19792
20457
  name: "redirect",
@@ -19902,99 +20567,103 @@ function createDb(d1$1) {
19902
20567
  }
19903
20568
 
19904
20569
  // src/index.ts
19905
- var VERSION = chunkLRZIAW7U_cjs.package_default.version;
20570
+ var VERSION = chunkAOUVUF32_cjs.package_default.version;
19906
20571
 
20572
+ Object.defineProperty(exports, "DocumentRepository", {
20573
+ enumerable: true,
20574
+ get: function () { return chunk7RUW244J_cjs.DocumentRepository; }
20575
+ });
19907
20576
  Object.defineProperty(exports, "ROUTES_INFO", {
19908
20577
  enumerable: true,
19909
- get: function () { return chunkVXE42MYF_cjs.ROUTES_INFO; }
20578
+ get: function () { return chunk7RUW244J_cjs.ROUTES_INFO; }
19910
20579
  });
19911
20580
  Object.defineProperty(exports, "adminApiRoutes", {
19912
20581
  enumerable: true,
19913
- get: function () { return chunkVXE42MYF_cjs.admin_api_default; }
20582
+ get: function () { return chunk7RUW244J_cjs.admin_api_default; }
19914
20583
  });
19915
20584
  Object.defineProperty(exports, "adminCheckboxRoutes", {
19916
20585
  enumerable: true,
19917
- get: function () { return chunkVXE42MYF_cjs.adminCheckboxRoutes; }
20586
+ get: function () { return chunk7RUW244J_cjs.adminCheckboxRoutes; }
19918
20587
  });
19919
20588
  Object.defineProperty(exports, "adminCollectionsRoutes", {
19920
20589
  enumerable: true,
19921
- get: function () { return chunkVXE42MYF_cjs.adminCollectionsRoutes; }
20590
+ get: function () { return chunk7RUW244J_cjs.adminCollectionsRoutes; }
19922
20591
  });
19923
20592
  Object.defineProperty(exports, "adminContentRoutes", {
19924
20593
  enumerable: true,
19925
- get: function () { return chunkVXE42MYF_cjs.admin_content_default; }
20594
+ get: function () { return chunk7RUW244J_cjs.admin_content_default; }
19926
20595
  });
19927
20596
  Object.defineProperty(exports, "adminDashboardRoutes", {
19928
20597
  enumerable: true,
19929
- get: function () { return chunkVXE42MYF_cjs.router; }
20598
+ get: function () { return chunk7RUW244J_cjs.router; }
19930
20599
  });
19931
20600
  Object.defineProperty(exports, "adminLogsRoutes", {
19932
20601
  enumerable: true,
19933
- get: function () { return chunkVXE42MYF_cjs.adminLogsRoutes; }
20602
+ get: function () { return chunk7RUW244J_cjs.adminLogsRoutes; }
19934
20603
  });
19935
20604
  Object.defineProperty(exports, "adminMediaRoutes", {
19936
20605
  enumerable: true,
19937
- get: function () { return chunkVXE42MYF_cjs.adminMediaRoutes; }
20606
+ get: function () { return chunk7RUW244J_cjs.adminMediaRoutes; }
19938
20607
  });
19939
20608
  Object.defineProperty(exports, "adminPluginRoutes", {
19940
20609
  enumerable: true,
19941
- get: function () { return chunkVXE42MYF_cjs.adminPluginRoutes; }
20610
+ get: function () { return chunk7RUW244J_cjs.adminPluginRoutes; }
19942
20611
  });
19943
20612
  Object.defineProperty(exports, "adminSettingsRoutes", {
19944
20613
  enumerable: true,
19945
- get: function () { return chunkVXE42MYF_cjs.adminSettingsRoutes; }
20614
+ get: function () { return chunk7RUW244J_cjs.adminSettingsRoutes; }
19946
20615
  });
19947
20616
  Object.defineProperty(exports, "adminUsersRoutes", {
19948
20617
  enumerable: true,
19949
- get: function () { return chunkVXE42MYF_cjs.userRoutes; }
20618
+ get: function () { return chunk7RUW244J_cjs.userRoutes; }
19950
20619
  });
19951
20620
  Object.defineProperty(exports, "apiContentCrudRoutes", {
19952
20621
  enumerable: true,
19953
- get: function () { return chunkVXE42MYF_cjs.api_content_crud_default; }
20622
+ get: function () { return chunk7RUW244J_cjs.api_content_crud_default; }
19954
20623
  });
19955
20624
  Object.defineProperty(exports, "apiMediaRoutes", {
19956
20625
  enumerable: true,
19957
- get: function () { return chunkVXE42MYF_cjs.api_media_default; }
20626
+ get: function () { return chunk7RUW244J_cjs.api_media_default; }
19958
20627
  });
19959
20628
  Object.defineProperty(exports, "apiRoutes", {
19960
20629
  enumerable: true,
19961
- get: function () { return chunkVXE42MYF_cjs.api_default; }
20630
+ get: function () { return chunk7RUW244J_cjs.api_default; }
19962
20631
  });
19963
20632
  Object.defineProperty(exports, "apiSystemRoutes", {
19964
20633
  enumerable: true,
19965
- get: function () { return chunkVXE42MYF_cjs.api_system_default; }
20634
+ get: function () { return chunk7RUW244J_cjs.api_system_default; }
19966
20635
  });
19967
20636
  Object.defineProperty(exports, "authRoutes", {
19968
20637
  enumerable: true,
19969
- get: function () { return chunkVXE42MYF_cjs.auth_default; }
20638
+ get: function () { return chunk7RUW244J_cjs.auth_default; }
19970
20639
  });
19971
20640
  Object.defineProperty(exports, "createUserProfilesPlugin", {
19972
20641
  enumerable: true,
19973
- get: function () { return chunkVXE42MYF_cjs.createUserProfilesPlugin; }
20642
+ get: function () { return chunk7RUW244J_cjs.createUserProfilesPlugin; }
19974
20643
  });
19975
20644
  Object.defineProperty(exports, "defineUserProfile", {
19976
20645
  enumerable: true,
19977
- get: function () { return chunkVXE42MYF_cjs.defineUserProfile; }
20646
+ get: function () { return chunk7RUW244J_cjs.defineUserProfile; }
19978
20647
  });
19979
20648
  Object.defineProperty(exports, "getUserProfileConfig", {
19980
20649
  enumerable: true,
19981
- get: function () { return chunkVXE42MYF_cjs.getUserProfileConfig; }
20650
+ get: function () { return chunk7RUW244J_cjs.getUserProfileConfig; }
19982
20651
  });
19983
20652
  Object.defineProperty(exports, "userProfilesPlugin", {
19984
20653
  enumerable: true,
19985
- get: function () { return chunkVXE42MYF_cjs.userProfilesPlugin; }
20654
+ get: function () { return chunk7RUW244J_cjs.userProfilesPlugin; }
19986
20655
  });
19987
20656
  Object.defineProperty(exports, "Logger", {
19988
20657
  enumerable: true,
19989
- get: function () { return chunkBDDABDAB_cjs.Logger; }
20658
+ get: function () { return chunk36Z3AKX3_cjs.Logger; }
19990
20659
  });
19991
20660
  Object.defineProperty(exports, "getLogger", {
19992
20661
  enumerable: true,
19993
- get: function () { return chunkBDDABDAB_cjs.getLogger; }
20662
+ get: function () { return chunk36Z3AKX3_cjs.getLogger; }
19994
20663
  });
19995
20664
  Object.defineProperty(exports, "initLogger", {
19996
20665
  enumerable: true,
19997
- get: function () { return chunkBDDABDAB_cjs.initLogger; }
20666
+ get: function () { return chunk36Z3AKX3_cjs.initLogger; }
19998
20667
  });
19999
20668
  Object.defineProperty(exports, "apiTokens", {
20000
20669
  enumerable: true,
@@ -20138,251 +20807,259 @@ Object.defineProperty(exports, "workflowHistory", {
20138
20807
  });
20139
20808
  Object.defineProperty(exports, "AuthManager", {
20140
20809
  enumerable: true,
20141
- get: function () { return chunkAAWNRBRB_cjs.AuthManager; }
20810
+ get: function () { return chunkFCLKX2OS_cjs.AuthManager; }
20142
20811
  });
20143
20812
  Object.defineProperty(exports, "PermissionManager", {
20144
20813
  enumerable: true,
20145
- get: function () { return chunkAAWNRBRB_cjs.PermissionManager; }
20814
+ get: function () { return chunkFCLKX2OS_cjs.PermissionManager; }
20146
20815
  });
20147
20816
  Object.defineProperty(exports, "bootstrapDocumentTypes", {
20148
20817
  enumerable: true,
20149
- get: function () { return chunkAAWNRBRB_cjs.bootstrapDocumentTypes; }
20818
+ get: function () { return chunkFCLKX2OS_cjs.bootstrapDocumentTypes; }
20150
20819
  });
20151
20820
  Object.defineProperty(exports, "bootstrapMiddleware", {
20152
20821
  enumerable: true,
20153
- get: function () { return chunkAAWNRBRB_cjs.bootstrapMiddleware; }
20822
+ get: function () { return chunkFCLKX2OS_cjs.bootstrapMiddleware; }
20154
20823
  });
20155
20824
  Object.defineProperty(exports, "cacheHeaders", {
20156
20825
  enumerable: true,
20157
- get: function () { return chunkAAWNRBRB_cjs.cacheHeaders; }
20826
+ get: function () { return chunkFCLKX2OS_cjs.cacheHeaders; }
20158
20827
  });
20159
20828
  Object.defineProperty(exports, "compressionMiddleware", {
20160
20829
  enumerable: true,
20161
- get: function () { return chunkAAWNRBRB_cjs.compressionMiddleware; }
20830
+ get: function () { return chunkFCLKX2OS_cjs.compressionMiddleware; }
20162
20831
  });
20163
20832
  Object.defineProperty(exports, "detailedLoggingMiddleware", {
20164
20833
  enumerable: true,
20165
- get: function () { return chunkAAWNRBRB_cjs.detailedLoggingMiddleware; }
20834
+ get: function () { return chunkFCLKX2OS_cjs.detailedLoggingMiddleware; }
20166
20835
  });
20167
20836
  Object.defineProperty(exports, "getActivePlugins", {
20168
20837
  enumerable: true,
20169
- get: function () { return chunkAAWNRBRB_cjs.getActivePlugins; }
20838
+ get: function () { return chunkFCLKX2OS_cjs.getActivePlugins; }
20170
20839
  });
20171
20840
  Object.defineProperty(exports, "isPluginActive", {
20172
20841
  enumerable: true,
20173
- get: function () { return chunkAAWNRBRB_cjs.isPluginActive; }
20842
+ get: function () { return chunkFCLKX2OS_cjs.isPluginActive; }
20174
20843
  });
20175
20844
  Object.defineProperty(exports, "logActivity", {
20176
20845
  enumerable: true,
20177
- get: function () { return chunkAAWNRBRB_cjs.logActivity; }
20846
+ get: function () { return chunkFCLKX2OS_cjs.logActivity; }
20178
20847
  });
20179
20848
  Object.defineProperty(exports, "loggingMiddleware", {
20180
20849
  enumerable: true,
20181
- get: function () { return chunkAAWNRBRB_cjs.loggingMiddleware; }
20850
+ get: function () { return chunkFCLKX2OS_cjs.loggingMiddleware; }
20182
20851
  });
20183
20852
  Object.defineProperty(exports, "optionalAuth", {
20184
20853
  enumerable: true,
20185
- get: function () { return chunkAAWNRBRB_cjs.optionalAuth; }
20854
+ get: function () { return chunkFCLKX2OS_cjs.optionalAuth; }
20186
20855
  });
20187
20856
  Object.defineProperty(exports, "performanceLoggingMiddleware", {
20188
20857
  enumerable: true,
20189
- get: function () { return chunkAAWNRBRB_cjs.performanceLoggingMiddleware; }
20858
+ get: function () { return chunkFCLKX2OS_cjs.performanceLoggingMiddleware; }
20190
20859
  });
20191
20860
  Object.defineProperty(exports, "requireActivePlugin", {
20192
20861
  enumerable: true,
20193
- get: function () { return chunkAAWNRBRB_cjs.requireActivePlugin; }
20862
+ get: function () { return chunkFCLKX2OS_cjs.requireActivePlugin; }
20194
20863
  });
20195
20864
  Object.defineProperty(exports, "requireActivePlugins", {
20196
20865
  enumerable: true,
20197
- get: function () { return chunkAAWNRBRB_cjs.requireActivePlugins; }
20866
+ get: function () { return chunkFCLKX2OS_cjs.requireActivePlugins; }
20198
20867
  });
20199
20868
  Object.defineProperty(exports, "requireAnyPermission", {
20200
20869
  enumerable: true,
20201
- get: function () { return chunkAAWNRBRB_cjs.requireAnyPermission; }
20870
+ get: function () { return chunkFCLKX2OS_cjs.requireAnyPermission; }
20202
20871
  });
20203
20872
  Object.defineProperty(exports, "requireAuth", {
20204
20873
  enumerable: true,
20205
- get: function () { return chunkAAWNRBRB_cjs.requireAuth; }
20874
+ get: function () { return chunkFCLKX2OS_cjs.requireAuth; }
20206
20875
  });
20207
20876
  Object.defineProperty(exports, "requirePermission", {
20208
20877
  enumerable: true,
20209
- get: function () { return chunkAAWNRBRB_cjs.requirePermission; }
20878
+ get: function () { return chunkFCLKX2OS_cjs.requirePermission; }
20210
20879
  });
20211
20880
  Object.defineProperty(exports, "requireRole", {
20212
20881
  enumerable: true,
20213
- get: function () { return chunkAAWNRBRB_cjs.requireRole; }
20882
+ get: function () { return chunkFCLKX2OS_cjs.requireRole; }
20214
20883
  });
20215
20884
  Object.defineProperty(exports, "securityHeaders", {
20216
20885
  enumerable: true,
20217
- get: function () { return chunkAAWNRBRB_cjs.securityHeadersMiddleware; }
20886
+ get: function () { return chunkFCLKX2OS_cjs.securityHeadersMiddleware; }
20218
20887
  });
20219
20888
  Object.defineProperty(exports, "securityLoggingMiddleware", {
20220
20889
  enumerable: true,
20221
- get: function () { return chunkAAWNRBRB_cjs.securityLoggingMiddleware; }
20890
+ get: function () { return chunkFCLKX2OS_cjs.securityLoggingMiddleware; }
20891
+ });
20892
+ Object.defineProperty(exports, "DocumentsService", {
20893
+ enumerable: true,
20894
+ get: function () { return chunkLTZ5WYOK_cjs.DocumentsService; }
20222
20895
  });
20223
20896
  Object.defineProperty(exports, "RbacService", {
20224
20897
  enumerable: true,
20225
- get: function () { return chunk2CB4KY7I_cjs.RbacService; }
20898
+ get: function () { return chunkLTZ5WYOK_cjs.RbacService; }
20226
20899
  });
20227
20900
  Object.defineProperty(exports, "PluginBootstrapService", {
20228
20901
  enumerable: true,
20229
- get: function () { return chunkQAYFOER6_cjs.PluginBootstrapService; }
20902
+ get: function () { return chunkKVBHB7QP_cjs.PluginBootstrapService; }
20230
20903
  });
20231
20904
  Object.defineProperty(exports, "PluginServiceClass", {
20232
20905
  enumerable: true,
20233
- get: function () { return chunkQAYFOER6_cjs.PluginService; }
20906
+ get: function () { return chunkKVBHB7QP_cjs.PluginService; }
20234
20907
  });
20235
20908
  Object.defineProperty(exports, "getAvailableCollectionNames", {
20236
20909
  enumerable: true,
20237
- get: function () { return chunkQAYFOER6_cjs.getAvailableCollectionNames; }
20910
+ get: function () { return chunkKVBHB7QP_cjs.getAvailableCollectionNames; }
20238
20911
  });
20239
20912
  Object.defineProperty(exports, "loadCollectionConfig", {
20240
20913
  enumerable: true,
20241
- get: function () { return chunkQAYFOER6_cjs.loadCollectionConfig; }
20914
+ get: function () { return chunkKVBHB7QP_cjs.loadCollectionConfig; }
20242
20915
  });
20243
20916
  Object.defineProperty(exports, "loadCollectionConfigs", {
20244
20917
  enumerable: true,
20245
- get: function () { return chunkQAYFOER6_cjs.loadCollectionConfigs; }
20918
+ get: function () { return chunkKVBHB7QP_cjs.loadCollectionConfigs; }
20246
20919
  });
20247
20920
  Object.defineProperty(exports, "registerCollections", {
20248
20921
  enumerable: true,
20249
- get: function () { return chunkQAYFOER6_cjs.registerCollections; }
20922
+ get: function () { return chunkKVBHB7QP_cjs.registerCollections; }
20250
20923
  });
20251
20924
  Object.defineProperty(exports, "validateCollectionConfig", {
20252
20925
  enumerable: true,
20253
- get: function () { return chunkQAYFOER6_cjs.validateCollectionConfig; }
20926
+ get: function () { return chunkKVBHB7QP_cjs.validateCollectionConfig; }
20254
20927
  });
20255
20928
  Object.defineProperty(exports, "MigrationService", {
20256
20929
  enumerable: true,
20257
- get: function () { return chunkDSA4UX5B_cjs.MigrationService; }
20930
+ get: function () { return chunkOJC4G5JE_cjs.MigrationService; }
20258
20931
  });
20259
20932
  Object.defineProperty(exports, "renderFilterBar", {
20260
20933
  enumerable: true,
20261
- get: function () { return chunkWULONYGB_cjs.renderFilterBar; }
20934
+ get: function () { return chunkCRGUD4KC_cjs.renderFilterBar; }
20262
20935
  });
20263
20936
  Object.defineProperty(exports, "getConfirmationDialogScript", {
20264
20937
  enumerable: true,
20265
- get: function () { return chunkMVIZJOO5_cjs.getConfirmationDialogScript; }
20938
+ get: function () { return chunkPXNTCCPE_cjs.getConfirmationDialogScript; }
20266
20939
  });
20267
20940
  Object.defineProperty(exports, "renderAlert", {
20268
20941
  enumerable: true,
20269
- get: function () { return chunkMVIZJOO5_cjs.renderAlert; }
20942
+ get: function () { return chunkPXNTCCPE_cjs.renderAlert; }
20270
20943
  });
20271
20944
  Object.defineProperty(exports, "renderConfirmationDialog", {
20272
20945
  enumerable: true,
20273
- get: function () { return chunkMVIZJOO5_cjs.renderConfirmationDialog; }
20946
+ get: function () { return chunkPXNTCCPE_cjs.renderConfirmationDialog; }
20274
20947
  });
20275
20948
  Object.defineProperty(exports, "renderForm", {
20276
20949
  enumerable: true,
20277
- get: function () { return chunkMVIZJOO5_cjs.renderForm; }
20950
+ get: function () { return chunkPXNTCCPE_cjs.renderForm; }
20278
20951
  });
20279
20952
  Object.defineProperty(exports, "renderFormField", {
20280
20953
  enumerable: true,
20281
- get: function () { return chunkMVIZJOO5_cjs.renderFormField; }
20954
+ get: function () { return chunkPXNTCCPE_cjs.renderFormField; }
20282
20955
  });
20283
20956
  Object.defineProperty(exports, "renderPagination", {
20284
20957
  enumerable: true,
20285
- get: function () { return chunkMVIZJOO5_cjs.renderPagination; }
20958
+ get: function () { return chunkPXNTCCPE_cjs.renderPagination; }
20286
20959
  });
20287
20960
  Object.defineProperty(exports, "renderTable", {
20288
20961
  enumerable: true,
20289
- get: function () { return chunkMVIZJOO5_cjs.renderTable; }
20962
+ get: function () { return chunkPXNTCCPE_cjs.renderTable; }
20963
+ });
20964
+ Object.defineProperty(exports, "renderAdminLayoutCatalyst", {
20965
+ enumerable: true,
20966
+ get: function () { return chunkK623Q6WD_cjs.renderAdminLayoutCatalyst; }
20290
20967
  });
20291
20968
  Object.defineProperty(exports, "HookSystemImpl", {
20292
20969
  enumerable: true,
20293
- get: function () { return chunkH2AXVCLS_cjs.HookSystemImpl; }
20970
+ get: function () { return chunk5UXU3LP4_cjs.HookSystemImpl; }
20294
20971
  });
20295
20972
  Object.defineProperty(exports, "HookUtils", {
20296
20973
  enumerable: true,
20297
- get: function () { return chunkH2AXVCLS_cjs.HookUtils; }
20974
+ get: function () { return chunk5UXU3LP4_cjs.HookUtils; }
20298
20975
  });
20299
20976
  Object.defineProperty(exports, "PluginDependencyCycleError", {
20300
20977
  enumerable: true,
20301
- get: function () { return chunkH2AXVCLS_cjs.PluginDependencyCycleError; }
20978
+ get: function () { return chunk5UXU3LP4_cjs.PluginDependencyCycleError; }
20302
20979
  });
20303
20980
  Object.defineProperty(exports, "PluginManagerClass", {
20304
20981
  enumerable: true,
20305
- get: function () { return chunkH2AXVCLS_cjs.PluginManager; }
20982
+ get: function () { return chunk5UXU3LP4_cjs.PluginManager; }
20306
20983
  });
20307
20984
  Object.defineProperty(exports, "PluginRegistryImpl", {
20308
20985
  enumerable: true,
20309
- get: function () { return chunkH2AXVCLS_cjs.PluginRegistryImpl; }
20986
+ get: function () { return chunk5UXU3LP4_cjs.PluginRegistryImpl; }
20310
20987
  });
20311
20988
  Object.defineProperty(exports, "PluginValidatorClass", {
20312
20989
  enumerable: true,
20313
- get: function () { return chunkH2AXVCLS_cjs.PluginValidator; }
20990
+ get: function () { return chunk5UXU3LP4_cjs.PluginValidator; }
20314
20991
  });
20315
20992
  Object.defineProperty(exports, "RegisterPluginsError", {
20316
20993
  enumerable: true,
20317
- get: function () { return chunkH2AXVCLS_cjs.RegisterPluginsError; }
20994
+ get: function () { return chunk5UXU3LP4_cjs.RegisterPluginsError; }
20318
20995
  });
20319
20996
  Object.defineProperty(exports, "ScopedHookSystemClass", {
20320
20997
  enumerable: true,
20321
- get: function () { return chunkH2AXVCLS_cjs.ScopedHookSystem; }
20998
+ get: function () { return chunk5UXU3LP4_cjs.ScopedHookSystem; }
20322
20999
  });
20323
21000
  Object.defineProperty(exports, "collectCronSchedules", {
20324
21001
  enumerable: true,
20325
- get: function () { return chunkH2AXVCLS_cjs.collectCronSchedules; }
21002
+ get: function () { return chunk5UXU3LP4_cjs.collectCronSchedules; }
20326
21003
  });
20327
21004
  Object.defineProperty(exports, "collectCrons", {
20328
21005
  enumerable: true,
20329
- get: function () { return chunkH2AXVCLS_cjs.collectCrons; }
21006
+ get: function () { return chunk5UXU3LP4_cjs.collectCrons; }
20330
21007
  });
20331
21008
  Object.defineProperty(exports, "createScheduledHandler", {
20332
21009
  enumerable: true,
20333
- get: function () { return chunkH2AXVCLS_cjs.createScheduledHandler; }
21010
+ get: function () { return chunk5UXU3LP4_cjs.createScheduledHandler; }
20334
21011
  });
20335
21012
  Object.defineProperty(exports, "dispatchCronTick", {
20336
21013
  enumerable: true,
20337
- get: function () { return chunkH2AXVCLS_cjs.dispatchCronTick; }
21014
+ get: function () { return chunk5UXU3LP4_cjs.dispatchCronTick; }
20338
21015
  });
20339
21016
  Object.defineProperty(exports, "getPluginMenu", {
20340
21017
  enumerable: true,
20341
- get: function () { return chunkH2AXVCLS_cjs.getPluginMenu; }
21018
+ get: function () { return chunk5UXU3LP4_cjs.getPluginMenu; }
20342
21019
  });
20343
21020
  Object.defineProperty(exports, "registerPlugins", {
20344
21021
  enumerable: true,
20345
- get: function () { return chunkH2AXVCLS_cjs.registerPlugins; }
21022
+ get: function () { return chunk5UXU3LP4_cjs.registerPlugins; }
20346
21023
  });
20347
21024
  Object.defineProperty(exports, "resetPluginMenu", {
20348
21025
  enumerable: true,
20349
- get: function () { return chunkH2AXVCLS_cjs.resetPluginMenu; }
21026
+ get: function () { return chunk5UXU3LP4_cjs.resetPluginMenu; }
20350
21027
  });
20351
21028
  Object.defineProperty(exports, "resolvePluginMenuItems", {
20352
21029
  enumerable: true,
20353
- get: function () { return chunkH2AXVCLS_cjs.resolvePluginMenuItems; }
21030
+ get: function () { return chunk5UXU3LP4_cjs.resolvePluginMenuItems; }
20354
21031
  });
20355
21032
  Object.defineProperty(exports, "setPluginMenu", {
20356
21033
  enumerable: true,
20357
- get: function () { return chunkH2AXVCLS_cjs.setPluginMenu; }
21034
+ get: function () { return chunk5UXU3LP4_cjs.setPluginMenu; }
20358
21035
  });
20359
21036
  Object.defineProperty(exports, "topoSort", {
20360
21037
  enumerable: true,
20361
- get: function () { return chunkH2AXVCLS_cjs.topoSort; }
21038
+ get: function () { return chunk5UXU3LP4_cjs.topoSort; }
20362
21039
  });
20363
21040
  Object.defineProperty(exports, "applySchemaDefaults", {
20364
21041
  enumerable: true,
20365
- get: function () { return chunkXW56B23A_cjs.applySchemaDefaults; }
21042
+ get: function () { return chunkA4KUJ3LD_cjs.applySchemaDefaults; }
20366
21043
  });
20367
21044
  Object.defineProperty(exports, "definePlugin", {
20368
21045
  enumerable: true,
20369
- get: function () { return chunkXW56B23A_cjs.definePlugin; }
21046
+ get: function () { return chunkA4KUJ3LD_cjs.definePlugin; }
20370
21047
  });
20371
21048
  Object.defineProperty(exports, "isDefinedPlugin", {
20372
21049
  enumerable: true,
20373
- get: function () { return chunkXW56B23A_cjs.isDefinedPlugin; }
21050
+ get: function () { return chunkA4KUJ3LD_cjs.isDefinedPlugin; }
20374
21051
  });
20375
21052
  Object.defineProperty(exports, "parseConfigSchema", {
20376
21053
  enumerable: true,
20377
- get: function () { return chunkXW56B23A_cjs.parseConfigSchema; }
21054
+ get: function () { return chunkA4KUJ3LD_cjs.parseConfigSchema; }
20378
21055
  });
20379
21056
  Object.defineProperty(exports, "parseFormDataToSettings", {
20380
21057
  enumerable: true,
20381
- get: function () { return chunkXW56B23A_cjs.parseFormDataToSettings; }
21058
+ get: function () { return chunkA4KUJ3LD_cjs.parseFormDataToSettings; }
20382
21059
  });
20383
21060
  Object.defineProperty(exports, "renderSchemaFields", {
20384
21061
  enumerable: true,
20385
- get: function () { return chunkXW56B23A_cjs.renderSchemaFields; }
21062
+ get: function () { return chunkA4KUJ3LD_cjs.renderSchemaFields; }
20386
21063
  });
20387
21064
  Object.defineProperty(exports, "getHookSystem", {
20388
21065
  enumerable: true,
@@ -20430,11 +21107,11 @@ Object.defineProperty(exports, "metricsTracker", {
20430
21107
  });
20431
21108
  Object.defineProperty(exports, "SONICJS_VERSION", {
20432
21109
  enumerable: true,
20433
- get: function () { return chunkLRZIAW7U_cjs.SONICJS_VERSION; }
21110
+ get: function () { return chunkAOUVUF32_cjs.SONICJS_VERSION; }
20434
21111
  });
20435
21112
  Object.defineProperty(exports, "getCoreVersion", {
20436
21113
  enumerable: true,
20437
- get: function () { return chunkLRZIAW7U_cjs.getCoreVersion; }
21114
+ get: function () { return chunkAOUVUF32_cjs.getCoreVersion; }
20438
21115
  });
20439
21116
  Object.defineProperty(exports, "escapeHtml", {
20440
21117
  enumerable: true,
@@ -20457,11 +21134,13 @@ exports.CloudflareEmailProvider = CloudflareEmailProvider2;
20457
21134
  exports.OAuthService = OAuthService;
20458
21135
  exports.VERSION = VERSION;
20459
21136
  exports.createDb = createDb;
21137
+ exports.createHelloWorldPlugin = createHelloWorldPlugin;
20460
21138
  exports.createOAuthProvidersPlugin = createOAuthProvidersPlugin;
20461
21139
  exports.createRedirectPlugin = createRedirectPlugin;
20462
21140
  exports.createSonicJSApp = createSonicJSApp;
20463
21141
  exports.emailReconciliationPlugin = emailReconciliationPlugin;
20464
21142
  exports.generateTriggersComment = generateTriggersComment;
21143
+ exports.helloWorldPlugin = helloWorldPlugin;
20465
21144
  exports.oauthProvidersPlugin = oauthProvidersPlugin;
20466
21145
  exports.parseCronTriggers = parseCronTriggers;
20467
21146
  exports.redirectPlugin = redirectPlugin;