@sonicjs-cms/core 3.0.0-beta.24 → 3.0.0-beta.26

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 (163) hide show
  1. package/bin/db-reset.js +39 -22
  2. package/dist/admin-documents-form.template-JWV5GITD.js +6 -0
  3. package/dist/{admin-documents-form.template-55V2ZGWT.js.map → admin-documents-form.template-JWV5GITD.js.map} +1 -1
  4. package/dist/admin-documents-form.template-UWKGVAMW.cjs +19 -0
  5. package/dist/{admin-layout-catalyst.template-6UQGLCKI.js.map → admin-documents-form.template-UWKGVAMW.cjs.map} +1 -1
  6. package/dist/admin-layout-catalyst.template-MOQ3BBXA.cjs +21 -0
  7. package/dist/{admin-layout-catalyst.template-3XZXDGF7.cjs.map → admin-layout-catalyst.template-MOQ3BBXA.cjs.map} +1 -1
  8. package/dist/admin-layout-catalyst.template-WCYMQVTZ.js +7 -0
  9. package/dist/{admin-documents-form.template-YNAVMJCV.cjs.map → admin-layout-catalyst.template-WCYMQVTZ.js.map} +1 -1
  10. package/dist/{app-01M0dIwt.d.ts → app-BP5IlK94.d.ts} +7 -7
  11. package/dist/{app-aj39TGHB.d.cts → app-fdq4K3vw.d.cts} +7 -7
  12. package/dist/catalog-56DR6OXI.cjs +41 -0
  13. package/dist/catalog-56DR6OXI.cjs.map +1 -0
  14. package/dist/catalog-6MB37KY7.js +4 -0
  15. package/dist/catalog-6MB37KY7.js.map +1 -0
  16. package/dist/{chunk-QCJHCSOK.cjs → chunk-4DHPR7KR.cjs} +77 -17
  17. package/dist/chunk-4DHPR7KR.cjs.map +1 -0
  18. package/dist/{chunk-UIHIXTIS.js → chunk-5YSFQO7X.js} +40 -13
  19. package/dist/chunk-5YSFQO7X.js.map +1 -0
  20. package/dist/{chunk-GMMCCIQO.cjs → chunk-6UAI4SGN.cjs} +3 -3
  21. package/dist/{chunk-GMMCCIQO.cjs.map → chunk-6UAI4SGN.cjs.map} +1 -1
  22. package/dist/{chunk-2XAQTPAE.js → chunk-6X22VFEV.js} +8 -2
  23. package/dist/chunk-6X22VFEV.js.map +1 -0
  24. package/dist/{chunk-URIBTX27.js → chunk-73RTFFMX.js} +3 -3
  25. package/dist/{chunk-URIBTX27.js.map → chunk-73RTFFMX.js.map} +1 -1
  26. package/dist/{chunk-QJUJNTIU.cjs → chunk-A22RBHO7.cjs} +43 -12
  27. package/dist/chunk-A22RBHO7.cjs.map +1 -0
  28. package/dist/{chunk-QZGABF2M.js → chunk-AMP4BSJE.js} +18 -7
  29. package/dist/chunk-AMP4BSJE.js.map +1 -0
  30. package/dist/{chunk-37V3RET3.cjs → chunk-BRKXMRMB.cjs} +99 -98
  31. package/dist/chunk-BRKXMRMB.cjs.map +1 -0
  32. package/dist/{chunk-36Z3AKX3.cjs → chunk-C5LDQ3SH.cjs} +8 -2
  33. package/dist/chunk-C5LDQ3SH.cjs.map +1 -0
  34. package/dist/{chunk-BBEKHLTW.cjs → chunk-CN3T3TDI.cjs} +9 -9
  35. package/dist/{chunk-BBEKHLTW.cjs.map → chunk-CN3T3TDI.cjs.map} +1 -1
  36. package/dist/{chunk-BHND5PEV.js → chunk-E3TQG7AA.js} +3 -3
  37. package/dist/{chunk-BHND5PEV.js.map → chunk-E3TQG7AA.js.map} +1 -1
  38. package/dist/{chunk-FHPEM77Y.js → chunk-EEA476CJ.js} +88 -83
  39. package/dist/chunk-EEA476CJ.js.map +1 -0
  40. package/dist/chunk-F6BTBE4S.js +119 -0
  41. package/dist/chunk-F6BTBE4S.js.map +1 -0
  42. package/dist/chunk-FZGIU5AZ.cjs +128 -0
  43. package/dist/chunk-FZGIU5AZ.cjs.map +1 -0
  44. package/dist/{chunk-BJROXF4N.js → chunk-HSDJDWLV.js} +19 -4
  45. package/dist/chunk-HSDJDWLV.js.map +1 -0
  46. package/dist/{chunk-VGEZNFWH.js → chunk-JD7BZU3A.js} +5 -4
  47. package/dist/chunk-JD7BZU3A.js.map +1 -0
  48. package/dist/{chunk-SOZUG52O.js → chunk-JG5J434C.js} +3 -3
  49. package/dist/{chunk-SOZUG52O.js.map → chunk-JG5J434C.js.map} +1 -1
  50. package/dist/{chunk-BP52BFIV.cjs → chunk-KWQNB6UM.cjs} +6 -5
  51. package/dist/chunk-KWQNB6UM.cjs.map +1 -0
  52. package/dist/{chunk-UYJQDDEE.cjs → chunk-MI2YXCK4.cjs} +14 -8
  53. package/dist/chunk-MI2YXCK4.cjs.map +1 -0
  54. package/dist/{chunk-VC5XVPLM.js → chunk-OJFIQGZB.js} +512 -148
  55. package/dist/chunk-OJFIQGZB.js.map +1 -0
  56. package/dist/{chunk-LTZ5WYOK.cjs → chunk-OLEOKHDX.cjs} +25 -2
  57. package/dist/chunk-OLEOKHDX.cjs.map +1 -0
  58. package/dist/{chunk-E66UVONV.cjs → chunk-OUBUS74I.cjs} +24 -9
  59. package/dist/chunk-OUBUS74I.cjs.map +1 -0
  60. package/dist/{chunk-A2SN3RVL.cjs → chunk-PAS7GZBS.cjs} +40 -13
  61. package/dist/chunk-PAS7GZBS.cjs.map +1 -0
  62. package/dist/{chunk-RJ2O5IIE.js → chunk-RVOX2WH2.js} +74 -18
  63. package/dist/chunk-RVOX2WH2.js.map +1 -0
  64. package/dist/{chunk-3TMTYJAJ.js → chunk-RXLI3ADU.js} +25 -2
  65. package/dist/chunk-RXLI3ADU.js.map +1 -0
  66. package/dist/{chunk-I767LVN7.cjs → chunk-S2QN4LFD.cjs} +881 -515
  67. package/dist/chunk-S2QN4LFD.cjs.map +1 -0
  68. package/dist/{chunk-IXUHXTHW.cjs → chunk-SFGYZUWU.cjs} +18 -7
  69. package/dist/chunk-SFGYZUWU.cjs.map +1 -0
  70. package/dist/{chunk-THFZSDIU.js → chunk-SXC4HPK6.js} +14 -8
  71. package/dist/chunk-SXC4HPK6.js.map +1 -0
  72. package/dist/{chunk-JMJM7DMM.cjs → chunk-TT3TQSCZ.cjs} +5 -5
  73. package/dist/{chunk-JMJM7DMM.cjs.map → chunk-TT3TQSCZ.cjs.map} +1 -1
  74. package/dist/{chunk-LNI3FYSI.js → chunk-UB5QSRO7.js} +9 -14
  75. package/dist/chunk-UB5QSRO7.js.map +1 -0
  76. package/dist/{chunk-VYQVDL2M.js → chunk-UKIDWRA3.js} +36 -5
  77. package/dist/chunk-UKIDWRA3.js.map +1 -0
  78. package/dist/{chunk-KKNEYIZJ.cjs → chunk-XZUEGFXE.cjs} +9 -14
  79. package/dist/chunk-XZUEGFXE.cjs.map +1 -0
  80. package/dist/{collection-config-BTzAvKt2.d.cts → collection-config-U2dydD_O.d.cts} +14 -0
  81. package/dist/{collection-config-BTzAvKt2.d.ts → collection-config-U2dydD_O.d.ts} +14 -0
  82. package/dist/config-DOAWXZBG.js +6 -0
  83. package/dist/{config-6FB2BXMP.js.map → config-DOAWXZBG.js.map} +1 -1
  84. package/dist/{config-OCH7S4WK.cjs → config-VLU73ZW7.cjs} +5 -5
  85. package/dist/{config-OCH7S4WK.cjs.map → config-VLU73ZW7.cjs.map} +1 -1
  86. package/dist/{define-plugin-D_6D9vVZ.d.ts → define-plugin-DDe8a_bh.d.ts} +3 -0
  87. package/dist/{define-plugin-DMcvEy_C.d.cts → define-plugin-rjXmGOgu.d.cts} +3 -0
  88. package/dist/index.cjs +698 -392
  89. package/dist/index.cjs.map +1 -1
  90. package/dist/index.d.cts +27 -12
  91. package/dist/index.d.ts +27 -12
  92. package/dist/index.js +340 -35
  93. package/dist/index.js.map +1 -1
  94. package/dist/middleware.cjs +47 -47
  95. package/dist/middleware.d.cts +10 -10
  96. package/dist/middleware.d.ts +10 -10
  97. package/dist/middleware.js +6 -6
  98. package/dist/migrations-6M6772UC.cjs +13 -0
  99. package/dist/{migrations-FGXZPKDC.cjs.map → migrations-6M6772UC.cjs.map} +1 -1
  100. package/dist/migrations-GZ2HIB4I.js +4 -0
  101. package/dist/{migrations-Z6D27NAW.js.map → migrations-GZ2HIB4I.js.map} +1 -1
  102. package/dist/{plugin-bootstrap-BHWQ2df8.d.cts → plugin-bootstrap-CfVILQeP.d.ts} +1 -1
  103. package/dist/{plugin-bootstrap-Bj4fxX1q.d.ts → plugin-bootstrap-RY5pkoOT.d.cts} +1 -1
  104. package/dist/plugins.cjs +40 -40
  105. package/dist/plugins.d.cts +1 -1
  106. package/dist/plugins.d.ts +1 -1
  107. package/dist/plugins.js +3 -3
  108. package/dist/rbac-TFUOYIVN.cjs +14 -0
  109. package/dist/{rbac-7QZ4JZ2E.cjs.map → rbac-TFUOYIVN.cjs.map} +1 -1
  110. package/dist/rbac-XSNP76CV.js +5 -0
  111. package/dist/{rbac-Y43IEQOP.js.map → rbac-XSNP76CV.js.map} +1 -1
  112. package/dist/routes.cjs +33 -32
  113. package/dist/routes.d.cts +3 -5
  114. package/dist/routes.d.ts +3 -5
  115. package/dist/routes.js +13 -12
  116. package/dist/services.cjs +30 -30
  117. package/dist/services.d.cts +10 -3
  118. package/dist/services.d.ts +10 -3
  119. package/dist/services.js +3 -3
  120. package/dist/{telemetry-Cku1ax74.d.cts → telemetry-QFlTv9f8.d.cts} +1 -1
  121. package/dist/{telemetry-Cku1ax74.d.ts → telemetry-QFlTv9f8.d.ts} +1 -1
  122. package/dist/templates.cjs +17 -17
  123. package/dist/templates.js +3 -3
  124. package/dist/types.d.cts +2 -2
  125. package/dist/types.d.ts +2 -2
  126. package/dist/utils.cjs +12 -12
  127. package/dist/utils.d.cts +2 -2
  128. package/dist/utils.d.ts +2 -2
  129. package/dist/utils.js +2 -2
  130. package/package.json +7 -12
  131. package/dist/admin-documents-form.template-55V2ZGWT.js +0 -6
  132. package/dist/admin-documents-form.template-YNAVMJCV.cjs +0 -19
  133. package/dist/admin-layout-catalyst.template-3XZXDGF7.cjs +0 -21
  134. package/dist/admin-layout-catalyst.template-6UQGLCKI.js +0 -7
  135. package/dist/chunk-2XAQTPAE.js.map +0 -1
  136. package/dist/chunk-36Z3AKX3.cjs.map +0 -1
  137. package/dist/chunk-37V3RET3.cjs.map +0 -1
  138. package/dist/chunk-3TMTYJAJ.js.map +0 -1
  139. package/dist/chunk-A2SN3RVL.cjs.map +0 -1
  140. package/dist/chunk-BJROXF4N.js.map +0 -1
  141. package/dist/chunk-BP52BFIV.cjs.map +0 -1
  142. package/dist/chunk-E66UVONV.cjs.map +0 -1
  143. package/dist/chunk-FHPEM77Y.js.map +0 -1
  144. package/dist/chunk-I767LVN7.cjs.map +0 -1
  145. package/dist/chunk-IXUHXTHW.cjs.map +0 -1
  146. package/dist/chunk-KKNEYIZJ.cjs.map +0 -1
  147. package/dist/chunk-LNI3FYSI.js.map +0 -1
  148. package/dist/chunk-LTZ5WYOK.cjs.map +0 -1
  149. package/dist/chunk-QCJHCSOK.cjs.map +0 -1
  150. package/dist/chunk-QJUJNTIU.cjs.map +0 -1
  151. package/dist/chunk-QZGABF2M.js.map +0 -1
  152. package/dist/chunk-RJ2O5IIE.js.map +0 -1
  153. package/dist/chunk-THFZSDIU.js.map +0 -1
  154. package/dist/chunk-UIHIXTIS.js.map +0 -1
  155. package/dist/chunk-UYJQDDEE.cjs.map +0 -1
  156. package/dist/chunk-VC5XVPLM.js.map +0 -1
  157. package/dist/chunk-VGEZNFWH.js.map +0 -1
  158. package/dist/chunk-VYQVDL2M.js.map +0 -1
  159. package/dist/config-6FB2BXMP.js +0 -6
  160. package/dist/migrations-FGXZPKDC.cjs +0 -13
  161. package/dist/migrations-Z6D27NAW.js +0 -4
  162. package/dist/rbac-7QZ4JZ2E.cjs +0 -14
  163. package/dist/rbac-Y43IEQOP.js +0 -5
@@ -1,20 +1,21 @@
1
1
  'use strict';
2
2
 
3
+ var chunkTT3TQSCZ_cjs = require('./chunk-TT3TQSCZ.cjs');
4
+ var chunkFZGIU5AZ_cjs = require('./chunk-FZGIU5AZ.cjs');
3
5
  var chunkXWVDSM2L_cjs = require('./chunk-XWVDSM2L.cjs');
4
- var chunkJMJM7DMM_cjs = require('./chunk-JMJM7DMM.cjs');
5
- var chunk36Z3AKX3_cjs = require('./chunk-36Z3AKX3.cjs');
6
- var chunk37V3RET3_cjs = require('./chunk-37V3RET3.cjs');
7
- var chunkLTZ5WYOK_cjs = require('./chunk-LTZ5WYOK.cjs');
6
+ var chunkC5LDQ3SH_cjs = require('./chunk-C5LDQ3SH.cjs');
7
+ var chunkBRKXMRMB_cjs = require('./chunk-BRKXMRMB.cjs');
8
+ var chunkOLEOKHDX_cjs = require('./chunk-OLEOKHDX.cjs');
8
9
  var chunkKIGVVO6N_cjs = require('./chunk-KIGVVO6N.cjs');
9
- var chunkQCJHCSOK_cjs = require('./chunk-QCJHCSOK.cjs');
10
- var chunkA2SN3RVL_cjs = require('./chunk-A2SN3RVL.cjs');
11
- var chunkE66UVONV_cjs = require('./chunk-E66UVONV.cjs');
12
- var chunkUYJQDDEE_cjs = require('./chunk-UYJQDDEE.cjs');
13
- var chunkBP52BFIV_cjs = require('./chunk-BP52BFIV.cjs');
10
+ var chunk4DHPR7KR_cjs = require('./chunk-4DHPR7KR.cjs');
11
+ var chunkPAS7GZBS_cjs = require('./chunk-PAS7GZBS.cjs');
12
+ var chunkOUBUS74I_cjs = require('./chunk-OUBUS74I.cjs');
13
+ var chunkMI2YXCK4_cjs = require('./chunk-MI2YXCK4.cjs');
14
+ var chunkKWQNB6UM_cjs = require('./chunk-KWQNB6UM.cjs');
14
15
  var chunkJ6JTWD2A_cjs = require('./chunk-J6JTWD2A.cjs');
15
- var chunkIXUHXTHW_cjs = require('./chunk-IXUHXTHW.cjs');
16
+ var chunkSFGYZUWU_cjs = require('./chunk-SFGYZUWU.cjs');
16
17
  var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
17
- var chunkKKNEYIZJ_cjs = require('./chunk-KKNEYIZJ.cjs');
18
+ var chunkXZUEGFXE_cjs = require('./chunk-XZUEGFXE.cjs');
18
19
  var chunkMNWKYY5E_cjs = require('./chunk-MNWKYY5E.cjs');
19
20
  var hono = require('hono');
20
21
  var zod = require('zod');
@@ -47,6 +48,7 @@ var DocumentPermissionsService = class {
47
48
  const publicGrants = baseGrants["public"] ?? [];
48
49
  if (publicGrants.includes(permission)) return true;
49
50
  } else if (principal.type === "role") {
51
+ if (principal.id === "public") continue;
50
52
  const roleGrants = baseGrants[principal.id] ?? [];
51
53
  if (roleGrants.includes(permission)) return true;
52
54
  }
@@ -271,7 +273,7 @@ function getDocumentRequestContext(c) {
271
273
 
272
274
  // src/routes/api-documents.ts
273
275
  async function aclAllowsRead(db, tenantId, principalSet, row, preloadedType) {
274
- const docType = preloadedType ?? await new chunk37V3RET3_cjs.DocumentTypeRegistry(db).findById(row.type_id);
276
+ const docType = preloadedType ?? await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(row.type_id);
275
277
  if (!docType) return false;
276
278
  return new DocumentRepository(db, tenantId).isAllowed(principalSet, row.root_id, "read", docType.settings);
277
279
  }
@@ -289,7 +291,7 @@ apiDocumentsRoutes.get("/", async (c) => {
289
291
  if (!typeId) {
290
292
  return c.json({ error: "type query parameter is required" }, 400);
291
293
  }
292
- const registry = new chunk37V3RET3_cjs.DocumentTypeRegistry(db);
294
+ const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
293
295
  const docType = await registry.findById(typeId);
294
296
  if (!docType || !docType.isActive) {
295
297
  return c.json({ error: "Unknown document type" }, 400);
@@ -371,7 +373,7 @@ apiDocumentsRoutes.get("/root/:rootId", async (c) => {
371
373
  AND (expires_at IS NULL OR expires_at > ?) LIMIT 1`
372
374
  ).bind(rootId, now, now).first();
373
375
  if (!row) return c.json({ error: "Not found" }, 404);
374
- const docType = await new chunk37V3RET3_cjs.DocumentTypeRegistry(db).findById(row.type_id);
376
+ const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(row.type_id);
375
377
  const effTenant = effectiveTenantForType(tenantId, docType?.settings);
376
378
  if (row.tenant_id !== effTenant) return c.json({ error: "Not found" }, 404);
377
379
  if (!await aclAllowsRead(db, effTenant, principalSet, row, docType)) {
@@ -407,7 +409,7 @@ apiDocumentsRoutes.get("/:id", async (c) => {
407
409
  AND (expires_at IS NULL OR expires_at > ?) LIMIT 1`
408
410
  ).bind(id, now, now).first();
409
411
  if (!row) return c.json({ error: "Not found" }, 404);
410
- const docType = await new chunk37V3RET3_cjs.DocumentTypeRegistry(db).findById(row.type_id);
412
+ const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(row.type_id);
411
413
  const effTenant = effectiveTenantForType(tenantId, docType?.settings);
412
414
  if (row.tenant_id !== effTenant) return c.json({ error: "Not found" }, 404);
413
415
  if (!await aclAllowsRead(db, effTenant, principalSet, row, docType)) {
@@ -477,17 +479,17 @@ async function resolveDocScope(c, db, by, opts = {}) {
477
479
  const draft = opts.currentDraftOnly ? " AND is_current_draft = 1" : "";
478
480
  const row = await db.prepare(`SELECT type_id, root_id, tenant_id FROM documents WHERE ${col} = ?${draft} LIMIT 1`).bind(val).first();
479
481
  if (!row) return null;
480
- const docType = await new chunk37V3RET3_cjs.DocumentTypeRegistry(db).findById(row.type_id);
482
+ const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(row.type_id);
481
483
  const tenantId = effectiveTenantForType(getRequestTenant(c), docType?.settings);
482
484
  if (row.tenant_id !== tenantId) return null;
483
485
  return { typeId: row.type_id, rootId: row.root_id, tenantId, docType };
484
486
  }
485
487
  var adminDocumentsRoutes = new hono.Hono();
486
- adminDocumentsRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
487
- adminDocumentsRoutes.use("*", chunk37V3RET3_cjs.requireRole(["admin", "editor"]));
488
+ adminDocumentsRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
489
+ adminDocumentsRoutes.use("*", chunkBRKXMRMB_cjs.requireRole(["admin", "editor"]));
488
490
  adminDocumentsRoutes.get("/types", async (c) => {
489
491
  try {
490
- const registry = new chunk37V3RET3_cjs.DocumentTypeRegistry(c.env.DB);
492
+ const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(c.env.DB);
491
493
  const types = await registry.findAll();
492
494
  return c.json({ data: types });
493
495
  } catch (error) {
@@ -515,7 +517,7 @@ adminDocumentsRoutes.get("/", async (c) => {
515
517
  if (!typeId) {
516
518
  return c.json({ error: "type query parameter is required" }, 400);
517
519
  }
518
- const registry = new chunk37V3RET3_cjs.DocumentTypeRegistry(db);
520
+ const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
519
521
  const docType = await registry.findById(typeId);
520
522
  if (!docType || !docType.isActive) {
521
523
  return c.json({ error: "Unknown document type" }, 400);
@@ -626,7 +628,7 @@ adminDocumentsRoutes.post("/", async (c) => {
626
628
  const input = validation.data;
627
629
  const db = c.env.DB;
628
630
  const user = c.get("user");
629
- const registry = new chunk37V3RET3_cjs.DocumentTypeRegistry(db);
631
+ const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
630
632
  const docType = await registry.findById(input.typeId);
631
633
  if (!docType || !docType.isActive) {
632
634
  return c.json({ error: "Unknown document type" }, 400);
@@ -634,7 +636,7 @@ adminDocumentsRoutes.post("/", async (c) => {
634
636
  const createDenied = await denyIfNotAllowed(c, db, "", "create", docType.settings);
635
637
  if (createDenied) return createDenied;
636
638
  const tenantId = effectiveTenantForType(getRequestTenant(c), docType.settings);
637
- const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
639
+ const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
638
640
  queryableFields: docType.queryableFields,
639
641
  typeSchemaVersion: docType.schemaVersion,
640
642
  maxVersionsPerRoot: docType.settings.maxVersionsPerRoot,
@@ -672,7 +674,7 @@ adminDocumentsRoutes.put("/:rootId", async (c) => {
672
674
  const docType = scope.docType;
673
675
  const updateDenied = await denyIfNotAllowed(c, db, rootId, "update", docType?.settings, scope.tenantId);
674
676
  if (updateDenied) return updateDenied;
675
- const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
677
+ const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
676
678
  queryableFields: docType?.queryableFields ?? [],
677
679
  typeSchemaVersion: docType?.schemaVersion,
678
680
  maxVersionsPerRoot: docType?.settings.maxVersionsPerRoot,
@@ -697,7 +699,7 @@ adminDocumentsRoutes.post("/:id/publish", async (c) => {
697
699
  const docType = scope.docType;
698
700
  const publishDenied = await denyIfNotAllowed(c, db, scope.rootId, "publish", docType?.settings, scope.tenantId);
699
701
  if (publishDenied) return publishDenied;
700
- const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
702
+ const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
701
703
  queryableFields: docType?.queryableFields ?? [],
702
704
  typeSchemaVersion: docType?.schemaVersion,
703
705
  tenantId: scope.tenantId,
@@ -720,7 +722,7 @@ adminDocumentsRoutes.post("/:id/unpublish", async (c) => {
720
722
  const docType = scope.docType;
721
723
  const unpublishDenied = await denyIfNotAllowed(c, db, scope.rootId, "publish", docType?.settings, scope.tenantId);
722
724
  if (unpublishDenied) return unpublishDenied;
723
- const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
725
+ const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
724
726
  queryableFields: docType?.queryableFields ?? [],
725
727
  tenantId: scope.tenantId
726
728
  });
@@ -742,7 +744,7 @@ adminDocumentsRoutes.delete("/:id", async (c) => {
742
744
  const docType = scope.docType;
743
745
  const deleteDenied = await denyIfNotAllowed(c, db, scope.rootId, "delete", docType?.settings, scope.tenantId);
744
746
  if (deleteDenied) return deleteDenied;
745
- const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, { queryableFields: docType?.queryableFields ?? [], tenantId: scope.tenantId });
747
+ const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, { queryableFields: docType?.queryableFields ?? [], tenantId: scope.tenantId });
746
748
  if (docType?.settings.pii) {
747
749
  if (scope.rootId) await svc.erase(scope.rootId, scope.tenantId);
748
750
  } else {
@@ -758,7 +760,7 @@ adminDocumentsRoutes.post("/types/:typeId/reindex", async (c) => {
758
760
  try {
759
761
  const { typeId } = c.req.param();
760
762
  const db = c.env.DB;
761
- const registry = new chunk37V3RET3_cjs.DocumentTypeRegistry(db);
763
+ const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
762
764
  const docType = await registry.findById(typeId);
763
765
  if (!docType) return c.json({ error: "Unknown document type" }, 400);
764
766
  const reindexTenant = effectiveTenantForType(getRequestTenant(c), docType.settings);
@@ -844,6 +846,34 @@ async function dispatchHookEvent(c, event, payload, mode = "fire-and-forget") {
844
846
  return hooks.dispatch(event, payload);
845
847
  }
846
848
 
849
+ // src/plugins/cache/services/swr.ts
850
+ var STALE_TTL_MS = 3e4;
851
+ var staleMap = /* @__PURE__ */ new Map();
852
+ function markStale(cacheKey, data, collection) {
853
+ staleMap.set(cacheKey, {
854
+ data,
855
+ collection,
856
+ expiresAt: Date.now() + STALE_TTL_MS
857
+ });
858
+ }
859
+ function getAndConsumeStale(cacheKey) {
860
+ const entry = staleMap.get(cacheKey);
861
+ if (!entry) return null;
862
+ if (Date.now() > entry.expiresAt) {
863
+ staleMap.delete(cacheKey);
864
+ return null;
865
+ }
866
+ staleMap.delete(cacheKey);
867
+ return entry.data;
868
+ }
869
+ function swrStats() {
870
+ const now = Date.now();
871
+ for (const [key, entry] of staleMap.entries()) {
872
+ if (now > entry.expiresAt) staleMap.delete(key);
873
+ }
874
+ return { count: staleMap.size };
875
+ }
876
+
847
877
  // src/plugins/core-plugins/global-variables-plugin/variable-resolver.ts
848
878
  var TOKEN_PATTERN = /\{([a-z0-9_]+)\}/g;
849
879
  function resolveVariables(text, variables) {
@@ -912,13 +942,13 @@ async function resolveContentVariables(contentData, db) {
912
942
  // src/routes/api-content-crud.ts
913
943
  var apiContentCrudRoutes = new hono.Hono();
914
944
  async function resolveDocBacking(db, collectionIdOrName) {
915
- const registry = chunkQCJHCSOK_cjs.getCollectionRegistry();
945
+ const registry = chunk4DHPR7KR_cjs.getCollectionRegistry();
916
946
  const record = registry.getBySlugOrName(collectionIdOrName) ?? registry.getById(collectionIdOrName);
917
947
  if (record) {
918
- const docType2 = await new chunk37V3RET3_cjs.DocumentTypeRegistry(db).findById(record.name);
948
+ const docType2 = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(record.name);
919
949
  return docType2 ? { coll: { id: record.id, name: record.name }, docType: docType2 } : null;
920
950
  }
921
- const docType = await new chunk37V3RET3_cjs.DocumentTypeRegistry(db).findById(collectionIdOrName);
951
+ const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(collectionIdOrName);
922
952
  if (docType) {
923
953
  return { coll: { id: collectionIdOrName, name: collectionIdOrName }, docType };
924
954
  }
@@ -961,7 +991,7 @@ apiContentCrudRoutes.get("/check-slug", async (c) => {
961
991
  }, 500);
962
992
  }
963
993
  });
964
- apiContentCrudRoutes.get("/:id", chunk37V3RET3_cjs.optionalAuth(), async (c) => {
994
+ apiContentCrudRoutes.get("/:id", chunkBRKXMRMB_cjs.optionalAuth(), async (c) => {
965
995
  try {
966
996
  const id = c.req.param("id");
967
997
  const db = c.env.DB;
@@ -971,7 +1001,7 @@ apiContentCrudRoutes.get("/:id", chunk37V3RET3_cjs.optionalAuth(), async (c) =>
971
1001
  ).bind(id, getRequestTenant(c)).first();
972
1002
  let transformedContent;
973
1003
  if (docRow) {
974
- const coll = chunkQCJHCSOK_cjs.getCollectionRegistry().getByName(docRow.type_id);
1004
+ const coll = chunk4DHPR7KR_cjs.getCollectionRegistry().getByName(docRow.type_id);
975
1005
  transformedContent = {
976
1006
  id: docRow.root_id,
977
1007
  title: docRow.title,
@@ -980,8 +1010,8 @@ apiContentCrudRoutes.get("/:id", chunk37V3RET3_cjs.optionalAuth(), async (c) =>
980
1010
  collectionId: coll?.id ?? docRow.type_id,
981
1011
  data: docRow.data ? JSON.parse(docRow.data) : {},
982
1012
  // D29: document timestamps are SECONDS; legacy `content` API contract is MILLISECONDS.
983
- created_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(docRow.created_at),
984
- updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(docRow.updated_at)
1013
+ created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(docRow.created_at),
1014
+ updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(docRow.updated_at)
985
1015
  };
986
1016
  } else {
987
1017
  return c.json({ error: "Content not found" }, 404);
@@ -996,6 +1026,32 @@ apiContentCrudRoutes.get("/:id", chunk37V3RET3_cjs.optionalAuth(), async (c) =>
996
1026
  { collection: docRow.type_id, id: docRow.root_id, data: transformedContent.data },
997
1027
  "fire-and-forget"
998
1028
  );
1029
+ const fieldsParam = c.req.query("fields");
1030
+ if (fieldsParam) {
1031
+ const projFields = fieldsParam.split(",").map((s) => s.trim()).filter(Boolean);
1032
+ if (projFields.length > 0) {
1033
+ const result = {};
1034
+ const dataSubFields = [];
1035
+ for (const f of projFields) {
1036
+ if (f === "data") {
1037
+ result.data = transformedContent.data;
1038
+ } else if (f.startsWith("data.")) {
1039
+ dataSubFields.push(f.slice(5));
1040
+ } else if (Object.prototype.hasOwnProperty.call(transformedContent, f)) {
1041
+ result[f] = transformedContent[f];
1042
+ }
1043
+ }
1044
+ if (dataSubFields.length > 0 && !result.data) {
1045
+ result.data = {};
1046
+ for (const sub of dataSubFields) {
1047
+ if (transformedContent.data && Object.prototype.hasOwnProperty.call(transformedContent.data, sub)) {
1048
+ result.data[sub] = transformedContent.data[sub];
1049
+ }
1050
+ }
1051
+ }
1052
+ return c.json({ data: result });
1053
+ }
1054
+ }
999
1055
  return c.json({ data: transformedContent });
1000
1056
  } catch (error) {
1001
1057
  console.error("Error fetching content:", error);
@@ -1005,7 +1061,7 @@ apiContentCrudRoutes.get("/:id", chunk37V3RET3_cjs.optionalAuth(), async (c) =>
1005
1061
  }, 500);
1006
1062
  }
1007
1063
  });
1008
- apiContentCrudRoutes.post("/", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
1064
+ apiContentCrudRoutes.post("/", chunkBRKXMRMB_cjs.requireAuth(), chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
1009
1065
  try {
1010
1066
  const db = c.env.DB;
1011
1067
  const user = c.get("user");
@@ -1039,7 +1095,7 @@ apiContentCrudRoutes.post("/", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_cj
1039
1095
  return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
1040
1096
  }
1041
1097
  const tenantId = getRequestTenant(c);
1042
- const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
1098
+ const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
1043
1099
  queryableFields: backing.docType.queryableFields ?? [],
1044
1100
  typeSchemaVersion: backing.docType.schemaVersion ?? 1,
1045
1101
  maxVersionsPerRoot: backing.docType.settings?.maxVersionsPerRoot ?? 50,
@@ -1058,9 +1114,9 @@ apiContentCrudRoutes.post("/", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_cj
1058
1114
  }),
1059
1115
  user?.userId
1060
1116
  );
1061
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
1062
- await cache.invalidate("content-filtered:*");
1063
- await cache.invalidate("collection-content-filtered:*");
1117
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
1118
+ await cache.invalidate("api:content-filtered:*");
1119
+ await cache.invalidate(`api:collection-content-filtered:${backing.coll.name}:*`);
1064
1120
  dispatchHookEvent(
1065
1121
  c,
1066
1122
  "content:after:create",
@@ -1068,7 +1124,7 @@ apiContentCrudRoutes.post("/", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_cj
1068
1124
  "fire-and-forget"
1069
1125
  );
1070
1126
  return c.json({
1071
- data: { id: doc.rootId, title: doc.title, slug: doc.slug, status: doc.status, collectionId: backing.coll.id, data: doc.data, created_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(doc.createdAt), updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(doc.updatedAt) }
1127
+ data: { id: doc.rootId, title: doc.title, slug: doc.slug, status: doc.status, collectionId: backing.coll.id, data: doc.data, created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(doc.createdAt), updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(doc.updatedAt) }
1072
1128
  }, 201);
1073
1129
  }
1074
1130
  return c.json({ error: "Collection is not document-backed" }, 400);
@@ -1080,7 +1136,7 @@ apiContentCrudRoutes.post("/", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_cj
1080
1136
  }, 500);
1081
1137
  }
1082
1138
  });
1083
- apiContentCrudRoutes.put("/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
1139
+ apiContentCrudRoutes.put("/:id", chunkBRKXMRMB_cjs.requireAuth(), chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
1084
1140
  try {
1085
1141
  const id = c.req.param("id");
1086
1142
  const db = c.env.DB;
@@ -1102,8 +1158,8 @@ apiContentCrudRoutes.put("/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_
1102
1158
  } catch (err) {
1103
1159
  return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
1104
1160
  }
1105
- const docType = await new chunk37V3RET3_cjs.DocumentTypeRegistry(db).findById(docRow.type_id);
1106
- const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
1161
+ const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(docRow.type_id);
1162
+ const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
1107
1163
  queryableFields: docType?.queryableFields ?? [],
1108
1164
  typeSchemaVersion: docType?.schemaVersion ?? 1,
1109
1165
  maxVersionsPerRoot: docType?.settings?.maxVersionsPerRoot ?? 50,
@@ -1122,10 +1178,10 @@ apiContentCrudRoutes.put("/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_
1122
1178
  } else if (body.status === "draft" && pub) {
1123
1179
  await svc.unpublish(pub.id);
1124
1180
  }
1125
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
1126
- await cache.invalidate("content-filtered:*");
1127
- await cache.invalidate("collection-content-filtered:*");
1128
- const coll = chunkQCJHCSOK_cjs.getCollectionRegistry().getByName(docRow.type_id);
1181
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
1182
+ await cache.invalidate("api:content-filtered:*");
1183
+ await cache.invalidate(`api:collection-content-filtered:${docRow.type_id}:*`);
1184
+ const coll = chunk4DHPR7KR_cjs.getCollectionRegistry().getByName(docRow.type_id);
1129
1185
  const saved = await db.prepare("SELECT * FROM documents WHERE id = ?").bind(newDraft.id).first();
1130
1186
  const savedData = saved?.data ? JSON.parse(saved.data) : {};
1131
1187
  dispatchHookEvent(c, "content:after:update", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
@@ -1134,7 +1190,7 @@ apiContentCrudRoutes.put("/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_
1134
1190
  dispatchHookEvent(c, "content:after:publish", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
1135
1191
  }
1136
1192
  return c.json({
1137
- data: { id: saved.root_id, title: saved.title, slug: saved.slug, status: saved.status, collectionId: coll?.id ?? docRow.type_id, data: savedData, created_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(saved.created_at), updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(saved.updated_at) }
1193
+ data: { id: saved.root_id, title: saved.title, slug: saved.slug, status: saved.status, collectionId: coll?.id ?? docRow.type_id, data: savedData, created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(saved.created_at), updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(saved.updated_at) }
1138
1194
  });
1139
1195
  }
1140
1196
  return c.json({ error: "Content not found" }, 404);
@@ -1146,7 +1202,7 @@ apiContentCrudRoutes.put("/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_
1146
1202
  }, 500);
1147
1203
  }
1148
1204
  });
1149
- apiContentCrudRoutes.delete("/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
1205
+ apiContentCrudRoutes.delete("/:id", chunkBRKXMRMB_cjs.requireAuth(), chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
1150
1206
  try {
1151
1207
  const id = c.req.param("id");
1152
1208
  const db = c.env.DB;
@@ -1162,9 +1218,9 @@ apiContentCrudRoutes.delete("/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3RE
1162
1218
  }
1163
1219
  const now = Math.floor(Date.now() / 1e3);
1164
1220
  await db.prepare("UPDATE documents SET deleted_at = ?, updated_at = ? WHERE root_id = ? AND tenant_id = ?").bind(now, now, id, tenantId).run();
1165
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
1166
- await cache.invalidate("content-filtered:*");
1167
- await cache.invalidate("collection-content-filtered:*");
1221
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
1222
+ await cache.invalidate("api:content-filtered:*");
1223
+ await cache.invalidate(`api:collection-content-filtered:${docRow.type_id}:*`);
1168
1224
  dispatchHookEvent(c, "content:after:delete", { collection: docRow.type_id, id, data: {}, user: actor }, "fire-and-forget");
1169
1225
  return c.json({ success: true });
1170
1226
  }
@@ -1180,6 +1236,22 @@ apiContentCrudRoutes.delete("/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3RE
1180
1236
  var api_content_crud_default = apiContentCrudRoutes;
1181
1237
 
1182
1238
  // src/routes/api.ts
1239
+ function isAnonPrincipal(principalSet) {
1240
+ return principalSet.length === 1 && principalSet[0]?.type === "public";
1241
+ }
1242
+ async function typeReadAllowed(db, principalSet, docType, typeName) {
1243
+ const perms = new DocumentPermissionsService(db);
1244
+ if (perms.isAllowedSync(principalSet, [], "read", docType?.settings ?? {})) return true;
1245
+ const rbac = new chunkOLEOKHDX_cjs.RbacService(db);
1246
+ let anyRbacRoleFound = false;
1247
+ for (const p of principalSet) {
1248
+ if (p.type !== "role") continue;
1249
+ if (!await rbac.hasRbacRole(p.id)) continue;
1250
+ anyRbacRoleFound = true;
1251
+ if (await rbac.isGrantedForRole(p.id, `document_type:${typeName}`, "read")) return true;
1252
+ }
1253
+ return !anyRbacRoleFound;
1254
+ }
1183
1255
  var DOC_SORTABLE_COLUMNS = /* @__PURE__ */ new Set([
1184
1256
  "created_at",
1185
1257
  "updated_at",
@@ -1259,10 +1331,37 @@ function mapDocRowToContent(row, collectionId) {
1259
1331
  collectionId,
1260
1332
  data: row.data ? JSON.parse(row.data) : {},
1261
1333
  // D29: document timestamps are SECONDS; the legacy `content` API contract is MILLISECONDS.
1262
- created_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(row.created_at),
1263
- updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(row.updated_at)
1334
+ created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(row.created_at),
1335
+ updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(row.updated_at)
1264
1336
  };
1265
1337
  }
1338
+ function projectFields(item, fields) {
1339
+ if (fields.length === 0) return item;
1340
+ const result = {};
1341
+ const dataSubFields = [];
1342
+ for (const f of fields) {
1343
+ if (f === "data") {
1344
+ result.data = item.data;
1345
+ } else if (f.startsWith("data.")) {
1346
+ dataSubFields.push(f.slice(5));
1347
+ } else if (Object.prototype.hasOwnProperty.call(item, f)) {
1348
+ result[f] = item[f];
1349
+ }
1350
+ }
1351
+ if (dataSubFields.length > 0 && !result.data) {
1352
+ result.data = {};
1353
+ for (const sub of dataSubFields) {
1354
+ if (item.data && Object.prototype.hasOwnProperty.call(item.data, sub)) {
1355
+ result.data[sub] = item.data[sub];
1356
+ }
1357
+ }
1358
+ }
1359
+ return result;
1360
+ }
1361
+ function parseFieldsParam(raw2) {
1362
+ if (!raw2) return [];
1363
+ return raw2.split(",").map((s) => s.trim()).filter(Boolean);
1364
+ }
1266
1365
  var apiRoutes = new hono.Hono();
1267
1366
  apiRoutes.use("*", async (c, next) => {
1268
1367
  const startTime = Date.now();
@@ -1272,7 +1371,8 @@ apiRoutes.use("*", async (c, next) => {
1272
1371
  c.header("X-Response-Time", `${totalTime}ms`);
1273
1372
  });
1274
1373
  apiRoutes.use("*", async (c, next) => {
1275
- const cacheEnabled = await chunk37V3RET3_cjs.isPluginActive(c.env.DB, "core-cache");
1374
+ const bypass = c.req.header("Cache-Control") === "no-cache";
1375
+ const cacheEnabled = !bypass && await chunk4DHPR7KR_cjs.isPluginActive(c.env.DB, "core-cache");
1276
1376
  c.set("cacheEnabled", cacheEnabled);
1277
1377
  await next();
1278
1378
  });
@@ -1295,7 +1395,7 @@ apiRoutes.get("/", (c) => {
1295
1395
  openapi: "3.0.0",
1296
1396
  info: {
1297
1397
  title: "SonicJS AI API",
1298
- version: chunkKKNEYIZJ_cjs.getCoreVersion(),
1398
+ version: chunkXZUEGFXE_cjs.getCoreVersion(),
1299
1399
  description: "RESTful API for SonicJS headless CMS - a modern, AI-powered content management system built on Cloudflare Workers",
1300
1400
  contact: {
1301
1401
  name: "SonicJS Support",
@@ -1699,7 +1799,7 @@ apiRoutes.get("/collections", async (c) => {
1699
1799
  try {
1700
1800
  const db = c.env.DB;
1701
1801
  const cacheEnabled = c.get("cacheEnabled");
1702
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
1802
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
1703
1803
  const cacheKey = cache.generateKey("collections", "all");
1704
1804
  if (cacheEnabled) {
1705
1805
  const cacheResult = await cache.getWithSource(cacheKey);
@@ -1725,8 +1825,8 @@ apiRoutes.get("/collections", async (c) => {
1725
1825
  }
1726
1826
  c.header("X-Cache-Status", "MISS");
1727
1827
  c.header("X-Cache-Source", "registry");
1728
- const records = chunkQCJHCSOK_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
1729
- const transformedResults = records.map(chunkQCJHCSOK_cjs.collectionRecordToRow);
1828
+ const records = chunk4DHPR7KR_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
1829
+ const transformedResults = records.map(chunk4DHPR7KR_cjs.collectionRecordToRow);
1730
1830
  const responseData = {
1731
1831
  data: transformedResults,
1732
1832
  meta: addTimingMeta(c, {
@@ -1747,16 +1847,21 @@ apiRoutes.get("/collections", async (c) => {
1747
1847
  return c.json({ error: "Failed to fetch collections" }, 500);
1748
1848
  }
1749
1849
  });
1750
- apiRoutes.get("/content", chunk37V3RET3_cjs.optionalAuth(), async (c) => {
1850
+ apiRoutes.get("/content", chunkBRKXMRMB_cjs.optionalAuth(), async (c) => {
1751
1851
  const executionStart = Date.now();
1752
1852
  try {
1753
1853
  const db = c.env.DB;
1754
1854
  const queryParams = c.req.query();
1855
+ const projFields = parseFieldsParam(queryParams.fields);
1856
+ if (queryParams.fields) delete queryParams.fields;
1755
1857
  const role = c.get("user")?.role;
1858
+ const { tenantId: cTenantId, principalSet: cPrincipalSet } = getDocumentRequestContext(c);
1859
+ const cAnon = isAnonPrincipal(cPrincipalSet);
1860
+ const cNeedsAcl = !cAnon && !canReadNonPublicContent(role);
1756
1861
  const collIdByName = /* @__PURE__ */ new Map();
1757
1862
  let typeId;
1758
1863
  let typeIds;
1759
- const registry = chunkQCJHCSOK_cjs.getCollectionRegistry();
1864
+ const registry = chunk4DHPR7KR_cjs.getCollectionRegistry();
1760
1865
  if (queryParams.collection) {
1761
1866
  const collectionName = queryParams.collection;
1762
1867
  const record = registry.getByName(collectionName);
@@ -1786,11 +1891,11 @@ apiRoutes.get("/content", chunk37V3RET3_cjs.optionalAuth(), async (c) => {
1786
1891
  return r.name;
1787
1892
  });
1788
1893
  }
1789
- const filter = chunkIXUHXTHW_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
1894
+ const filter = chunkSFGYZUWU_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
1790
1895
  const normalizedFilter = augmentFilterForDocuments(filter, { typeId, typeIds, role });
1791
1896
  if (!normalizedFilter.limit) normalizedFilter.limit = 50;
1792
1897
  normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
1793
- const builder = new chunkIXUHXTHW_cjs.QueryFilterBuilder();
1898
+ const builder = new chunkSFGYZUWU_cjs.QueryFilterBuilder();
1794
1899
  const queryResult = builder.build("documents", normalizedFilter);
1795
1900
  if (queryResult.errors.length > 0) {
1796
1901
  return c.json({
@@ -1798,8 +1903,8 @@ apiRoutes.get("/content", chunk37V3RET3_cjs.optionalAuth(), async (c) => {
1798
1903
  details: queryResult.errors
1799
1904
  }, 400);
1800
1905
  }
1801
- const cacheEnabled = c.get("cacheEnabled");
1802
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
1906
+ const cacheEnabled = c.get("cacheEnabled") && !cNeedsAcl;
1907
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
1803
1908
  const cacheKey = cache.generateKey("content-filtered", JSON.stringify({ filter: normalizedFilter, query: queryResult.sql }));
1804
1909
  if (cacheEnabled) {
1805
1910
  const cacheResult = await cache.getWithSource(cacheKey);
@@ -1820,19 +1925,61 @@ apiRoutes.get("/content", chunk37V3RET3_cjs.optionalAuth(), async (c) => {
1820
1925
  }
1821
1926
  }, executionStart)
1822
1927
  };
1928
+ chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: typeId ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: cacheResult.source });
1929
+ chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
1823
1930
  return c.json(dataWithMeta);
1824
1931
  }
1932
+ const swrData = getAndConsumeStale(cacheKey);
1933
+ if (swrData) {
1934
+ c.header("X-Cache-Status", "STALE");
1935
+ c.header("X-Cache-Source", "swr");
1936
+ chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: typeId ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: "swr" });
1937
+ chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
1938
+ return c.json({ ...swrData, meta: addTimingMeta(c, { ...swrData.meta, cache: { hit: true, source: "swr", stale: true } }, executionStart) });
1939
+ }
1940
+ chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: typeId ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: "miss" });
1941
+ chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
1825
1942
  }
1826
1943
  c.header("X-Cache-Status", "MISS");
1827
1944
  c.header("X-Cache-Source", "database");
1828
1945
  const stmt = db.prepare(queryResult.sql);
1829
1946
  const boundStmt = queryResult.params.length > 0 ? stmt.bind(...queryResult.params) : stmt;
1830
1947
  const { results } = await boundStmt.all();
1831
- const transformedResults = results.map((row) => mapDocRowToContent(row, collIdByName.get(row.type_id) ?? null));
1948
+ let aclResults = results;
1949
+ if (cNeedsAcl) {
1950
+ const typeReg = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
1951
+ const repo = new DocumentRepository(db, cTenantId);
1952
+ const uniqueTypeIds = [...new Set(results.map((r) => r.type_id))];
1953
+ const typeSettingsMap = /* @__PURE__ */ new Map();
1954
+ const typeRbacOnlyMap = /* @__PURE__ */ new Map();
1955
+ const typeDeniedMap = /* @__PURE__ */ new Map();
1956
+ await Promise.all(uniqueTypeIds.map(async (tid) => {
1957
+ const dt = await typeReg.findById(tid);
1958
+ const settings = dt?.settings ?? {};
1959
+ typeSettingsMap.set(tid, settings);
1960
+ const allowed2 = await typeReadAllowed(db, cPrincipalSet, dt, tid);
1961
+ if (!allowed2) {
1962
+ typeDeniedMap.set(tid, true);
1963
+ return;
1964
+ }
1965
+ const perms = new DocumentPermissionsService(db);
1966
+ typeRbacOnlyMap.set(tid, !perms.isAllowedSync(cPrincipalSet, [], "read", settings));
1967
+ }));
1968
+ const allowed = await Promise.all(
1969
+ results.map((row) => {
1970
+ const tid = row.type_id;
1971
+ if (typeDeniedMap.get(tid)) return Promise.resolve(false);
1972
+ if (typeRbacOnlyMap.get(tid)) return Promise.resolve(true);
1973
+ return repo.isAllowed(cPrincipalSet, row.root_id, "read", typeSettingsMap.get(tid) ?? {});
1974
+ })
1975
+ );
1976
+ aclResults = results.filter((_, i) => allowed[i]);
1977
+ }
1978
+ const transformedResults = aclResults.map((row) => mapDocRowToContent(row, collIdByName.get(row.type_id) ?? null));
1832
1979
  const responseData = {
1833
- data: transformedResults,
1980
+ data: projFields.length ? transformedResults.map((item) => projectFields(item, projFields)) : transformedResults,
1834
1981
  meta: addTimingMeta(c, {
1835
- count: results.length,
1982
+ count: aclResults.length,
1836
1983
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1837
1984
  // D44: echo the caller's filter with the access policy applied (status=published forced for
1838
1985
  // anonymous callers — the visible enforcement proof), NOT the internal doc-augmented where-tree.
@@ -1843,7 +1990,7 @@ apiRoutes.get("/content", chunk37V3RET3_cjs.optionalAuth(), async (c) => {
1843
1990
  }
1844
1991
  }, executionStart)
1845
1992
  };
1846
- if (cacheEnabled) {
1993
+ if (cacheEnabled && projFields.length === 0) {
1847
1994
  await cache.set(cacheKey, responseData);
1848
1995
  }
1849
1996
  return c.json(responseData);
@@ -1855,26 +2002,36 @@ apiRoutes.get("/content", chunk37V3RET3_cjs.optionalAuth(), async (c) => {
1855
2002
  }, 500);
1856
2003
  }
1857
2004
  });
1858
- apiRoutes.get("/collections/:collection/content", chunk37V3RET3_cjs.optionalAuth(), async (c) => {
2005
+ apiRoutes.get("/collections/:collection/content", chunkBRKXMRMB_cjs.optionalAuth(), async (c) => {
1859
2006
  const executionStart = Date.now();
1860
2007
  try {
1861
2008
  const collection = c.req.param("collection");
1862
2009
  const db = c.env.DB;
1863
2010
  const queryParams = c.req.query();
1864
- const record = chunkQCJHCSOK_cjs.getCollectionRegistry().getBySlugOrName(collection);
2011
+ const record = chunk4DHPR7KR_cjs.getCollectionRegistry().getBySlugOrName(collection);
1865
2012
  if (!record || record.isActive === false) {
1866
2013
  return c.json({ error: "Collection not found" }, 404);
1867
2014
  }
1868
2015
  const collIdByName = /* @__PURE__ */ new Map();
1869
2016
  collIdByName.set(collection, record.id);
1870
2017
  const role = c.get("user")?.role;
1871
- const filter = chunkIXUHXTHW_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
2018
+ const { tenantId: ccTenantId, principalSet: ccPrincipalSet } = getDocumentRequestContext(c);
2019
+ const ccAnon = isAnonPrincipal(ccPrincipalSet);
2020
+ const ccNeedsAcl = !ccAnon && !canReadNonPublicContent(role);
2021
+ let ccDocType;
2022
+ if (ccNeedsAcl) {
2023
+ ccDocType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(record.name);
2024
+ if (!await typeReadAllowed(db, ccPrincipalSet, ccDocType, record.name)) {
2025
+ return c.json({ error: "Forbidden" }, 403);
2026
+ }
2027
+ }
2028
+ const filter = chunkSFGYZUWU_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
1872
2029
  const normalizedFilter = augmentFilterForDocuments(filter, { typeId: collection, role });
1873
2030
  if (!normalizedFilter.limit) {
1874
2031
  normalizedFilter.limit = 50;
1875
2032
  }
1876
2033
  normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
1877
- const builder = new chunkIXUHXTHW_cjs.QueryFilterBuilder();
2034
+ const builder = new chunkSFGYZUWU_cjs.QueryFilterBuilder();
1878
2035
  const queryResult = builder.build("documents", normalizedFilter);
1879
2036
  if (queryResult.errors.length > 0) {
1880
2037
  return c.json({
@@ -1882,8 +2039,8 @@ apiRoutes.get("/collections/:collection/content", chunk37V3RET3_cjs.optionalAuth
1882
2039
  details: queryResult.errors
1883
2040
  }, 400);
1884
2041
  }
1885
- const cacheEnabled = c.get("cacheEnabled");
1886
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
2042
+ const cacheEnabled = c.get("cacheEnabled") && !ccNeedsAcl;
2043
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
1887
2044
  const includeCollection = queryParams.include?.split(",").map((s) => s.trim()).includes("collection");
1888
2045
  const cacheKey = cache.generateKey("collection-content-filtered", `${collection}:${JSON.stringify({ filter: normalizedFilter, query: queryResult.sql, includeCollection })}`);
1889
2046
  if (cacheEnabled) {
@@ -1905,20 +2062,44 @@ apiRoutes.get("/collections/:collection/content", chunk37V3RET3_cjs.optionalAuth
1905
2062
  }
1906
2063
  }, executionStart)
1907
2064
  };
2065
+ chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: collection ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: cacheResult.source });
2066
+ chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
1908
2067
  return c.json(dataWithMeta);
1909
2068
  }
2069
+ const swrData = getAndConsumeStale(cacheKey);
2070
+ if (swrData) {
2071
+ c.header("X-Cache-Status", "STALE");
2072
+ c.header("X-Cache-Source", "swr");
2073
+ chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: collection ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: "swr" });
2074
+ chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
2075
+ return c.json({ ...swrData, meta: addTimingMeta(c, { ...swrData.meta, cache: { hit: true, source: "swr", stale: true } }, executionStart) });
2076
+ }
2077
+ chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: collection ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: "miss" });
2078
+ chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
1910
2079
  }
1911
2080
  c.header("X-Cache-Status", "MISS");
1912
2081
  c.header("X-Cache-Source", "database");
1913
2082
  const stmt = db.prepare(queryResult.sql);
1914
2083
  const boundStmt = queryResult.params.length > 0 ? stmt.bind(...queryResult.params) : stmt;
1915
2084
  const { results } = await boundStmt.all();
1916
- const transformedResults = results.map((row) => mapDocRowToContent(row, collIdByName.get(row.type_id) ?? null));
2085
+ let ccAclResults = results;
2086
+ if (ccNeedsAcl) {
2087
+ const ccPerms = new DocumentPermissionsService(db);
2088
+ const ccBaseGrantsPass = ccPerms.isAllowedSync(ccPrincipalSet, [], "read", ccDocType?.settings ?? {});
2089
+ if (ccBaseGrantsPass) {
2090
+ const repo = new DocumentRepository(db, ccTenantId);
2091
+ const allowed = await Promise.all(
2092
+ results.map((row) => repo.isAllowed(ccPrincipalSet, row.root_id, "read", ccDocType?.settings ?? {}))
2093
+ );
2094
+ ccAclResults = results.filter((_, i) => allowed[i]);
2095
+ }
2096
+ }
2097
+ const transformedResults = ccAclResults.map((row) => mapDocRowToContent(row, collIdByName.get(row.type_id) ?? null));
1917
2098
  const responseData = {
1918
2099
  data: transformedResults,
1919
2100
  meta: addTimingMeta(c, {
1920
- ...includeCollection ? { collection: chunkQCJHCSOK_cjs.collectionRecordToRow(record) } : {},
1921
- count: results.length,
2101
+ ...includeCollection ? { collection: chunk4DHPR7KR_cjs.collectionRecordToRow(record) } : {},
2102
+ count: ccAclResults.length,
1922
2103
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1923
2104
  // D44: echo the caller's filter with the access policy applied (status=published forced for
1924
2105
  // anonymous callers — the visible enforcement proof), NOT the internal doc-augmented where-tree.
@@ -1942,32 +2123,44 @@ apiRoutes.get("/collections/:collection/content", chunk37V3RET3_cjs.optionalAuth
1942
2123
  }
1943
2124
  });
1944
2125
  apiRoutes.route("/content", api_content_crud_default);
1945
- apiRoutes.get("/:collection", chunk37V3RET3_cjs.optionalAuth(), async (c) => {
2126
+ apiRoutes.get("/:collection", chunkBRKXMRMB_cjs.optionalAuth(), async (c) => {
1946
2127
  const executionStart = Date.now();
1947
2128
  try {
1948
2129
  const collection = c.req.param("collection");
1949
2130
  const db = c.env.DB;
1950
2131
  const queryParams = c.req.query();
1951
- const record = chunkQCJHCSOK_cjs.getCollectionRegistry().getBySlugOrName(collection);
2132
+ const projFields = parseFieldsParam(queryParams.fields);
2133
+ if (queryParams.fields) delete queryParams.fields;
2134
+ const record = chunk4DHPR7KR_cjs.getCollectionRegistry().getBySlugOrName(collection);
1952
2135
  if (!record || record.isActive === false) {
1953
2136
  return c.json({ error: "Collection not found" }, 404);
1954
2137
  }
1955
2138
  const collIdByName = /* @__PURE__ */ new Map();
1956
2139
  collIdByName.set(record.name, record.id);
1957
2140
  const role = c.get("user")?.role;
1958
- const filter = chunkIXUHXTHW_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
2141
+ const { tenantId, principalSet } = getDocumentRequestContext(c);
2142
+ const anon = isAnonPrincipal(principalSet);
2143
+ const needsAcl = !anon && !canReadNonPublicContent(role);
2144
+ let docTypeForCheck;
2145
+ if (needsAcl) {
2146
+ docTypeForCheck = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(record.name);
2147
+ if (!await typeReadAllowed(db, principalSet, docTypeForCheck, record.name)) {
2148
+ return c.json({ error: "Forbidden" }, 403);
2149
+ }
2150
+ }
2151
+ const filter = chunkSFGYZUWU_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
1959
2152
  const normalizedFilter = augmentFilterForDocuments(filter, { typeId: record.name, role });
1960
2153
  if (!normalizedFilter.limit) normalizedFilter.limit = 50;
1961
2154
  normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
1962
- const builder = new chunkIXUHXTHW_cjs.QueryFilterBuilder();
2155
+ const builder = new chunkSFGYZUWU_cjs.QueryFilterBuilder();
1963
2156
  const queryResult = builder.build("documents", normalizedFilter);
1964
2157
  if (queryResult.errors.length > 0) {
1965
2158
  return c.json({ error: "Invalid filter parameters", details: queryResult.errors }, 400);
1966
2159
  }
1967
2160
  const collectionCache = record.cache;
1968
2161
  const collectionCacheDisabled = collectionCache?.enabled === false;
1969
- const cacheEnabled = c.get("cacheEnabled") && !collectionCacheDisabled;
1970
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
2162
+ const cacheEnabled = c.get("cacheEnabled") && !collectionCacheDisabled && projFields.length === 0 && !needsAcl;
2163
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
1971
2164
  const includeCollection = queryParams.include?.split(",").map((s) => s.trim()).includes("collection");
1972
2165
  const cacheKey = cache.generateKey("collection-content-filtered", `${collection}:${JSON.stringify({ filter: normalizedFilter, query: queryResult.sql, includeCollection })}`);
1973
2166
  if (cacheEnabled) {
@@ -1976,20 +2169,45 @@ apiRoutes.get("/:collection", chunk37V3RET3_cjs.optionalAuth(), async (c) => {
1976
2169
  c.header("X-Cache-Status", "HIT");
1977
2170
  c.header("X-Cache-Source", cacheResult.source);
1978
2171
  if (cacheResult.ttl) c.header("X-Cache-TTL", Math.floor(cacheResult.ttl).toString());
2172
+ chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: collection ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: cacheResult.source });
2173
+ chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
1979
2174
  return c.json({ ...cacheResult.data, meta: addTimingMeta(c, { ...cacheResult.data.meta, cache: { hit: true, source: cacheResult.source, ttl: cacheResult.ttl ? Math.floor(cacheResult.ttl) : void 0 } }, executionStart) });
1980
2175
  }
2176
+ const swrData = getAndConsumeStale(cacheKey);
2177
+ if (swrData) {
2178
+ c.header("X-Cache-Status", "STALE");
2179
+ c.header("X-Cache-Source", "swr");
2180
+ chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: collection ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: "swr" });
2181
+ chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
2182
+ return c.json({ ...swrData, meta: addTimingMeta(c, { ...swrData.meta, cache: { hit: true, source: "swr", stale: true } }, executionStart) });
2183
+ }
2184
+ chunkFZGIU5AZ_cjs.recordCatalogRequest({ cacheKey, collection: collection ?? null, path: c.req.path, queryString: c.req.raw.url.split("?")[1] ?? "", source: "miss" });
2185
+ chunkFZGIU5AZ_cjs.scheduleKvWrite(cacheKey, c.executionCtx);
1981
2186
  }
1982
2187
  c.header("X-Cache-Status", "MISS");
1983
2188
  c.header("X-Cache-Source", "database");
1984
2189
  const stmt = db.prepare(queryResult.sql);
1985
2190
  const boundStmt = queryResult.params.length > 0 ? stmt.bind(...queryResult.params) : stmt;
1986
2191
  const { results } = await boundStmt.all();
1987
- const transformedResults = results.map((row) => mapDocRowToContent(row, collIdByName.get(row.type_id) ?? null));
2192
+ let aclResults = results;
2193
+ if (needsAcl) {
2194
+ const perms = new DocumentPermissionsService(db);
2195
+ const baseGrantsPass = perms.isAllowedSync(principalSet, [], "read", docTypeForCheck?.settings ?? {});
2196
+ if (!baseGrantsPass) {
2197
+ } else {
2198
+ const repo = new DocumentRepository(db, tenantId);
2199
+ const allowed = await Promise.all(
2200
+ results.map((row) => repo.isAllowed(principalSet, row.root_id, "read", docTypeForCheck?.settings ?? {}))
2201
+ );
2202
+ aclResults = results.filter((_, i) => allowed[i]);
2203
+ }
2204
+ }
2205
+ const transformedResults = aclResults.map((row) => mapDocRowToContent(row, collIdByName.get(row.type_id) ?? null));
1988
2206
  const responseData = {
1989
- data: transformedResults,
2207
+ data: projFields.length ? transformedResults.map((item) => projectFields(item, projFields)) : transformedResults,
1990
2208
  meta: addTimingMeta(c, {
1991
- ...includeCollection ? { collection: chunkQCJHCSOK_cjs.collectionRecordToRow(record) } : {},
1992
- count: results.length,
2209
+ ...includeCollection ? { collection: chunk4DHPR7KR_cjs.collectionRecordToRow(record) } : {},
2210
+ count: aclResults.length,
1993
2211
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1994
2212
  filter: normalizePublicContentFilter(filter, role),
1995
2213
  cache: { hit: false, source: "database" }
@@ -2006,12 +2224,12 @@ apiRoutes.get("/:collection", chunk37V3RET3_cjs.optionalAuth(), async (c) => {
2006
2224
  return c.json({ error: "Failed to fetch content", details: error instanceof Error ? error.message : String(error) }, 500);
2007
2225
  }
2008
2226
  });
2009
- apiRoutes.get("/:collection/:id", chunk37V3RET3_cjs.optionalAuth(), async (c) => {
2227
+ apiRoutes.get("/:collection/:id", chunkBRKXMRMB_cjs.optionalAuth(), async (c) => {
2010
2228
  try {
2011
2229
  const collection = c.req.param("collection");
2012
2230
  const id = c.req.param("id");
2013
2231
  const db = c.env.DB;
2014
- const record = chunkQCJHCSOK_cjs.getCollectionRegistry().getBySlugOrName(collection);
2232
+ const record = chunk4DHPR7KR_cjs.getCollectionRegistry().getBySlugOrName(collection);
2015
2233
  if (!record || record.isActive === false) {
2016
2234
  return c.json({ error: "Collection not found" }, 404);
2017
2235
  }
@@ -2020,7 +2238,24 @@ apiRoutes.get("/:collection/:id", chunk37V3RET3_cjs.optionalAuth(), async (c) =>
2020
2238
  privileged ? "SELECT * FROM documents WHERE root_id = ? AND type_id = ? AND tenant_id = 'default' AND is_current_draft = 1 AND deleted_at IS NULL" : "SELECT * FROM documents WHERE root_id = ? AND type_id = ? AND tenant_id = 'default' AND is_published = 1 AND deleted_at IS NULL"
2021
2239
  ).bind(id, record.name).first();
2022
2240
  if (!docRow) return c.json({ error: "Content not found" }, 404);
2023
- const coll = chunkQCJHCSOK_cjs.getCollectionRegistry().getByName(docRow.type_id);
2241
+ const colRole = c.get("user")?.role;
2242
+ const { tenantId: colTenantId, principalSet: colPrincipalSet } = getDocumentRequestContext(c);
2243
+ const colNeedsAcl = !isAnonPrincipal(colPrincipalSet) && !canReadNonPublicContent(colRole);
2244
+ if (colNeedsAcl) {
2245
+ const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(record.name);
2246
+ if (!await typeReadAllowed(db, colPrincipalSet, docType, record.name)) {
2247
+ return c.json({ error: "Content not found" }, 404);
2248
+ }
2249
+ const perms = new DocumentPermissionsService(db);
2250
+ if (perms.isAllowedSync(colPrincipalSet, [], "read", docType?.settings ?? {})) {
2251
+ const repo = new DocumentRepository(db, colTenantId);
2252
+ if (!await repo.isAllowed(colPrincipalSet, docRow.root_id, "read", docType?.settings ?? {})) {
2253
+ return c.json({ error: "Content not found" }, 404);
2254
+ }
2255
+ }
2256
+ }
2257
+ const projFields = parseFieldsParam(c.req.query("fields"));
2258
+ const coll = chunk4DHPR7KR_cjs.getCollectionRegistry().getByName(docRow.type_id);
2024
2259
  const transformedContent = {
2025
2260
  id: docRow.root_id,
2026
2261
  title: docRow.title,
@@ -2028,17 +2263,17 @@ apiRoutes.get("/:collection/:id", chunk37V3RET3_cjs.optionalAuth(), async (c) =>
2028
2263
  status: docRow.status,
2029
2264
  collectionId: coll?.id ?? docRow.type_id,
2030
2265
  data: docRow.data ? JSON.parse(docRow.data) : {},
2031
- created_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(docRow.created_at),
2032
- updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(docRow.updated_at)
2266
+ created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(docRow.created_at),
2267
+ updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(docRow.updated_at)
2033
2268
  };
2034
2269
  dispatchHookEvent(c, "content:read", { collection: docRow.type_id, id: docRow.root_id, data: transformedContent.data }, "fire-and-forget");
2035
- return c.json({ data: transformedContent });
2270
+ return c.json({ data: projFields.length ? projectFields(transformedContent, projFields) : transformedContent });
2036
2271
  } catch (error) {
2037
2272
  console.error("Error fetching content:", error);
2038
2273
  return c.json({ error: "Failed to fetch content", details: error instanceof Error ? error.message : String(error) }, 500);
2039
2274
  }
2040
2275
  });
2041
- apiRoutes.post("/:collection", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
2276
+ apiRoutes.post("/:collection", chunkBRKXMRMB_cjs.requireAuth(), chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
2042
2277
  try {
2043
2278
  const collection = c.req.param("collection");
2044
2279
  const db = c.env.DB;
@@ -2059,26 +2294,29 @@ apiRoutes.post("/:collection", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_cj
2059
2294
  } catch (err) {
2060
2295
  return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
2061
2296
  }
2062
- const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, { queryableFields: backing.docType.queryableFields ?? [], typeSchemaVersion: backing.docType.schemaVersion ?? 1, maxVersionsPerRoot: backing.docType.settings?.maxVersionsPerRoot ?? 50, tenantId: "default", versioning: backing.docType.settings?.versioning ?? false });
2297
+ const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, { queryableFields: backing.docType.queryableFields ?? [], typeSchemaVersion: backing.docType.schemaVersion ?? 1, maxVersionsPerRoot: backing.docType.settings?.maxVersionsPerRoot ?? 50, tenantId: "default", versioning: backing.docType.settings?.versioning ?? false });
2063
2298
  const doc = await svc.create(createDocumentSchema.parse({ typeId: backing.coll.name, tenantId: "default", locale: "default", title, slug: finalSlug, data: hookData, publishOnCreate: (status || "draft") === "published" }), user?.userId);
2064
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
2065
- await cache.invalidate("content-filtered:*");
2066
- await cache.invalidate("collection-content-filtered:*");
2299
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
2300
+ const createAffectedKeys = (await cache.listKeys()).map((k) => k.key).filter((k) => k.startsWith("api:content-filtered:") || k.startsWith(`api:collection-content-filtered:${backing.coll.name}:`));
2301
+ const createStaleValues = await cache.getMany(createAffectedKeys);
2302
+ for (const [key, val] of createStaleValues) markStale(key, val, backing.coll.name);
2303
+ await cache.invalidate("api:content-filtered:*");
2304
+ await cache.invalidate(`api:collection-content-filtered:${backing.coll.name}:*`);
2067
2305
  dispatchHookEvent(c, "content:after:create", { collection: backing.coll.name, id: doc.rootId, data: doc.data ?? {}, user: actor }, "fire-and-forget");
2068
- return c.json({ data: { id: doc.rootId, title: doc.title, slug: doc.slug, status: doc.status, collectionId: backing.coll.id, data: doc.data, created_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(doc.createdAt), updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(doc.updatedAt) } }, 201);
2306
+ return c.json({ data: { id: doc.rootId, title: doc.title, slug: doc.slug, status: doc.status, collectionId: backing.coll.id, data: doc.data, created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(doc.createdAt), updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(doc.updatedAt) } }, 201);
2069
2307
  } catch (error) {
2070
2308
  console.error("Error creating content:", error);
2071
2309
  return c.json({ error: "Failed to create content", details: error instanceof Error ? error.message : String(error) }, 500);
2072
2310
  }
2073
2311
  });
2074
- apiRoutes.put("/:collection/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
2312
+ apiRoutes.put("/:collection/:id", chunkBRKXMRMB_cjs.requireAuth(), chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
2075
2313
  try {
2076
2314
  const collection = c.req.param("collection");
2077
2315
  const id = c.req.param("id");
2078
2316
  const db = c.env.DB;
2079
2317
  const user = c.get("user");
2080
2318
  const body = await c.req.json();
2081
- const collRecord = chunkQCJHCSOK_cjs.getCollectionRegistry().getBySlugOrName(collection);
2319
+ const collRecord = chunk4DHPR7KR_cjs.getCollectionRegistry().getBySlugOrName(collection);
2082
2320
  const typeName = collRecord?.name ?? collection;
2083
2321
  const docRow = await db.prepare("SELECT root_id, type_id FROM documents WHERE root_id = ? AND type_id = ? AND tenant_id = 'default' AND is_current_draft = 1 AND deleted_at IS NULL").bind(id, typeName).first();
2084
2322
  if (!docRow) return c.json({ error: "Content not found" }, 404);
@@ -2090,8 +2328,8 @@ apiRoutes.put("/:collection/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3
2090
2328
  } catch (err) {
2091
2329
  return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
2092
2330
  }
2093
- const docType = await new chunk37V3RET3_cjs.DocumentTypeRegistry(db).findById(docRow.type_id);
2094
- const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, { queryableFields: docType?.queryableFields ?? [], typeSchemaVersion: docType?.schemaVersion ?? 1, maxVersionsPerRoot: docType?.settings?.maxVersionsPerRoot ?? 50, tenantId: "default", versioning: docType?.settings?.versioning ?? false });
2331
+ const docType = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(docRow.type_id);
2332
+ const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, { queryableFields: docType?.queryableFields ?? [], typeSchemaVersion: docType?.schemaVersion ?? 1, maxVersionsPerRoot: docType?.settings?.maxVersionsPerRoot ?? 50, tenantId: "default", versioning: docType?.settings?.versioning ?? false });
2095
2333
  const input = {};
2096
2334
  if (body.title !== void 0) input.title = body.title;
2097
2335
  if (body.slug !== void 0) input.slug = slugify(body.slug);
@@ -2104,28 +2342,31 @@ apiRoutes.put("/:collection/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3
2104
2342
  } else if (body.status === "draft" && pub) {
2105
2343
  await svc.unpublish(pub.id);
2106
2344
  }
2107
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
2108
- await cache.invalidate("content-filtered:*");
2109
- await cache.invalidate("collection-content-filtered:*");
2110
- const coll = chunkQCJHCSOK_cjs.getCollectionRegistry().getByName(docRow.type_id);
2345
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
2346
+ const updateAffectedKeys = (await cache.listKeys()).map((k) => k.key).filter((k) => k.startsWith("api:content-filtered:") || k.startsWith(`api:collection-content-filtered:${docRow.type_id}:`));
2347
+ const updateStaleValues = await cache.getMany(updateAffectedKeys);
2348
+ for (const [key, val] of updateStaleValues) markStale(key, val, docRow.type_id);
2349
+ await cache.invalidate("api:content-filtered:*");
2350
+ await cache.invalidate(`api:collection-content-filtered:${docRow.type_id}:*`);
2351
+ const coll = chunk4DHPR7KR_cjs.getCollectionRegistry().getByName(docRow.type_id);
2111
2352
  const saved = await db.prepare("SELECT * FROM documents WHERE id = ?").bind(newDraft.id).first();
2112
2353
  const savedData = saved?.data ? JSON.parse(saved.data) : {};
2113
2354
  dispatchHookEvent(c, "content:after:update", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
2114
2355
  const nowPublished = body.status === "published" || body.status === void 0 && wasPublished;
2115
2356
  if (nowPublished && !wasPublished) dispatchHookEvent(c, "content:after:publish", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
2116
- return c.json({ data: { id: saved.root_id, title: saved.title, slug: saved.slug, status: saved.status, collectionId: coll?.id ?? docRow.type_id, data: savedData, created_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(saved.created_at), updated_at: chunkLTZ5WYOK_cjs.documentSecondsToMs(saved.updated_at) } });
2357
+ return c.json({ data: { id: saved.root_id, title: saved.title, slug: saved.slug, status: saved.status, collectionId: coll?.id ?? docRow.type_id, data: savedData, created_at: chunkOLEOKHDX_cjs.documentSecondsToMs(saved.created_at), updated_at: chunkOLEOKHDX_cjs.documentSecondsToMs(saved.updated_at) } });
2117
2358
  } catch (error) {
2118
2359
  console.error("Error updating content:", error);
2119
2360
  return c.json({ error: "Failed to update content", details: error instanceof Error ? error.message : String(error) }, 500);
2120
2361
  }
2121
2362
  });
2122
- apiRoutes.delete("/:collection/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3RET3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
2363
+ apiRoutes.delete("/:collection/:id", chunkBRKXMRMB_cjs.requireAuth(), chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
2123
2364
  try {
2124
2365
  const collection = c.req.param("collection");
2125
2366
  const id = c.req.param("id");
2126
2367
  const db = c.env.DB;
2127
2368
  const user = c.get("user");
2128
- const collRecord = chunkQCJHCSOK_cjs.getCollectionRegistry().getBySlugOrName(collection);
2369
+ const collRecord = chunk4DHPR7KR_cjs.getCollectionRegistry().getBySlugOrName(collection);
2129
2370
  const typeName = collRecord?.name ?? collection;
2130
2371
  const docRow = await db.prepare("SELECT type_id FROM documents WHERE root_id = ? AND type_id = ? AND tenant_id = 'default' AND deleted_at IS NULL LIMIT 1").bind(id, typeName).first();
2131
2372
  if (!docRow) return c.json({ error: "Content not found" }, 404);
@@ -2137,9 +2378,12 @@ apiRoutes.delete("/:collection/:id", chunk37V3RET3_cjs.requireAuth(), chunk37V3R
2137
2378
  }
2138
2379
  const now = Math.floor(Date.now() / 1e3);
2139
2380
  await db.prepare("UPDATE documents SET deleted_at = ?, updated_at = ? WHERE root_id = ? AND tenant_id = 'default'").bind(now, now, id).run();
2140
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
2141
- await cache.invalidate("content-filtered:*");
2142
- await cache.invalidate("collection-content-filtered:*");
2381
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
2382
+ const deleteAffectedKeys = (await cache.listKeys()).map((k) => k.key).filter((k) => k.startsWith("api:content-filtered:") || k.startsWith(`api:collection-content-filtered:${docRow.type_id}:`));
2383
+ const deleteStaleValues = await cache.getMany(deleteAffectedKeys);
2384
+ for (const [key, val] of deleteStaleValues) markStale(key, val, docRow.type_id);
2385
+ await cache.invalidate("api:content-filtered:*");
2386
+ await cache.invalidate(`api:collection-content-filtered:${docRow.type_id}:*`);
2143
2387
  dispatchHookEvent(c, "content:after:delete", { collection: docRow.type_id, id, data: {}, user: actor }, "fire-and-forget");
2144
2388
  return c.json({ success: true });
2145
2389
  } catch (error) {
@@ -2212,7 +2456,7 @@ var MediaDocumentService = class {
2212
2456
  tenantId;
2213
2457
  /** Create a media_asset document from R2 upload metadata. Published-on-create (immediately usable). */
2214
2458
  async createFromUpload(meta, createdBy) {
2215
- const svc = new chunkLTZ5WYOK_cjs.DocumentsService(this.db, { queryableFields: MEDIA_QUERYABLE, tenantId: this.tenantId, maxVersionsPerRoot: 5 });
2459
+ const svc = new chunkOLEOKHDX_cjs.DocumentsService(this.db, { queryableFields: MEDIA_QUERYABLE, tenantId: this.tenantId, maxVersionsPerRoot: 5 });
2216
2460
  return svc.create(
2217
2461
  createDocumentSchema.parse({
2218
2462
  typeId: "media_asset",
@@ -2290,7 +2534,7 @@ var MediaDocumentService = class {
2290
2534
  }
2291
2535
  /** Update alt/caption/tags on a media_asset document (saveDraft + publish atomically). */
2292
2536
  async updateMetadata(rootId, meta, updatedBy) {
2293
- const svc = new chunkLTZ5WYOK_cjs.DocumentsService(this.db, { queryableFields: MEDIA_QUERYABLE, tenantId: this.tenantId, maxVersionsPerRoot: 5 });
2537
+ const svc = new chunkOLEOKHDX_cjs.DocumentsService(this.db, { queryableFields: MEDIA_QUERYABLE, tenantId: this.tenantId, maxVersionsPerRoot: 5 });
2294
2538
  const newDraft = await svc.saveDraft(rootId, { data: meta }, updatedBy);
2295
2539
  return svc.publish(newDraft.id, updatedBy);
2296
2540
  }
@@ -2347,7 +2591,7 @@ var fileValidationSchema = zod.z.object({
2347
2591
  // 50MB max
2348
2592
  });
2349
2593
  var apiMediaRoutes = new hono.Hono();
2350
- apiMediaRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
2594
+ apiMediaRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
2351
2595
  apiMediaRoutes.post("/upload", async (c) => {
2352
2596
  try {
2353
2597
  const user = c.get("user");
@@ -2701,9 +2945,13 @@ apiMediaRoutes.post("/create-folder", async (c) => {
2701
2945
  error: "Folder name can only contain lowercase letters, numbers, hyphens, and underscores"
2702
2946
  }, 400);
2703
2947
  }
2704
- const checkStmt = c.env.DB.prepare("SELECT COUNT(*) as count FROM media WHERE folder = ? AND deleted_at IS NULL");
2705
- const existingFolder = await checkStmt.bind(folderName).first();
2706
- if (existingFolder && existingFolder.count > 0) {
2948
+ let folderExists = false;
2949
+ try {
2950
+ const existing = await c.env.DB.prepare("SELECT COUNT(*) as count FROM documents WHERE type_id = 'media_asset' AND tenant_id = 'default' AND json_extract(data, '$.folder') = ? AND deleted_at IS NULL AND is_current_draft = 1").bind(folderName).first();
2951
+ folderExists = (existing?.count ?? 0) > 0;
2952
+ } catch {
2953
+ }
2954
+ if (folderExists) {
2707
2955
  return c.json({
2708
2956
  success: false,
2709
2957
  error: `Folder "${folderName}" already exists`
@@ -3045,7 +3293,7 @@ apiSystemRoutes.get("/info", (c) => {
3045
3293
  apiSystemRoutes.get("/stats", async (c) => {
3046
3294
  try {
3047
3295
  const db = c.env.DB;
3048
- const typeIds = chunkQCJHCSOK_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => r.name);
3296
+ const typeIds = chunk4DHPR7KR_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => r.name);
3049
3297
  let contentStats = null;
3050
3298
  if (typeIds.length > 0) {
3051
3299
  const placeholders = typeIds.map(() => "?").join(",");
@@ -3120,12 +3368,12 @@ apiSystemRoutes.get("/env", (c) => {
3120
3368
  });
3121
3369
  var api_system_default = apiSystemRoutes;
3122
3370
  var adminApiRoutes = new hono.Hono();
3123
- adminApiRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
3124
- adminApiRoutes.use("*", chunk37V3RET3_cjs.requireRole(["admin", "editor"]));
3371
+ adminApiRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
3372
+ adminApiRoutes.use("*", chunkBRKXMRMB_cjs.requireRole(["admin", "editor"]));
3125
3373
  adminApiRoutes.get("/stats", async (c) => {
3126
3374
  try {
3127
3375
  const db = c.env.DB;
3128
- const userCollections = chunkQCJHCSOK_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
3376
+ const userCollections = chunk4DHPR7KR_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
3129
3377
  const collectionsCount = userCollections.length;
3130
3378
  let contentCount = 0;
3131
3379
  if (userCollections.length > 0) {
@@ -3216,7 +3464,7 @@ adminApiRoutes.get("/collections", async (c) => {
3216
3464
  try {
3217
3465
  const search = c.req.query("search") || "";
3218
3466
  const includeInactive = c.req.query("includeInactive") === "true";
3219
- let records = chunkQCJHCSOK_cjs.getCollectionRegistry().list().filter((r) => !r.internal);
3467
+ let records = chunk4DHPR7KR_cjs.getCollectionRegistry().list().filter((r) => !r.internal);
3220
3468
  if (!includeInactive) records = records.filter((r) => r.isActive !== false);
3221
3469
  if (search) {
3222
3470
  const needle = search.toLowerCase();
@@ -3248,7 +3496,7 @@ adminApiRoutes.get("/collections", async (c) => {
3248
3496
  adminApiRoutes.get("/collections/:id", async (c) => {
3249
3497
  try {
3250
3498
  const id = c.req.param("id");
3251
- const registry = chunkQCJHCSOK_cjs.getCollectionRegistry();
3499
+ const registry = chunk4DHPR7KR_cjs.getCollectionRegistry();
3252
3500
  const record = registry.getById(id) ?? registry.getByName(id);
3253
3501
  if (!record) {
3254
3502
  return c.json({ error: "Collection not found" }, 404);
@@ -3298,7 +3546,7 @@ adminApiRoutes.get("/references", async (c) => {
3298
3546
  if (collectionParams.length === 0) {
3299
3547
  return c.json({ error: "Collection is required" }, 400);
3300
3548
  }
3301
- const registry = chunkQCJHCSOK_cjs.getCollectionRegistry();
3549
+ const registry = chunk4DHPR7KR_cjs.getCollectionRegistry();
3302
3550
  const matched = collectionParams.map((param) => registry.getById(param) ?? registry.getByName(param)).filter((r) => !!r);
3303
3551
  const seen = /* @__PURE__ */ new Set();
3304
3552
  const collections = matched.filter((r) => {
@@ -3413,7 +3661,7 @@ adminApiRoutes.patch("/collections/:id", collectionsReadOnly);
3413
3661
  adminApiRoutes.delete("/collections/:id", collectionsReadOnly);
3414
3662
  adminApiRoutes.get("/migrations/status", async (c) => {
3415
3663
  try {
3416
- const { MigrationService: MigrationService2 } = await import('./migrations-FGXZPKDC.cjs');
3664
+ const { MigrationService: MigrationService2 } = await import('./migrations-6M6772UC.cjs');
3417
3665
  const db = c.env.DB;
3418
3666
  const migrationService = new MigrationService2(db);
3419
3667
  const status = await migrationService.getMigrationStatus();
@@ -3456,7 +3704,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
3456
3704
  });
3457
3705
  adminApiRoutes.get("/migrations/validate", async (c) => {
3458
3706
  try {
3459
- const { MigrationService: MigrationService2 } = await import('./migrations-FGXZPKDC.cjs');
3707
+ const { MigrationService: MigrationService2 } = await import('./migrations-6M6772UC.cjs');
3460
3708
  const db = c.env.DB;
3461
3709
  const migrationService = new MigrationService2(db);
3462
3710
  const validation = await migrationService.validateSchema();
@@ -3606,8 +3854,8 @@ function renderLoginPage(data, demoLoginActive = false) {
3606
3854
  <div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
3607
3855
  <div class="bg-zinc-900 shadow-sm ring-1 ring-white/10 rounded-xl px-6 py-8 sm:px-10">
3608
3856
  <!-- Alerts -->
3609
- ${data.error ? `<div class="mb-6">${chunkE66UVONV_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
3610
- ${data.message ? `<div class="mb-6">${chunkE66UVONV_cjs.renderAlert({ type: "success", message: data.message })}</div>` : ""}
3857
+ ${data.error ? `<div class="mb-6">${chunkOUBUS74I_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
3858
+ ${data.message ? `<div class="mb-6">${chunkOUBUS74I_cjs.renderAlert({ type: "success", message: data.message })}</div>` : ""}
3611
3859
 
3612
3860
  <!-- Form Response (HTMX target) -->
3613
3861
  <div id="form-response" class="mb-6"></div>
@@ -3615,6 +3863,8 @@ function renderLoginPage(data, demoLoginActive = false) {
3615
3863
  <!-- Form -->
3616
3864
  <form
3617
3865
  id="login-form"
3866
+ action="/auth/login/form${data.redirect ? `?redirect=${encodeURIComponent(data.redirect)}` : ""}"
3867
+ method="post"
3618
3868
  hx-post="/auth/login/form${data.redirect ? `?redirect=${encodeURIComponent(data.redirect)}` : ""}"
3619
3869
  hx-target="#form-response"
3620
3870
  hx-swap="innerHTML"
@@ -3771,7 +4021,7 @@ function renderRegisterPage(data) {
3771
4021
  <div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
3772
4022
  <div class="bg-zinc-900 shadow-sm ring-1 ring-white/10 rounded-xl px-6 py-8 sm:px-10">
3773
4023
  <!-- Alerts -->
3774
- ${data.error ? `<div class="mb-6">${chunkE66UVONV_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
4024
+ ${data.error ? `<div class="mb-6">${chunkOUBUS74I_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
3775
4025
 
3776
4026
  <!-- Form -->
3777
4027
  <form
@@ -3871,7 +4121,7 @@ function renderRegisterPage(data) {
3871
4121
  }
3872
4122
 
3873
4123
  // src/services/email/email-service-singleton.ts
3874
- var singleton = chunkBP52BFIV_cjs.createServiceSingleton("EmailService");
4124
+ var singleton = chunkKWQNB6UM_cjs.createServiceSingleton("EmailService");
3875
4125
  function setEmailService(service2) {
3876
4126
  singleton.set(service2);
3877
4127
  }
@@ -3915,7 +4165,7 @@ function emptyProfile() {
3915
4165
  return { custom: {} };
3916
4166
  }
3917
4167
  function service(db) {
3918
- return new chunkLTZ5WYOK_cjs.DocumentsService(db, { tenantId: "default", maxVersionsPerRoot: 1, queryableFields: [] });
4168
+ return new chunkOLEOKHDX_cjs.DocumentsService(db, { tenantId: "default", maxVersionsPerRoot: 1, queryableFields: [] });
3919
4169
  }
3920
4170
  async function readProfileData(db, userId) {
3921
4171
  const row = await db.prepare(
@@ -4679,7 +4929,7 @@ function getLexicalInitScript(settings = {}) {
4679
4929
  </script>
4680
4930
  `;
4681
4931
  }
4682
- var lexicalEditorPlugin = chunkBP52BFIV_cjs.definePlugin({
4932
+ var lexicalEditorPlugin = chunkKWQNB6UM_cjs.definePlugin({
4683
4933
  id: "lexical-editor",
4684
4934
  version: "1.0.0",
4685
4935
  name: "Lexical Editor",
@@ -5130,9 +5380,11 @@ function renderDynamicField(field, options = {}) {
5130
5380
  min="${opts.min || ""}"
5131
5381
  max="${opts.max || ""}"
5132
5382
  class="${baseClasses} ${errorClasses} !w-auto dark:[color-scheme:dark]"
5383
+ placeholder="YYYY-MM-DD"
5133
5384
  ${required}
5134
5385
  ${disabled ? "disabled" : ""}
5135
5386
  >
5387
+ <p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Format: YYYY-MM-DD</p>
5136
5388
  `;
5137
5389
  break;
5138
5390
  case "datetime":
@@ -5148,6 +5400,7 @@ function renderDynamicField(field, options = {}) {
5148
5400
  ${required}
5149
5401
  ${disabled ? "disabled" : ""}
5150
5402
  >
5403
+ <p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Format: YYYY-MM-DD HH:MM</p>
5151
5404
  `;
5152
5405
  break;
5153
5406
  case "slug":
@@ -7085,7 +7338,7 @@ api.put("/:userId", async (c) => {
7085
7338
  await saveCustomData(db, userId, sanitized);
7086
7339
  return c.json({ success: true });
7087
7340
  });
7088
- var userProfilesPlugin = chunkBP52BFIV_cjs.definePlugin({
7341
+ var userProfilesPlugin = chunkKWQNB6UM_cjs.definePlugin({
7089
7342
  id: "user-profiles",
7090
7343
  version: "1.0.0",
7091
7344
  name: "User Profiles",
@@ -7102,8 +7355,32 @@ function createUserProfilesPlugin() {
7102
7355
  return userProfilesPlugin;
7103
7356
  }
7104
7357
 
7358
+ // src/services/demo-mode.ts
7359
+ var _demoModeActive = false;
7360
+ function setDemoModeActive() {
7361
+ _demoModeActive = true;
7362
+ }
7363
+ function isDemoModeActive() {
7364
+ return _demoModeActive;
7365
+ }
7366
+
7105
7367
  // src/routes/auth.ts
7106
7368
  var JWT_SECRET_FALLBACK = "your-super-secret-jwt-key-change-in-production";
7369
+ var DEMO_EMAIL = "admin@sonicjs.com";
7370
+ var STATS_EVENTS_ENDPOINT = "https://stats.sonicjs.com/v1/events";
7371
+ async function trackDemoLogin(kv) {
7372
+ try {
7373
+ const installationId = await kv?.get("_sonicjs_installation_id") ?? "demo-unknown";
7374
+ await fetch(STATS_EVENTS_ENDPOINT, {
7375
+ method: "POST",
7376
+ headers: { "Content-Type": "application/json" },
7377
+ body: JSON.stringify({
7378
+ data: { installation_id: installationId, event_type: "demo_login", properties: {}, timestamp: (/* @__PURE__ */ new Date()).toISOString() }
7379
+ })
7380
+ });
7381
+ } catch {
7382
+ }
7383
+ }
7107
7384
  function renderPasswordResetEmail(resetLink, firstName) {
7108
7385
  const greeting = firstName ? `Hi ${firstName},` : "Hello,";
7109
7386
  return `<!DOCTYPE html>
@@ -7123,8 +7400,8 @@ function renderPasswordResetEmail(resetLink, firstName) {
7123
7400
  async function setCsrfCookie(c, maxAge) {
7124
7401
  const secret = c.env?.JWT_SECRET || JWT_SECRET_FALLBACK;
7125
7402
  const isDev = c.env?.ENVIRONMENT === "development" || !c.env?.ENVIRONMENT;
7126
- const csrfToken = await chunk37V3RET3_cjs.generateCsrfToken(secret);
7127
- const cookieMaxAge = await chunk37V3RET3_cjs.getJwtExpirySecondsFromDb(c.env?.DB, c.env);
7403
+ const csrfToken = await chunkBRKXMRMB_cjs.generateCsrfToken(secret);
7404
+ const cookieMaxAge = await chunkBRKXMRMB_cjs.getJwtExpirySecondsFromDb(c.env?.DB, c.env);
7128
7405
  cookie.setCookie(c, "csrf_token", csrfToken, {
7129
7406
  httpOnly: false,
7130
7407
  secure: !isDev,
@@ -7153,13 +7430,7 @@ authRoutes.get("/login", async (c) => {
7153
7430
  version: c.get("appVersion"),
7154
7431
  redirect: redirect && redirect.startsWith("/") ? redirect : void 0
7155
7432
  };
7156
- const db = c.env.DB;
7157
- let demoLoginActive = false;
7158
- try {
7159
- const plugin = await db.prepare("SELECT * FROM plugins WHERE id = ? AND status = ?").bind("demo-login-prefill", "active").first();
7160
- demoLoginActive = !!plugin;
7161
- } catch (error2) {
7162
- }
7433
+ const demoLoginActive = isDemoModeActive();
7163
7434
  return c.html(renderLoginPage(pageData, demoLoginActive));
7164
7435
  });
7165
7436
  authRoutes.get("/register", async (c) => {
@@ -7183,7 +7454,7 @@ var loginSchema = zod.z.object({
7183
7454
  });
7184
7455
  authRoutes.post(
7185
7456
  "/register",
7186
- chunk37V3RET3_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
7457
+ chunkBRKXMRMB_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
7187
7458
  async (c) => {
7188
7459
  try {
7189
7460
  const db = c.env.DB;
@@ -7219,7 +7490,7 @@ authRoutes.post(
7219
7490
  if (existingUser) {
7220
7491
  return c.json({ error: "User with this email already exists" }, 400);
7221
7492
  }
7222
- const passwordHash = await chunk37V3RET3_cjs.AuthManager.hashPassword(password);
7493
+ const passwordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(password);
7223
7494
  const userId = crypto.randomUUID();
7224
7495
  const now = /* @__PURE__ */ new Date();
7225
7496
  const nowSec = Math.floor(now.getTime() / 1e3);
@@ -7252,8 +7523,8 @@ authRoutes.post(
7252
7523
  { user: { id: userId, email: normalizedEmail, role: "viewer" } },
7253
7524
  "fire-and-forget"
7254
7525
  );
7255
- const tokenTtl = await chunk37V3RET3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7256
- const token = await chunk37V3RET3_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer", c.env.JWT_SECRET, tokenTtl);
7526
+ const tokenTtl = await chunkBRKXMRMB_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7527
+ const token = await chunkBRKXMRMB_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer", c.env.JWT_SECRET, tokenTtl);
7257
7528
  cookie.setCookie(c, "auth_token", token, {
7258
7529
  httpOnly: true,
7259
7530
  secure: true,
@@ -7285,7 +7556,7 @@ authRoutes.post(
7285
7556
  );
7286
7557
  authRoutes.post(
7287
7558
  "/login",
7288
- chunk37V3RET3_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
7559
+ chunkBRKXMRMB_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
7289
7560
  async (c) => {
7290
7561
  try {
7291
7562
  const body = await c.req.json();
@@ -7295,8 +7566,8 @@ authRoutes.post(
7295
7566
  }
7296
7567
  const { email, password } = validation.data;
7297
7568
  const normalizedEmail = email.toLowerCase();
7298
- const { createAuth } = await import('./config-OCH7S4WK.cjs');
7299
- const auth = createAuth(c.env);
7569
+ const { createAuth } = await import('./config-VLU73ZW7.cjs');
7570
+ const auth = createAuth(c.env, void 0, new URL(c.req.url).origin);
7300
7571
  const baReq = new Request(new URL("/auth/sign-in/email", c.req.url).href, {
7301
7572
  method: "POST",
7302
7573
  headers: { "Content-Type": "application/json", "Origin": new URL(c.req.url).origin },
@@ -7306,19 +7577,21 @@ authRoutes.post(
7306
7577
  if (!baRes.ok) {
7307
7578
  return c.json({ error: "Invalid email or password" }, 401);
7308
7579
  }
7309
- const rawSetCookie = baRes.headers.get("set-cookie");
7310
- if (rawSetCookie) {
7311
- c.res.headers.append("Set-Cookie", rawSetCookie);
7312
- } else if (baRes.headers.getSetCookie) {
7580
+ if (baRes.headers.getSetCookie) {
7313
7581
  for (const sc of baRes.headers.getSetCookie()) {
7314
- c.res.headers.append("Set-Cookie", sc);
7582
+ c.header("Set-Cookie", sc, { append: true });
7583
+ }
7584
+ } else {
7585
+ const rawSetCookie = baRes.headers.get("set-cookie");
7586
+ if (rawSetCookie) {
7587
+ c.header("Set-Cookie", rawSetCookie, { append: true });
7315
7588
  }
7316
7589
  }
7317
7590
  await setCsrfCookie(c);
7318
7591
  const baBody = await baRes.json();
7319
7592
  const user = baBody.user ?? {};
7320
- const tokenTtl = await chunk37V3RET3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7321
- const token = await chunk37V3RET3_cjs.AuthManager.generateToken(
7593
+ const tokenTtl = await chunkBRKXMRMB_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7594
+ const token = await chunkBRKXMRMB_cjs.AuthManager.generateToken(
7322
7595
  user.id,
7323
7596
  user.email,
7324
7597
  user.role ?? "viewer",
@@ -7331,6 +7604,9 @@ authRoutes.post(
7331
7604
  sameSite: "Strict",
7332
7605
  maxAge: tokenTtl
7333
7606
  });
7607
+ if (normalizedEmail === DEMO_EMAIL) {
7608
+ c.executionCtx?.waitUntil(trackDemoLogin(c.env.CACHE_KV));
7609
+ }
7334
7610
  return c.json({
7335
7611
  user: {
7336
7612
  id: user.id,
@@ -7349,8 +7625,8 @@ authRoutes.post(
7349
7625
  );
7350
7626
  authRoutes.post("/logout", async (c) => {
7351
7627
  try {
7352
- const { createAuth } = await import('./config-OCH7S4WK.cjs');
7353
- const auth = createAuth(c.env);
7628
+ const { createAuth } = await import('./config-VLU73ZW7.cjs');
7629
+ const auth = createAuth(c.env, void 0, new URL(c.req.url).origin);
7354
7630
  const baReq = new Request(new URL("/auth/sign-out", c.req.url).href, {
7355
7631
  method: "POST",
7356
7632
  headers: { "Content-Type": "application/json", "Origin": new URL(c.req.url).origin, "Cookie": c.req.header("Cookie") || "" },
@@ -7359,14 +7635,15 @@ authRoutes.post("/logout", async (c) => {
7359
7635
  await auth.handler(baReq);
7360
7636
  } catch {
7361
7637
  }
7362
- cookie.setCookie(c, "better-auth.session_token", "", { httpOnly: true, sameSite: "Lax", path: "/", maxAge: 0 });
7638
+ const isSecure = new URL(c.req.url).protocol === "https:";
7639
+ cookie.setCookie(c, "better-auth.session_token", "", { httpOnly: true, sameSite: "Lax", path: "/", maxAge: 0, secure: isSecure });
7363
7640
  clearCsrfCookie(c);
7364
7641
  return c.json({ message: "Logged out successfully" });
7365
7642
  });
7366
7643
  authRoutes.get("/logout", async (c) => {
7367
7644
  try {
7368
- const { createAuth } = await import('./config-OCH7S4WK.cjs');
7369
- const auth = createAuth(c.env);
7645
+ const { createAuth } = await import('./config-VLU73ZW7.cjs');
7646
+ const auth = createAuth(c.env, void 0, new URL(c.req.url).origin);
7370
7647
  const baReq = new Request(new URL("/auth/sign-out", c.req.url).href, {
7371
7648
  method: "POST",
7372
7649
  headers: { "Content-Type": "application/json", "Origin": new URL(c.req.url).origin, "Cookie": c.req.header("Cookie") || "" },
@@ -7375,11 +7652,12 @@ authRoutes.get("/logout", async (c) => {
7375
7652
  await auth.handler(baReq);
7376
7653
  } catch {
7377
7654
  }
7378
- cookie.setCookie(c, "better-auth.session_token", "", { httpOnly: true, sameSite: "Lax", path: "/", maxAge: 0 });
7655
+ const isSecure = new URL(c.req.url).protocol === "https:";
7656
+ cookie.setCookie(c, "better-auth.session_token", "", { httpOnly: true, sameSite: "Lax", path: "/", maxAge: 0, secure: isSecure });
7379
7657
  clearCsrfCookie(c);
7380
7658
  return c.redirect("/auth/login?message=You have been logged out successfully");
7381
7659
  });
7382
- authRoutes.get("/me", chunk37V3RET3_cjs.requireAuth(), async (c) => {
7660
+ authRoutes.get("/me", chunkBRKXMRMB_cjs.requireAuth(), async (c) => {
7383
7661
  try {
7384
7662
  const user = c.get("user");
7385
7663
  if (!user) {
@@ -7399,7 +7677,7 @@ authRoutes.get("/me", chunk37V3RET3_cjs.requireAuth(), async (c) => {
7399
7677
  });
7400
7678
  authRoutes.post(
7401
7679
  "/refresh",
7402
- chunk37V3RET3_cjs.rateLimit({ max: 60, windowMs: 60 * 1e3, keyPrefix: "refresh" }),
7680
+ chunkBRKXMRMB_cjs.rateLimit({ max: 60, windowMs: 60 * 1e3, keyPrefix: "refresh" }),
7403
7681
  async (c) => {
7404
7682
  try {
7405
7683
  let token = c.req.header("Authorization")?.replace("Bearer ", "");
@@ -7408,8 +7686,8 @@ authRoutes.post(
7408
7686
  return c.json({ error: "Authentication required" }, 401);
7409
7687
  }
7410
7688
  const db = c.env.DB;
7411
- const grace = await chunk37V3RET3_cjs.getJwtRefreshGraceSecondsFromDb(db, c.env);
7412
- const payload = await chunk37V3RET3_cjs.AuthManager.verifyToken(token, c.env.JWT_SECRET, grace);
7689
+ const grace = await chunkBRKXMRMB_cjs.getJwtRefreshGraceSecondsFromDb(db, c.env);
7690
+ const payload = await chunkBRKXMRMB_cjs.AuthManager.verifyToken(token, c.env.JWT_SECRET, grace);
7413
7691
  if (!payload) {
7414
7692
  return c.json({ error: "Invalid or expired token" }, 401);
7415
7693
  }
@@ -7417,8 +7695,8 @@ authRoutes.post(
7417
7695
  if (!row || !row.is_active) {
7418
7696
  return c.json({ error: "User is not active" }, 401);
7419
7697
  }
7420
- const tokenTtl = await chunk37V3RET3_cjs.getJwtExpirySecondsFromDb(db, c.env);
7421
- const newToken = await chunk37V3RET3_cjs.AuthManager.generateToken(row.id, row.email, row.role, c.env.JWT_SECRET, tokenTtl);
7698
+ const tokenTtl = await chunkBRKXMRMB_cjs.getJwtExpirySecondsFromDb(db, c.env);
7699
+ const newToken = await chunkBRKXMRMB_cjs.AuthManager.generateToken(row.id, row.email, row.role, c.env.JWT_SECRET, tokenTtl);
7422
7700
  cookie.setCookie(c, "auth_token", newToken, {
7423
7701
  httpOnly: true,
7424
7702
  secure: true,
@@ -7438,7 +7716,7 @@ authRoutes.post(
7438
7716
  );
7439
7717
  authRoutes.post(
7440
7718
  "/register/form",
7441
- chunk37V3RET3_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
7719
+ chunkBRKXMRMB_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
7442
7720
  async (c) => {
7443
7721
  try {
7444
7722
  const db = c.env.DB;
@@ -7483,7 +7761,7 @@ authRoutes.post(
7483
7761
  </div>
7484
7762
  `);
7485
7763
  }
7486
- const passwordHash = await chunk37V3RET3_cjs.AuthManager.hashPassword(password);
7764
+ const passwordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(password);
7487
7765
  const role = isFirstUser ? "admin" : "viewer";
7488
7766
  const userId = crypto.randomUUID();
7489
7767
  const now = /* @__PURE__ */ new Date();
@@ -7517,7 +7795,7 @@ authRoutes.post(
7517
7795
  await saveCustomData(db, userId, sanitized);
7518
7796
  }
7519
7797
  }
7520
- const rbacService = new chunkLTZ5WYOK_cjs.RbacService(db);
7798
+ const rbacService = new chunkOLEOKHDX_cjs.RbacService(db);
7521
7799
  await rbacService.addUserRoleByName(userId, role);
7522
7800
  dispatchHookEvent(
7523
7801
  c,
@@ -7525,8 +7803,8 @@ authRoutes.post(
7525
7803
  { user: { id: userId, email: normalizedEmail, role } },
7526
7804
  "fire-and-forget"
7527
7805
  );
7528
- const tokenTtl = await chunk37V3RET3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7529
- const token = await chunk37V3RET3_cjs.AuthManager.generateToken(userId, normalizedEmail, role, c.env.JWT_SECRET, tokenTtl);
7806
+ const tokenTtl = await chunkBRKXMRMB_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7807
+ const token = await chunkBRKXMRMB_cjs.AuthManager.generateToken(userId, normalizedEmail, role, c.env.JWT_SECRET, tokenTtl);
7530
7808
  cookie.setCookie(c, "auth_token", token, {
7531
7809
  httpOnly: true,
7532
7810
  secure: false,
@@ -7558,7 +7836,7 @@ authRoutes.post(
7558
7836
  );
7559
7837
  authRoutes.post(
7560
7838
  "/login/form",
7561
- chunk37V3RET3_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
7839
+ chunkBRKXMRMB_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
7562
7840
  async (c) => {
7563
7841
  try {
7564
7842
  const formData = await c.req.formData();
@@ -7572,8 +7850,8 @@ authRoutes.post(
7572
7850
  </div>
7573
7851
  `);
7574
7852
  }
7575
- const { createAuth } = await import('./config-OCH7S4WK.cjs');
7576
- const auth = createAuth(c.env);
7853
+ const { createAuth } = await import('./config-VLU73ZW7.cjs');
7854
+ const auth = createAuth(c.env, void 0, new URL(c.req.url).origin);
7577
7855
  const baReq = new Request(new URL("/auth/sign-in/email", c.req.url).href, {
7578
7856
  method: "POST",
7579
7857
  headers: { "Content-Type": "application/json", "Origin": new URL(c.req.url).origin },
@@ -7587,17 +7865,27 @@ authRoutes.post(
7587
7865
  </div>
7588
7866
  `);
7589
7867
  }
7590
- const rawSetCookie = baRes.headers.get("set-cookie");
7591
- if (rawSetCookie) {
7592
- c.res.headers.append("Set-Cookie", rawSetCookie);
7593
- } else if (baRes.headers.getSetCookie) {
7868
+ if (baRes.headers.getSetCookie) {
7594
7869
  for (const sc of baRes.headers.getSetCookie()) {
7595
- c.res.headers.append("Set-Cookie", sc);
7870
+ c.header("Set-Cookie", sc, { append: true });
7871
+ }
7872
+ } else {
7873
+ const rawSetCookie = baRes.headers.get("set-cookie");
7874
+ if (rawSetCookie) {
7875
+ c.header("Set-Cookie", rawSetCookie, { append: true });
7596
7876
  }
7597
7877
  }
7598
7878
  await setCsrfCookie(c);
7879
+ if (email === DEMO_EMAIL) {
7880
+ c.executionCtx?.waitUntil(trackDemoLogin(c.env.CACHE_KV));
7881
+ }
7599
7882
  const rawRedirect = c.req.query("redirect");
7600
7883
  const redirectUrl = rawRedirect && rawRedirect.startsWith("/") ? rawRedirect : "/admin/content";
7884
+ const isHtmx = c.req.header("HX-Request") === "true";
7885
+ if (isHtmx) {
7886
+ c.header("HX-Redirect", redirectUrl);
7887
+ return c.html(html.html`<div id="form-response"><p class="text-sm text-green-600">Login successful! Redirecting...</p></div>`);
7888
+ }
7601
7889
  return c.html(html.html`
7602
7890
  <div id="form-response">
7603
7891
  <div class="rounded-lg bg-green-100 dark:bg-lime-500/10 p-4 ring-1 ring-green-400 dark:ring-lime-500/20">
@@ -7627,14 +7915,14 @@ authRoutes.post(
7627
7915
  );
7628
7916
  authRoutes.post(
7629
7917
  "/seed-admin",
7630
- chunk37V3RET3_cjs.rateLimit({ max: 10, windowMs: 60 * 1e3, keyPrefix: "seed-admin" }),
7918
+ chunkBRKXMRMB_cjs.rateLimit({ max: 10, windowMs: 60 * 1e3, keyPrefix: "seed-admin" }),
7631
7919
  async (c) => {
7632
7920
  try {
7633
7921
  const db = c.env.DB;
7634
- const rbac = new chunkLTZ5WYOK_cjs.RbacService(db);
7922
+ const rbac = new chunkOLEOKHDX_cjs.RbacService(db);
7635
7923
  const results = [];
7636
7924
  const upsertSeedUser = async (opts) => {
7637
- const passwordHash = await chunk37V3RET3_cjs.AuthManager.hashPassword(opts.password);
7925
+ const passwordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(opts.password);
7638
7926
  const nowMs = Date.now();
7639
7927
  const nowSec = Math.floor(nowMs / 1e3);
7640
7928
  const existing = await db.prepare("SELECT id FROM auth_user WHERE email = ?").bind(opts.email).first();
@@ -7859,7 +8147,7 @@ authRoutes.post("/accept-invitation", async (c) => {
7859
8147
  if (invitationAge > maxAge) {
7860
8148
  return c.json({ error: "Invitation has expired" }, 400);
7861
8149
  }
7862
- const passwordHash = await chunk37V3RET3_cjs.AuthManager.hashPassword(password);
8150
+ const passwordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(password);
7863
8151
  const updateStmt = db.prepare(`
7864
8152
  UPDATE auth_user SET
7865
8153
  password_hash = ?,
@@ -7876,8 +8164,8 @@ authRoutes.post("/accept-invitation", async (c) => {
7876
8164
  Date.now(),
7877
8165
  invitedUser.id
7878
8166
  ).run();
7879
- const tokenTtl = await chunk37V3RET3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7880
- const authToken = await chunk37V3RET3_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role, c.env.JWT_SECRET, tokenTtl);
8167
+ const tokenTtl = await chunkBRKXMRMB_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
8168
+ const authToken = await chunkBRKXMRMB_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role, c.env.JWT_SECRET, tokenTtl);
7881
8169
  cookie.setCookie(c, "auth_token", authToken, {
7882
8170
  httpOnly: true,
7883
8171
  secure: true,
@@ -7893,7 +8181,7 @@ authRoutes.post("/accept-invitation", async (c) => {
7893
8181
  });
7894
8182
  authRoutes.post(
7895
8183
  "/request-password-reset",
7896
- chunk37V3RET3_cjs.rateLimit({ max: 3, windowMs: 15 * 60 * 1e3, keyPrefix: "password-reset" }),
8184
+ chunkBRKXMRMB_cjs.rateLimit({ max: 3, windowMs: 15 * 60 * 1e3, keyPrefix: "password-reset" }),
7897
8185
  async (c) => {
7898
8186
  try {
7899
8187
  const formData = await c.req.formData();
@@ -8130,7 +8418,7 @@ authRoutes.post("/reset-password", async (c) => {
8130
8418
  if (Date.now() > user.password_reset_expires) {
8131
8419
  return c.json({ error: "Reset token has expired" }, 400);
8132
8420
  }
8133
- const newPasswordHash = await chunk37V3RET3_cjs.AuthManager.hashPassword(password);
8421
+ const newPasswordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(password);
8134
8422
  try {
8135
8423
  const historyStmt = db.prepare(`
8136
8424
  INSERT INTO auth_password_history (id, user_id, password_hash, created_at)
@@ -8344,7 +8632,7 @@ app.post("/test-seed-defaults", async (c) => {
8344
8632
  var test_cleanup_default = app;
8345
8633
 
8346
8634
  // src/plugins/available/easy-mdx/index.ts
8347
- chunkBP52BFIV_cjs.definePlugin({
8635
+ chunkKWQNB6UM_cjs.definePlugin({
8348
8636
  id: "easy-mdx",
8349
8637
  version: "1.0.0",
8350
8638
  name: "EasyMDE Markdown Editor",
@@ -8544,7 +8832,7 @@ function getMDXEditorInitScript(config) {
8544
8832
  }
8545
8833
 
8546
8834
  // src/plugins/available/tinymce-plugin/index.ts
8547
- chunkBP52BFIV_cjs.definePlugin({
8835
+ chunkKWQNB6UM_cjs.definePlugin({
8548
8836
  id: "tinymce-plugin",
8549
8837
  version: "1.0.0",
8550
8838
  name: "TinyMCE",
@@ -8814,7 +9102,7 @@ function getQuillCDN(version = "2.0.2") {
8814
9102
  </style>
8815
9103
  `;
8816
9104
  }
8817
- chunkBP52BFIV_cjs.definePlugin({
9105
+ chunkKWQNB6UM_cjs.definePlugin({
8818
9106
  id: "quill-editor",
8819
9107
  version: "1.0.0",
8820
9108
  name: "Quill Editor",
@@ -8826,7 +9114,7 @@ chunkBP52BFIV_cjs.definePlugin({
8826
9114
  });
8827
9115
 
8828
9116
  // src/templates/pages/admin-content-form.template.ts
8829
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
9117
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
8830
9118
  function renderContentFormPage(data, opts) {
8831
9119
  const isEdit = data.isEdit || !!data.id;
8832
9120
  const title = isEdit ? `Edit: ${data.title || "Content"}` : `New ${data.collection.display_name}`;
@@ -8908,8 +9196,8 @@ function renderContentFormPage(data, opts) {
8908
9196
  <!-- Form Content -->
8909
9197
  <div class="px-6 py-6">
8910
9198
  <div id="form-messages">
8911
- ${data.error ? chunkE66UVONV_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
8912
- ${data.success ? chunkE66UVONV_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
9199
+ ${data.error ? chunkOUBUS74I_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
9200
+ ${data.success ? chunkOUBUS74I_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
8913
9201
  </div>
8914
9202
 
8915
9203
  <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
@@ -9109,33 +9397,44 @@ function renderContentFormPage(data, opts) {
9109
9397
  </a>
9110
9398
 
9111
9399
  <div class="flex items-center gap-x-3">
9112
- ${data.versioningEnabled ? `
9113
- <button
9114
- type="submit"
9115
- form="content-form"
9116
- name="action"
9117
- value="save"
9118
- class="inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm"
9119
- >
9120
- <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
9121
- <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
9122
- </svg>
9123
- ${isEdit ? "Update" : "Save"}
9124
- </button>
9125
- ` : ""}
9400
+ <button
9401
+ type="submit"
9402
+ form="content-form"
9403
+ name="action"
9404
+ value="save"
9405
+ class="inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm"
9406
+ >
9407
+ <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
9408
+ <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
9409
+ </svg>
9410
+ Save
9411
+ </button>
9412
+
9413
+ <button
9414
+ type="submit"
9415
+ form="content-form"
9416
+ name="action"
9417
+ value="save_and_close"
9418
+ class="inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm"
9419
+ >
9420
+ <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
9421
+ <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
9422
+ </svg>
9423
+ Save & close
9424
+ </button>
9126
9425
 
9127
- ${data.user?.role !== "viewer" ? `
9426
+ ${data.user?.role !== "viewer" && data.versioningEnabled ? `
9128
9427
  <button
9129
9428
  type="submit"
9130
9429
  form="content-form"
9131
9430
  name="action"
9132
9431
  value="save_and_publish"
9133
- class="inline-flex items-center justify-center gap-x-1.5 rounded-lg ${data.versioningEnabled ? "bg-lime-600 dark:bg-lime-500 hover:bg-lime-700 dark:hover:bg-lime-600" : "bg-zinc-950 dark:bg-white hover:bg-zinc-800 dark:hover:bg-zinc-100 text-white dark:text-zinc-950"} px-3.5 py-2.5 text-sm font-semibold text-white transition-colors shadow-sm"
9432
+ class="inline-flex items-center justify-center gap-x-1.5 rounded-lg bg-lime-600 dark:bg-lime-500 hover:bg-lime-700 dark:hover:bg-lime-600 px-3.5 py-2.5 text-sm font-semibold text-white transition-colors shadow-sm"
9134
9433
  >
9135
9434
  <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
9136
9435
  <path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
9137
9436
  </svg>
9138
- ${data.versioningEnabled ? `${isEdit ? "Update" : "Save"} & Publish` : isEdit ? "Update" : "Save"}
9437
+ Publish
9139
9438
  </button>
9140
9439
  ` : ""}
9141
9440
  </div>
@@ -9145,7 +9444,7 @@ function renderContentFormPage(data, opts) {
9145
9444
  </div>
9146
9445
 
9147
9446
  <!-- Confirmation Dialogs -->
9148
- ${chunkE66UVONV_cjs.renderConfirmationDialog({
9447
+ ${chunkOUBUS74I_cjs.renderConfirmationDialog({
9149
9448
  id: "duplicate-content-confirm",
9150
9449
  title: "Duplicate Content",
9151
9450
  message: "Create a copy of this content?",
@@ -9156,7 +9455,7 @@ function renderContentFormPage(data, opts) {
9156
9455
  onConfirm: "performDuplicateContent()"
9157
9456
  })}
9158
9457
 
9159
- ${chunkE66UVONV_cjs.renderConfirmationDialog({
9458
+ ${chunkOUBUS74I_cjs.renderConfirmationDialog({
9160
9459
  id: "delete-content-confirm",
9161
9460
  title: "Delete Content",
9162
9461
  message: "Are you sure you want to delete this content? This action cannot be undone.",
@@ -9167,7 +9466,7 @@ function renderContentFormPage(data, opts) {
9167
9466
  onConfirm: `performDeleteContent('${data.id}')`
9168
9467
  })}
9169
9468
 
9170
- ${chunkE66UVONV_cjs.renderConfirmationDialog({
9469
+ ${chunkOUBUS74I_cjs.renderConfirmationDialog({
9171
9470
  id: "delete-repeater-item-confirm",
9172
9471
  title: "Delete Item",
9173
9472
  message: "Are you sure you want to delete this item? This action cannot be undone.",
@@ -9178,7 +9477,7 @@ function renderContentFormPage(data, opts) {
9178
9477
  onConfirm: "performRepeaterDelete()"
9179
9478
  })}
9180
9479
 
9181
- ${chunkE66UVONV_cjs.renderConfirmationDialog({
9480
+ ${chunkOUBUS74I_cjs.renderConfirmationDialog({
9182
9481
  id: "delete-block-confirm",
9183
9482
  title: "Delete Block",
9184
9483
  message: "Are you sure you want to delete this block? This action cannot be undone.",
@@ -9189,7 +9488,7 @@ function renderContentFormPage(data, opts) {
9189
9488
  onConfirm: "performRepeaterDelete()"
9190
9489
  })}
9191
9490
 
9192
- ${chunkE66UVONV_cjs.getConfirmationDialogScript()}
9491
+ ${chunkOUBUS74I_cjs.getConfirmationDialogScript()}
9193
9492
 
9194
9493
  ${data.lexicalEnabled ? getLexicalStyles() : "<!-- Lexical plugin not active -->"}
9195
9494
 
@@ -10275,11 +10574,11 @@ function renderContentFormPage(data, opts) {
10275
10574
  content: pageContent,
10276
10575
  version: data.version
10277
10576
  };
10278
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
10577
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
10279
10578
  }
10280
10579
 
10281
10580
  // src/templates/pages/admin-content-list.template.ts
10282
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
10581
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
10283
10582
  function renderContentListPage(data) {
10284
10583
  const urlParams = new URLSearchParams();
10285
10584
  if (data.modelName && data.modelName !== "all") urlParams.set("model", data.modelName);
@@ -10713,8 +11012,8 @@ function renderContentListPage(data) {
10713
11012
 
10714
11013
  <!-- Content List -->
10715
11014
  <div id="content-list">
10716
- ${chunkE66UVONV_cjs.renderTable(tableData)}
10717
- ${chunkE66UVONV_cjs.renderPagination(paginationData)}
11015
+ ${chunkOUBUS74I_cjs.renderTable(tableData)}
11016
+ ${chunkOUBUS74I_cjs.renderPagination(paginationData)}
10718
11017
  </div>
10719
11018
 
10720
11019
  </div>
@@ -10924,7 +11223,7 @@ function renderContentListPage(data) {
10924
11223
  </script>
10925
11224
 
10926
11225
  <!-- Confirmation Dialog for Bulk Actions -->
10927
- ${chunkE66UVONV_cjs.renderConfirmationDialog({
11226
+ ${chunkOUBUS74I_cjs.renderConfirmationDialog({
10928
11227
  id: "bulk-action-confirm",
10929
11228
  title: "Confirm Bulk Action",
10930
11229
  message: "Are you sure you want to perform this action? This operation will affect multiple items.",
@@ -10936,7 +11235,7 @@ function renderContentListPage(data) {
10936
11235
  })}
10937
11236
 
10938
11237
  <!-- Confirmation Dialog Script -->
10939
- ${chunkE66UVONV_cjs.getConfirmationDialogScript()}
11238
+ ${chunkOUBUS74I_cjs.getConfirmationDialogScript()}
10940
11239
 
10941
11240
  <!-- Advanced Search Modal -->
10942
11241
  <div id="advancedSearchModal" class="hidden fixed inset-0 z-50 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
@@ -11233,7 +11532,7 @@ function renderContentListPage(data) {
11233
11532
  version: data.version,
11234
11533
  content: pageContent
11235
11534
  };
11236
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
11535
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
11237
11536
  }
11238
11537
 
11239
11538
  // src/routes/admin-content-field-types.ts
@@ -11276,9 +11575,9 @@ function parseFieldValue(field, formData, options = {}) {
11276
11575
  const { skipValidation = false } = options;
11277
11576
  const value = formData.get(field.field_name);
11278
11577
  const errors = [];
11279
- const blocksConfig = chunkIXUHXTHW_cjs.getBlocksFieldConfig(field.field_options);
11578
+ const blocksConfig = chunkSFGYZUWU_cjs.getBlocksFieldConfig(field.field_options);
11280
11579
  if (blocksConfig) {
11281
- const parsed = chunkIXUHXTHW_cjs.parseBlocksValue(value, blocksConfig);
11580
+ const parsed = chunkSFGYZUWU_cjs.parseBlocksValue(value, blocksConfig);
11282
11581
  if (!skipValidation && field.is_required && parsed.value.length === 0) {
11283
11582
  parsed.errors.push(`${field.field_label} is required`);
11284
11583
  }
@@ -11388,7 +11687,7 @@ function extractFieldData(fields, formData, options = {}) {
11388
11687
  }
11389
11688
  return { data, errors };
11390
11689
  }
11391
- adminContentRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
11690
+ adminContentRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
11392
11691
  async function getCollectionFields(db, collectionId) {
11393
11692
  console.log(`[getCollectionFields] Loading fields for collection: ${collectionId}`);
11394
11693
  const collectionStmt = db.prepare("SELECT schema, queryable_fields FROM document_types WHERE id = ?");
@@ -11415,7 +11714,7 @@ async function getCollectionFields(db, collectionId) {
11415
11714
  };
11416
11715
  });
11417
11716
  }
11418
- const codeCollections2 = await chunkQCJHCSOK_cjs.loadCollectionConfigs();
11717
+ const codeCollections2 = await chunk4DHPR7KR_cjs.loadCollectionConfigs();
11419
11718
  const codeMatch = codeCollections2.find((c) => c.name === collectionId);
11420
11719
  if (codeMatch && codeMatch.schema?.properties) {
11421
11720
  console.log(`[getCollectionFields] DB doc type has no properties \u2014 using code collection schema`);
@@ -11447,7 +11746,7 @@ async function getCollectionFields(db, collectionId) {
11447
11746
  }
11448
11747
  }
11449
11748
  console.log(`[getCollectionFields] Not in database, checking code collections`);
11450
- const codeCollections = await chunkQCJHCSOK_cjs.loadCollectionConfigs();
11749
+ const codeCollections = await chunk4DHPR7KR_cjs.loadCollectionConfigs();
11451
11750
  console.log(`[getCollectionFields] Found ${codeCollections.length} code collections`);
11452
11751
  const codeCollection = codeCollections.find((c) => c.name === collectionId);
11453
11752
  if (codeCollection && codeCollection.schema) {
@@ -11483,7 +11782,7 @@ async function getCollectionFields(db, collectionId) {
11483
11782
  }
11484
11783
  async function getCollection(db, collectionId) {
11485
11784
  console.log(`[getCollection] Loading collection by ID: ${collectionId}`);
11486
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.collection);
11785
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.collection);
11487
11786
  return cache.getOrSet(
11488
11787
  cache.generateKey("collection", collectionId),
11489
11788
  async () => {
@@ -11501,7 +11800,7 @@ async function getCollection(db, collectionId) {
11501
11800
  };
11502
11801
  }
11503
11802
  console.log(`[getCollection] Not in database, checking code collections`);
11504
- const codeCollections = await chunkQCJHCSOK_cjs.loadCollectionConfigs();
11803
+ const codeCollections = await chunk4DHPR7KR_cjs.loadCollectionConfigs();
11505
11804
  const codeCollection = codeCollections.find((c) => c.name === collectionId);
11506
11805
  if (codeCollection) {
11507
11806
  console.log(`[getCollection] Found code collection: ${collectionId}`);
@@ -11520,7 +11819,7 @@ async function getCollection(db, collectionId) {
11520
11819
  }
11521
11820
  async function getDocBackingType(db, collectionName) {
11522
11821
  if (!collectionName) return null;
11523
- const dt = await new chunk37V3RET3_cjs.DocumentTypeRegistry(db).findById(collectionName);
11822
+ const dt = await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db).findById(collectionName);
11524
11823
  return dt && dt.isActive ? dt : null;
11525
11824
  }
11526
11825
  async function getCollectionByName(db, name) {
@@ -11537,7 +11836,7 @@ async function getCollectionByName(db, name) {
11537
11836
  };
11538
11837
  }
11539
11838
  console.log(`[getCollectionByName] Not in database, checking code collections`);
11540
- const codeCollections = await chunkQCJHCSOK_cjs.loadCollectionConfigs();
11839
+ const codeCollections = await chunk4DHPR7KR_cjs.loadCollectionConfigs();
11541
11840
  const codeCollection = codeCollections.find((c) => c.name === name);
11542
11841
  if (codeCollection) {
11543
11842
  console.log(`[getCollectionByName] Found code collection: ${name}`);
@@ -11553,7 +11852,7 @@ async function getCollectionByName(db, name) {
11553
11852
  return null;
11554
11853
  }
11555
11854
  async function loadContentEditorFlags(db) {
11556
- const flags = { workflowEnabled: await chunk37V3RET3_cjs.isPluginActive(db, "workflow") };
11855
+ const flags = { workflowEnabled: await chunk4DHPR7KR_cjs.isPluginActive(db, "workflow") };
11557
11856
  const editors = [
11558
11857
  ["tinymce-plugin", "tinymce"],
11559
11858
  ["quill-editor", "quill"],
@@ -11561,10 +11860,10 @@ async function loadContentEditorFlags(db) {
11561
11860
  ["lexical-editor", "lexical"]
11562
11861
  ];
11563
11862
  for (const [plugin, key] of editors) {
11564
- const enabled = await chunk37V3RET3_cjs.isPluginActive(db, plugin);
11863
+ const enabled = await chunk4DHPR7KR_cjs.isPluginActive(db, plugin);
11565
11864
  flags[`${key}Enabled`] = enabled;
11566
11865
  if (enabled) {
11567
- const ps = new chunkQCJHCSOK_cjs.PluginService(db);
11866
+ const ps = new chunk4DHPR7KR_cjs.PluginService(db);
11568
11867
  const p = await ps.getPlugin(plugin);
11569
11868
  flags[`${key}Settings`] = p?.settings;
11570
11869
  }
@@ -11572,7 +11871,7 @@ async function loadContentEditorFlags(db) {
11572
11871
  return flags;
11573
11872
  }
11574
11873
  function makeDocService(db, docType, tenantId) {
11575
- return new chunkLTZ5WYOK_cjs.DocumentsService(db, {
11874
+ return new chunkOLEOKHDX_cjs.DocumentsService(db, {
11576
11875
  queryableFields: docType.queryableFields ?? [],
11577
11876
  typeSchemaVersion: docType.schemaVersion ?? 1,
11578
11877
  maxVersionsPerRoot: docType.settings?.maxVersionsPerRoot ?? 50,
@@ -11600,9 +11899,9 @@ adminContentRoutes.get("/", async (c) => {
11600
11899
  const offset = (page - 1) * limit;
11601
11900
  const collectionsStmt = db.prepare("SELECT id, name, display_name FROM document_types WHERE is_active = 1 ORDER BY display_name");
11602
11901
  const { results: collectionsResults } = await collectionsStmt.all();
11603
- const codeCollections = await chunkQCJHCSOK_cjs.loadCollectionConfigs();
11902
+ const codeCollections = await chunk4DHPR7KR_cjs.loadCollectionConfigs();
11604
11903
  const codeCollectionMap = new Map(codeCollections.map((c2) => [c2.name, c2]));
11605
- const docTypeRegistry = new chunk37V3RET3_cjs.DocumentTypeRegistry(db);
11904
+ const docTypeRegistry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
11606
11905
  const docTypes = (await docTypeRegistry.findAll()).filter((dt) => !dt.settings?.internal && !dt.isAuth);
11607
11906
  const visibleTypeIds = new Set(docTypes.map((dt) => dt.id));
11608
11907
  const allCollections = [
@@ -11614,7 +11913,7 @@ adminContentRoutes.get("/", async (c) => {
11614
11913
  ...allCollections.map((c2) => ({ name: c2.name, displayName: c2.displayName })),
11615
11914
  ...docTypes.filter((dt) => !collectionNames.has(dt.id)).map((dt) => ({ name: `doc:${dt.id}`, displayName: dt.displayName }))
11616
11915
  ];
11617
- const newContentCollections = await chunkQCJHCSOK_cjs.getVisibleCollections(db);
11916
+ const newContentCollections = await chunk4DHPR7KR_cjs.getVisibleCollections(db);
11618
11917
  const docBackedCollection = !modelName.startsWith("doc:") && modelName !== "all" ? docTypes.find((dt) => dt.id === modelName) : void 0;
11619
11918
  const isDocModel = modelName.startsWith("doc:") || !!docBackedCollection;
11620
11919
  if (isDocModel) {
@@ -11899,9 +12198,9 @@ adminContentRoutes.get("/new", async (c) => {
11899
12198
  const collectionsStmt = db2.prepare("SELECT id, name, display_name, description FROM document_types WHERE is_active = 1 ORDER BY display_name");
11900
12199
  const { results } = await collectionsStmt.all();
11901
12200
  const visibleTypeIds = new Set(
11902
- (await new chunk37V3RET3_cjs.DocumentTypeRegistry(db2).findAll()).filter((dt) => !dt.settings?.internal && !dt.isAuth).map((dt) => dt.id)
12201
+ (await new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db2).findAll()).filter((dt) => !dt.settings?.internal && !dt.isAuth).map((dt) => dt.id)
11903
12202
  );
11904
- const codeCollections = await chunkQCJHCSOK_cjs.loadCollectionConfigs();
12203
+ const codeCollections = await chunk4DHPR7KR_cjs.loadCollectionConfigs();
11905
12204
  const dbCollectionNames = new Set((results || []).map((r) => r.name));
11906
12205
  const allCollections = [
11907
12206
  ...codeCollections.filter((c2) => !dbCollectionNames.has(c2.name)).map((c2) => ({
@@ -11967,32 +12266,32 @@ adminContentRoutes.get("/new", async (c) => {
11967
12266
  return c.html(renderContentFormPage(formData2));
11968
12267
  }
11969
12268
  const fields = await getCollectionFields(db, collection.id);
11970
- const workflowEnabled = await chunk37V3RET3_cjs.isPluginActive(db, "workflow");
11971
- const tinymceEnabled = await chunk37V3RET3_cjs.isPluginActive(db, "tinymce-plugin");
12269
+ const workflowEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "workflow");
12270
+ const tinymceEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "tinymce-plugin");
11972
12271
  let tinymceSettings;
11973
12272
  if (tinymceEnabled) {
11974
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
12273
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
11975
12274
  const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
11976
12275
  tinymceSettings = tinymcePlugin2?.settings;
11977
12276
  }
11978
- const quillEnabled = await chunk37V3RET3_cjs.isPluginActive(db, "quill-editor");
12277
+ const quillEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "quill-editor");
11979
12278
  let quillSettings;
11980
12279
  if (quillEnabled) {
11981
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
12280
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
11982
12281
  const quillPlugin = await pluginService.getPlugin("quill-editor");
11983
12282
  quillSettings = quillPlugin?.settings;
11984
12283
  }
11985
- const mdxeditorEnabled = await chunk37V3RET3_cjs.isPluginActive(db, "easy-mdx");
12284
+ const mdxeditorEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "easy-mdx");
11986
12285
  let mdxeditorSettings;
11987
12286
  if (mdxeditorEnabled) {
11988
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
12287
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
11989
12288
  const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
11990
12289
  mdxeditorSettings = mdxeditorPlugin?.settings;
11991
12290
  }
11992
- const lexicalEnabled = await chunk37V3RET3_cjs.isPluginActive(db, "lexical-editor");
12291
+ const lexicalEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "lexical-editor");
11993
12292
  let lexicalSettings;
11994
12293
  if (lexicalEnabled) {
11995
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
12294
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
11996
12295
  const lexicalPlugin = await pluginService.getPlugin("lexical-editor");
11997
12296
  lexicalSettings = lexicalPlugin?.settings;
11998
12297
  }
@@ -12091,7 +12390,7 @@ adminContentRoutes.get("/:id/edit", async (c) => {
12091
12390
  } : void 0
12092
12391
  };
12093
12392
  return c.html(renderContentFormPage(notFoundData));
12094
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content);
12393
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content);
12095
12394
  const content = await cache.getOrSet(
12096
12395
  cache.generateKey("content", id),
12097
12396
  async () => {
@@ -12128,32 +12427,32 @@ adminContentRoutes.get("/:id/edit", async (c) => {
12128
12427
  };
12129
12428
  const fields = await getCollectionFields(db, content.collection_id);
12130
12429
  const contentData = content.data ? JSON.parse(content.data) : {};
12131
- const workflowEnabled = await chunk37V3RET3_cjs.isPluginActive(db, "workflow");
12132
- const tinymceEnabled = await chunk37V3RET3_cjs.isPluginActive(db, "tinymce-plugin");
12430
+ const workflowEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "workflow");
12431
+ const tinymceEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "tinymce-plugin");
12133
12432
  let tinymceSettings;
12134
12433
  if (tinymceEnabled) {
12135
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
12434
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
12136
12435
  const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
12137
12436
  tinymceSettings = tinymcePlugin2?.settings;
12138
12437
  }
12139
- const quillEnabled = await chunk37V3RET3_cjs.isPluginActive(db, "quill-editor");
12438
+ const quillEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "quill-editor");
12140
12439
  let quillSettings;
12141
12440
  if (quillEnabled) {
12142
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
12441
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
12143
12442
  const quillPlugin = await pluginService.getPlugin("quill-editor");
12144
12443
  quillSettings = quillPlugin?.settings;
12145
12444
  }
12146
- const mdxeditorEnabled = await chunk37V3RET3_cjs.isPluginActive(db, "easy-mdx");
12445
+ const mdxeditorEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "easy-mdx");
12147
12446
  let mdxeditorSettings;
12148
12447
  if (mdxeditorEnabled) {
12149
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
12448
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
12150
12449
  const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
12151
12450
  mdxeditorSettings = mdxeditorPlugin?.settings;
12152
12451
  }
12153
- const lexicalEnabled = await chunk37V3RET3_cjs.isPluginActive(db, "lexical-editor");
12452
+ const lexicalEnabled = await chunk4DHPR7KR_cjs.isPluginActive(db, "lexical-editor");
12154
12453
  let lexicalSettings;
12155
12454
  if (lexicalEnabled) {
12156
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
12455
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
12157
12456
  const lexicalPlugin = await pluginService.getPlugin("lexical-editor");
12158
12457
  lexicalSettings = lexicalPlugin?.settings;
12159
12458
  }
@@ -12276,8 +12575,11 @@ adminContentRoutes.post("/", async (c) => {
12276
12575
  data,
12277
12576
  publishOnCreate: status === "published"
12278
12577
  }), user?.userId);
12279
- const cache2 = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content);
12578
+ const cache2 = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content);
12280
12579
  await cache2.invalidate(`content:list:${collectionId}:*`);
12580
+ const apiCacheCreate = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
12581
+ await apiCacheCreate.invalidate("api:content-filtered:*");
12582
+ await apiCacheCreate.invalidate(`api:collection-content-filtered:${createDocType.id}:*`);
12281
12583
  const redirectUrl2 = `/admin/content/${doc.rootId}/edit?success=Content created successfully!`;
12282
12584
  return c.req.header("HX-Request") === "true" ? c.text("", 200, { "HX-Redirect": redirectUrl2 }) : c.redirect(redirectUrl2);
12283
12585
  }
@@ -12306,7 +12608,7 @@ adminContentRoutes.post("/", async (c) => {
12306
12608
  now,
12307
12609
  now
12308
12610
  ).run();
12309
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content);
12611
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content);
12310
12612
  await cache.invalidate(`content:list:${collectionId}:*`);
12311
12613
  const versionStmt = db.prepare(`
12312
12614
  INSERT INTO content_versions (id, content_id, version, data, author_id, created_at)
@@ -12395,9 +12697,29 @@ adminContentRoutes.put("/:id", async (c) => {
12395
12697
  const pub = await db.prepare("SELECT id FROM documents WHERE root_id = ? AND is_published = 1 AND tenant_id = ?").bind(id, tenantId).first();
12396
12698
  if (status2 === "published") await svc.publish(newDraft.id, user?.userId);
12397
12699
  else if (pub) await svc.unpublish(pub.id);
12398
- await chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content).invalidate(`content:list:*`);
12700
+ await chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content).invalidate(`content:list:*`);
12701
+ const apiCacheEdit = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
12702
+ await apiCacheEdit.invalidate("api:content-filtered:*");
12703
+ await apiCacheEdit.invalidate(`api:collection-content-filtered:${docRowU.type_id}:*`);
12704
+ const isHTMX2 = c.req.header("HX-Request") === "true";
12705
+ const referrerParams = formData.get("referrer_params");
12706
+ const listUrl = referrerParams ? `/admin/content?${referrerParams}` : `/admin/content?collection=${dcoll.id}`;
12707
+ if (action === "save_and_close") {
12708
+ return isHTMX2 ? c.text("", 200, { "HX-Redirect": listUrl }) : c.redirect(listUrl);
12709
+ }
12710
+ if (isHTMX2) {
12711
+ const label = status2 === "published" ? "Content published successfully!" : "Content saved successfully!";
12712
+ return c.html(html.html`<div id="form-messages">
12713
+ <div class="rounded-lg bg-green-50 dark:bg-green-900/20 p-4 mb-4 flex items-center gap-3 border border-green-200 dark:border-green-800">
12714
+ <svg class="h-5 w-5 text-green-500 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
12715
+ <path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
12716
+ </svg>
12717
+ <span class="text-sm font-medium text-green-800 dark:text-green-200">${label}</span>
12718
+ </div>
12719
+ </div>`);
12720
+ }
12399
12721
  const redirectUrl2 = `/admin/content/${id}/edit?success=Content updated successfully!`;
12400
- return c.req.header("HX-Request") === "true" ? c.text("", 200, { "HX-Redirect": redirectUrl2 }) : c.redirect(redirectUrl2);
12722
+ return c.redirect(redirectUrl2);
12401
12723
  }
12402
12724
  }
12403
12725
  return c.html(html.html`
@@ -12478,7 +12800,7 @@ adminContentRoutes.put("/:id", async (c) => {
12478
12800
  now,
12479
12801
  id
12480
12802
  ).run();
12481
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content);
12803
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content);
12482
12804
  await cache.delete(cache.generateKey("content", id));
12483
12805
  await cache.invalidate(`content:list:${existingContent.collection_id}:*`);
12484
12806
  const existingData = JSON.parse(existingContent.data || "{}");
@@ -12530,7 +12852,7 @@ adminContentRoutes.put("/:id", async (c) => {
12530
12852
  `);
12531
12853
  }
12532
12854
  });
12533
- adminContentRoutes.post("/preview", chunk37V3RET3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
12855
+ adminContentRoutes.post("/preview", chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
12534
12856
  try {
12535
12857
  const formData = await c.req.formData();
12536
12858
  const collectionId = formData.get("collection_id");
@@ -12785,14 +13107,14 @@ adminContentRoutes.post("/bulk-action", async (c) => {
12785
13107
  }
12786
13108
  }
12787
13109
  }
12788
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content);
13110
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content);
12789
13111
  for (const contentId of ids) {
12790
13112
  await cache.delete(cache.generateKey("content", contentId));
12791
13113
  }
12792
13114
  await cache.invalidate("content:list:*");
12793
- const apiCache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
12794
- await apiCache.invalidate("content-filtered:*");
12795
- await apiCache.invalidate("collection-content-filtered:*");
13115
+ const apiCache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
13116
+ await apiCache.invalidate("api:content-filtered:*");
13117
+ await apiCache.invalidate("api:collection-content-filtered:*");
12796
13118
  return c.json({ success: true, count: ids.length });
12797
13119
  } catch (error) {
12798
13120
  console.error("Bulk action error:", error);
@@ -12809,7 +13131,10 @@ adminContentRoutes.delete("/:id", async (c) => {
12809
13131
  if (docDel && await getDocBackingType(db, docDel.type_id)) {
12810
13132
  const now2 = Math.floor(Date.now() / 1e3);
12811
13133
  await db.prepare("UPDATE documents SET deleted_at = ?, updated_at = ? WHERE root_id = ? AND tenant_id = ?").bind(now2, now2, id, tenantId).run();
12812
- await chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content).invalidate("content:list:*");
13134
+ await chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content).invalidate("content:list:*");
13135
+ const apiCacheDel = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.api);
13136
+ await apiCacheDel.invalidate("api:content-filtered:*");
13137
+ await apiCacheDel.invalidate(`api:collection-content-filtered:${docDel.type_id}:*`);
12813
13138
  return c.html(`
12814
13139
  <div id="content-list" hx-get="/admin/content?model=${docDel.type_id}" hx-trigger="load" hx-swap="outerHTML">
12815
13140
  <div class="flex items-center justify-center p-8"><span class="text-zinc-500">Deleting\u2026</span></div>
@@ -12829,7 +13154,7 @@ adminContentRoutes.delete("/:id", async (c) => {
12829
13154
  WHERE id = ?
12830
13155
  `);
12831
13156
  await deleteStmt.bind(now, id).run();
12832
- const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.content);
13157
+ const cache = chunkC5LDQ3SH_cjs.getCacheService(chunkC5LDQ3SH_cjs.CACHE_CONFIGS.content);
12833
13158
  await cache.delete(cache.generateKey("content", id));
12834
13159
  await cache.invalidate("content:list:*");
12835
13160
  return c.html(`
@@ -12849,7 +13174,7 @@ adminContentRoutes.delete("/:id", async (c) => {
12849
13174
  return c.json({ success: false, error: "Failed to delete content" }, 500);
12850
13175
  }
12851
13176
  });
12852
- adminContentRoutes.get("/:id/version/:version/preview", chunk37V3RET3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
13177
+ adminContentRoutes.get("/:id/version/:version/preview", chunkBRKXMRMB_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
12853
13178
  try {
12854
13179
  const id = c.req.param("id");
12855
13180
  const version = parseInt(c.req.param("version") || "0");
@@ -12945,9 +13270,9 @@ function parseDocFormData(formData, queryableFields = []) {
12945
13270
  return { title, slug, data };
12946
13271
  }
12947
13272
  async function getDocService(db, typeId, tenantId) {
12948
- const registry = new chunk37V3RET3_cjs.DocumentTypeRegistry(db);
13273
+ const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
12949
13274
  const docType = await registry.findById(typeId);
12950
- const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
13275
+ const svc = new chunkOLEOKHDX_cjs.DocumentsService(db, {
12951
13276
  queryableFields: docType?.queryableFields ?? [],
12952
13277
  typeSchemaVersion: docType?.schemaVersion ?? 1,
12953
13278
  maxVersionsPerRoot: docType?.settings?.maxVersionsPerRoot ?? 50,
@@ -12958,10 +13283,10 @@ async function getDocService(db, typeId, tenantId) {
12958
13283
  }
12959
13284
  adminContentRoutes.get("/documents/:typeId/new", async (c) => {
12960
13285
  const { typeId } = c.req.param();
12961
- const registry = new chunk37V3RET3_cjs.DocumentTypeRegistry(c.env.DB);
13286
+ const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(c.env.DB);
12962
13287
  const docType = await registry.findById(typeId);
12963
13288
  if (!docType) return c.html("<p>Unknown document type.</p>", 404);
12964
- return c.html(chunkJMJM7DMM_cjs.renderDocumentFormPage({ docType, isEdit: false, user: userCtx(c) }));
13289
+ return c.html(chunkTT3TQSCZ_cjs.renderDocumentFormPage({ docType, isEdit: false, user: userCtx(c) }));
12965
13290
  });
12966
13291
  adminContentRoutes.post("/documents/:typeId/new", async (c) => {
12967
13292
  const { typeId } = c.req.param();
@@ -12983,17 +13308,17 @@ adminContentRoutes.post("/documents/:typeId/new", async (c) => {
12983
13308
  }), user?.userId);
12984
13309
  return c.redirect(`/admin/content/documents/${typeId}/${doc.rootId}/edit?message=Created+successfully`);
12985
13310
  } catch (err) {
12986
- const registry = new chunk37V3RET3_cjs.DocumentTypeRegistry(c.env.DB);
13311
+ const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(c.env.DB);
12987
13312
  const docType = await registry.findById(typeId);
12988
13313
  if (!docType) return c.html("<p>Unknown document type.</p>", 404);
12989
- return c.html(chunkJMJM7DMM_cjs.renderDocumentFormPage({ docType, isEdit: false, user: userCtx(c), message: err?.message ?? "Failed to create", messageType: "error" }));
13314
+ return c.html(chunkTT3TQSCZ_cjs.renderDocumentFormPage({ docType, isEdit: false, user: userCtx(c), message: err?.message ?? "Failed to create", messageType: "error" }));
12990
13315
  }
12991
13316
  });
12992
13317
  adminContentRoutes.get("/documents/:typeId/:rootId/edit", async (c) => {
12993
13318
  const { typeId, rootId } = c.req.param();
12994
13319
  const db = c.env.DB;
12995
13320
  const message = c.req.query("message");
12996
- const registry = new chunk37V3RET3_cjs.DocumentTypeRegistry(db);
13321
+ const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
12997
13322
  const docType = await registry.findById(typeId);
12998
13323
  if (!docType) return c.html("<p>Unknown document type.</p>", 404);
12999
13324
  const tenantId = reqTenant(c);
@@ -13040,7 +13365,7 @@ adminContentRoutes.get("/documents/:typeId/:rootId/edit", async (c) => {
13040
13365
  createdAt: draftRow.created_at,
13041
13366
  updatedAt: draftRow.updated_at
13042
13367
  };
13043
- return c.html(chunkJMJM7DMM_cjs.renderDocumentFormPage({ docType, doc, publishedDoc, isEdit: true, message, user: userCtx(c), versioningEnabled: docType?.settings?.versioning === true }));
13368
+ return c.html(chunkTT3TQSCZ_cjs.renderDocumentFormPage({ docType, doc, publishedDoc, isEdit: true, message, user: userCtx(c), versioningEnabled: docType?.settings?.versioning === true }));
13044
13369
  });
13045
13370
  adminContentRoutes.post("/documents/:typeId/:rootId", async (c) => {
13046
13371
  const { typeId, rootId } = c.req.param();
@@ -13105,8 +13430,8 @@ adminContentRoutes.post("/documents/:typeId/:documentId/delete", async (c) => {
13105
13430
  adminContentRoutes.get("/documents/:typeId/:rootId/versions", async (c) => {
13106
13431
  const { typeId, rootId } = c.req.param();
13107
13432
  const db = c.env.DB;
13108
- const { renderVersionHistoryFragment } = await import('./admin-documents-form.template-YNAVMJCV.cjs');
13109
- const registry = new chunk37V3RET3_cjs.DocumentTypeRegistry(db);
13433
+ const { renderVersionHistoryFragment } = await import('./admin-documents-form.template-UWKGVAMW.cjs');
13434
+ const registry = new chunkBRKXMRMB_cjs.DocumentTypeRegistry(db);
13110
13435
  const docType = await registry.findById(typeId);
13111
13436
  if (!docType) return c.html("<div>Unknown type.</div>", 404);
13112
13437
  const result = await db.prepare(
@@ -13126,7 +13451,7 @@ adminContentRoutes.get("/documents/:typeId/:rootId/versions", async (c) => {
13126
13451
  var admin_content_default = adminContentRoutes;
13127
13452
 
13128
13453
  // src/templates/pages/admin-profile.template.ts
13129
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
13454
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
13130
13455
  function renderAvatarImage(avatarUrl, firstName, lastName) {
13131
13456
  return `<div id="avatar-image-container" class="w-24 h-24 rounded-full mx-auto mb-4 overflow-hidden bg-gradient-to-br from-cyan-400 to-purple-400 flex items-center justify-center ring-4 ring-zinc-950/5 dark:ring-white/10">
13132
13457
  ${avatarUrl ? `<img src="${avatarUrl}" alt="Profile picture" class="w-full h-full object-cover">` : `<span class="text-2xl font-bold text-white">${firstName.charAt(0)}${lastName.charAt(0)}</span>`}
@@ -13146,8 +13471,8 @@ function renderProfilePage(data) {
13146
13471
  </div>
13147
13472
 
13148
13473
  <!-- Alert Messages -->
13149
- ${data.error ? chunkE66UVONV_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
13150
- ${data.success ? chunkE66UVONV_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
13474
+ ${data.error ? chunkOUBUS74I_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
13475
+ ${data.success ? chunkOUBUS74I_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
13151
13476
 
13152
13477
  <!-- Profile Form -->
13153
13478
  <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
@@ -13524,7 +13849,7 @@ function renderProfilePage(data) {
13524
13849
  version: data.version,
13525
13850
  content: pageContent
13526
13851
  };
13527
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
13852
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
13528
13853
  }
13529
13854
 
13530
13855
  // src/templates/pages/admin-activity-logs.template.ts
@@ -13734,7 +14059,7 @@ function renderActivityLogsPage(data) {
13734
14059
  user: data.user,
13735
14060
  content: pageContent
13736
14061
  };
13737
- return chunkE66UVONV_cjs.renderAdminLayout(layoutData);
14062
+ return chunkOUBUS74I_cjs.renderAdminLayout(layoutData);
13738
14063
  }
13739
14064
  function getActionBadgeClass(action) {
13740
14065
  if (action.includes("login") || action.includes("logout")) {
@@ -13754,7 +14079,7 @@ function formatAction(action) {
13754
14079
  }
13755
14080
 
13756
14081
  // src/templates/pages/admin-user-edit.template.ts
13757
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
14082
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
13758
14083
 
13759
14084
  // src/templates/components/confirmation-dialog.template.ts
13760
14085
  function renderConfirmationDialog2(options) {
@@ -13950,8 +14275,8 @@ function renderUserEditPage(data) {
13950
14275
 
13951
14276
  <!-- Alert Messages -->
13952
14277
  <div id="form-messages" class="mb-6 empty:mb-0">
13953
- ${data.error ? chunkE66UVONV_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
13954
- ${data.success ? chunkE66UVONV_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
14278
+ ${data.error ? chunkOUBUS74I_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
14279
+ ${data.success ? chunkOUBUS74I_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
13955
14280
  </div>
13956
14281
 
13957
14282
  <!-- User Edit Form -->
@@ -14273,11 +14598,11 @@ function renderUserEditPage(data) {
14273
14598
  user: data.user,
14274
14599
  content: pageContent
14275
14600
  };
14276
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
14601
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
14277
14602
  }
14278
14603
 
14279
14604
  // src/templates/pages/admin-user-new.template.ts
14280
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
14605
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
14281
14606
  function renderUserNewPage(data) {
14282
14607
  const pageContent = `
14283
14608
  <div>
@@ -14316,8 +14641,8 @@ function renderUserNewPage(data) {
14316
14641
 
14317
14642
  <!-- Alert Messages -->
14318
14643
  <div id="form-messages">
14319
- ${data.error ? chunkE66UVONV_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
14320
- ${data.success ? chunkE66UVONV_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
14644
+ ${data.error ? chunkOUBUS74I_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
14645
+ ${data.success ? chunkOUBUS74I_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
14321
14646
  </div>
14322
14647
 
14323
14648
  <!-- User New Form -->
@@ -14547,11 +14872,11 @@ function renderUserNewPage(data) {
14547
14872
  user: data.user,
14548
14873
  content: pageContent
14549
14874
  };
14550
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
14875
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
14551
14876
  }
14552
14877
 
14553
14878
  // src/templates/pages/admin-users-list.template.ts
14554
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
14879
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
14555
14880
  function renderUsersListPage(data) {
14556
14881
  const columns = [
14557
14882
  {
@@ -14707,8 +15032,8 @@ function renderUsersListPage(data) {
14707
15032
  </div>
14708
15033
 
14709
15034
  <!-- Alert Messages -->
14710
- ${data.error ? chunkE66UVONV_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
14711
- ${data.success ? chunkE66UVONV_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
15035
+ ${data.error ? chunkOUBUS74I_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
15036
+ ${data.success ? chunkOUBUS74I_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
14712
15037
 
14713
15038
  <!-- Stats -->
14714
15039
  <div class="mb-6">
@@ -14885,10 +15210,10 @@ function renderUsersListPage(data) {
14885
15210
  </div>
14886
15211
 
14887
15212
  <!-- Users Table -->
14888
- ${chunkE66UVONV_cjs.renderTable(tableData)}
15213
+ ${chunkOUBUS74I_cjs.renderTable(tableData)}
14889
15214
 
14890
15215
  <!-- Pagination -->
14891
- ${data.pagination ? chunkE66UVONV_cjs.renderPagination(data.pagination) : ""}
15216
+ ${data.pagination ? chunkOUBUS74I_cjs.renderPagination(data.pagination) : ""}
14892
15217
  </div>
14893
15218
 
14894
15219
  <script>
@@ -14959,7 +15284,7 @@ function renderUsersListPage(data) {
14959
15284
  version: data.version,
14960
15285
  content: pageContent
14961
15286
  };
14962
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
15287
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
14963
15288
  }
14964
15289
 
14965
15290
  // src/plugins/core-plugins/multi-tenant-plugin/services/tenant-service.ts
@@ -15039,7 +15364,7 @@ var TenantService = class {
15039
15364
  SET name = ?, domain = ?, status = ?, notes = ?, updated_at = ?
15040
15365
  WHERE slug = ?
15041
15366
  `).bind(name, domain, status, notes, now, slug).run();
15042
- chunkQCJHCSOK_cjs.invalidateTenantCache();
15367
+ chunk4DHPR7KR_cjs.invalidateTenantCache();
15043
15368
  const updated = await this.getTenantBySlug(slug);
15044
15369
  if (!updated) throw new Error("Tenant not found");
15045
15370
  return updated;
@@ -15057,7 +15382,7 @@ var TenantService = class {
15057
15382
  throw new Error(`Tenant '${slug}' still owns ${docCount} document(s). Delete or migrate its content first.`);
15058
15383
  }
15059
15384
  await this.db.prepare(`DELETE FROM auth_tenant WHERE slug = ?`).bind(slug).run();
15060
- chunkQCJHCSOK_cjs.invalidateTenantCache();
15385
+ chunk4DHPR7KR_cjs.invalidateTenantCache();
15061
15386
  }
15062
15387
  // ─── Membership (auth_tenant_member) ───────────────────────────────────────
15063
15388
  // Tenant resolution and the admin switcher are gated on membership: an authed user may only
@@ -15301,7 +15626,7 @@ var TenantService = class {
15301
15626
  INSERT INTO auth_tenant (id, name, slug, status, domain, notes, metadata, created_at, updated_at)
15302
15627
  VALUES (?, ?, ?, 'active', ?, ?, '{}', ?, ?)
15303
15628
  `).bind(id, input.name, input.slug, input.domain, input.notes, now, now).run();
15304
- chunkQCJHCSOK_cjs.invalidateTenantCache();
15629
+ chunk4DHPR7KR_cjs.invalidateTenantCache();
15305
15630
  const created = await this.getTenantBySlug(input.slug);
15306
15631
  if (!created) throw new Error("Failed to create tenant");
15307
15632
  return created;
@@ -15325,14 +15650,14 @@ function mapRowToTenant(row) {
15325
15650
 
15326
15651
  // src/routes/admin-users.ts
15327
15652
  var userRoutes = new hono.Hono();
15328
- userRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
15329
- userRoutes.use("/users/*", chunk37V3RET3_cjs.requireRole(["admin"]));
15330
- userRoutes.use("/users", chunk37V3RET3_cjs.requireRole(["admin"]));
15331
- userRoutes.use("/invite-user", chunk37V3RET3_cjs.requireRole(["admin"]));
15332
- userRoutes.use("/resend-invitation/*", chunk37V3RET3_cjs.requireRole(["admin"]));
15333
- userRoutes.use("/cancel-invitation/*", chunk37V3RET3_cjs.requireRole(["admin"]));
15334
- userRoutes.use("/activity-logs", chunk37V3RET3_cjs.requireRole(["admin"]));
15335
- userRoutes.use("/activity-logs/*", chunk37V3RET3_cjs.requireRole(["admin"]));
15653
+ userRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
15654
+ userRoutes.use("/users/*", chunkBRKXMRMB_cjs.requireRole(["admin"]));
15655
+ userRoutes.use("/users", chunkBRKXMRMB_cjs.requireRole(["admin"]));
15656
+ userRoutes.use("/invite-user", chunkBRKXMRMB_cjs.requireRole(["admin"]));
15657
+ userRoutes.use("/resend-invitation/*", chunkBRKXMRMB_cjs.requireRole(["admin"]));
15658
+ userRoutes.use("/cancel-invitation/*", chunkBRKXMRMB_cjs.requireRole(["admin"]));
15659
+ userRoutes.use("/activity-logs", chunkBRKXMRMB_cjs.requireRole(["admin"]));
15660
+ userRoutes.use("/activity-logs/*", chunkBRKXMRMB_cjs.requireRole(["admin"]));
15336
15661
  userRoutes.get("/", (c) => {
15337
15662
  return c.redirect("/admin/dashboard");
15338
15663
  });
@@ -15360,12 +15685,10 @@ var LANGUAGES = [
15360
15685
  { value: "ko", label: "Korean" },
15361
15686
  { value: "zh", label: "Chinese" }
15362
15687
  ];
15363
- var ROLES = [
15364
- { value: "admin", label: "Administrator" },
15365
- { value: "editor", label: "Editor" },
15366
- { value: "author", label: "Author" },
15367
- { value: "viewer", label: "Viewer" }
15368
- ];
15688
+ async function fetchRoleOptions(db) {
15689
+ const roles = await new chunkOLEOKHDX_cjs.RbacService(db).getRoles();
15690
+ return roles.map((r) => ({ value: r.id, label: r.display_name }));
15691
+ }
15369
15692
  userRoutes.get("/profile", async (c) => {
15370
15693
  const user = c.get("user");
15371
15694
  const db = c.env.DB;
@@ -15443,7 +15766,7 @@ userRoutes.put("/profile", async (c) => {
15443
15766
  const language = formData.get("language")?.toString() || "en";
15444
15767
  const emailNotifications = formData.get("email_notifications") === "1";
15445
15768
  if (!firstName || !lastName || !email) {
15446
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15769
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15447
15770
  type: "error",
15448
15771
  message: "First name, last name, and email are required.",
15449
15772
  dismissible: true
@@ -15451,7 +15774,7 @@ userRoutes.put("/profile", async (c) => {
15451
15774
  }
15452
15775
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
15453
15776
  if (!emailRegex.test(email)) {
15454
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15777
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15455
15778
  type: "error",
15456
15779
  message: "Please enter a valid email address.",
15457
15780
  dismissible: true
@@ -15463,7 +15786,7 @@ userRoutes.put("/profile", async (c) => {
15463
15786
  `);
15464
15787
  const existingUser = await checkStmt.bind(email, user.userId).first();
15465
15788
  if (existingUser) {
15466
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15789
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15467
15790
  type: "error",
15468
15791
  message: "Email is already taken by another user.",
15469
15792
  dismissible: true
@@ -15495,11 +15818,11 @@ userRoutes.put("/profile", async (c) => {
15495
15818
  const validation = validateCustomData(sanitized, profileConfig);
15496
15819
  if (!validation.valid) {
15497
15820
  const errorMessages = Object.values(validation.errors).join(", ");
15498
- return c.html(chunkJMJM7DMM_cjs.renderAlert({ type: "error", message: errorMessages, dismissible: true }), 400);
15821
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({ type: "error", message: errorMessages, dismissible: true }), 400);
15499
15822
  }
15500
15823
  await saveCustomData(db, user.userId, sanitized);
15501
15824
  }
15502
- await chunk37V3RET3_cjs.logActivity(
15825
+ await chunkBRKXMRMB_cjs.logActivity(
15503
15826
  db,
15504
15827
  user.userId,
15505
15828
  "profile.update",
@@ -15509,14 +15832,14 @@ userRoutes.put("/profile", async (c) => {
15509
15832
  c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
15510
15833
  c.req.header("user-agent")
15511
15834
  );
15512
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15835
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15513
15836
  type: "success",
15514
15837
  message: "Profile updated successfully!",
15515
15838
  dismissible: true
15516
15839
  }));
15517
15840
  } catch (error) {
15518
15841
  console.error("Profile update error:", error);
15519
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15842
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15520
15843
  type: "error",
15521
15844
  message: "Failed to update profile. Please try again.",
15522
15845
  dismissible: true
@@ -15530,7 +15853,7 @@ userRoutes.post("/profile/avatar", async (c) => {
15530
15853
  const formData = await c.req.formData();
15531
15854
  const avatarFile = formData.get("avatar");
15532
15855
  if (!avatarFile || typeof avatarFile === "string" || !avatarFile.name) {
15533
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15856
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15534
15857
  type: "error",
15535
15858
  message: "Please select an image file.",
15536
15859
  dismissible: true
@@ -15538,7 +15861,7 @@ userRoutes.post("/profile/avatar", async (c) => {
15538
15861
  }
15539
15862
  const allowedTypes = ["image/jpeg", "image/png", "image/gif", "image/webp"];
15540
15863
  if (!allowedTypes.includes(avatarFile.type)) {
15541
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15864
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15542
15865
  type: "error",
15543
15866
  message: "Please upload a valid image file (JPEG, PNG, GIF, or WebP).",
15544
15867
  dismissible: true
@@ -15546,7 +15869,7 @@ userRoutes.post("/profile/avatar", async (c) => {
15546
15869
  }
15547
15870
  const maxSize = 5 * 1024 * 1024;
15548
15871
  if (avatarFile.size > maxSize) {
15549
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15872
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15550
15873
  type: "error",
15551
15874
  message: "Image file must be smaller than 5MB.",
15552
15875
  dismissible: true
@@ -15562,7 +15885,7 @@ userRoutes.post("/profile/avatar", async (c) => {
15562
15885
  SELECT first_name, last_name FROM auth_user WHERE id = ?
15563
15886
  `);
15564
15887
  const userData = await userStmt.bind(user.userId).first();
15565
- await chunk37V3RET3_cjs.logActivity(
15888
+ await chunkBRKXMRMB_cjs.logActivity(
15566
15889
  db,
15567
15890
  user.userId,
15568
15891
  "profile.avatar_update",
@@ -15572,7 +15895,7 @@ userRoutes.post("/profile/avatar", async (c) => {
15572
15895
  c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
15573
15896
  c.req.header("user-agent")
15574
15897
  );
15575
- const alertHtml = chunkJMJM7DMM_cjs.renderAlert({
15898
+ const alertHtml = chunkTT3TQSCZ_cjs.renderAlert({
15576
15899
  type: "success",
15577
15900
  message: "Profile picture updated successfully!",
15578
15901
  dismissible: true
@@ -15586,7 +15909,7 @@ userRoutes.post("/profile/avatar", async (c) => {
15586
15909
  return c.html(alertHtml + avatarImageWithOob);
15587
15910
  } catch (error) {
15588
15911
  console.error("Avatar upload error:", error);
15589
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15912
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15590
15913
  type: "error",
15591
15914
  message: "Failed to upload profile picture. Please try again.",
15592
15915
  dismissible: true
@@ -15602,21 +15925,21 @@ userRoutes.post("/profile/password", async (c) => {
15602
15925
  const newPassword = formData.get("new_password")?.toString() || "";
15603
15926
  const confirmPassword = formData.get("confirm_password")?.toString() || "";
15604
15927
  if (!currentPassword || !newPassword || !confirmPassword) {
15605
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15928
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15606
15929
  type: "error",
15607
15930
  message: "All password fields are required.",
15608
15931
  dismissible: true
15609
15932
  }));
15610
15933
  }
15611
15934
  if (newPassword !== confirmPassword) {
15612
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15935
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15613
15936
  type: "error",
15614
15937
  message: "New passwords do not match.",
15615
15938
  dismissible: true
15616
15939
  }));
15617
15940
  }
15618
15941
  if (newPassword.length < 8) {
15619
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15942
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15620
15943
  type: "error",
15621
15944
  message: "New password must be at least 8 characters long.",
15622
15945
  dismissible: true
@@ -15627,21 +15950,21 @@ userRoutes.post("/profile/password", async (c) => {
15627
15950
  `);
15628
15951
  const userData = await userStmt.bind(user.userId).first();
15629
15952
  if (!userData) {
15630
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15953
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15631
15954
  type: "error",
15632
15955
  message: "User not found.",
15633
15956
  dismissible: true
15634
15957
  }));
15635
15958
  }
15636
- const validPassword = await chunk37V3RET3_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
15959
+ const validPassword = await chunkBRKXMRMB_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
15637
15960
  if (!validPassword) {
15638
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15961
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15639
15962
  type: "error",
15640
15963
  message: "Current password is incorrect.",
15641
15964
  dismissible: true
15642
15965
  }));
15643
15966
  }
15644
- const newPasswordHash = await chunk37V3RET3_cjs.AuthManager.hashPassword(newPassword);
15967
+ const newPasswordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(newPassword);
15645
15968
  const historyStmt = db.prepare(`
15646
15969
  INSERT INTO auth_password_history (id, user_id, password_hash, created_at)
15647
15970
  VALUES (?, ?, ?, ?)
@@ -15657,7 +15980,7 @@ userRoutes.post("/profile/password", async (c) => {
15657
15980
  WHERE id = ?
15658
15981
  `);
15659
15982
  await updateStmt.bind(newPasswordHash, Date.now(), user.userId).run();
15660
- await chunk37V3RET3_cjs.logActivity(
15983
+ await chunkBRKXMRMB_cjs.logActivity(
15661
15984
  db,
15662
15985
  user.userId,
15663
15986
  "profile.password_change",
@@ -15667,14 +15990,14 @@ userRoutes.post("/profile/password", async (c) => {
15667
15990
  c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
15668
15991
  c.req.header("user-agent")
15669
15992
  );
15670
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
15993
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15671
15994
  type: "success",
15672
15995
  message: "Password updated successfully!",
15673
15996
  dismissible: true
15674
15997
  }));
15675
15998
  } catch (error) {
15676
15999
  console.error("Password change error:", error);
15677
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16000
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15678
16001
  type: "error",
15679
16002
  message: "Failed to update password. Please try again.",
15680
16003
  dismissible: true
@@ -15724,7 +16047,7 @@ userRoutes.get("/users", async (c) => {
15724
16047
  `);
15725
16048
  const countResult = await countStmt.bind(...params).first();
15726
16049
  const totalUsers = countResult?.total || 0;
15727
- await chunk37V3RET3_cjs.logActivity(
16050
+ await chunkBRKXMRMB_cjs.logActivity(
15728
16051
  db,
15729
16052
  user.userId,
15730
16053
  "users.list_view",
@@ -15795,7 +16118,7 @@ userRoutes.get("/users", async (c) => {
15795
16118
  if (isApiRequest) {
15796
16119
  return c.json({ error: "Failed to load users" }, 500);
15797
16120
  }
15798
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16121
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15799
16122
  type: "error",
15800
16123
  message: "Failed to load users. Please try again.",
15801
16124
  dismissible: true
@@ -15814,8 +16137,9 @@ userRoutes.get("/users/new", async (c) => {
15814
16137
  const regFieldNames = profileConfig?.registrationFields ?? [];
15815
16138
  const regFields = profileConfig && upRow ? regFieldNames.length > 0 ? profileConfig.fields.filter((f) => regFieldNames.includes(f.name)) : profileConfig.fields : [];
15816
16139
  const registrationFieldsHtml = regFields.length > 0 ? renderCustomProfileSection({ fields: regFields }, {}) : void 0;
16140
+ const roles = await fetchRoleOptions(db);
15817
16141
  const pageData = {
15818
- roles: ROLES,
16142
+ roles,
15819
16143
  registrationFieldsHtml,
15820
16144
  user: {
15821
16145
  name: user.email.split("@")[0] || user.email,
@@ -15826,7 +16150,7 @@ userRoutes.get("/users/new", async (c) => {
15826
16150
  return c.html(renderUserNewPage(pageData));
15827
16151
  } catch (error) {
15828
16152
  console.error("User new page error:", error);
15829
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16153
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15830
16154
  type: "error",
15831
16155
  message: "Failed to load user creation page. Please try again.",
15832
16156
  dismissible: true
@@ -15843,9 +16167,9 @@ userRoutes.post("/users/new", async (c) => {
15843
16167
  const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
15844
16168
  const phone = chunkMNWKYY5E_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
15845
16169
  const bio = chunkMNWKYY5E_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
15846
- const roleInput = formData.get("role")?.toString() || "viewer";
15847
- const validRoles = ["admin", "editor", "author", "viewer"];
15848
- const role = validRoles.includes(roleInput) ? roleInput : "viewer";
16170
+ const roleInput = formData.get("role")?.toString() || "";
16171
+ const validRoles = (await new chunkOLEOKHDX_cjs.RbacService(db).getRoles()).map((r) => r.id);
16172
+ const role = validRoles.includes(roleInput) ? roleInput : validRoles[0] ?? "admin";
15849
16173
  const password = formData.get("password")?.toString() || "";
15850
16174
  const confirmPassword = formData.get("confirm_password")?.toString() || "";
15851
16175
  const isActive = formData.get("is_active") === "1";
@@ -15860,12 +16184,12 @@ userRoutes.post("/users/new", async (c) => {
15860
16184
  const validation = validateCustomData(sanitized, profileConfig);
15861
16185
  if (!validation.valid) {
15862
16186
  const errorMessages = Object.values(validation.errors).join(", ");
15863
- return c.html(chunkJMJM7DMM_cjs.renderAlert({ type: "error", message: errorMessages, dismissible: true }), 400);
16187
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({ type: "error", message: errorMessages, dismissible: true }), 400);
15864
16188
  }
15865
16189
  sanitizedRegistrationCustom = sanitized;
15866
16190
  }
15867
16191
  if (!firstName || !lastName || !email || !password) {
15868
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16192
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15869
16193
  type: "error",
15870
16194
  message: "First name, last name, email, and password are required.",
15871
16195
  dismissible: true
@@ -15873,21 +16197,21 @@ userRoutes.post("/users/new", async (c) => {
15873
16197
  }
15874
16198
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
15875
16199
  if (!emailRegex.test(email)) {
15876
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16200
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15877
16201
  type: "error",
15878
16202
  message: "Please enter a valid email address.",
15879
16203
  dismissible: true
15880
16204
  }));
15881
16205
  }
15882
16206
  if (password.length < 8) {
15883
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16207
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15884
16208
  type: "error",
15885
16209
  message: "Password must be at least 8 characters long.",
15886
16210
  dismissible: true
15887
16211
  }));
15888
16212
  }
15889
16213
  if (password !== confirmPassword) {
15890
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16214
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15891
16215
  type: "error",
15892
16216
  message: "Passwords do not match.",
15893
16217
  dismissible: true
@@ -15899,13 +16223,13 @@ userRoutes.post("/users/new", async (c) => {
15899
16223
  `);
15900
16224
  const existingUser = await checkStmt.bind(email).first();
15901
16225
  if (existingUser) {
15902
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16226
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15903
16227
  type: "error",
15904
16228
  message: "Email is already taken.",
15905
16229
  dismissible: true
15906
16230
  }));
15907
16231
  }
15908
- const passwordHash = await chunk37V3RET3_cjs.AuthManager.hashPassword(password);
16232
+ const passwordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(password);
15909
16233
  const userId = crypto.randomUUID();
15910
16234
  const createStmt = db.prepare(`
15911
16235
  INSERT INTO auth_user (
@@ -15930,7 +16254,7 @@ userRoutes.post("/users/new", async (c) => {
15930
16254
  if (sanitizedRegistrationCustom !== null && Object.keys(sanitizedRegistrationCustom).length > 0) {
15931
16255
  await writeProfileData(db, userId, { custom: sanitizedRegistrationCustom }, user.userId);
15932
16256
  }
15933
- await chunk37V3RET3_cjs.logActivity(
16257
+ await chunkBRKXMRMB_cjs.logActivity(
15934
16258
  db,
15935
16259
  user.userId,
15936
16260
  "user!.create",
@@ -15944,7 +16268,7 @@ userRoutes.post("/users/new", async (c) => {
15944
16268
  return c.body(null, 200);
15945
16269
  } catch (error) {
15946
16270
  console.error("User creation error:", error);
15947
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16271
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
15948
16272
  type: "error",
15949
16273
  message: "Failed to create user!. Please try again.",
15950
16274
  dismissible: true
@@ -15969,7 +16293,7 @@ userRoutes.get("/users/:id", async (c) => {
15969
16293
  if (!userRecord) {
15970
16294
  return c.json({ error: "User not found" }, 404);
15971
16295
  }
15972
- await chunk37V3RET3_cjs.logActivity(
16296
+ await chunkBRKXMRMB_cjs.logActivity(
15973
16297
  db,
15974
16298
  user.userId,
15975
16299
  "user!.view",
@@ -16014,7 +16338,7 @@ userRoutes.get("/users/:id/edit", async (c) => {
16014
16338
  `);
16015
16339
  const userToEdit = await userStmt.bind(userId).first();
16016
16340
  if (!userToEdit) {
16017
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16341
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
16018
16342
  type: "error",
16019
16343
  message: "User not found",
16020
16344
  dismissible: true
@@ -16067,9 +16391,10 @@ userRoutes.get("/users/:id/edit", async (c) => {
16067
16391
  }
16068
16392
  const queryMessage = c.req.query("message");
16069
16393
  const queryType = c.req.query("type") === "error" ? "error" : "success";
16394
+ const roles = await fetchRoleOptions(db);
16070
16395
  const pageData = {
16071
16396
  userToEdit: editData,
16072
- roles: ROLES,
16397
+ roles,
16073
16398
  hasProfilePlugin: profileConfig !== null && upRow !== null,
16074
16399
  customProfileFieldsHtml,
16075
16400
  tenantMemberships,
@@ -16084,7 +16409,7 @@ userRoutes.get("/users/:id/edit", async (c) => {
16084
16409
  return c.html(renderUserEditPage(pageData));
16085
16410
  } catch (error) {
16086
16411
  console.error("User edit page error:", error);
16087
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16412
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
16088
16413
  type: "error",
16089
16414
  message: "Failed to load user. Please try again.",
16090
16415
  dismissible: true
@@ -16101,9 +16426,9 @@ userRoutes.put("/users/:id", async (c) => {
16101
16426
  const lastName = chunkMNWKYY5E_cjs.sanitizeInput(formData.get("last_name")?.toString());
16102
16427
  const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
16103
16428
  const phone = chunkMNWKYY5E_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
16104
- const roleInput = formData.get("role")?.toString() || "viewer";
16105
- const validRoles = ["admin", "editor", "author", "viewer"];
16106
- const role = validRoles.includes(roleInput) ? roleInput : "viewer";
16429
+ const roleInput = formData.get("role")?.toString() || "";
16430
+ const validRoles = (await new chunkOLEOKHDX_cjs.RbacService(db).getRoles()).map((r) => r.id);
16431
+ const role = validRoles.includes(roleInput) ? roleInput : validRoles[0] ?? "admin";
16107
16432
  const isActive = formData.get("is_active") === "1";
16108
16433
  const emailVerified = formData.get("email_verified") === "1";
16109
16434
  const newPassword = formData.get("new_password")?.toString() || "";
@@ -16117,12 +16442,12 @@ userRoutes.put("/users/:id", async (c) => {
16117
16442
  const validation = validateCustomData(sanitized, profileConfig);
16118
16443
  if (!validation.valid) {
16119
16444
  const errorMessages = Object.values(validation.errors).join(", ");
16120
- return c.html(chunkJMJM7DMM_cjs.renderAlert({ type: "error", message: errorMessages, dismissible: true }), 400);
16445
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({ type: "error", message: errorMessages, dismissible: true }), 400);
16121
16446
  }
16122
16447
  sanitizedCustom = sanitized;
16123
16448
  }
16124
16449
  if (!email) {
16125
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16450
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
16126
16451
  type: "error",
16127
16452
  message: "Email is required.",
16128
16453
  dismissible: true
@@ -16130,7 +16455,7 @@ userRoutes.put("/users/:id", async (c) => {
16130
16455
  }
16131
16456
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
16132
16457
  if (!emailRegex.test(email)) {
16133
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16458
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
16134
16459
  type: "error",
16135
16460
  message: "Please enter a valid email address.",
16136
16461
  dismissible: true
@@ -16138,14 +16463,14 @@ userRoutes.put("/users/:id", async (c) => {
16138
16463
  }
16139
16464
  if (newPassword) {
16140
16465
  if (newPassword.length < 8) {
16141
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16466
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
16142
16467
  type: "error",
16143
16468
  message: "Password must be at least 8 characters long.",
16144
16469
  dismissible: true
16145
16470
  }));
16146
16471
  }
16147
16472
  if (newPassword !== confirmPassword) {
16148
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16473
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
16149
16474
  type: "error",
16150
16475
  message: "Passwords do not match.",
16151
16476
  dismissible: true
@@ -16158,7 +16483,7 @@ userRoutes.put("/users/:id", async (c) => {
16158
16483
  `);
16159
16484
  const existingUser = await checkStmt.bind(email, userId).first();
16160
16485
  if (existingUser) {
16161
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16486
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
16162
16487
  type: "error",
16163
16488
  message: "Email is already taken by another user.",
16164
16489
  dismissible: true
@@ -16183,7 +16508,7 @@ userRoutes.put("/users/:id", async (c) => {
16183
16508
  userId
16184
16509
  ).run();
16185
16510
  if (newPassword) {
16186
- const passwordHash = await chunk37V3RET3_cjs.AuthManager.hashPassword(newPassword);
16511
+ const passwordHash = await chunkBRKXMRMB_cjs.AuthManager.hashPassword(newPassword);
16187
16512
  const updatePasswordStmt = db.prepare(`
16188
16513
  UPDATE auth_user SET password_hash = ?, updated_at = ? WHERE id = ?
16189
16514
  `);
@@ -16196,7 +16521,7 @@ userRoutes.put("/users/:id", async (c) => {
16196
16521
  ...sanitizedCustom !== null ? { custom: sanitizedCustom } : {}
16197
16522
  }, user.userId);
16198
16523
  }
16199
- await chunk37V3RET3_cjs.logActivity(
16524
+ await chunkBRKXMRMB_cjs.logActivity(
16200
16525
  db,
16201
16526
  user.userId,
16202
16527
  "user.update",
@@ -16206,7 +16531,7 @@ userRoutes.put("/users/:id", async (c) => {
16206
16531
  c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
16207
16532
  c.req.header("user-agent")
16208
16533
  );
16209
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16534
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
16210
16535
  type: "success",
16211
16536
  message: "User updated successfully!",
16212
16537
  dismissible: true,
@@ -16214,7 +16539,7 @@ userRoutes.put("/users/:id", async (c) => {
16214
16539
  }));
16215
16540
  } catch (error) {
16216
16541
  console.error("User update error:", error);
16217
- return c.html(chunkJMJM7DMM_cjs.renderAlert({
16542
+ return c.html(chunkTT3TQSCZ_cjs.renderAlert({
16218
16543
  type: "error",
16219
16544
  message: "Failed to update user. Please try again.",
16220
16545
  dismissible: true
@@ -16242,7 +16567,7 @@ userRoutes.post("/users/:id/toggle", async (c) => {
16242
16567
  UPDATE auth_user SET is_active = ?, updated_at = ? WHERE id = ?
16243
16568
  `);
16244
16569
  await toggleStmt.bind(active ? 1 : 0, Date.now(), userId).run();
16245
- await chunk37V3RET3_cjs.logActivity(
16570
+ await chunkBRKXMRMB_cjs.logActivity(
16246
16571
  db,
16247
16572
  user.userId,
16248
16573
  active ? "user.activate" : "user.deactivate",
@@ -16283,7 +16608,7 @@ userRoutes.delete("/users/:id", async (c) => {
16283
16608
  DELETE FROM auth_user WHERE id = ?
16284
16609
  `);
16285
16610
  await deleteStmt.bind(userId).run();
16286
- await chunk37V3RET3_cjs.logActivity(
16611
+ await chunkBRKXMRMB_cjs.logActivity(
16287
16612
  db,
16288
16613
  user.userId,
16289
16614
  "user!.hard_delete",
@@ -16302,7 +16627,7 @@ userRoutes.delete("/users/:id", async (c) => {
16302
16627
  UPDATE auth_user SET is_active = 0, updated_at = ? WHERE id = ?
16303
16628
  `);
16304
16629
  await deleteStmt.bind(Date.now(), userId).run();
16305
- await chunk37V3RET3_cjs.logActivity(
16630
+ await chunkBRKXMRMB_cjs.logActivity(
16306
16631
  db,
16307
16632
  user.userId,
16308
16633
  "user!.soft_delete",
@@ -16368,7 +16693,7 @@ userRoutes.post("/invite-user", async (c) => {
16368
16693
  Date.now(),
16369
16694
  Date.now()
16370
16695
  ).run();
16371
- await chunk37V3RET3_cjs.logActivity(
16696
+ await chunkBRKXMRMB_cjs.logActivity(
16372
16697
  db,
16373
16698
  user.userId,
16374
16699
  "user!.invite_sent",
@@ -16425,7 +16750,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
16425
16750
  Date.now(),
16426
16751
  userId
16427
16752
  ).run();
16428
- await chunk37V3RET3_cjs.logActivity(
16753
+ await chunkBRKXMRMB_cjs.logActivity(
16429
16754
  db,
16430
16755
  user.userId,
16431
16756
  "user!.invitation_resent",
@@ -16461,7 +16786,7 @@ userRoutes.delete("/cancel-invitation/:id", async (c) => {
16461
16786
  }
16462
16787
  const deleteStmt = db.prepare(`DELETE FROM auth_user WHERE id = ?`);
16463
16788
  await deleteStmt.bind(userId).run();
16464
- await chunk37V3RET3_cjs.logActivity(
16789
+ await chunkBRKXMRMB_cjs.logActivity(
16465
16790
  db,
16466
16791
  user.userId,
16467
16792
  "user!.invitation_cancelled",
@@ -16710,7 +17035,7 @@ function getFileIcon(mimeType) {
16710
17035
  }
16711
17036
 
16712
17037
  // src/templates/pages/admin-media-library.template.ts
16713
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
17038
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
16714
17039
  function renderMediaLibraryPage(data) {
16715
17040
  const pageContent = `
16716
17041
  <div>
@@ -17645,7 +17970,7 @@ function renderMediaLibraryPage(data) {
17645
17970
  version: data.version,
17646
17971
  content: pageContent
17647
17972
  };
17648
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
17973
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
17649
17974
  }
17650
17975
 
17651
17976
  // src/templates/components/media-file-details.template.ts
@@ -17842,7 +18167,7 @@ var fileValidationSchema2 = zod.z.object({
17842
18167
  // 50MB max
17843
18168
  });
17844
18169
  var adminMediaRoutes = new hono.Hono();
17845
- adminMediaRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
18170
+ adminMediaRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
17846
18171
  adminMediaRoutes.get("/", async (c) => {
17847
18172
  try {
17848
18173
  const user = c.get("user");
@@ -17884,7 +18209,7 @@ adminMediaRoutes.get("/selector", async (c) => {
17884
18209
  const { searchParams } = new URL(c.req.url);
17885
18210
  const search = searchParams.get("search") || "";
17886
18211
  const db = c.env.DB;
17887
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
18212
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
17888
18213
  const mediaPlugin = await pluginService.getPlugin("core-media");
17889
18214
  if (!mediaPlugin || mediaPlugin.status !== "active") {
17890
18215
  return c.html(html.html`
@@ -18260,7 +18585,7 @@ adminMediaRoutes.put("/:id", async (c) => {
18260
18585
  `);
18261
18586
  }
18262
18587
  });
18263
- adminMediaRoutes.delete("/cleanup", chunk37V3RET3_cjs.requireRole("admin"), async (c) => {
18588
+ adminMediaRoutes.delete("/cleanup", chunkBRKXMRMB_cjs.requireRole("admin"), async (c) => {
18264
18589
  try {
18265
18590
  const db = c.env.DB;
18266
18591
  const allMediaStmt = db.prepare("SELECT id, r2_key, filename FROM media WHERE deleted_at IS NULL");
@@ -18518,7 +18843,7 @@ function generateMediaItemHTML(file) {
18518
18843
  }
18519
18844
 
18520
18845
  // src/templates/pages/admin-plugins-list.template.ts
18521
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
18846
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
18522
18847
  function renderPluginsListPage(data) {
18523
18848
  const categories = [
18524
18849
  { value: "content", label: "Content Management" },
@@ -18690,15 +19015,6 @@ function renderPluginsListPage(data) {
18690
19015
  </div>
18691
19016
 
18692
19017
  <div class="flex items-center gap-3 w-full sm:w-auto">
18693
- <select id="sort-filter" onchange="filterAndSortPlugins()" class="block w-full sm:w-auto h-9 rounded-md border-0 py-1.5 pl-3 pr-8 text-zinc-900 ring-1 ring-inset ring-zinc-300 focus:ring-2 focus:ring-inset focus:ring-zinc-600 dark:bg-zinc-900 dark:text-white dark:ring-zinc-700 dark:focus:ring-zinc-500 sm:text-sm sm:leading-6">
18694
- <option value="name-asc">Name (A-Z)</option>
18695
- <option value="name-desc">Name (Z-A)</option>
18696
- <option value="newest">Newest Installed</option>
18697
- <option value="updated">Recently Updated</option>
18698
- <option value="popular">Popularity</option>
18699
- <option value="rating">Highest Rated</option>
18700
- </select>
18701
-
18702
19018
  <button
18703
19019
  onclick="location.reload()"
18704
19020
  class="inline-flex items-center gap-x-1.5 rounded-md bg-white dark:bg-zinc-900 px-3 py-1.5 h-9 text-sm font-semibold text-zinc-900 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800"
@@ -18862,8 +19178,6 @@ function renderPluginsListPage(data) {
18862
19178
  .forEach(cb => params.append('status', cb.value));
18863
19179
  const search = document.getElementById('search-input').value;
18864
19180
  if (search) params.set('search', search);
18865
- const sort = document.getElementById('sort-filter').value;
18866
- if (sort && sort !== 'name-asc') params.set('sort', sort);
18867
19181
  const url = new URL(window.location.href);
18868
19182
  url.search = params.toString();
18869
19183
  history.replaceState(null, '', url.toString());
@@ -18881,8 +19195,6 @@ function renderPluginsListPage(data) {
18881
19195
  });
18882
19196
  const search = params.get('search');
18883
19197
  if (search) document.getElementById('search-input').value = search;
18884
- const sort = params.get('sort');
18885
- if (sort) document.getElementById('sort-filter').value = sort;
18886
19198
  if (params.toString()) filterAndSortPlugins();
18887
19199
  }
18888
19200
 
@@ -18898,7 +19210,6 @@ function renderPluginsListPage(data) {
18898
19210
  .map(cb => cb.value.toLowerCase());
18899
19211
 
18900
19212
  const searchInput = document.getElementById('search-input').value.toLowerCase();
18901
- const sortValue = document.getElementById('sort-filter').value;
18902
19213
 
18903
19214
  const pluginsGrid = document.getElementById('plugins-grid');
18904
19215
  const pluginCards = Array.from(pluginsGrid.querySelectorAll('.plugin-card'));
@@ -18922,30 +19233,6 @@ function renderPluginsListPage(data) {
18922
19233
  return true;
18923
19234
  });
18924
19235
 
18925
- // Sort
18926
- visibleCards.sort((a, b) => {
18927
- const aName = a.getAttribute('data-name') || '';
18928
- const bName = b.getAttribute('data-name') || '';
18929
- const aInstalled = parseInt(a.getAttribute('data-installed') || '0');
18930
- const bInstalled = parseInt(b.getAttribute('data-installed') || '0');
18931
- const aUpdated = parseInt(a.getAttribute('data-updated') || '0');
18932
- const bUpdated = parseInt(b.getAttribute('data-updated') || '0');
18933
- const aDownloads = parseInt(a.getAttribute('data-downloads') || '0');
18934
- const bDownloads = parseInt(b.getAttribute('data-downloads') || '0');
18935
- const aRating = parseFloat(a.getAttribute('data-rating') || '0');
18936
- const bRating = parseFloat(b.getAttribute('data-rating') || '0');
18937
-
18938
- switch (sortValue) {
18939
- case 'name-desc': return bName.localeCompare(aName);
18940
- case 'newest': return bInstalled - aInstalled;
18941
- case 'updated': return bUpdated - aUpdated;
18942
- case 'popular': return bDownloads - aDownloads;
18943
- case 'rating': return bRating - aRating;
18944
- case 'name-asc':
18945
- default: return aName.localeCompare(bName);
18946
- }
18947
- });
18948
-
18949
19236
  // Re-append
18950
19237
  pluginCards.forEach(card => card.style.display = 'none'); // Hide all first
18951
19238
 
@@ -19001,7 +19288,7 @@ function renderPluginsListPage(data) {
19001
19288
  version: data.version,
19002
19289
  content: pageContent
19003
19290
  };
19004
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
19291
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
19005
19292
  }
19006
19293
  function renderPluginCard(plugin) {
19007
19294
  const statusColors = {
@@ -19379,8 +19666,9 @@ function escapeHtmlAttr(value) {
19379
19666
  }
19380
19667
  function renderPluginSettingsPage(data) {
19381
19668
  const { plugin, activity = [], user, settingsTabData } = data;
19382
- const pluginDef = chunkBP52BFIV_cjs.getPluginDefinition(plugin.id || plugin.name);
19383
- const hasUserSettings = pluginDef?.settingsTabContent != null || Object.keys(plugin.settings || {}).some((k) => !k.startsWith("_"));
19669
+ const pluginDef = chunkKWQNB6UM_cjs.getPluginDefinition(plugin.id || plugin.name);
19670
+ const pluginId = plugin.id || plugin.name;
19671
+ const hasUserSettings = pluginDef?.settingsTabContent != null || Object.keys(plugin.settings || {}).some((k) => !k.startsWith("_")) || hasCustomSettingsComponent(pluginId);
19384
19672
  const defaultTab = hasUserSettings ? "settings" : "info";
19385
19673
  const pageContent = `
19386
19674
  <div class="w-full px-4 sm:px-6 lg:px-8 py-6">
@@ -19545,9 +19833,28 @@ function renderPluginSettingsPage(data) {
19545
19833
  const form = document.getElementById('settings-form');
19546
19834
  const formData = new FormData(form);
19547
19835
  const isAuthPlugin = '${plugin.id}' === 'core-auth';
19836
+ const isOAuthPlugin = '${plugin.id}' === 'oauth-providers';
19548
19837
  let settings = {};
19549
19838
 
19550
- if (isAuthPlugin) {
19839
+ if (isOAuthPlugin) {
19840
+ // Build nested provider settings structure
19841
+ const getVal = id => (document.getElementById(id) || {}).value || '';
19842
+ const getChecked = id => !!(document.getElementById(id) || {}).checked;
19843
+ settings = {
19844
+ providers: {
19845
+ github: {
19846
+ clientId: getVal('oauth_github_clientId'),
19847
+ clientSecret: getVal('oauth_github_clientSecret'),
19848
+ enabled: getChecked('oauth_github_enabled'),
19849
+ },
19850
+ google: {
19851
+ clientId: getVal('oauth_google_clientId'),
19852
+ clientSecret: getVal('oauth_google_clientSecret'),
19853
+ enabled: getChecked('oauth_google_enabled'),
19854
+ },
19855
+ }
19856
+ };
19857
+ } else if (isAuthPlugin) {
19551
19858
  // Handle nested auth settings structure
19552
19859
  settings = {
19553
19860
  requiredFields: {},
@@ -19656,7 +19963,7 @@ function renderPluginSettingsPage(data) {
19656
19963
  user,
19657
19964
  content: pageContent
19658
19965
  };
19659
- return chunkE66UVONV_cjs.renderAdminLayout(layoutData);
19966
+ return chunkOUBUS74I_cjs.renderAdminLayout(layoutData);
19660
19967
  }
19661
19968
  function renderStatusBadge(status) {
19662
19969
  const statusColors = {
@@ -19685,7 +19992,7 @@ function renderSettingsTab(plugin, settingsTabData) {
19685
19992
  const settings = plugin.settings || {};
19686
19993
  const pluginId = plugin.id || plugin.name;
19687
19994
  const hasUserKeys = Object.keys(settings).some((k) => !k.startsWith("_"));
19688
- const pluginDef = chunkBP52BFIV_cjs.getPluginDefinition(pluginId);
19995
+ const pluginDef = chunkKWQNB6UM_cjs.getPluginDefinition(pluginId);
19689
19996
  if (pluginDef?.settingsTabContent) {
19690
19997
  return pluginDef.settingsTabContent.render({ plugin, settings, data: settingsTabData });
19691
19998
  }
@@ -20035,7 +20342,8 @@ function formatTimestamp(timestamp) {
20035
20342
  }
20036
20343
  var pluginSettingsComponents = {
20037
20344
  "otp-login": renderOTPLoginSettingsContent,
20038
- "email": renderEmailSettingsContent
20345
+ "email": renderEmailSettingsContent,
20346
+ "oauth-providers": renderOAuthProvidersSettingsContent
20039
20347
  };
20040
20348
  function renderOTPLoginSettingsContent(plugin, settings) {
20041
20349
  const siteName = settings.siteName || "SonicJS";
@@ -20758,6 +21066,62 @@ defineUserProfile({
20758
21066
  </div>
20759
21067
  `;
20760
21068
  }
21069
+ function renderOAuthProvidersSettingsContent(plugin, settings) {
21070
+ const providers = settings.providers || {};
21071
+ const gh = providers.github || {};
21072
+ const gg = providers.google || {};
21073
+ const inputClass = "backdrop-blur-sm bg-white/10 border border-white/20 rounded-lg px-3 py-2 text-white placeholder-gray-300 focus:border-blue-400 focus:outline-none transition-colors w-full";
21074
+ return `
21075
+ <div class="space-y-6">
21076
+ <form id="settings-form">
21077
+ <div class="backdrop-blur-md bg-white/5 rounded-xl border border-white/10 p-6 space-y-6">
21078
+ <h3 class="text-lg font-semibold text-white">GitHub OAuth</h3>
21079
+ <div>
21080
+ <label for="oauth_github_clientId" class="block text-sm font-medium text-gray-300 mb-2">Client ID</label>
21081
+ <input type="text" id="oauth_github_clientId" name="oauth_github_clientId"
21082
+ value="${escapeHtmlAttr(gh.clientId || "")}"
21083
+ placeholder="GitHub OAuth App Client ID" class="${inputClass}" />
21084
+ </div>
21085
+ <div>
21086
+ <label for="oauth_github_clientSecret" class="block text-sm font-medium text-gray-300 mb-2">Client Secret</label>
21087
+ <input type="password" id="oauth_github_clientSecret" name="oauth_github_clientSecret"
21088
+ value="${escapeHtmlAttr(gh.clientSecret || "")}"
21089
+ placeholder="GitHub OAuth App Client Secret" class="${inputClass}" />
21090
+ </div>
21091
+ <div class="flex items-center gap-3">
21092
+ <input type="checkbox" id="oauth_github_enabled" name="oauth_github_enabled"
21093
+ ${gh.enabled ? "checked" : ""} class="w-4 h-4 rounded border-white/10" />
21094
+ <label for="oauth_github_enabled" class="text-sm text-gray-300">Enable GitHub login</label>
21095
+ </div>
21096
+ </div>
21097
+
21098
+ <div class="backdrop-blur-md bg-white/5 rounded-xl border border-white/10 p-6 space-y-6 mt-6">
21099
+ <h3 class="text-lg font-semibold text-white">Google OAuth</h3>
21100
+ <div>
21101
+ <label for="oauth_google_clientId" class="block text-sm font-medium text-gray-300 mb-2">Client ID</label>
21102
+ <input type="text" id="oauth_google_clientId" name="oauth_google_clientId"
21103
+ value="${escapeHtmlAttr(gg.clientId || "")}"
21104
+ placeholder="Google OAuth Client ID" class="${inputClass}" />
21105
+ </div>
21106
+ <div>
21107
+ <label for="oauth_google_clientSecret" class="block text-sm font-medium text-gray-300 mb-2">Client Secret</label>
21108
+ <input type="password" id="oauth_google_clientSecret" name="oauth_google_clientSecret"
21109
+ value="${escapeHtmlAttr(gg.clientSecret || "")}"
21110
+ placeholder="Google OAuth Client Secret" class="${inputClass}" />
21111
+ </div>
21112
+ <div class="flex items-center gap-3">
21113
+ <input type="checkbox" id="oauth_google_enabled" name="oauth_google_enabled"
21114
+ ${gg.enabled ? "checked" : ""} class="w-4 h-4 rounded border-white/10" />
21115
+ <label for="oauth_google_enabled" class="text-sm text-gray-300">Enable Google login</label>
21116
+ </div>
21117
+ </div>
21118
+ </form>
21119
+ </div>
21120
+ `;
21121
+ }
21122
+ function hasCustomSettingsComponent(pluginId) {
21123
+ return pluginId in pluginSettingsComponents;
21124
+ }
20761
21125
 
20762
21126
  // src/plugins/core-plugins/menu-plugin/services/menu-reconcile.ts
20763
21127
  async function upsertPluginRow(db, slug, entry, visible) {
@@ -20875,8 +21239,8 @@ async function fetchActivePluginIds(db) {
20875
21239
  }
20876
21240
  async function reconcileMenuFromPlugins(db) {
20877
21241
  try {
20878
- const singletonEntries = chunkBP52BFIV_cjs.getPluginMenu();
20879
- const manifestEntries = Object.values(chunkQCJHCSOK_cjs.PLUGIN_REGISTRY).filter(
21242
+ const singletonEntries = chunkKWQNB6UM_cjs.getPluginMenu();
21243
+ const manifestEntries = Object.values(chunk4DHPR7KR_cjs.PLUGIN_REGISTRY).filter(
20880
21244
  (p) => p.adminMenu !== null
20881
21245
  );
20882
21246
  const byPluginId = /* @__PURE__ */ new Map();
@@ -20913,8 +21277,8 @@ async function reconcileMenuFromPlugins(db) {
20913
21277
 
20914
21278
  // src/routes/admin-plugins.ts
20915
21279
  var adminPluginRoutes = new hono.Hono();
20916
- adminPluginRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
20917
- var AVAILABLE_PLUGINS = Object.values(chunkQCJHCSOK_cjs.PLUGIN_REGISTRY).map((p) => ({
21280
+ adminPluginRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
21281
+ var AVAILABLE_PLUGINS = Object.values(chunk4DHPR7KR_cjs.PLUGIN_REGISTRY).map((p) => ({
20918
21282
  id: p.id,
20919
21283
  name: p.codeName,
20920
21284
  display_name: p.displayName,
@@ -20934,7 +21298,7 @@ adminPluginRoutes.get("/", async (c) => {
20934
21298
  if (user?.role !== "admin") {
20935
21299
  return c.text("Access denied", 403);
20936
21300
  }
20937
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
21301
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
20938
21302
  let installedPlugins = [];
20939
21303
  let stats = { total: 0, active: 0, inactive: 0, errors: 0, uninstalled: 0 };
20940
21304
  try {
@@ -21008,10 +21372,10 @@ adminPluginRoutes.get("/:id", async (c) => {
21008
21372
  if (user?.role !== "admin") {
21009
21373
  return c.redirect("/admin/plugins");
21010
21374
  }
21011
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
21375
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
21012
21376
  let plugin = await pluginService.getPlugin(pluginId);
21013
21377
  if (!plugin) {
21014
- const def = chunkBP52BFIV_cjs.getPluginDefinition(pluginId);
21378
+ const def = chunkKWQNB6UM_cjs.getPluginDefinition(pluginId);
21015
21379
  if (!def) return c.text("Plugin not found", 404);
21016
21380
  plugin = await pluginService.ensurePlugin(pluginId, {
21017
21381
  displayName: def.displayName ?? pluginId,
@@ -21023,7 +21387,7 @@ adminPluginRoutes.get("/:id", async (c) => {
21023
21387
  const activity = await pluginService.getPluginActivity(pluginId, 20);
21024
21388
  let enrichedSettings = plugin.settings || {};
21025
21389
  if (pluginId === "otp-login") {
21026
- const settingsService = new chunk36Z3AKX3_cjs.SettingsService(db);
21390
+ const settingsService = new chunkC5LDQ3SH_cjs.SettingsService(db);
21027
21391
  const generalSettings = await settingsService.getGeneralSettings();
21028
21392
  const siteName = generalSettings.siteName || "SonicJS";
21029
21393
  const emailPlugin = await db.prepare(`
@@ -21082,7 +21446,7 @@ adminPluginRoutes.get("/:id", async (c) => {
21082
21446
  timestamp: item.timestamp,
21083
21447
  user: item.userId || null
21084
21448
  }));
21085
- const pluginDef = chunkBP52BFIV_cjs.getPluginDefinition(pluginId);
21449
+ const pluginDef = chunkKWQNB6UM_cjs.getPluginDefinition(pluginId);
21086
21450
  let settingsTabData = void 0;
21087
21451
  if (pluginDef?.settingsTabContent?.loadData) {
21088
21452
  try {
@@ -21112,14 +21476,14 @@ adminPluginRoutes.get("/:id/configure", async (c) => {
21112
21476
  const user = c.get("user");
21113
21477
  const pluginId = c.req.param("id");
21114
21478
  if (user?.role !== "admin") return c.redirect("/admin/plugins");
21115
- const def = chunkBP52BFIV_cjs.getPluginDefinition(pluginId);
21479
+ const def = chunkKWQNB6UM_cjs.getPluginDefinition(pluginId);
21116
21480
  if (!def?.configSchema) return c.text("No schema-driven settings for this plugin", 404);
21117
21481
  const db = c.env.DB;
21118
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
21482
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
21119
21483
  const plugin = await pluginService.getPlugin(pluginId);
21120
21484
  const stored = plugin?.settings ?? {};
21121
- const values = chunkBP52BFIV_cjs.applySchemaDefaults(def.configSchema, stored);
21122
- const fieldsHtml = chunkBP52BFIV_cjs.renderSchemaFields(def.configSchema, values);
21485
+ const values = chunkKWQNB6UM_cjs.applySchemaDefaults(def.configSchema, stored);
21486
+ const fieldsHtml = chunkKWQNB6UM_cjs.renderSchemaFields(def.configSchema, values);
21123
21487
  const displayName = plugin?.display_name ?? def.displayName ?? def.id;
21124
21488
  return c.html(`<!DOCTYPE html>
21125
21489
  <html lang="en"><head>
@@ -21146,12 +21510,12 @@ adminPluginRoutes.post("/:id/configure", async (c) => {
21146
21510
  const user = c.get("user");
21147
21511
  const pluginId = c.req.param("id");
21148
21512
  if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
21149
- const def = chunkBP52BFIV_cjs.getPluginDefinition(pluginId);
21513
+ const def = chunkKWQNB6UM_cjs.getPluginDefinition(pluginId);
21150
21514
  if (!def?.configSchema) return c.text("No schema-driven settings for this plugin", 404);
21151
21515
  const form = await c.req.formData();
21152
- const parsed = chunkBP52BFIV_cjs.parseFormDataToSettings(def.configSchema, form);
21516
+ const parsed = chunkKWQNB6UM_cjs.parseFormDataToSettings(def.configSchema, form);
21153
21517
  const db = c.env.DB;
21154
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
21518
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
21155
21519
  await pluginService.ensurePlugin(pluginId, {
21156
21520
  displayName: def.displayName ?? pluginId,
21157
21521
  version: def.version,
@@ -21175,7 +21539,7 @@ adminPluginRoutes.post("/:id/activate", async (c) => {
21175
21539
  if (user?.role !== "admin") {
21176
21540
  return c.json({ error: "Access denied" }, 403);
21177
21541
  }
21178
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
21542
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
21179
21543
  await pluginService.activatePlugin(pluginId);
21180
21544
  await reconcileMenuFromPlugins(db);
21181
21545
  return c.json({ success: true });
@@ -21193,7 +21557,7 @@ adminPluginRoutes.post("/:id/deactivate", async (c) => {
21193
21557
  if (user?.role !== "admin") {
21194
21558
  return c.json({ error: "Access denied" }, 403);
21195
21559
  }
21196
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
21560
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
21197
21561
  await pluginService.deactivatePlugin(pluginId);
21198
21562
  await reconcileMenuFromPlugins(db);
21199
21563
  return c.json({ success: true });
@@ -21211,8 +21575,8 @@ adminPluginRoutes.post("/install", async (c) => {
21211
21575
  return c.json({ error: "Access denied" }, 403);
21212
21576
  }
21213
21577
  const body = await c.req.json();
21214
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
21215
- const registryEntry = chunkQCJHCSOK_cjs.findPluginByCodeName(body.name) || chunkQCJHCSOK_cjs.PLUGIN_REGISTRY[body.name] || chunkQCJHCSOK_cjs.PLUGIN_REGISTRY[body.id];
21578
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
21579
+ const registryEntry = chunk4DHPR7KR_cjs.findPluginByCodeName(body.name) || chunk4DHPR7KR_cjs.PLUGIN_REGISTRY[body.name] || chunk4DHPR7KR_cjs.PLUGIN_REGISTRY[body.id];
21216
21580
  if (!registryEntry) {
21217
21581
  return c.json({ error: "Plugin not found in registry" }, 404);
21218
21582
  }
@@ -21245,7 +21609,7 @@ adminPluginRoutes.post("/:id/uninstall", async (c) => {
21245
21609
  if (user?.role !== "admin") {
21246
21610
  return c.json({ error: "Access denied" }, 403);
21247
21611
  }
21248
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
21612
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
21249
21613
  await pluginService.uninstallPlugin(pluginId);
21250
21614
  return c.json({ success: true });
21251
21615
  } catch (error) {
@@ -21263,7 +21627,7 @@ adminPluginRoutes.post("/:id/settings", async (c) => {
21263
21627
  return c.json({ error: "Access denied" }, 403);
21264
21628
  }
21265
21629
  const settings = await c.req.json();
21266
- const pluginService = new chunkQCJHCSOK_cjs.PluginService(db);
21630
+ const pluginService = new chunk4DHPR7KR_cjs.PluginService(db);
21267
21631
  const existingPlugin = await pluginService.getPlugin(pluginId);
21268
21632
  const existingSettings = existingPlugin?.settings ?? {};
21269
21633
  await pluginService.updatePluginSettings(pluginId, { ...existingSettings, ...settings });
@@ -21298,7 +21662,7 @@ function formatLastUpdated(timestamp) {
21298
21662
  }
21299
21663
 
21300
21664
  // src/templates/pages/admin-logs-list.template.ts
21301
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
21665
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
21302
21666
  function renderLogsListPage(data) {
21303
21667
  const { logs, pagination, filters, user } = data;
21304
21668
  const content = `
@@ -21609,7 +21973,7 @@ function renderLogsListPage(data) {
21609
21973
  user,
21610
21974
  content
21611
21975
  };
21612
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
21976
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
21613
21977
  }
21614
21978
  function renderLogDetailsPage(data) {
21615
21979
  const { log, user } = data;
@@ -21821,7 +22185,7 @@ function renderLogDetailsPage(data) {
21821
22185
  </div>
21822
22186
  </div>
21823
22187
  `;
21824
- return chunkE66UVONV_cjs.adminLayoutV2({
22188
+ return chunkOUBUS74I_cjs.adminLayoutV2({
21825
22189
  title: `Log Details - ${log.id}`,
21826
22190
  user,
21827
22191
  content
@@ -22064,7 +22428,7 @@ function renderLogConfigPage(data) {
22064
22428
 
22065
22429
  <script src="https://unpkg.com/htmx.org@1.9.6"></script>
22066
22430
  `;
22067
- return chunkE66UVONV_cjs.adminLayoutV2({
22431
+ return chunkOUBUS74I_cjs.adminLayoutV2({
22068
22432
  title: "Log Configuration",
22069
22433
  user,
22070
22434
  content
@@ -22073,11 +22437,11 @@ function renderLogConfigPage(data) {
22073
22437
 
22074
22438
  // src/routes/admin-logs.ts
22075
22439
  var adminLogsRoutes = new hono.Hono();
22076
- adminLogsRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
22440
+ adminLogsRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
22077
22441
  adminLogsRoutes.get("/", async (c) => {
22078
22442
  try {
22079
22443
  const user = c.get("user");
22080
- const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
22444
+ const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
22081
22445
  const query = c.req.query();
22082
22446
  const page = parseInt(query.page || "1");
22083
22447
  const limit = parseInt(query.limit || "50");
@@ -22157,7 +22521,7 @@ adminLogsRoutes.get("/:id", async (c) => {
22157
22521
  try {
22158
22522
  const id = c.req.param("id");
22159
22523
  const user = c.get("user");
22160
- const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
22524
+ const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
22161
22525
  const { logs } = await logger.getLogs({
22162
22526
  limit: 1,
22163
22527
  offset: 0,
@@ -22194,7 +22558,7 @@ adminLogsRoutes.get("/:id", async (c) => {
22194
22558
  adminLogsRoutes.get("/config", async (c) => {
22195
22559
  try {
22196
22560
  const user = c.get("user");
22197
- const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
22561
+ const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
22198
22562
  const configs = await logger.getAllConfigs();
22199
22563
  const pageData = {
22200
22564
  configs,
@@ -22218,7 +22582,7 @@ adminLogsRoutes.post("/config/:category", async (c) => {
22218
22582
  const level = formData.get("level");
22219
22583
  const retention = parseInt(formData.get("retention"));
22220
22584
  const maxSize = parseInt(formData.get("max_size"));
22221
- const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
22585
+ const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
22222
22586
  await logger.updateConfig(category, {
22223
22587
  enabled,
22224
22588
  level,
@@ -22247,7 +22611,7 @@ adminLogsRoutes.get("/export", async (c) => {
22247
22611
  const category = query.category;
22248
22612
  const startDate = query.start_date;
22249
22613
  const endDate = query.end_date;
22250
- const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
22614
+ const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
22251
22615
  const filter = {
22252
22616
  limit: 1e4,
22253
22617
  // Export up to 10k logs
@@ -22328,7 +22692,7 @@ adminLogsRoutes.post("/cleanup", async (c) => {
22328
22692
  error: "Unauthorized. Admin access required."
22329
22693
  }, 403);
22330
22694
  }
22331
- const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
22695
+ const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
22332
22696
  await logger.cleanupByRetention();
22333
22697
  return c.html(html.html`
22334
22698
  <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded">
@@ -22350,7 +22714,7 @@ adminLogsRoutes.post("/search", async (c) => {
22350
22714
  const search = formData.get("search");
22351
22715
  const level = formData.get("level");
22352
22716
  const category = formData.get("category");
22353
- const logger = chunk36Z3AKX3_cjs.getLogger(c.env.DB);
22717
+ const logger = chunkC5LDQ3SH_cjs.getLogger(c.env.DB);
22354
22718
  const filter = {
22355
22719
  limit: 20,
22356
22720
  offset: 0,
@@ -22445,7 +22809,7 @@ adminCheckboxRoutes.get("/", (c) => {
22445
22809
  role: user.role
22446
22810
  } : void 0
22447
22811
  };
22448
- return c.html(chunkE66UVONV_cjs.renderCheckboxPage(pageData));
22812
+ return c.html(chunkOUBUS74I_cjs.renderCheckboxPage(pageData));
22449
22813
  });
22450
22814
 
22451
22815
  // src/templates/pages/admin-dashboard.template.ts
@@ -22517,7 +22881,7 @@ function renderDashboardPage(data) {
22517
22881
  version: data.version,
22518
22882
  content: pageContent
22519
22883
  };
22520
- return chunkE66UVONV_cjs.renderAdminLayout(layoutData);
22884
+ return chunkOUBUS74I_cjs.renderAdminLayout(layoutData);
22521
22885
  }
22522
22886
  function renderStatsCards(stats) {
22523
22887
  const cards = [
@@ -23065,9 +23429,9 @@ function renderStorageUsage(databaseSizeBytes, mediaSizeBytes) {
23065
23429
  }
23066
23430
 
23067
23431
  // src/routes/admin-dashboard.ts
23068
- var VERSION = chunkKKNEYIZJ_cjs.getCoreVersion();
23432
+ var VERSION = chunkXZUEGFXE_cjs.getCoreVersion();
23069
23433
  var router = new hono.Hono();
23070
- router.use("*", chunk37V3RET3_cjs.requireAuth());
23434
+ router.use("*", chunkBRKXMRMB_cjs.requireAuth());
23071
23435
  router.get("/", async (c) => {
23072
23436
  const user = c.get("user");
23073
23437
  try {
@@ -23257,7 +23621,7 @@ router.get("/system-status", async (c) => {
23257
23621
  });
23258
23622
 
23259
23623
  // src/templates/pages/admin-collections-list.template.ts
23260
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
23624
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
23261
23625
 
23262
23626
  // src/templates/components/table.template.ts
23263
23627
  function renderTable2(data) {
@@ -23739,11 +24103,11 @@ function renderCollectionsListPage(data) {
23739
24103
  version: data.version,
23740
24104
  content: pageContent
23741
24105
  };
23742
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
24106
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
23743
24107
  }
23744
24108
 
23745
24109
  // src/templates/pages/admin-collections-form.template.ts
23746
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
24110
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
23747
24111
  function getFieldTypeBadge(fieldType) {
23748
24112
  const typeLabels = {
23749
24113
  "text": "Text",
@@ -23916,8 +24280,8 @@ function renderCollectionFormPage(data) {
23916
24280
  <!-- Form Content -->
23917
24281
  <div class="px-6 py-6">
23918
24282
  <div id="form-messages"></div>
23919
- ${data.error ? chunkJMJM7DMM_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
23920
- ${data.success ? chunkJMJM7DMM_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
24283
+ ${data.error ? chunkTT3TQSCZ_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
24284
+ ${data.success ? chunkTT3TQSCZ_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
23921
24285
 
23922
24286
  <!-- Form Styling -->
23923
24287
  <style>
@@ -24028,7 +24392,7 @@ function renderCollectionFormPage(data) {
24028
24392
  }
24029
24393
  </style>
24030
24394
 
24031
- ${chunkE66UVONV_cjs.renderForm(formData)}
24395
+ ${chunkOUBUS74I_cjs.renderForm(formData)}
24032
24396
 
24033
24397
  ${isEdit && data.managed ? `
24034
24398
  <!-- Read-Only Fields Display for Managed Collections -->
@@ -25026,13 +25390,13 @@ function renderCollectionFormPage(data) {
25026
25390
  version: data.version,
25027
25391
  content: pageContent
25028
25392
  };
25029
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
25393
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
25030
25394
  }
25031
25395
 
25032
25396
  // src/routes/admin-collections.ts
25033
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
25397
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
25034
25398
  var adminCollectionsRoutes = new hono.Hono();
25035
- adminCollectionsRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
25399
+ adminCollectionsRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
25036
25400
  adminCollectionsRoutes.get("/", async (c) => {
25037
25401
  try {
25038
25402
  const user = c.get("user");
@@ -25049,7 +25413,7 @@ adminCollectionsRoutes.get("/", async (c) => {
25049
25413
  results = queryResults.results ?? [];
25050
25414
  } catch (e) {
25051
25415
  }
25052
- const codeCollections = chunkQCJHCSOK_cjs.getCollectionRegistry().list();
25416
+ const codeCollections = chunk4DHPR7KR_cjs.getCollectionRegistry().list();
25053
25417
  const codeCollectionsMap = new Map(
25054
25418
  codeCollections.map((cfg) => {
25055
25419
  const fieldCount = cfg.schema?.properties ? Object.keys(cfg.schema.properties).length : 0;
@@ -25063,7 +25427,7 @@ adminCollectionsRoutes.get("/", async (c) => {
25063
25427
  field_count: fieldCount,
25064
25428
  managed: cfg.managed !== false,
25065
25429
  source_type: "code",
25066
- internal: chunkQCJHCSOK_cjs.isCodeCollectionInternal(cfg),
25430
+ internal: chunk4DHPR7KR_cjs.isCodeCollectionInternal(cfg),
25067
25431
  versioning: cfg.versioning === true
25068
25432
  }];
25069
25433
  })
@@ -25102,7 +25466,7 @@ adminCollectionsRoutes.get("/", async (c) => {
25102
25466
  field_count: fieldCount,
25103
25467
  managed: false,
25104
25468
  source_type: row.source === "code" || row.source === "system" || row.source === "plugin" ? "code" : "user",
25105
- internal: chunkQCJHCSOK_cjs.isDbDocTypeInternal(row.source),
25469
+ internal: chunk4DHPR7KR_cjs.isDbDocTypeInternal(row.source),
25106
25470
  versioning: dbVersioning
25107
25471
  };
25108
25472
  });
@@ -25259,11 +25623,11 @@ export const myPlugin = definePlugin({
25259
25623
  `;
25260
25624
  const u = user;
25261
25625
  return c.html(
25262
- chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst({
25626
+ chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst({
25263
25627
  title: "Add a Collection",
25264
25628
  pageTitle: "Add a Collection",
25265
25629
  currentPath: "/admin/collections",
25266
- version: chunkKKNEYIZJ_cjs.getCoreVersion(),
25630
+ version: chunkXZUEGFXE_cjs.getCoreVersion(),
25267
25631
  user: u ? { name: u.email ?? "Admin", email: u.email ?? "", role: u.role ?? "admin" } : void 0,
25268
25632
  content
25269
25633
  })
@@ -25280,7 +25644,7 @@ adminCollectionsRoutes.get("/:id", async (c) => {
25280
25644
  collection = await stmt.bind(id).first();
25281
25645
  } catch {
25282
25646
  }
25283
- const registryRecord = chunkQCJHCSOK_cjs.getCollectionRegistry().getById(id) ?? chunkQCJHCSOK_cjs.getCollectionRegistry().getByName(id);
25647
+ const registryRecord = chunk4DHPR7KR_cjs.getCollectionRegistry().getById(id) ?? chunk4DHPR7KR_cjs.getCollectionRegistry().getByName(id);
25284
25648
  if (!collection && !registryRecord) {
25285
25649
  const formData2 = {
25286
25650
  isEdit: true,
@@ -25327,9 +25691,9 @@ adminCollectionsRoutes.get("/:id", async (c) => {
25327
25691
  isCodeDriven = true;
25328
25692
  }
25329
25693
  const [tinymceActive, quillActive, mdxeditorActive] = await Promise.all([
25330
- chunk37V3RET3_cjs.isPluginActive(db, "tinymce-plugin"),
25331
- chunk37V3RET3_cjs.isPluginActive(db, "quill-editor"),
25332
- chunk37V3RET3_cjs.isPluginActive(db, "easy-mdx")
25694
+ chunk4DHPR7KR_cjs.isPluginActive(db, "tinymce-plugin"),
25695
+ chunk4DHPR7KR_cjs.isPluginActive(db, "quill-editor"),
25696
+ chunk4DHPR7KR_cjs.isPluginActive(db, "easy-mdx")
25333
25697
  ]);
25334
25698
  const displayName = collection?.display_name ?? registryRecord?.displayName ?? id;
25335
25699
  const formData = {
@@ -25349,9 +25713,9 @@ adminCollectionsRoutes.get("/:id", async (c) => {
25349
25713
  console.error("Error fetching collection:", error);
25350
25714
  const user = c.get("user");
25351
25715
  const [tinymceActive, quillActive, mdxeditorActive] = await Promise.all([
25352
- chunk37V3RET3_cjs.isPluginActive(db, "tinymce-plugin"),
25353
- chunk37V3RET3_cjs.isPluginActive(db, "quill-editor"),
25354
- chunk37V3RET3_cjs.isPluginActive(db, "easy-mdx")
25716
+ chunk4DHPR7KR_cjs.isPluginActive(db, "tinymce-plugin"),
25717
+ chunk4DHPR7KR_cjs.isPluginActive(db, "quill-editor"),
25718
+ chunk4DHPR7KR_cjs.isPluginActive(db, "easy-mdx")
25355
25719
  ]);
25356
25720
  const formData = {
25357
25721
  isEdit: true,
@@ -25365,7 +25729,7 @@ adminCollectionsRoutes.get("/:id", async (c) => {
25365
25729
  });
25366
25730
 
25367
25731
  // src/templates/pages/admin-settings.template.ts
25368
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
25732
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
25369
25733
  function renderSettingsPage(data) {
25370
25734
  const activeTab = data.activeTab || "general";
25371
25735
  const pageContent = `
@@ -25755,7 +26119,7 @@ function renderSettingsPage(data) {
25755
26119
  version: data.version,
25756
26120
  content: pageContent
25757
26121
  };
25758
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
26122
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
25759
26123
  }
25760
26124
  function renderTabButton(tabId, label, iconPath, activeTab) {
25761
26125
  const isActive = activeTab === tabId;
@@ -26300,7 +26664,7 @@ function renderDatabaseToolsSettings(settings) {
26300
26664
 
26301
26665
  // src/routes/admin-settings.ts
26302
26666
  var adminSettingsRoutes = new hono.Hono();
26303
- adminSettingsRoutes.use("*", chunk37V3RET3_cjs.requireAuth());
26667
+ adminSettingsRoutes.use("*", chunkBRKXMRMB_cjs.requireAuth());
26304
26668
  function getMockSettings(user) {
26305
26669
  return {
26306
26670
  general: {
@@ -26334,7 +26698,7 @@ adminSettingsRoutes.get("/", (c) => {
26334
26698
  adminSettingsRoutes.get("/general", async (c) => {
26335
26699
  const user = c.get("user");
26336
26700
  const db = c.env.DB;
26337
- const settingsService = new chunk36Z3AKX3_cjs.SettingsService(db);
26701
+ const settingsService = new chunkC5LDQ3SH_cjs.SettingsService(db);
26338
26702
  const generalSettings = await settingsService.getGeneralSettings(user?.email);
26339
26703
  const mockSettings = getMockSettings(user);
26340
26704
  mockSettings.general = generalSettings;
@@ -26353,7 +26717,7 @@ adminSettingsRoutes.get("/general", async (c) => {
26353
26717
  adminSettingsRoutes.get("/security", async (c) => {
26354
26718
  const user = c.get("user");
26355
26719
  const db = c.env.DB;
26356
- const settingsService = new chunk36Z3AKX3_cjs.SettingsService(db);
26720
+ const settingsService = new chunkC5LDQ3SH_cjs.SettingsService(db);
26357
26721
  const persisted = await settingsService.getSecuritySettings();
26358
26722
  const mockSettings = getMockSettings(user);
26359
26723
  mockSettings.security = {
@@ -26403,7 +26767,7 @@ adminSettingsRoutes.get("/database-tools", (c) => {
26403
26767
  adminSettingsRoutes.get("/api/migrations/status", async (c) => {
26404
26768
  try {
26405
26769
  const db = c.env.DB;
26406
- const migrationService = new chunkA2SN3RVL_cjs.MigrationService(db);
26770
+ const migrationService = new chunkPAS7GZBS_cjs.MigrationService(db);
26407
26771
  const status = await migrationService.getMigrationStatus();
26408
26772
  return c.json({
26409
26773
  success: true,
@@ -26443,7 +26807,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
26443
26807
  adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
26444
26808
  try {
26445
26809
  const db = c.env.DB;
26446
- const migrationService = new chunkA2SN3RVL_cjs.MigrationService(db);
26810
+ const migrationService = new chunkPAS7GZBS_cjs.MigrationService(db);
26447
26811
  const validation = await migrationService.validateSchema();
26448
26812
  return c.json({
26449
26813
  success: true,
@@ -26612,7 +26976,7 @@ adminSettingsRoutes.post("/general", async (c) => {
26612
26976
  }
26613
26977
  const formData = await c.req.formData();
26614
26978
  const db = c.env.DB;
26615
- const settingsService = new chunk36Z3AKX3_cjs.SettingsService(db);
26979
+ const settingsService = new chunkC5LDQ3SH_cjs.SettingsService(db);
26616
26980
  const settings = {
26617
26981
  siteName: formData.get("siteName"),
26618
26982
  siteDescription: formData.get("siteDescription"),
@@ -26658,7 +27022,7 @@ adminSettingsRoutes.post("/security", async (c) => {
26658
27022
  }
26659
27023
  const formData = await c.req.formData();
26660
27024
  const db = c.env.DB;
26661
- const settingsService = new chunk36Z3AKX3_cjs.SettingsService(db);
27025
+ const settingsService = new chunkC5LDQ3SH_cjs.SettingsService(db);
26662
27026
  const jwtExpiresInRaw = formData.get("jwtExpiresIn")?.trim() || "";
26663
27027
  const graceRaw = formData.get("jwtRefreshGraceSeconds")?.trim() || "";
26664
27028
  if (!/^\d+(?:s|m|h|d)?$/i.test(jwtExpiresInRaw)) {
@@ -26701,7 +27065,7 @@ adminSettingsRoutes.post("/", async (c) => {
26701
27065
  });
26702
27066
 
26703
27067
  // src/templates/pages/admin-api-reference.template.ts
26704
- chunkUYJQDDEE_cjs.init_admin_layout_catalyst_template();
27068
+ chunkMI2YXCK4_cjs.init_admin_layout_catalyst_template();
26705
27069
  function renderAuthBadge(auth) {
26706
27070
  if (auth === true) {
26707
27071
  return `
@@ -26842,7 +27206,7 @@ function renderAPIReferencePage(data) {
26842
27206
  >
26843
27207
  <option value="">All Categories</option>
26844
27208
  ${categories.map((category) => {
26845
- const info = chunk36Z3AKX3_cjs.CATEGORY_INFO[category];
27209
+ const info = chunkC5LDQ3SH_cjs.CATEGORY_INFO[category];
26846
27210
  const title = info ? info.title : category;
26847
27211
  return `<option value="${category}">${title}</option>`;
26848
27212
  }).join("\n ")}
@@ -26859,7 +27223,7 @@ function renderAPIReferencePage(data) {
26859
27223
  <!-- API Categories -->
26860
27224
  <div class="space-y-6">
26861
27225
  ${Object.entries(endpointsByCategory).map(([category, endpoints]) => {
26862
- const info = chunk36Z3AKX3_cjs.CATEGORY_INFO[category] || { title: category, description: "", icon: "&#x1f4cb;" };
27226
+ const info = chunkC5LDQ3SH_cjs.CATEGORY_INFO[category] || { title: category, description: "", icon: "&#x1f4cb;" };
26863
27227
  return `
26864
27228
  <div class="api-category" data-category="${category}">
26865
27229
  <div class="rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden">
@@ -27032,20 +27396,20 @@ function renderAPIReferencePage(data) {
27032
27396
  version: data.version,
27033
27397
  content: pageContent
27034
27398
  };
27035
- return chunkUYJQDDEE_cjs.renderAdminLayoutCatalyst(layoutData);
27399
+ return chunkMI2YXCK4_cjs.renderAdminLayoutCatalyst(layoutData);
27036
27400
  }
27037
27401
 
27038
27402
  // src/routes/admin-api-reference.ts
27039
- var VERSION2 = chunkKKNEYIZJ_cjs.getCoreVersion();
27403
+ var VERSION2 = chunkXZUEGFXE_cjs.getCoreVersion();
27040
27404
  var router2 = new hono.Hono();
27041
- router2.use("*", chunk37V3RET3_cjs.requireAuth());
27405
+ router2.use("*", chunkBRKXMRMB_cjs.requireAuth());
27042
27406
  router2.get("/", async (c) => {
27043
27407
  const user = c.get("user");
27044
27408
  try {
27045
- const app2 = chunk36Z3AKX3_cjs.getAppInstance();
27046
- const baseEndpoints = chunk36Z3AKX3_cjs.buildRouteList(app2);
27409
+ const app2 = chunkC5LDQ3SH_cjs.getAppInstance();
27410
+ const baseEndpoints = chunkC5LDQ3SH_cjs.buildRouteList(app2);
27047
27411
  const collectionRoutes = [];
27048
- const collections = chunkQCJHCSOK_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
27412
+ const collections = chunk4DHPR7KR_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
27049
27413
  const methodOrder = { GET: 0, POST: 1, PUT: 2, PATCH: 3, DELETE: 4 };
27050
27414
  for (const col of collections) {
27051
27415
  const displayName = col.displayName || col.name;
@@ -27160,11 +27524,13 @@ exports.resolveDocScope = resolveDocScope;
27160
27524
  exports.resolveVariablesInObject = resolveVariablesInObject;
27161
27525
  exports.router = router;
27162
27526
  exports.router2 = router2;
27527
+ exports.setDemoModeActive = setDemoModeActive;
27163
27528
  exports.setEmailService = setEmailService;
27164
27529
  exports.setVariablesCache = setVariablesCache;
27530
+ exports.swrStats = swrStats;
27165
27531
  exports.test_cleanup_default = test_cleanup_default;
27166
27532
  exports.updateDocumentSchema = updateDocumentSchema;
27167
27533
  exports.userProfilesPlugin = userProfilesPlugin;
27168
27534
  exports.userRoutes = userRoutes;
27169
- //# sourceMappingURL=chunk-I767LVN7.cjs.map
27170
- //# sourceMappingURL=chunk-I767LVN7.cjs.map
27535
+ //# sourceMappingURL=chunk-S2QN4LFD.cjs.map
27536
+ //# sourceMappingURL=chunk-S2QN4LFD.cjs.map