@sonicjs-cms/core 3.0.0-beta.20 → 3.0.0-beta.22

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 (51) hide show
  1. package/dist/{chunk-DSXEVMOM.js → chunk-2FCKKOA5.js} +2 -2
  2. package/dist/{chunk-DSXEVMOM.js.map → chunk-2FCKKOA5.js.map} +1 -1
  3. package/dist/{chunk-TQG5FNNR.cjs → chunk-3CT3SUR4.cjs} +2 -2
  4. package/dist/{chunk-TQG5FNNR.cjs.map → chunk-3CT3SUR4.cjs.map} +1 -1
  5. package/dist/{chunk-5UCMLBRQ.js → chunk-6KNTZ67K.js} +121 -17
  6. package/dist/chunk-6KNTZ67K.js.map +1 -0
  7. package/dist/{chunk-W53J3BJ2.js → chunk-73O4GPJ6.js} +3 -3
  8. package/dist/{chunk-W53J3BJ2.js.map → chunk-73O4GPJ6.js.map} +1 -1
  9. package/dist/{chunk-WCA4VENG.js → chunk-CHWT5KBK.js} +5 -5
  10. package/dist/{chunk-WCA4VENG.js.map → chunk-CHWT5KBK.js.map} +1 -1
  11. package/dist/{chunk-RDH6PUOP.js → chunk-DOMXI5PM.js} +2 -2
  12. package/dist/{chunk-RDH6PUOP.js.map → chunk-DOMXI5PM.js.map} +1 -1
  13. package/dist/{chunk-5RSB5SEK.cjs → chunk-EUJAEB6W.cjs} +4 -4
  14. package/dist/{chunk-5RSB5SEK.cjs.map → chunk-EUJAEB6W.cjs.map} +1 -1
  15. package/dist/{chunk-4SHNHNRP.cjs → chunk-FTXGZ3BF.cjs} +15 -15
  16. package/dist/{chunk-4SHNHNRP.cjs.map → chunk-FTXGZ3BF.cjs.map} +1 -1
  17. package/dist/{chunk-MYQ7KZUQ.js → chunk-GB2Q2DNK.js} +4 -4
  18. package/dist/{chunk-MYQ7KZUQ.js.map → chunk-GB2Q2DNK.js.map} +1 -1
  19. package/dist/{chunk-GMZ5TGYP.js → chunk-I2DM27HP.js} +3 -3
  20. package/dist/{chunk-GMZ5TGYP.js.map → chunk-I2DM27HP.js.map} +1 -1
  21. package/dist/{chunk-3E7IROND.cjs → chunk-JFLZHOQP.cjs} +314 -210
  22. package/dist/chunk-JFLZHOQP.cjs.map +1 -0
  23. package/dist/{chunk-DTGCXWWM.cjs → chunk-MGHHPNJN.cjs} +10 -10
  24. package/dist/{chunk-DTGCXWWM.cjs.map → chunk-MGHHPNJN.cjs.map} +1 -1
  25. package/dist/{chunk-5ARIHAGN.cjs → chunk-PYZYU7EK.cjs} +2 -2
  26. package/dist/{chunk-5ARIHAGN.cjs.map → chunk-PYZYU7EK.cjs.map} +1 -1
  27. package/dist/{chunk-AQJEMVAY.cjs → chunk-QWSR4THH.cjs} +3 -3
  28. package/dist/{chunk-AQJEMVAY.cjs.map → chunk-QWSR4THH.cjs.map} +1 -1
  29. package/dist/index.cjs +499 -327
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.js +253 -81
  32. package/dist/index.js.map +1 -1
  33. package/dist/middleware.cjs +33 -33
  34. package/dist/middleware.js +4 -4
  35. package/dist/migrations-HLK2QF4T.js +4 -0
  36. package/dist/{migrations-HZJ6U6SX.js.map → migrations-HLK2QF4T.js.map} +1 -1
  37. package/dist/migrations-UIMA6ZL6.cjs +13 -0
  38. package/dist/{migrations-VQAFXMU7.cjs.map → migrations-UIMA6ZL6.cjs.map} +1 -1
  39. package/dist/plugins.cjs +40 -40
  40. package/dist/plugins.js +3 -3
  41. package/dist/routes.cjs +26 -26
  42. package/dist/routes.js +6 -6
  43. package/dist/services.cjs +18 -18
  44. package/dist/services.js +2 -2
  45. package/dist/utils.cjs +3 -3
  46. package/dist/utils.js +1 -1
  47. package/package.json +1 -1
  48. package/dist/chunk-3E7IROND.cjs.map +0 -1
  49. package/dist/chunk-5UCMLBRQ.js.map +0 -1
  50. package/dist/migrations-HZJ6U6SX.js +0 -4
  51. package/dist/migrations-VQAFXMU7.cjs +0 -13
@@ -3,18 +3,18 @@
3
3
  var chunkXWVDSM2L_cjs = require('./chunk-XWVDSM2L.cjs');
4
4
  var chunkN32OWET6_cjs = require('./chunk-N32OWET6.cjs');
5
5
  var chunk36Z3AKX3_cjs = require('./chunk-36Z3AKX3.cjs');
6
- var chunk4SHNHNRP_cjs = require('./chunk-4SHNHNRP.cjs');
6
+ var chunkFTXGZ3BF_cjs = require('./chunk-FTXGZ3BF.cjs');
7
7
  var chunkLTZ5WYOK_cjs = require('./chunk-LTZ5WYOK.cjs');
8
8
  var chunkKIGVVO6N_cjs = require('./chunk-KIGVVO6N.cjs');
9
- var chunk5ARIHAGN_cjs = require('./chunk-5ARIHAGN.cjs');
10
- var chunkTQG5FNNR_cjs = require('./chunk-TQG5FNNR.cjs');
9
+ var chunkPYZYU7EK_cjs = require('./chunk-PYZYU7EK.cjs');
10
+ var chunk3CT3SUR4_cjs = require('./chunk-3CT3SUR4.cjs');
11
11
  var chunkPXNTCCPE_cjs = require('./chunk-PXNTCCPE.cjs');
12
12
  var chunkK623Q6WD_cjs = require('./chunk-K623Q6WD.cjs');
13
- var chunk5RSB5SEK_cjs = require('./chunk-5RSB5SEK.cjs');
13
+ var chunkEUJAEB6W_cjs = require('./chunk-EUJAEB6W.cjs');
14
14
  var chunkJ6JTWD2A_cjs = require('./chunk-J6JTWD2A.cjs');
15
15
  var chunkIXUHXTHW_cjs = require('./chunk-IXUHXTHW.cjs');
16
16
  var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
17
- var chunkAQJEMVAY_cjs = require('./chunk-AQJEMVAY.cjs');
17
+ var chunkQWSR4THH_cjs = require('./chunk-QWSR4THH.cjs');
18
18
  var chunkMNWKYY5E_cjs = require('./chunk-MNWKYY5E.cjs');
19
19
  var hono = require('hono');
20
20
  var zod = require('zod');
@@ -259,7 +259,7 @@ function getDocumentRequestContext(c) {
259
259
 
260
260
  // src/routes/api-documents.ts
261
261
  async function aclAllowsRead(db, tenantId, principalSet, row, preloadedType) {
262
- const docType = preloadedType ?? await new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db).findById(row.type_id);
262
+ const docType = preloadedType ?? await new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db).findById(row.type_id);
263
263
  if (!docType) return false;
264
264
  return new DocumentRepository(db, tenantId).isAllowed(principalSet, row.root_id, "read", docType.settings);
265
265
  }
@@ -277,7 +277,7 @@ apiDocumentsRoutes.get("/", async (c) => {
277
277
  if (!typeId) {
278
278
  return c.json({ error: "type query parameter is required" }, 400);
279
279
  }
280
- const registry = new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db);
280
+ const registry = new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db);
281
281
  const docType = await registry.findById(typeId);
282
282
  if (!docType || !docType.isActive) {
283
283
  return c.json({ error: "Unknown document type" }, 400);
@@ -359,7 +359,7 @@ apiDocumentsRoutes.get("/root/:rootId", async (c) => {
359
359
  AND (expires_at IS NULL OR expires_at > ?) LIMIT 1`
360
360
  ).bind(rootId, now, now).first();
361
361
  if (!row) return c.json({ error: "Not found" }, 404);
362
- const docType = await new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db).findById(row.type_id);
362
+ const docType = await new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db).findById(row.type_id);
363
363
  const effTenant = effectiveTenantForType(tenantId, docType?.settings);
364
364
  if (row.tenant_id !== effTenant) return c.json({ error: "Not found" }, 404);
365
365
  if (!await aclAllowsRead(db, effTenant, principalSet, row, docType)) {
@@ -395,7 +395,7 @@ apiDocumentsRoutes.get("/:id", async (c) => {
395
395
  AND (expires_at IS NULL OR expires_at > ?) LIMIT 1`
396
396
  ).bind(id, now, now).first();
397
397
  if (!row) return c.json({ error: "Not found" }, 404);
398
- const docType = await new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db).findById(row.type_id);
398
+ const docType = await new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db).findById(row.type_id);
399
399
  const effTenant = effectiveTenantForType(tenantId, docType?.settings);
400
400
  if (row.tenant_id !== effTenant) return c.json({ error: "Not found" }, 404);
401
401
  if (!await aclAllowsRead(db, effTenant, principalSet, row, docType)) {
@@ -465,17 +465,17 @@ async function resolveDocScope(c, db, by, opts = {}) {
465
465
  const draft = opts.currentDraftOnly ? " AND is_current_draft = 1" : "";
466
466
  const row = await db.prepare(`SELECT type_id, root_id, tenant_id FROM documents WHERE ${col} = ?${draft} LIMIT 1`).bind(val).first();
467
467
  if (!row) return null;
468
- const docType = await new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db).findById(row.type_id);
468
+ const docType = await new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db).findById(row.type_id);
469
469
  const tenantId = effectiveTenantForType(getRequestTenant(c), docType?.settings);
470
470
  if (row.tenant_id !== tenantId) return null;
471
471
  return { typeId: row.type_id, rootId: row.root_id, tenantId, docType };
472
472
  }
473
473
  var adminDocumentsRoutes = new hono.Hono();
474
- adminDocumentsRoutes.use("*", chunk4SHNHNRP_cjs.requireAuth());
475
- adminDocumentsRoutes.use("*", chunk4SHNHNRP_cjs.requireRole(["admin", "editor"]));
474
+ adminDocumentsRoutes.use("*", chunkFTXGZ3BF_cjs.requireAuth());
475
+ adminDocumentsRoutes.use("*", chunkFTXGZ3BF_cjs.requireRole(["admin", "editor"]));
476
476
  adminDocumentsRoutes.get("/types", async (c) => {
477
477
  try {
478
- const registry = new chunk4SHNHNRP_cjs.DocumentTypeRegistry(c.env.DB);
478
+ const registry = new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(c.env.DB);
479
479
  const types = await registry.findAll();
480
480
  return c.json({ data: types });
481
481
  } catch (error) {
@@ -503,7 +503,7 @@ adminDocumentsRoutes.get("/", async (c) => {
503
503
  if (!typeId) {
504
504
  return c.json({ error: "type query parameter is required" }, 400);
505
505
  }
506
- const registry = new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db);
506
+ const registry = new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db);
507
507
  const docType = await registry.findById(typeId);
508
508
  if (!docType || !docType.isActive) {
509
509
  return c.json({ error: "Unknown document type" }, 400);
@@ -614,7 +614,7 @@ adminDocumentsRoutes.post("/", async (c) => {
614
614
  const input = validation.data;
615
615
  const db = c.env.DB;
616
616
  const user = c.get("user");
617
- const registry = new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db);
617
+ const registry = new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db);
618
618
  const docType = await registry.findById(input.typeId);
619
619
  if (!docType || !docType.isActive) {
620
620
  return c.json({ error: "Unknown document type" }, 400);
@@ -746,7 +746,7 @@ adminDocumentsRoutes.post("/types/:typeId/reindex", async (c) => {
746
746
  try {
747
747
  const { typeId } = c.req.param();
748
748
  const db = c.env.DB;
749
- const registry = new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db);
749
+ const registry = new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db);
750
750
  const docType = await registry.findById(typeId);
751
751
  if (!docType) return c.json({ error: "Unknown document type" }, 400);
752
752
  const reindexTenant = effectiveTenantForType(getRequestTenant(c), docType.settings);
@@ -900,13 +900,13 @@ async function resolveContentVariables(contentData, db) {
900
900
  // src/routes/api-content-crud.ts
901
901
  var apiContentCrudRoutes = new hono.Hono();
902
902
  async function resolveDocBacking(db, collectionIdOrName) {
903
- const registry = chunk5ARIHAGN_cjs.getCollectionRegistry();
903
+ const registry = chunkPYZYU7EK_cjs.getCollectionRegistry();
904
904
  const record = registry.getBySlugOrName(collectionIdOrName) ?? registry.getById(collectionIdOrName);
905
905
  if (record) {
906
- const docType2 = await new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db).findById(record.name);
906
+ const docType2 = await new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db).findById(record.name);
907
907
  return docType2 ? { coll: { id: record.id, name: record.name }, docType: docType2 } : null;
908
908
  }
909
- const docType = await new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db).findById(collectionIdOrName);
909
+ const docType = await new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db).findById(collectionIdOrName);
910
910
  if (docType) {
911
911
  return { coll: { id: collectionIdOrName, name: collectionIdOrName }, docType };
912
912
  }
@@ -949,7 +949,7 @@ apiContentCrudRoutes.get("/check-slug", async (c) => {
949
949
  }, 500);
950
950
  }
951
951
  });
952
- apiContentCrudRoutes.get("/:id", chunk4SHNHNRP_cjs.optionalAuth(), async (c) => {
952
+ apiContentCrudRoutes.get("/:id", chunkFTXGZ3BF_cjs.optionalAuth(), async (c) => {
953
953
  try {
954
954
  const id = c.req.param("id");
955
955
  const db = c.env.DB;
@@ -959,7 +959,7 @@ apiContentCrudRoutes.get("/:id", chunk4SHNHNRP_cjs.optionalAuth(), async (c) =>
959
959
  ).bind(id, getRequestTenant(c)).first();
960
960
  let transformedContent;
961
961
  if (docRow) {
962
- const coll = chunk5ARIHAGN_cjs.getCollectionRegistry().getByName(docRow.type_id);
962
+ const coll = chunkPYZYU7EK_cjs.getCollectionRegistry().getByName(docRow.type_id);
963
963
  transformedContent = {
964
964
  id: docRow.root_id,
965
965
  title: docRow.title,
@@ -993,7 +993,7 @@ apiContentCrudRoutes.get("/:id", chunk4SHNHNRP_cjs.optionalAuth(), async (c) =>
993
993
  }, 500);
994
994
  }
995
995
  });
996
- apiContentCrudRoutes.post("/", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
996
+ apiContentCrudRoutes.post("/", chunkFTXGZ3BF_cjs.requireAuth(), chunkFTXGZ3BF_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
997
997
  try {
998
998
  const db = c.env.DB;
999
999
  const user = c.get("user");
@@ -1068,7 +1068,7 @@ apiContentCrudRoutes.post("/", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP_cj
1068
1068
  }, 500);
1069
1069
  }
1070
1070
  });
1071
- apiContentCrudRoutes.put("/:id", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
1071
+ apiContentCrudRoutes.put("/:id", chunkFTXGZ3BF_cjs.requireAuth(), chunkFTXGZ3BF_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
1072
1072
  try {
1073
1073
  const id = c.req.param("id");
1074
1074
  const db = c.env.DB;
@@ -1090,7 +1090,7 @@ apiContentCrudRoutes.put("/:id", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP_
1090
1090
  } catch (err) {
1091
1091
  return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
1092
1092
  }
1093
- const docType = await new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db).findById(docRow.type_id);
1093
+ const docType = await new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db).findById(docRow.type_id);
1094
1094
  const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
1095
1095
  queryableFields: docType?.queryableFields ?? [],
1096
1096
  typeSchemaVersion: docType?.schemaVersion ?? 1,
@@ -1113,7 +1113,7 @@ apiContentCrudRoutes.put("/:id", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP_
1113
1113
  const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
1114
1114
  await cache.invalidate("content-filtered:*");
1115
1115
  await cache.invalidate("collection-content-filtered:*");
1116
- const coll = chunk5ARIHAGN_cjs.getCollectionRegistry().getByName(docRow.type_id);
1116
+ const coll = chunkPYZYU7EK_cjs.getCollectionRegistry().getByName(docRow.type_id);
1117
1117
  const saved = await db.prepare("SELECT * FROM documents WHERE id = ?").bind(newDraft.id).first();
1118
1118
  const savedData = saved?.data ? JSON.parse(saved.data) : {};
1119
1119
  dispatchHookEvent(c, "content:after:update", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
@@ -1134,7 +1134,7 @@ apiContentCrudRoutes.put("/:id", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP_
1134
1134
  }, 500);
1135
1135
  }
1136
1136
  });
1137
- apiContentCrudRoutes.delete("/:id", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
1137
+ apiContentCrudRoutes.delete("/:id", chunkFTXGZ3BF_cjs.requireAuth(), chunkFTXGZ3BF_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
1138
1138
  try {
1139
1139
  const id = c.req.param("id");
1140
1140
  const db = c.env.DB;
@@ -1260,7 +1260,7 @@ apiRoutes.use("*", async (c, next) => {
1260
1260
  c.header("X-Response-Time", `${totalTime}ms`);
1261
1261
  });
1262
1262
  apiRoutes.use("*", async (c, next) => {
1263
- const cacheEnabled = await chunk4SHNHNRP_cjs.isPluginActive(c.env.DB, "core-cache");
1263
+ const cacheEnabled = await chunkFTXGZ3BF_cjs.isPluginActive(c.env.DB, "core-cache");
1264
1264
  c.set("cacheEnabled", cacheEnabled);
1265
1265
  await next();
1266
1266
  });
@@ -1283,7 +1283,7 @@ apiRoutes.get("/", (c) => {
1283
1283
  openapi: "3.0.0",
1284
1284
  info: {
1285
1285
  title: "SonicJS AI API",
1286
- version: chunkAQJEMVAY_cjs.getCoreVersion(),
1286
+ version: chunkQWSR4THH_cjs.getCoreVersion(),
1287
1287
  description: "RESTful API for SonicJS headless CMS - a modern, AI-powered content management system built on Cloudflare Workers",
1288
1288
  contact: {
1289
1289
  name: "SonicJS Support",
@@ -1713,8 +1713,8 @@ apiRoutes.get("/collections", async (c) => {
1713
1713
  }
1714
1714
  c.header("X-Cache-Status", "MISS");
1715
1715
  c.header("X-Cache-Source", "registry");
1716
- const records = chunk5ARIHAGN_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
1717
- const transformedResults = records.map(chunk5ARIHAGN_cjs.collectionRecordToRow);
1716
+ const records = chunkPYZYU7EK_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
1717
+ const transformedResults = records.map(chunkPYZYU7EK_cjs.collectionRecordToRow);
1718
1718
  const responseData = {
1719
1719
  data: transformedResults,
1720
1720
  meta: addTimingMeta(c, {
@@ -1735,7 +1735,7 @@ apiRoutes.get("/collections", async (c) => {
1735
1735
  return c.json({ error: "Failed to fetch collections" }, 500);
1736
1736
  }
1737
1737
  });
1738
- apiRoutes.get("/content", chunk4SHNHNRP_cjs.optionalAuth(), async (c) => {
1738
+ apiRoutes.get("/content", chunkFTXGZ3BF_cjs.optionalAuth(), async (c) => {
1739
1739
  const executionStart = Date.now();
1740
1740
  try {
1741
1741
  const db = c.env.DB;
@@ -1744,7 +1744,7 @@ apiRoutes.get("/content", chunk4SHNHNRP_cjs.optionalAuth(), async (c) => {
1744
1744
  const collIdByName = /* @__PURE__ */ new Map();
1745
1745
  let typeId;
1746
1746
  let typeIds;
1747
- const registry = chunk5ARIHAGN_cjs.getCollectionRegistry();
1747
+ const registry = chunkPYZYU7EK_cjs.getCollectionRegistry();
1748
1748
  if (queryParams.collection) {
1749
1749
  const collectionName = queryParams.collection;
1750
1750
  const record = registry.getByName(collectionName);
@@ -1843,13 +1843,13 @@ apiRoutes.get("/content", chunk4SHNHNRP_cjs.optionalAuth(), async (c) => {
1843
1843
  }, 500);
1844
1844
  }
1845
1845
  });
1846
- apiRoutes.get("/collections/:collection/content", chunk4SHNHNRP_cjs.optionalAuth(), async (c) => {
1846
+ apiRoutes.get("/collections/:collection/content", chunkFTXGZ3BF_cjs.optionalAuth(), async (c) => {
1847
1847
  const executionStart = Date.now();
1848
1848
  try {
1849
1849
  const collection = c.req.param("collection");
1850
1850
  const db = c.env.DB;
1851
1851
  const queryParams = c.req.query();
1852
- const record = chunk5ARIHAGN_cjs.getCollectionRegistry().getBySlugOrName(collection);
1852
+ const record = chunkPYZYU7EK_cjs.getCollectionRegistry().getBySlugOrName(collection);
1853
1853
  if (!record || record.isActive === false) {
1854
1854
  return c.json({ error: "Collection not found" }, 404);
1855
1855
  }
@@ -1905,7 +1905,7 @@ apiRoutes.get("/collections/:collection/content", chunk4SHNHNRP_cjs.optionalAuth
1905
1905
  const responseData = {
1906
1906
  data: transformedResults,
1907
1907
  meta: addTimingMeta(c, {
1908
- ...includeCollection ? { collection: chunk5ARIHAGN_cjs.collectionRecordToRow(record) } : {},
1908
+ ...includeCollection ? { collection: chunkPYZYU7EK_cjs.collectionRecordToRow(record) } : {},
1909
1909
  count: results.length,
1910
1910
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1911
1911
  // D44: echo the caller's filter with the access policy applied (status=published forced for
@@ -1930,13 +1930,13 @@ apiRoutes.get("/collections/:collection/content", chunk4SHNHNRP_cjs.optionalAuth
1930
1930
  }
1931
1931
  });
1932
1932
  apiRoutes.route("/content", api_content_crud_default);
1933
- apiRoutes.get("/:collection", chunk4SHNHNRP_cjs.optionalAuth(), async (c) => {
1933
+ apiRoutes.get("/:collection", chunkFTXGZ3BF_cjs.optionalAuth(), async (c) => {
1934
1934
  const executionStart = Date.now();
1935
1935
  try {
1936
1936
  const collection = c.req.param("collection");
1937
1937
  const db = c.env.DB;
1938
1938
  const queryParams = c.req.query();
1939
- const record = chunk5ARIHAGN_cjs.getCollectionRegistry().getBySlugOrName(collection);
1939
+ const record = chunkPYZYU7EK_cjs.getCollectionRegistry().getBySlugOrName(collection);
1940
1940
  if (!record || record.isActive === false) {
1941
1941
  return c.json({ error: "Collection not found" }, 404);
1942
1942
  }
@@ -1976,7 +1976,7 @@ apiRoutes.get("/:collection", chunk4SHNHNRP_cjs.optionalAuth(), async (c) => {
1976
1976
  const responseData = {
1977
1977
  data: transformedResults,
1978
1978
  meta: addTimingMeta(c, {
1979
- ...includeCollection ? { collection: chunk5ARIHAGN_cjs.collectionRecordToRow(record) } : {},
1979
+ ...includeCollection ? { collection: chunkPYZYU7EK_cjs.collectionRecordToRow(record) } : {},
1980
1980
  count: results.length,
1981
1981
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1982
1982
  filter: normalizePublicContentFilter(filter, role),
@@ -1994,12 +1994,12 @@ apiRoutes.get("/:collection", chunk4SHNHNRP_cjs.optionalAuth(), async (c) => {
1994
1994
  return c.json({ error: "Failed to fetch content", details: error instanceof Error ? error.message : String(error) }, 500);
1995
1995
  }
1996
1996
  });
1997
- apiRoutes.get("/:collection/:id", chunk4SHNHNRP_cjs.optionalAuth(), async (c) => {
1997
+ apiRoutes.get("/:collection/:id", chunkFTXGZ3BF_cjs.optionalAuth(), async (c) => {
1998
1998
  try {
1999
1999
  const collection = c.req.param("collection");
2000
2000
  const id = c.req.param("id");
2001
2001
  const db = c.env.DB;
2002
- const record = chunk5ARIHAGN_cjs.getCollectionRegistry().getBySlugOrName(collection);
2002
+ const record = chunkPYZYU7EK_cjs.getCollectionRegistry().getBySlugOrName(collection);
2003
2003
  if (!record || record.isActive === false) {
2004
2004
  return c.json({ error: "Collection not found" }, 404);
2005
2005
  }
@@ -2008,7 +2008,7 @@ apiRoutes.get("/:collection/:id", chunk4SHNHNRP_cjs.optionalAuth(), async (c) =>
2008
2008
  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"
2009
2009
  ).bind(id, record.name).first();
2010
2010
  if (!docRow) return c.json({ error: "Content not found" }, 404);
2011
- const coll = chunk5ARIHAGN_cjs.getCollectionRegistry().getByName(docRow.type_id);
2011
+ const coll = chunkPYZYU7EK_cjs.getCollectionRegistry().getByName(docRow.type_id);
2012
2012
  const transformedContent = {
2013
2013
  id: docRow.root_id,
2014
2014
  title: docRow.title,
@@ -2026,7 +2026,7 @@ apiRoutes.get("/:collection/:id", chunk4SHNHNRP_cjs.optionalAuth(), async (c) =>
2026
2026
  return c.json({ error: "Failed to fetch content", details: error instanceof Error ? error.message : String(error) }, 500);
2027
2027
  }
2028
2028
  });
2029
- apiRoutes.post("/:collection", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
2029
+ apiRoutes.post("/:collection", chunkFTXGZ3BF_cjs.requireAuth(), chunkFTXGZ3BF_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
2030
2030
  try {
2031
2031
  const collection = c.req.param("collection");
2032
2032
  const db = c.env.DB;
@@ -2059,14 +2059,14 @@ apiRoutes.post("/:collection", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP_cj
2059
2059
  return c.json({ error: "Failed to create content", details: error instanceof Error ? error.message : String(error) }, 500);
2060
2060
  }
2061
2061
  });
2062
- apiRoutes.put("/:collection/:id", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
2062
+ apiRoutes.put("/:collection/:id", chunkFTXGZ3BF_cjs.requireAuth(), chunkFTXGZ3BF_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
2063
2063
  try {
2064
2064
  const collection = c.req.param("collection");
2065
2065
  const id = c.req.param("id");
2066
2066
  const db = c.env.DB;
2067
2067
  const user = c.get("user");
2068
2068
  const body = await c.req.json();
2069
- const collRecord = chunk5ARIHAGN_cjs.getCollectionRegistry().getBySlugOrName(collection);
2069
+ const collRecord = chunkPYZYU7EK_cjs.getCollectionRegistry().getBySlugOrName(collection);
2070
2070
  const typeName = collRecord?.name ?? collection;
2071
2071
  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();
2072
2072
  if (!docRow) return c.json({ error: "Content not found" }, 404);
@@ -2078,7 +2078,7 @@ apiRoutes.put("/:collection/:id", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP
2078
2078
  } catch (err) {
2079
2079
  return c.json({ error: "Write cancelled by plugin", details: String(err) }, 400);
2080
2080
  }
2081
- const docType = await new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db).findById(docRow.type_id);
2081
+ const docType = await new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db).findById(docRow.type_id);
2082
2082
  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 });
2083
2083
  const input = {};
2084
2084
  if (body.title !== void 0) input.title = body.title;
@@ -2095,7 +2095,7 @@ apiRoutes.put("/:collection/:id", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP
2095
2095
  const cache = chunk36Z3AKX3_cjs.getCacheService(chunk36Z3AKX3_cjs.CACHE_CONFIGS.api);
2096
2096
  await cache.invalidate("content-filtered:*");
2097
2097
  await cache.invalidate("collection-content-filtered:*");
2098
- const coll = chunk5ARIHAGN_cjs.getCollectionRegistry().getByName(docRow.type_id);
2098
+ const coll = chunkPYZYU7EK_cjs.getCollectionRegistry().getByName(docRow.type_id);
2099
2099
  const saved = await db.prepare("SELECT * FROM documents WHERE id = ?").bind(newDraft.id).first();
2100
2100
  const savedData = saved?.data ? JSON.parse(saved.data) : {};
2101
2101
  dispatchHookEvent(c, "content:after:update", { collection: docRow.type_id, id, data: savedData, user: actor }, "fire-and-forget");
@@ -2107,13 +2107,13 @@ apiRoutes.put("/:collection/:id", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP
2107
2107
  return c.json({ error: "Failed to update content", details: error instanceof Error ? error.message : String(error) }, 500);
2108
2108
  }
2109
2109
  });
2110
- apiRoutes.delete("/:collection/:id", chunk4SHNHNRP_cjs.requireAuth(), chunk4SHNHNRP_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
2110
+ apiRoutes.delete("/:collection/:id", chunkFTXGZ3BF_cjs.requireAuth(), chunkFTXGZ3BF_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
2111
2111
  try {
2112
2112
  const collection = c.req.param("collection");
2113
2113
  const id = c.req.param("id");
2114
2114
  const db = c.env.DB;
2115
2115
  const user = c.get("user");
2116
- const collRecord = chunk5ARIHAGN_cjs.getCollectionRegistry().getBySlugOrName(collection);
2116
+ const collRecord = chunkPYZYU7EK_cjs.getCollectionRegistry().getBySlugOrName(collection);
2117
2117
  const typeName = collRecord?.name ?? collection;
2118
2118
  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();
2119
2119
  if (!docRow) return c.json({ error: "Content not found" }, 404);
@@ -2251,12 +2251,17 @@ var MediaDocumentService = class {
2251
2251
  where.push("(json_extract(data, '$.filename') LIKE ? OR json_extract(data, '$.originalName') LIKE ? OR json_extract(data, '$.alt') LIKE ?)");
2252
2252
  params.push(term, term, term);
2253
2253
  }
2254
- const listed = await this.db.prepare(`SELECT * FROM documents WHERE ${where.join(" AND ")} ORDER BY updated_at DESC LIMIT ? OFFSET ?`).bind(...params, limit, offset).all();
2254
+ const [listed, countResult] = await Promise.all([
2255
+ this.db.prepare(`SELECT * FROM documents WHERE ${where.join(" AND ")} ORDER BY updated_at DESC LIMIT ? OFFSET ?`).bind(...params, limit, offset).all(),
2256
+ this.db.prepare(`SELECT COUNT(*) AS total FROM documents WHERE ${where.join(" AND ")}`).bind(...params).first()
2257
+ ]);
2255
2258
  const files = (listed.results ?? []).map(rowToMinimalDoc);
2259
+ const total = countResult?.total ?? 0;
2256
2260
  const folderAgg = await this.db.prepare(`SELECT q_media_folder AS folder, COUNT(*) AS count, SUM(q_media_size) AS totalSize FROM documents WHERE ${base} GROUP BY q_media_folder ORDER BY q_media_folder`).bind(this.tenantId).all();
2257
2261
  const typeAgg = await this.db.prepare(`SELECT CASE WHEN q_media_mime LIKE 'image/%' THEN 'images' WHEN q_media_mime LIKE 'video/%' THEN 'videos' WHEN q_media_mime IN ('application/pdf', 'text/plain') THEN 'documents' ELSE 'other' END AS type, COUNT(*) AS count FROM documents WHERE ${base} GROUP BY type`).bind(this.tenantId).all();
2258
2262
  return {
2259
2263
  files,
2264
+ total,
2260
2265
  folders: (folderAgg.results ?? []).map((f) => ({ folder: f.folder, count: f.count, totalSize: f.totalSize ?? 0 })),
2261
2266
  types: (typeAgg.results ?? []).map((t) => ({ type: t.type, count: t.count }))
2262
2267
  };
@@ -2330,7 +2335,7 @@ var fileValidationSchema = zod.z.object({
2330
2335
  // 50MB max
2331
2336
  });
2332
2337
  var apiMediaRoutes = new hono.Hono();
2333
- apiMediaRoutes.use("*", chunk4SHNHNRP_cjs.requireAuth());
2338
+ apiMediaRoutes.use("*", chunkFTXGZ3BF_cjs.requireAuth());
2334
2339
  apiMediaRoutes.post("/upload", async (c) => {
2335
2340
  try {
2336
2341
  const user = c.get("user");
@@ -3028,7 +3033,7 @@ apiSystemRoutes.get("/info", (c) => {
3028
3033
  apiSystemRoutes.get("/stats", async (c) => {
3029
3034
  try {
3030
3035
  const db = c.env.DB;
3031
- const typeIds = chunk5ARIHAGN_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => r.name);
3036
+ const typeIds = chunkPYZYU7EK_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal).map((r) => r.name);
3032
3037
  let contentStats = null;
3033
3038
  if (typeIds.length > 0) {
3034
3039
  const placeholders = typeIds.map(() => "?").join(",");
@@ -3103,12 +3108,12 @@ apiSystemRoutes.get("/env", (c) => {
3103
3108
  });
3104
3109
  var api_system_default = apiSystemRoutes;
3105
3110
  var adminApiRoutes = new hono.Hono();
3106
- adminApiRoutes.use("*", chunk4SHNHNRP_cjs.requireAuth());
3107
- adminApiRoutes.use("*", chunk4SHNHNRP_cjs.requireRole(["admin", "editor"]));
3111
+ adminApiRoutes.use("*", chunkFTXGZ3BF_cjs.requireAuth());
3112
+ adminApiRoutes.use("*", chunkFTXGZ3BF_cjs.requireRole(["admin", "editor"]));
3108
3113
  adminApiRoutes.get("/stats", async (c) => {
3109
3114
  try {
3110
3115
  const db = c.env.DB;
3111
- const userCollections = chunk5ARIHAGN_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
3116
+ const userCollections = chunkPYZYU7EK_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
3112
3117
  const collectionsCount = userCollections.length;
3113
3118
  let contentCount = 0;
3114
3119
  if (userCollections.length > 0) {
@@ -3199,7 +3204,7 @@ adminApiRoutes.get("/collections", async (c) => {
3199
3204
  try {
3200
3205
  const search = c.req.query("search") || "";
3201
3206
  const includeInactive = c.req.query("includeInactive") === "true";
3202
- let records = chunk5ARIHAGN_cjs.getCollectionRegistry().list().filter((r) => !r.internal);
3207
+ let records = chunkPYZYU7EK_cjs.getCollectionRegistry().list().filter((r) => !r.internal);
3203
3208
  if (!includeInactive) records = records.filter((r) => r.isActive !== false);
3204
3209
  if (search) {
3205
3210
  const needle = search.toLowerCase();
@@ -3231,7 +3236,7 @@ adminApiRoutes.get("/collections", async (c) => {
3231
3236
  adminApiRoutes.get("/collections/:id", async (c) => {
3232
3237
  try {
3233
3238
  const id = c.req.param("id");
3234
- const registry = chunk5ARIHAGN_cjs.getCollectionRegistry();
3239
+ const registry = chunkPYZYU7EK_cjs.getCollectionRegistry();
3235
3240
  const record = registry.getById(id) ?? registry.getByName(id);
3236
3241
  if (!record) {
3237
3242
  return c.json({ error: "Collection not found" }, 404);
@@ -3281,7 +3286,7 @@ adminApiRoutes.get("/references", async (c) => {
3281
3286
  if (collectionParams.length === 0) {
3282
3287
  return c.json({ error: "Collection is required" }, 400);
3283
3288
  }
3284
- const registry = chunk5ARIHAGN_cjs.getCollectionRegistry();
3289
+ const registry = chunkPYZYU7EK_cjs.getCollectionRegistry();
3285
3290
  const matched = collectionParams.map((param) => registry.getById(param) ?? registry.getByName(param)).filter((r) => !!r);
3286
3291
  const seen = /* @__PURE__ */ new Set();
3287
3292
  const collections = matched.filter((r) => {
@@ -3396,7 +3401,7 @@ adminApiRoutes.patch("/collections/:id", collectionsReadOnly);
3396
3401
  adminApiRoutes.delete("/collections/:id", collectionsReadOnly);
3397
3402
  adminApiRoutes.get("/migrations/status", async (c) => {
3398
3403
  try {
3399
- const { MigrationService: MigrationService2 } = await import('./migrations-VQAFXMU7.cjs');
3404
+ const { MigrationService: MigrationService2 } = await import('./migrations-UIMA6ZL6.cjs');
3400
3405
  const db = c.env.DB;
3401
3406
  const migrationService = new MigrationService2(db);
3402
3407
  const status = await migrationService.getMigrationStatus();
@@ -3439,7 +3444,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
3439
3444
  });
3440
3445
  adminApiRoutes.get("/migrations/validate", async (c) => {
3441
3446
  try {
3442
- const { MigrationService: MigrationService2 } = await import('./migrations-VQAFXMU7.cjs');
3447
+ const { MigrationService: MigrationService2 } = await import('./migrations-UIMA6ZL6.cjs');
3443
3448
  const db = c.env.DB;
3444
3449
  const migrationService = new MigrationService2(db);
3445
3450
  const validation = await migrationService.validateSchema();
@@ -3854,7 +3859,7 @@ function renderRegisterPage(data) {
3854
3859
  }
3855
3860
 
3856
3861
  // src/services/email/email-service-singleton.ts
3857
- var singleton = chunk5RSB5SEK_cjs.createServiceSingleton("EmailService");
3862
+ var singleton = chunkEUJAEB6W_cjs.createServiceSingleton("EmailService");
3858
3863
  function setEmailService(service2) {
3859
3864
  singleton.set(service2);
3860
3865
  }
@@ -4662,7 +4667,7 @@ function getLexicalInitScript(settings = {}) {
4662
4667
  </script>
4663
4668
  `;
4664
4669
  }
4665
- var lexicalEditorPlugin = chunk5RSB5SEK_cjs.definePlugin({
4670
+ var lexicalEditorPlugin = chunkEUJAEB6W_cjs.definePlugin({
4666
4671
  id: "lexical-editor",
4667
4672
  version: "1.0.0",
4668
4673
  name: "Lexical Editor",
@@ -7068,7 +7073,7 @@ api.put("/:userId", async (c) => {
7068
7073
  await saveCustomData(db, userId, sanitized);
7069
7074
  return c.json({ success: true });
7070
7075
  });
7071
- var userProfilesPlugin = chunk5RSB5SEK_cjs.definePlugin({
7076
+ var userProfilesPlugin = chunkEUJAEB6W_cjs.definePlugin({
7072
7077
  id: "user-profiles",
7073
7078
  version: "1.0.0",
7074
7079
  name: "User Profiles",
@@ -7106,8 +7111,8 @@ function renderPasswordResetEmail(resetLink, firstName) {
7106
7111
  async function setCsrfCookie(c, maxAge) {
7107
7112
  const secret = c.env?.JWT_SECRET || JWT_SECRET_FALLBACK;
7108
7113
  const isDev = c.env?.ENVIRONMENT === "development" || !c.env?.ENVIRONMENT;
7109
- const csrfToken = await chunk4SHNHNRP_cjs.generateCsrfToken(secret);
7110
- const cookieMaxAge = await chunk4SHNHNRP_cjs.getJwtExpirySecondsFromDb(c.env?.DB, c.env);
7114
+ const csrfToken = await chunkFTXGZ3BF_cjs.generateCsrfToken(secret);
7115
+ const cookieMaxAge = await chunkFTXGZ3BF_cjs.getJwtExpirySecondsFromDb(c.env?.DB, c.env);
7111
7116
  cookie.setCookie(c, "csrf_token", csrfToken, {
7112
7117
  httpOnly: false,
7113
7118
  secure: !isDev,
@@ -7166,7 +7171,7 @@ var loginSchema = zod.z.object({
7166
7171
  });
7167
7172
  authRoutes.post(
7168
7173
  "/register",
7169
- chunk4SHNHNRP_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
7174
+ chunkFTXGZ3BF_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
7170
7175
  async (c) => {
7171
7176
  try {
7172
7177
  const db = c.env.DB;
@@ -7202,7 +7207,7 @@ authRoutes.post(
7202
7207
  if (existingUser) {
7203
7208
  return c.json({ error: "User with this email already exists" }, 400);
7204
7209
  }
7205
- const passwordHash = await chunk4SHNHNRP_cjs.AuthManager.hashPassword(password);
7210
+ const passwordHash = await chunkFTXGZ3BF_cjs.AuthManager.hashPassword(password);
7206
7211
  const userId = crypto.randomUUID();
7207
7212
  const now = /* @__PURE__ */ new Date();
7208
7213
  const nowSec = Math.floor(now.getTime() / 1e3);
@@ -7235,8 +7240,8 @@ authRoutes.post(
7235
7240
  { user: { id: userId, email: normalizedEmail, role: "viewer" } },
7236
7241
  "fire-and-forget"
7237
7242
  );
7238
- const tokenTtl = await chunk4SHNHNRP_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7239
- const token = await chunk4SHNHNRP_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer", c.env.JWT_SECRET, tokenTtl);
7243
+ const tokenTtl = await chunkFTXGZ3BF_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7244
+ const token = await chunkFTXGZ3BF_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer", c.env.JWT_SECRET, tokenTtl);
7240
7245
  cookie.setCookie(c, "auth_token", token, {
7241
7246
  httpOnly: true,
7242
7247
  secure: true,
@@ -7268,7 +7273,7 @@ authRoutes.post(
7268
7273
  );
7269
7274
  authRoutes.post(
7270
7275
  "/login",
7271
- chunk4SHNHNRP_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
7276
+ chunkFTXGZ3BF_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
7272
7277
  async (c) => {
7273
7278
  try {
7274
7279
  const body = await c.req.json();
@@ -7300,8 +7305,8 @@ authRoutes.post(
7300
7305
  await setCsrfCookie(c);
7301
7306
  const baBody = await baRes.json();
7302
7307
  const user = baBody.user ?? {};
7303
- const tokenTtl = await chunk4SHNHNRP_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7304
- const token = await chunk4SHNHNRP_cjs.AuthManager.generateToken(
7308
+ const tokenTtl = await chunkFTXGZ3BF_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7309
+ const token = await chunkFTXGZ3BF_cjs.AuthManager.generateToken(
7305
7310
  user.id,
7306
7311
  user.email,
7307
7312
  user.role ?? "viewer",
@@ -7362,7 +7367,7 @@ authRoutes.get("/logout", async (c) => {
7362
7367
  clearCsrfCookie(c);
7363
7368
  return c.redirect("/auth/login?message=You have been logged out successfully");
7364
7369
  });
7365
- authRoutes.get("/me", chunk4SHNHNRP_cjs.requireAuth(), async (c) => {
7370
+ authRoutes.get("/me", chunkFTXGZ3BF_cjs.requireAuth(), async (c) => {
7366
7371
  try {
7367
7372
  const user = c.get("user");
7368
7373
  if (!user) {
@@ -7382,7 +7387,7 @@ authRoutes.get("/me", chunk4SHNHNRP_cjs.requireAuth(), async (c) => {
7382
7387
  });
7383
7388
  authRoutes.post(
7384
7389
  "/refresh",
7385
- chunk4SHNHNRP_cjs.rateLimit({ max: 60, windowMs: 60 * 1e3, keyPrefix: "refresh" }),
7390
+ chunkFTXGZ3BF_cjs.rateLimit({ max: 60, windowMs: 60 * 1e3, keyPrefix: "refresh" }),
7386
7391
  async (c) => {
7387
7392
  try {
7388
7393
  let token = c.req.header("Authorization")?.replace("Bearer ", "");
@@ -7391,8 +7396,8 @@ authRoutes.post(
7391
7396
  return c.json({ error: "Authentication required" }, 401);
7392
7397
  }
7393
7398
  const db = c.env.DB;
7394
- const grace = await chunk4SHNHNRP_cjs.getJwtRefreshGraceSecondsFromDb(db, c.env);
7395
- const payload = await chunk4SHNHNRP_cjs.AuthManager.verifyToken(token, c.env.JWT_SECRET, grace);
7399
+ const grace = await chunkFTXGZ3BF_cjs.getJwtRefreshGraceSecondsFromDb(db, c.env);
7400
+ const payload = await chunkFTXGZ3BF_cjs.AuthManager.verifyToken(token, c.env.JWT_SECRET, grace);
7396
7401
  if (!payload) {
7397
7402
  return c.json({ error: "Invalid or expired token" }, 401);
7398
7403
  }
@@ -7400,8 +7405,8 @@ authRoutes.post(
7400
7405
  if (!row || !row.is_active) {
7401
7406
  return c.json({ error: "User is not active" }, 401);
7402
7407
  }
7403
- const tokenTtl = await chunk4SHNHNRP_cjs.getJwtExpirySecondsFromDb(db, c.env);
7404
- const newToken = await chunk4SHNHNRP_cjs.AuthManager.generateToken(row.id, row.email, row.role, c.env.JWT_SECRET, tokenTtl);
7408
+ const tokenTtl = await chunkFTXGZ3BF_cjs.getJwtExpirySecondsFromDb(db, c.env);
7409
+ const newToken = await chunkFTXGZ3BF_cjs.AuthManager.generateToken(row.id, row.email, row.role, c.env.JWT_SECRET, tokenTtl);
7405
7410
  cookie.setCookie(c, "auth_token", newToken, {
7406
7411
  httpOnly: true,
7407
7412
  secure: true,
@@ -7421,7 +7426,7 @@ authRoutes.post(
7421
7426
  );
7422
7427
  authRoutes.post(
7423
7428
  "/register/form",
7424
- chunk4SHNHNRP_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
7429
+ chunkFTXGZ3BF_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
7425
7430
  async (c) => {
7426
7431
  try {
7427
7432
  const db = c.env.DB;
@@ -7466,7 +7471,7 @@ authRoutes.post(
7466
7471
  </div>
7467
7472
  `);
7468
7473
  }
7469
- const passwordHash = await chunk4SHNHNRP_cjs.AuthManager.hashPassword(password);
7474
+ const passwordHash = await chunkFTXGZ3BF_cjs.AuthManager.hashPassword(password);
7470
7475
  const role = isFirstUser ? "admin" : "viewer";
7471
7476
  const userId = crypto.randomUUID();
7472
7477
  const now = /* @__PURE__ */ new Date();
@@ -7508,8 +7513,8 @@ authRoutes.post(
7508
7513
  { user: { id: userId, email: normalizedEmail, role } },
7509
7514
  "fire-and-forget"
7510
7515
  );
7511
- const tokenTtl = await chunk4SHNHNRP_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7512
- const token = await chunk4SHNHNRP_cjs.AuthManager.generateToken(userId, normalizedEmail, role, c.env.JWT_SECRET, tokenTtl);
7516
+ const tokenTtl = await chunkFTXGZ3BF_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7517
+ const token = await chunkFTXGZ3BF_cjs.AuthManager.generateToken(userId, normalizedEmail, role, c.env.JWT_SECRET, tokenTtl);
7513
7518
  cookie.setCookie(c, "auth_token", token, {
7514
7519
  httpOnly: true,
7515
7520
  secure: false,
@@ -7541,7 +7546,7 @@ authRoutes.post(
7541
7546
  );
7542
7547
  authRoutes.post(
7543
7548
  "/login/form",
7544
- chunk4SHNHNRP_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
7549
+ chunkFTXGZ3BF_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
7545
7550
  async (c) => {
7546
7551
  try {
7547
7552
  const formData = await c.req.formData();
@@ -7610,14 +7615,14 @@ authRoutes.post(
7610
7615
  );
7611
7616
  authRoutes.post(
7612
7617
  "/seed-admin",
7613
- chunk4SHNHNRP_cjs.rateLimit({ max: 10, windowMs: 60 * 1e3, keyPrefix: "seed-admin" }),
7618
+ chunkFTXGZ3BF_cjs.rateLimit({ max: 10, windowMs: 60 * 1e3, keyPrefix: "seed-admin" }),
7614
7619
  async (c) => {
7615
7620
  try {
7616
7621
  const db = c.env.DB;
7617
7622
  const rbac = new chunkLTZ5WYOK_cjs.RbacService(db);
7618
7623
  const results = [];
7619
7624
  const upsertSeedUser = async (opts) => {
7620
- const passwordHash = await chunk4SHNHNRP_cjs.AuthManager.hashPassword(opts.password);
7625
+ const passwordHash = await chunkFTXGZ3BF_cjs.AuthManager.hashPassword(opts.password);
7621
7626
  const nowMs = Date.now();
7622
7627
  const nowSec = Math.floor(nowMs / 1e3);
7623
7628
  const existing = await db.prepare("SELECT id FROM auth_user WHERE email = ?").bind(opts.email).first();
@@ -7842,7 +7847,7 @@ authRoutes.post("/accept-invitation", async (c) => {
7842
7847
  if (invitationAge > maxAge) {
7843
7848
  return c.json({ error: "Invitation has expired" }, 400);
7844
7849
  }
7845
- const passwordHash = await chunk4SHNHNRP_cjs.AuthManager.hashPassword(password);
7850
+ const passwordHash = await chunkFTXGZ3BF_cjs.AuthManager.hashPassword(password);
7846
7851
  const updateStmt = db.prepare(`
7847
7852
  UPDATE auth_user SET
7848
7853
  password_hash = ?,
@@ -7859,8 +7864,8 @@ authRoutes.post("/accept-invitation", async (c) => {
7859
7864
  Date.now(),
7860
7865
  invitedUser.id
7861
7866
  ).run();
7862
- const tokenTtl = await chunk4SHNHNRP_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7863
- const authToken = await chunk4SHNHNRP_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role, c.env.JWT_SECRET, tokenTtl);
7867
+ const tokenTtl = await chunkFTXGZ3BF_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
7868
+ const authToken = await chunkFTXGZ3BF_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role, c.env.JWT_SECRET, tokenTtl);
7864
7869
  cookie.setCookie(c, "auth_token", authToken, {
7865
7870
  httpOnly: true,
7866
7871
  secure: true,
@@ -7876,7 +7881,7 @@ authRoutes.post("/accept-invitation", async (c) => {
7876
7881
  });
7877
7882
  authRoutes.post(
7878
7883
  "/request-password-reset",
7879
- chunk4SHNHNRP_cjs.rateLimit({ max: 3, windowMs: 15 * 60 * 1e3, keyPrefix: "password-reset" }),
7884
+ chunkFTXGZ3BF_cjs.rateLimit({ max: 3, windowMs: 15 * 60 * 1e3, keyPrefix: "password-reset" }),
7880
7885
  async (c) => {
7881
7886
  try {
7882
7887
  const formData = await c.req.formData();
@@ -8113,7 +8118,7 @@ authRoutes.post("/reset-password", async (c) => {
8113
8118
  if (Date.now() > user.password_reset_expires) {
8114
8119
  return c.json({ error: "Reset token has expired" }, 400);
8115
8120
  }
8116
- const newPasswordHash = await chunk4SHNHNRP_cjs.AuthManager.hashPassword(password);
8121
+ const newPasswordHash = await chunkFTXGZ3BF_cjs.AuthManager.hashPassword(password);
8117
8122
  try {
8118
8123
  const historyStmt = db.prepare(`
8119
8124
  INSERT INTO auth_password_history (id, user_id, password_hash, created_at)
@@ -8327,7 +8332,7 @@ app.post("/test-seed-defaults", async (c) => {
8327
8332
  var test_cleanup_default = app;
8328
8333
 
8329
8334
  // src/plugins/available/easy-mdx/index.ts
8330
- chunk5RSB5SEK_cjs.definePlugin({
8335
+ chunkEUJAEB6W_cjs.definePlugin({
8331
8336
  id: "easy-mdx",
8332
8337
  version: "1.0.0",
8333
8338
  name: "EasyMDE Markdown Editor",
@@ -8527,7 +8532,7 @@ function getMDXEditorInitScript(config) {
8527
8532
  }
8528
8533
 
8529
8534
  // src/plugins/available/tinymce-plugin/index.ts
8530
- chunk5RSB5SEK_cjs.definePlugin({
8535
+ chunkEUJAEB6W_cjs.definePlugin({
8531
8536
  id: "tinymce-plugin",
8532
8537
  version: "1.0.0",
8533
8538
  name: "TinyMCE",
@@ -8797,7 +8802,7 @@ function getQuillCDN(version = "2.0.2") {
8797
8802
  </style>
8798
8803
  `;
8799
8804
  }
8800
- chunk5RSB5SEK_cjs.definePlugin({
8805
+ chunkEUJAEB6W_cjs.definePlugin({
8801
8806
  id: "quill-editor",
8802
8807
  version: "1.0.0",
8803
8808
  name: "Quill Editor",
@@ -11371,7 +11376,7 @@ function extractFieldData(fields, formData, options = {}) {
11371
11376
  }
11372
11377
  return { data, errors };
11373
11378
  }
11374
- adminContentRoutes.use("*", chunk4SHNHNRP_cjs.requireAuth());
11379
+ adminContentRoutes.use("*", chunkFTXGZ3BF_cjs.requireAuth());
11375
11380
  async function getCollectionFields(db, collectionId) {
11376
11381
  console.log(`[getCollectionFields] Loading fields for collection: ${collectionId}`);
11377
11382
  const collectionStmt = db.prepare("SELECT schema, queryable_fields FROM document_types WHERE id = ?");
@@ -11398,7 +11403,7 @@ async function getCollectionFields(db, collectionId) {
11398
11403
  };
11399
11404
  });
11400
11405
  }
11401
- const codeCollections2 = await chunk5ARIHAGN_cjs.loadCollectionConfigs();
11406
+ const codeCollections2 = await chunkPYZYU7EK_cjs.loadCollectionConfigs();
11402
11407
  const codeMatch = codeCollections2.find((c) => c.name === collectionId);
11403
11408
  if (codeMatch && codeMatch.schema?.properties) {
11404
11409
  console.log(`[getCollectionFields] DB doc type has no properties \u2014 using code collection schema`);
@@ -11430,7 +11435,7 @@ async function getCollectionFields(db, collectionId) {
11430
11435
  }
11431
11436
  }
11432
11437
  console.log(`[getCollectionFields] Not in database, checking code collections`);
11433
- const codeCollections = await chunk5ARIHAGN_cjs.loadCollectionConfigs();
11438
+ const codeCollections = await chunkPYZYU7EK_cjs.loadCollectionConfigs();
11434
11439
  console.log(`[getCollectionFields] Found ${codeCollections.length} code collections`);
11435
11440
  const codeCollection = codeCollections.find((c) => c.name === collectionId);
11436
11441
  if (codeCollection && codeCollection.schema) {
@@ -11484,7 +11489,7 @@ async function getCollection(db, collectionId) {
11484
11489
  };
11485
11490
  }
11486
11491
  console.log(`[getCollection] Not in database, checking code collections`);
11487
- const codeCollections = await chunk5ARIHAGN_cjs.loadCollectionConfigs();
11492
+ const codeCollections = await chunkPYZYU7EK_cjs.loadCollectionConfigs();
11488
11493
  const codeCollection = codeCollections.find((c) => c.name === collectionId);
11489
11494
  if (codeCollection) {
11490
11495
  console.log(`[getCollection] Found code collection: ${collectionId}`);
@@ -11503,7 +11508,7 @@ async function getCollection(db, collectionId) {
11503
11508
  }
11504
11509
  async function getDocBackingType(db, collectionName) {
11505
11510
  if (!collectionName) return null;
11506
- const dt = await new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db).findById(collectionName);
11511
+ const dt = await new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db).findById(collectionName);
11507
11512
  return dt && dt.isActive ? dt : null;
11508
11513
  }
11509
11514
  async function getCollectionByName(db, name) {
@@ -11520,7 +11525,7 @@ async function getCollectionByName(db, name) {
11520
11525
  };
11521
11526
  }
11522
11527
  console.log(`[getCollectionByName] Not in database, checking code collections`);
11523
- const codeCollections = await chunk5ARIHAGN_cjs.loadCollectionConfigs();
11528
+ const codeCollections = await chunkPYZYU7EK_cjs.loadCollectionConfigs();
11524
11529
  const codeCollection = codeCollections.find((c) => c.name === name);
11525
11530
  if (codeCollection) {
11526
11531
  console.log(`[getCollectionByName] Found code collection: ${name}`);
@@ -11536,7 +11541,7 @@ async function getCollectionByName(db, name) {
11536
11541
  return null;
11537
11542
  }
11538
11543
  async function loadContentEditorFlags(db) {
11539
- const flags = { workflowEnabled: await chunk4SHNHNRP_cjs.isPluginActive(db, "workflow") };
11544
+ const flags = { workflowEnabled: await chunkFTXGZ3BF_cjs.isPluginActive(db, "workflow") };
11540
11545
  const editors = [
11541
11546
  ["tinymce-plugin", "tinymce"],
11542
11547
  ["quill-editor", "quill"],
@@ -11544,10 +11549,10 @@ async function loadContentEditorFlags(db) {
11544
11549
  ["lexical-editor", "lexical"]
11545
11550
  ];
11546
11551
  for (const [plugin, key] of editors) {
11547
- const enabled = await chunk4SHNHNRP_cjs.isPluginActive(db, plugin);
11552
+ const enabled = await chunkFTXGZ3BF_cjs.isPluginActive(db, plugin);
11548
11553
  flags[`${key}Enabled`] = enabled;
11549
11554
  if (enabled) {
11550
- const ps = new chunk5ARIHAGN_cjs.PluginService(db);
11555
+ const ps = new chunkPYZYU7EK_cjs.PluginService(db);
11551
11556
  const p = await ps.getPlugin(plugin);
11552
11557
  flags[`${key}Settings`] = p?.settings;
11553
11558
  }
@@ -11583,9 +11588,9 @@ adminContentRoutes.get("/", async (c) => {
11583
11588
  const offset = (page - 1) * limit;
11584
11589
  const collectionsStmt = db.prepare("SELECT id, name, display_name FROM document_types WHERE is_active = 1 ORDER BY display_name");
11585
11590
  const { results: collectionsResults } = await collectionsStmt.all();
11586
- const codeCollections = await chunk5ARIHAGN_cjs.loadCollectionConfigs();
11591
+ const codeCollections = await chunkPYZYU7EK_cjs.loadCollectionConfigs();
11587
11592
  const codeCollectionMap = new Map(codeCollections.map((c2) => [c2.name, c2]));
11588
- const docTypeRegistry = new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db);
11593
+ const docTypeRegistry = new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db);
11589
11594
  const docTypes = (await docTypeRegistry.findAll()).filter((dt) => !dt.settings?.internal && !dt.isAuth);
11590
11595
  const visibleTypeIds = new Set(docTypes.map((dt) => dt.id));
11591
11596
  const allCollections = [
@@ -11597,7 +11602,7 @@ adminContentRoutes.get("/", async (c) => {
11597
11602
  ...allCollections.map((c2) => ({ name: c2.name, displayName: c2.displayName })),
11598
11603
  ...docTypes.filter((dt) => !collectionNames.has(dt.id)).map((dt) => ({ name: `doc:${dt.id}`, displayName: dt.displayName }))
11599
11604
  ];
11600
- const newContentCollections = await chunk5ARIHAGN_cjs.getVisibleCollections(db);
11605
+ const newContentCollections = await chunkPYZYU7EK_cjs.getVisibleCollections(db);
11601
11606
  const docBackedCollection = !modelName.startsWith("doc:") && modelName !== "all" ? docTypes.find((dt) => dt.id === modelName) : void 0;
11602
11607
  const isDocModel = modelName.startsWith("doc:") || !!docBackedCollection;
11603
11608
  if (isDocModel) {
@@ -11874,9 +11879,9 @@ adminContentRoutes.get("/new", async (c) => {
11874
11879
  const collectionsStmt = db2.prepare("SELECT id, name, display_name, description FROM document_types WHERE is_active = 1 ORDER BY display_name");
11875
11880
  const { results } = await collectionsStmt.all();
11876
11881
  const visibleTypeIds = new Set(
11877
- (await new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db2).findAll()).filter((dt) => !dt.settings?.internal && !dt.isAuth).map((dt) => dt.id)
11882
+ (await new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db2).findAll()).filter((dt) => !dt.settings?.internal && !dt.isAuth).map((dt) => dt.id)
11878
11883
  );
11879
- const codeCollections = await chunk5ARIHAGN_cjs.loadCollectionConfigs();
11884
+ const codeCollections = await chunkPYZYU7EK_cjs.loadCollectionConfigs();
11880
11885
  const dbCollectionNames = new Set((results || []).map((r) => r.name));
11881
11886
  const allCollections = [
11882
11887
  ...codeCollections.filter((c2) => !dbCollectionNames.has(c2.name)).map((c2) => ({
@@ -11942,32 +11947,32 @@ adminContentRoutes.get("/new", async (c) => {
11942
11947
  return c.html(renderContentFormPage(formData2));
11943
11948
  }
11944
11949
  const fields = await getCollectionFields(db, collection.id);
11945
- const workflowEnabled = await chunk4SHNHNRP_cjs.isPluginActive(db, "workflow");
11946
- const tinymceEnabled = await chunk4SHNHNRP_cjs.isPluginActive(db, "tinymce-plugin");
11950
+ const workflowEnabled = await chunkFTXGZ3BF_cjs.isPluginActive(db, "workflow");
11951
+ const tinymceEnabled = await chunkFTXGZ3BF_cjs.isPluginActive(db, "tinymce-plugin");
11947
11952
  let tinymceSettings;
11948
11953
  if (tinymceEnabled) {
11949
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
11954
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
11950
11955
  const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
11951
11956
  tinymceSettings = tinymcePlugin2?.settings;
11952
11957
  }
11953
- const quillEnabled = await chunk4SHNHNRP_cjs.isPluginActive(db, "quill-editor");
11958
+ const quillEnabled = await chunkFTXGZ3BF_cjs.isPluginActive(db, "quill-editor");
11954
11959
  let quillSettings;
11955
11960
  if (quillEnabled) {
11956
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
11961
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
11957
11962
  const quillPlugin = await pluginService.getPlugin("quill-editor");
11958
11963
  quillSettings = quillPlugin?.settings;
11959
11964
  }
11960
- const mdxeditorEnabled = await chunk4SHNHNRP_cjs.isPluginActive(db, "easy-mdx");
11965
+ const mdxeditorEnabled = await chunkFTXGZ3BF_cjs.isPluginActive(db, "easy-mdx");
11961
11966
  let mdxeditorSettings;
11962
11967
  if (mdxeditorEnabled) {
11963
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
11968
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
11964
11969
  const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
11965
11970
  mdxeditorSettings = mdxeditorPlugin?.settings;
11966
11971
  }
11967
- const lexicalEnabled = await chunk4SHNHNRP_cjs.isPluginActive(db, "lexical-editor");
11972
+ const lexicalEnabled = await chunkFTXGZ3BF_cjs.isPluginActive(db, "lexical-editor");
11968
11973
  let lexicalSettings;
11969
11974
  if (lexicalEnabled) {
11970
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
11975
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
11971
11976
  const lexicalPlugin = await pluginService.getPlugin("lexical-editor");
11972
11977
  lexicalSettings = lexicalPlugin?.settings;
11973
11978
  }
@@ -12095,32 +12100,32 @@ adminContentRoutes.get("/:id/edit", async (c) => {
12095
12100
  };
12096
12101
  const fields = await getCollectionFields(db, content.collection_id);
12097
12102
  const contentData = content.data ? JSON.parse(content.data) : {};
12098
- const workflowEnabled = await chunk4SHNHNRP_cjs.isPluginActive(db, "workflow");
12099
- const tinymceEnabled = await chunk4SHNHNRP_cjs.isPluginActive(db, "tinymce-plugin");
12103
+ const workflowEnabled = await chunkFTXGZ3BF_cjs.isPluginActive(db, "workflow");
12104
+ const tinymceEnabled = await chunkFTXGZ3BF_cjs.isPluginActive(db, "tinymce-plugin");
12100
12105
  let tinymceSettings;
12101
12106
  if (tinymceEnabled) {
12102
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
12107
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
12103
12108
  const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
12104
12109
  tinymceSettings = tinymcePlugin2?.settings;
12105
12110
  }
12106
- const quillEnabled = await chunk4SHNHNRP_cjs.isPluginActive(db, "quill-editor");
12111
+ const quillEnabled = await chunkFTXGZ3BF_cjs.isPluginActive(db, "quill-editor");
12107
12112
  let quillSettings;
12108
12113
  if (quillEnabled) {
12109
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
12114
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
12110
12115
  const quillPlugin = await pluginService.getPlugin("quill-editor");
12111
12116
  quillSettings = quillPlugin?.settings;
12112
12117
  }
12113
- const mdxeditorEnabled = await chunk4SHNHNRP_cjs.isPluginActive(db, "easy-mdx");
12118
+ const mdxeditorEnabled = await chunkFTXGZ3BF_cjs.isPluginActive(db, "easy-mdx");
12114
12119
  let mdxeditorSettings;
12115
12120
  if (mdxeditorEnabled) {
12116
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
12121
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
12117
12122
  const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
12118
12123
  mdxeditorSettings = mdxeditorPlugin?.settings;
12119
12124
  }
12120
- const lexicalEnabled = await chunk4SHNHNRP_cjs.isPluginActive(db, "lexical-editor");
12125
+ const lexicalEnabled = await chunkFTXGZ3BF_cjs.isPluginActive(db, "lexical-editor");
12121
12126
  let lexicalSettings;
12122
12127
  if (lexicalEnabled) {
12123
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
12128
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
12124
12129
  const lexicalPlugin = await pluginService.getPlugin("lexical-editor");
12125
12130
  lexicalSettings = lexicalPlugin?.settings;
12126
12131
  }
@@ -12493,7 +12498,7 @@ adminContentRoutes.put("/:id", async (c) => {
12493
12498
  `);
12494
12499
  }
12495
12500
  });
12496
- adminContentRoutes.post("/preview", chunk4SHNHNRP_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
12501
+ adminContentRoutes.post("/preview", chunkFTXGZ3BF_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
12497
12502
  try {
12498
12503
  const formData = await c.req.formData();
12499
12504
  const collectionId = formData.get("collection_id");
@@ -12812,7 +12817,7 @@ adminContentRoutes.delete("/:id", async (c) => {
12812
12817
  return c.json({ success: false, error: "Failed to delete content" }, 500);
12813
12818
  }
12814
12819
  });
12815
- adminContentRoutes.get("/:id/version/:version/preview", chunk4SHNHNRP_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
12820
+ adminContentRoutes.get("/:id/version/:version/preview", chunkFTXGZ3BF_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
12816
12821
  try {
12817
12822
  const id = c.req.param("id");
12818
12823
  const version = parseInt(c.req.param("version") || "0");
@@ -12908,7 +12913,7 @@ function parseDocFormData(formData, queryableFields = []) {
12908
12913
  return { title, slug, data };
12909
12914
  }
12910
12915
  async function getDocService(db, typeId, tenantId) {
12911
- const registry = new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db);
12916
+ const registry = new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db);
12912
12917
  const docType = await registry.findById(typeId);
12913
12918
  const svc = new chunkLTZ5WYOK_cjs.DocumentsService(db, {
12914
12919
  queryableFields: docType?.queryableFields ?? [],
@@ -12921,7 +12926,7 @@ async function getDocService(db, typeId, tenantId) {
12921
12926
  }
12922
12927
  adminContentRoutes.get("/documents/:typeId/new", async (c) => {
12923
12928
  const { typeId } = c.req.param();
12924
- const registry = new chunk4SHNHNRP_cjs.DocumentTypeRegistry(c.env.DB);
12929
+ const registry = new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(c.env.DB);
12925
12930
  const docType = await registry.findById(typeId);
12926
12931
  if (!docType) return c.html("<p>Unknown document type.</p>", 404);
12927
12932
  return c.html(chunkN32OWET6_cjs.renderDocumentFormPage({ docType, isEdit: false, user: userCtx(c) }));
@@ -12946,7 +12951,7 @@ adminContentRoutes.post("/documents/:typeId/new", async (c) => {
12946
12951
  }), user?.userId);
12947
12952
  return c.redirect(`/admin/content/documents/${typeId}/${doc.rootId}/edit?message=Created+successfully`);
12948
12953
  } catch (err) {
12949
- const registry = new chunk4SHNHNRP_cjs.DocumentTypeRegistry(c.env.DB);
12954
+ const registry = new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(c.env.DB);
12950
12955
  const docType = await registry.findById(typeId);
12951
12956
  if (!docType) return c.html("<p>Unknown document type.</p>", 404);
12952
12957
  return c.html(chunkN32OWET6_cjs.renderDocumentFormPage({ docType, isEdit: false, user: userCtx(c), message: err?.message ?? "Failed to create", messageType: "error" }));
@@ -12956,7 +12961,7 @@ adminContentRoutes.get("/documents/:typeId/:rootId/edit", async (c) => {
12956
12961
  const { typeId, rootId } = c.req.param();
12957
12962
  const db = c.env.DB;
12958
12963
  const message = c.req.query("message");
12959
- const registry = new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db);
12964
+ const registry = new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db);
12960
12965
  const docType = await registry.findById(typeId);
12961
12966
  if (!docType) return c.html("<p>Unknown document type.</p>", 404);
12962
12967
  const tenantId = reqTenant(c);
@@ -13069,7 +13074,7 @@ adminContentRoutes.get("/documents/:typeId/:rootId/versions", async (c) => {
13069
13074
  const { typeId, rootId } = c.req.param();
13070
13075
  const db = c.env.DB;
13071
13076
  const { renderVersionHistoryFragment } = await import('./admin-documents-form.template-LSZKGA5J.cjs');
13072
- const registry = new chunk4SHNHNRP_cjs.DocumentTypeRegistry(db);
13077
+ const registry = new chunkFTXGZ3BF_cjs.DocumentTypeRegistry(db);
13073
13078
  const docType = await registry.findById(typeId);
13074
13079
  if (!docType) return c.html("<div>Unknown type.</div>", 404);
13075
13080
  const result = await db.prepare(
@@ -15002,7 +15007,7 @@ var TenantService = class {
15002
15007
  SET name = ?, domain = ?, status = ?, notes = ?, updated_at = ?
15003
15008
  WHERE slug = ?
15004
15009
  `).bind(name, domain, status, notes, now, slug).run();
15005
- chunk5ARIHAGN_cjs.invalidateTenantCache();
15010
+ chunkPYZYU7EK_cjs.invalidateTenantCache();
15006
15011
  const updated = await this.getTenantBySlug(slug);
15007
15012
  if (!updated) throw new Error("Tenant not found");
15008
15013
  return updated;
@@ -15020,7 +15025,7 @@ var TenantService = class {
15020
15025
  throw new Error(`Tenant '${slug}' still owns ${docCount} document(s). Delete or migrate its content first.`);
15021
15026
  }
15022
15027
  await this.db.prepare(`DELETE FROM auth_tenant WHERE slug = ?`).bind(slug).run();
15023
- chunk5ARIHAGN_cjs.invalidateTenantCache();
15028
+ chunkPYZYU7EK_cjs.invalidateTenantCache();
15024
15029
  }
15025
15030
  // ─── Membership (auth_tenant_member) ───────────────────────────────────────
15026
15031
  // Tenant resolution and the admin switcher are gated on membership: an authed user may only
@@ -15264,7 +15269,7 @@ var TenantService = class {
15264
15269
  INSERT INTO auth_tenant (id, name, slug, status, domain, notes, metadata, created_at, updated_at)
15265
15270
  VALUES (?, ?, ?, 'active', ?, ?, '{}', ?, ?)
15266
15271
  `).bind(id, input.name, input.slug, input.domain, input.notes, now, now).run();
15267
- chunk5ARIHAGN_cjs.invalidateTenantCache();
15272
+ chunkPYZYU7EK_cjs.invalidateTenantCache();
15268
15273
  const created = await this.getTenantBySlug(input.slug);
15269
15274
  if (!created) throw new Error("Failed to create tenant");
15270
15275
  return created;
@@ -15288,14 +15293,14 @@ function mapRowToTenant(row) {
15288
15293
 
15289
15294
  // src/routes/admin-users.ts
15290
15295
  var userRoutes = new hono.Hono();
15291
- userRoutes.use("*", chunk4SHNHNRP_cjs.requireAuth());
15292
- userRoutes.use("/users/*", chunk4SHNHNRP_cjs.requireRole(["admin"]));
15293
- userRoutes.use("/users", chunk4SHNHNRP_cjs.requireRole(["admin"]));
15294
- userRoutes.use("/invite-user", chunk4SHNHNRP_cjs.requireRole(["admin"]));
15295
- userRoutes.use("/resend-invitation/*", chunk4SHNHNRP_cjs.requireRole(["admin"]));
15296
- userRoutes.use("/cancel-invitation/*", chunk4SHNHNRP_cjs.requireRole(["admin"]));
15297
- userRoutes.use("/activity-logs", chunk4SHNHNRP_cjs.requireRole(["admin"]));
15298
- userRoutes.use("/activity-logs/*", chunk4SHNHNRP_cjs.requireRole(["admin"]));
15296
+ userRoutes.use("*", chunkFTXGZ3BF_cjs.requireAuth());
15297
+ userRoutes.use("/users/*", chunkFTXGZ3BF_cjs.requireRole(["admin"]));
15298
+ userRoutes.use("/users", chunkFTXGZ3BF_cjs.requireRole(["admin"]));
15299
+ userRoutes.use("/invite-user", chunkFTXGZ3BF_cjs.requireRole(["admin"]));
15300
+ userRoutes.use("/resend-invitation/*", chunkFTXGZ3BF_cjs.requireRole(["admin"]));
15301
+ userRoutes.use("/cancel-invitation/*", chunkFTXGZ3BF_cjs.requireRole(["admin"]));
15302
+ userRoutes.use("/activity-logs", chunkFTXGZ3BF_cjs.requireRole(["admin"]));
15303
+ userRoutes.use("/activity-logs/*", chunkFTXGZ3BF_cjs.requireRole(["admin"]));
15299
15304
  userRoutes.get("/", (c) => {
15300
15305
  return c.redirect("/admin/dashboard");
15301
15306
  });
@@ -15462,7 +15467,7 @@ userRoutes.put("/profile", async (c) => {
15462
15467
  }
15463
15468
  await saveCustomData(db, user.userId, sanitized);
15464
15469
  }
15465
- await chunk4SHNHNRP_cjs.logActivity(
15470
+ await chunkFTXGZ3BF_cjs.logActivity(
15466
15471
  db,
15467
15472
  user.userId,
15468
15473
  "profile.update",
@@ -15525,7 +15530,7 @@ userRoutes.post("/profile/avatar", async (c) => {
15525
15530
  SELECT first_name, last_name FROM auth_user WHERE id = ?
15526
15531
  `);
15527
15532
  const userData = await userStmt.bind(user.userId).first();
15528
- await chunk4SHNHNRP_cjs.logActivity(
15533
+ await chunkFTXGZ3BF_cjs.logActivity(
15529
15534
  db,
15530
15535
  user.userId,
15531
15536
  "profile.avatar_update",
@@ -15596,7 +15601,7 @@ userRoutes.post("/profile/password", async (c) => {
15596
15601
  dismissible: true
15597
15602
  }));
15598
15603
  }
15599
- const validPassword = await chunk4SHNHNRP_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
15604
+ const validPassword = await chunkFTXGZ3BF_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
15600
15605
  if (!validPassword) {
15601
15606
  return c.html(chunkN32OWET6_cjs.renderAlert({
15602
15607
  type: "error",
@@ -15604,7 +15609,7 @@ userRoutes.post("/profile/password", async (c) => {
15604
15609
  dismissible: true
15605
15610
  }));
15606
15611
  }
15607
- const newPasswordHash = await chunk4SHNHNRP_cjs.AuthManager.hashPassword(newPassword);
15612
+ const newPasswordHash = await chunkFTXGZ3BF_cjs.AuthManager.hashPassword(newPassword);
15608
15613
  const historyStmt = db.prepare(`
15609
15614
  INSERT INTO auth_password_history (id, user_id, password_hash, created_at)
15610
15615
  VALUES (?, ?, ?, ?)
@@ -15620,7 +15625,7 @@ userRoutes.post("/profile/password", async (c) => {
15620
15625
  WHERE id = ?
15621
15626
  `);
15622
15627
  await updateStmt.bind(newPasswordHash, Date.now(), user.userId).run();
15623
- await chunk4SHNHNRP_cjs.logActivity(
15628
+ await chunkFTXGZ3BF_cjs.logActivity(
15624
15629
  db,
15625
15630
  user.userId,
15626
15631
  "profile.password_change",
@@ -15687,7 +15692,7 @@ userRoutes.get("/users", async (c) => {
15687
15692
  `);
15688
15693
  const countResult = await countStmt.bind(...params).first();
15689
15694
  const totalUsers = countResult?.total || 0;
15690
- await chunk4SHNHNRP_cjs.logActivity(
15695
+ await chunkFTXGZ3BF_cjs.logActivity(
15691
15696
  db,
15692
15697
  user.userId,
15693
15698
  "users.list_view",
@@ -15868,7 +15873,7 @@ userRoutes.post("/users/new", async (c) => {
15868
15873
  dismissible: true
15869
15874
  }));
15870
15875
  }
15871
- const passwordHash = await chunk4SHNHNRP_cjs.AuthManager.hashPassword(password);
15876
+ const passwordHash = await chunkFTXGZ3BF_cjs.AuthManager.hashPassword(password);
15872
15877
  const userId = crypto.randomUUID();
15873
15878
  const createStmt = db.prepare(`
15874
15879
  INSERT INTO auth_user (
@@ -15893,7 +15898,7 @@ userRoutes.post("/users/new", async (c) => {
15893
15898
  if (sanitizedRegistrationCustom !== null && Object.keys(sanitizedRegistrationCustom).length > 0) {
15894
15899
  await writeProfileData(db, userId, { custom: sanitizedRegistrationCustom }, user.userId);
15895
15900
  }
15896
- await chunk4SHNHNRP_cjs.logActivity(
15901
+ await chunkFTXGZ3BF_cjs.logActivity(
15897
15902
  db,
15898
15903
  user.userId,
15899
15904
  "user!.create",
@@ -15932,7 +15937,7 @@ userRoutes.get("/users/:id", async (c) => {
15932
15937
  if (!userRecord) {
15933
15938
  return c.json({ error: "User not found" }, 404);
15934
15939
  }
15935
- await chunk4SHNHNRP_cjs.logActivity(
15940
+ await chunkFTXGZ3BF_cjs.logActivity(
15936
15941
  db,
15937
15942
  user.userId,
15938
15943
  "user!.view",
@@ -16146,7 +16151,7 @@ userRoutes.put("/users/:id", async (c) => {
16146
16151
  userId
16147
16152
  ).run();
16148
16153
  if (newPassword) {
16149
- const passwordHash = await chunk4SHNHNRP_cjs.AuthManager.hashPassword(newPassword);
16154
+ const passwordHash = await chunkFTXGZ3BF_cjs.AuthManager.hashPassword(newPassword);
16150
16155
  const updatePasswordStmt = db.prepare(`
16151
16156
  UPDATE auth_user SET password_hash = ?, updated_at = ? WHERE id = ?
16152
16157
  `);
@@ -16159,7 +16164,7 @@ userRoutes.put("/users/:id", async (c) => {
16159
16164
  ...sanitizedCustom !== null ? { custom: sanitizedCustom } : {}
16160
16165
  }, user.userId);
16161
16166
  }
16162
- await chunk4SHNHNRP_cjs.logActivity(
16167
+ await chunkFTXGZ3BF_cjs.logActivity(
16163
16168
  db,
16164
16169
  user.userId,
16165
16170
  "user.update",
@@ -16205,7 +16210,7 @@ userRoutes.post("/users/:id/toggle", async (c) => {
16205
16210
  UPDATE auth_user SET is_active = ?, updated_at = ? WHERE id = ?
16206
16211
  `);
16207
16212
  await toggleStmt.bind(active ? 1 : 0, Date.now(), userId).run();
16208
- await chunk4SHNHNRP_cjs.logActivity(
16213
+ await chunkFTXGZ3BF_cjs.logActivity(
16209
16214
  db,
16210
16215
  user.userId,
16211
16216
  active ? "user.activate" : "user.deactivate",
@@ -16246,7 +16251,7 @@ userRoutes.delete("/users/:id", async (c) => {
16246
16251
  DELETE FROM auth_user WHERE id = ?
16247
16252
  `);
16248
16253
  await deleteStmt.bind(userId).run();
16249
- await chunk4SHNHNRP_cjs.logActivity(
16254
+ await chunkFTXGZ3BF_cjs.logActivity(
16250
16255
  db,
16251
16256
  user.userId,
16252
16257
  "user!.hard_delete",
@@ -16265,7 +16270,7 @@ userRoutes.delete("/users/:id", async (c) => {
16265
16270
  UPDATE auth_user SET is_active = 0, updated_at = ? WHERE id = ?
16266
16271
  `);
16267
16272
  await deleteStmt.bind(Date.now(), userId).run();
16268
- await chunk4SHNHNRP_cjs.logActivity(
16273
+ await chunkFTXGZ3BF_cjs.logActivity(
16269
16274
  db,
16270
16275
  user.userId,
16271
16276
  "user!.soft_delete",
@@ -16331,7 +16336,7 @@ userRoutes.post("/invite-user", async (c) => {
16331
16336
  Date.now(),
16332
16337
  Date.now()
16333
16338
  ).run();
16334
- await chunk4SHNHNRP_cjs.logActivity(
16339
+ await chunkFTXGZ3BF_cjs.logActivity(
16335
16340
  db,
16336
16341
  user.userId,
16337
16342
  "user!.invite_sent",
@@ -16388,7 +16393,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
16388
16393
  Date.now(),
16389
16394
  userId
16390
16395
  ).run();
16391
- await chunk4SHNHNRP_cjs.logActivity(
16396
+ await chunkFTXGZ3BF_cjs.logActivity(
16392
16397
  db,
16393
16398
  user.userId,
16394
16399
  "user!.invitation_resent",
@@ -16424,7 +16429,7 @@ userRoutes.delete("/cancel-invitation/:id", async (c) => {
16424
16429
  }
16425
16430
  const deleteStmt = db.prepare(`DELETE FROM auth_user WHERE id = ?`);
16426
16431
  await deleteStmt.bind(userId).run();
16427
- await chunk4SHNHNRP_cjs.logActivity(
16432
+ await chunkFTXGZ3BF_cjs.logActivity(
16428
16433
  db,
16429
16434
  user.userId,
16430
16435
  "user!.invitation_cancelled",
@@ -17805,7 +17810,7 @@ var fileValidationSchema2 = zod.z.object({
17805
17810
  // 50MB max
17806
17811
  });
17807
17812
  var adminMediaRoutes = new hono.Hono();
17808
- adminMediaRoutes.use("*", chunk4SHNHNRP_cjs.requireAuth());
17813
+ adminMediaRoutes.use("*", chunkFTXGZ3BF_cjs.requireAuth());
17809
17814
  adminMediaRoutes.get("/", async (c) => {
17810
17815
  try {
17811
17816
  const user = c.get("user");
@@ -17817,7 +17822,7 @@ adminMediaRoutes.get("/", async (c) => {
17817
17822
  const limit = 24;
17818
17823
  const offset = (page - 1) * limit;
17819
17824
  const mediaSvc = new MediaDocumentService(c.env.DB, getRequestTenant(c));
17820
- const { files, folders: folderAgg, types: typeAgg } = await mediaSvc.list({ folder, type, limit, offset });
17825
+ const { files, total, folders: folderAgg, types: typeAgg } = await mediaSvc.list({ folder, type, limit, offset });
17821
17826
  const mediaFiles = files.map((doc) => mediaDocToFile(doc));
17822
17827
  const pageData = {
17823
17828
  files: mediaFiles,
@@ -17827,8 +17832,8 @@ adminMediaRoutes.get("/", async (c) => {
17827
17832
  currentType: type,
17828
17833
  currentView: view,
17829
17834
  currentPage: page,
17830
- totalFiles: mediaFiles.length,
17831
- hasNextPage: mediaFiles.length === limit,
17835
+ totalFiles: total,
17836
+ hasNextPage: offset + mediaFiles.length < total,
17832
17837
  user: {
17833
17838
  name: user.email,
17834
17839
  email: user.email,
@@ -17847,7 +17852,7 @@ adminMediaRoutes.get("/selector", async (c) => {
17847
17852
  const { searchParams } = new URL(c.req.url);
17848
17853
  const search = searchParams.get("search") || "";
17849
17854
  const db = c.env.DB;
17850
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
17855
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
17851
17856
  const mediaPlugin = await pluginService.getPlugin("core-media");
17852
17857
  if (!mediaPlugin || mediaPlugin.status !== "active") {
17853
17858
  return c.html(html.html`
@@ -17868,12 +17873,14 @@ adminMediaRoutes.get("/selector", async (c) => {
17868
17873
  <input
17869
17874
  type="search"
17870
17875
  id="media-selector-search"
17876
+ name="search"
17871
17877
  placeholder="Search files..."
17872
17878
  class="w-full rounded-lg bg-white dark:bg-zinc-800 px-4 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow"
17873
17879
  hx-get="/admin/media/selector"
17874
17880
  hx-trigger="keyup changed delay:300ms"
17875
17881
  hx-target="#media-selector-grid"
17876
- hx-include="[name='search']"
17882
+ hx-swap="outerHTML"
17883
+ hx-select="#media-selector-grid"
17877
17884
  >
17878
17885
  </div>
17879
17886
 
@@ -18221,7 +18228,7 @@ adminMediaRoutes.put("/:id", async (c) => {
18221
18228
  `);
18222
18229
  }
18223
18230
  });
18224
- adminMediaRoutes.delete("/cleanup", chunk4SHNHNRP_cjs.requireRole("admin"), async (c) => {
18231
+ adminMediaRoutes.delete("/cleanup", chunkFTXGZ3BF_cjs.requireRole("admin"), async (c) => {
18225
18232
  try {
18226
18233
  const db = c.env.DB;
18227
18234
  const allMediaStmt = db.prepare("SELECT id, r2_key, filename FROM media WHERE deleted_at IS NULL");
@@ -19340,7 +19347,7 @@ function escapeHtmlAttr(value) {
19340
19347
  }
19341
19348
  function renderPluginSettingsPage(data) {
19342
19349
  const { plugin, activity = [], user } = data;
19343
- const hasUserSettings = Object.keys(plugin.settings || {}).some((k) => !k.startsWith("_"));
19350
+ const hasUserSettings = plugin.id in pluginSettingsComponents || Object.keys(plugin.settings || {}).some((k) => !k.startsWith("_"));
19344
19351
  const defaultTab = hasUserSettings ? "settings" : "info";
19345
19352
  const pageContent = `
19346
19353
  <div class="w-full px-4 sm:px-6 lg:px-8 py-6">
@@ -19991,7 +19998,8 @@ function formatTimestamp(timestamp) {
19991
19998
  }
19992
19999
  var pluginSettingsComponents = {
19993
20000
  "otp-login": renderOTPLoginSettingsContent,
19994
- "email": renderEmailSettingsContent
20001
+ "email": renderEmailSettingsContent,
20002
+ "oauth-providers": renderOAuthProvidersSettingsContent
19995
20003
  };
19996
20004
  function renderOTPLoginSettingsContent(plugin, settings) {
19997
20005
  const siteName = settings.siteName || "SonicJS";
@@ -20714,11 +20722,105 @@ defineUserProfile({
20714
20722
  </div>
20715
20723
  `;
20716
20724
  }
20725
+ function renderOAuthProvidersSettingsContent(_plugin, settings) {
20726
+ const providers = settings.providers || {};
20727
+ const github = providers.github || {};
20728
+ const google = providers.google || {};
20729
+ const inputClass = "w-full px-3 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none text-white";
20730
+ function renderProviderCard(name, label, icon, data) {
20731
+ const clientId = escapeHtmlAttr(data.clientId || "");
20732
+ const clientSecret = escapeHtmlAttr(data.clientSecret || "");
20733
+ const enabled = data.enabled === true;
20734
+ return `
20735
+ <div class="backdrop-blur-md bg-white/5 rounded-xl border border-white/10 p-6">
20736
+ <div class="flex items-center justify-between mb-4">
20737
+ <h3 class="text-lg font-semibold text-white flex items-center gap-2">
20738
+ <span>${icon}</span> ${label}
20739
+ </h3>
20740
+ <label class="relative inline-flex items-center cursor-pointer">
20741
+ <input type="checkbox" id="oauth_${name}_enabled" ${enabled ? "checked" : ""} class="sr-only peer">
20742
+ <div class="w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600"></div>
20743
+ <span class="ml-2 text-sm text-gray-300">Enabled</span>
20744
+ </label>
20745
+ </div>
20746
+ <div class="space-y-4">
20747
+ <div>
20748
+ <label for="oauth_${name}_clientId" class="block text-sm font-medium text-gray-300 mb-2">Client ID</label>
20749
+ <input type="text" id="oauth_${name}_clientId" value="${clientId}" placeholder="${label} OAuth Client ID" class="${inputClass}">
20750
+ </div>
20751
+ <div>
20752
+ <label for="oauth_${name}_clientSecret" class="block text-sm font-medium text-gray-300 mb-2">Client Secret</label>
20753
+ <input type="password" id="oauth_${name}_clientSecret" value="${clientSecret}" placeholder="${label} OAuth Client Secret" class="${inputClass}">
20754
+ </div>
20755
+ </div>
20756
+ </div>
20757
+ `;
20758
+ }
20759
+ return `
20760
+ <div class="space-y-6">
20761
+ <div class="bg-blue-500/10 border border-blue-500/20 rounded-lg p-4">
20762
+ <p class="text-blue-200 text-sm">
20763
+ Configure OAuth provider credentials below. Credentials are stored securely and used server-side only.
20764
+ Make sure to add the callback URL <code class="text-blue-300">/auth/oauth/[provider]/callback</code> to your OAuth app's allowed redirect URIs.
20765
+ </p>
20766
+ </div>
20767
+
20768
+ ${renderProviderCard("github", "GitHub", "\u{1F419}", github)}
20769
+ ${renderProviderCard("google", "Google", "\u{1F535}", google)}
20770
+ </div>
20771
+
20772
+ <script>
20773
+ (function () {
20774
+ const origSave = window.saveSettings;
20775
+ window.saveSettings = async function () {
20776
+ const settings = {
20777
+ providers: {
20778
+ github: {
20779
+ clientId: document.getElementById('oauth_github_clientId').value,
20780
+ clientSecret: document.getElementById('oauth_github_clientSecret').value,
20781
+ enabled: document.getElementById('oauth_github_enabled').checked,
20782
+ },
20783
+ google: {
20784
+ clientId: document.getElementById('oauth_google_clientId').value,
20785
+ clientSecret: document.getElementById('oauth_google_clientSecret').value,
20786
+ enabled: document.getElementById('oauth_google_enabled').checked,
20787
+ },
20788
+ }
20789
+ };
20790
+
20791
+ const saveButton = document.getElementById('save-button');
20792
+ saveButton.disabled = true;
20793
+ saveButton.textContent = 'Saving...';
20794
+
20795
+ try {
20796
+ const response = await fetch('/admin/plugins/oauth-providers/settings', {
20797
+ method: 'POST',
20798
+ headers: { 'Content-Type': 'application/json' },
20799
+ body: JSON.stringify(settings),
20800
+ });
20801
+ const result = await response.json();
20802
+ if (result.success) {
20803
+ showNotification('Settings saved successfully', 'success');
20804
+ setTimeout(() => location.reload(), 1000);
20805
+ } else {
20806
+ throw new Error(result.error || 'Failed to save settings');
20807
+ }
20808
+ } catch (error) {
20809
+ showNotification(error.message, 'error');
20810
+ } finally {
20811
+ saveButton.disabled = false;
20812
+ saveButton.textContent = 'Save Settings';
20813
+ }
20814
+ };
20815
+ })();
20816
+ </script>
20817
+ `;
20818
+ }
20717
20819
 
20718
20820
  // src/routes/admin-plugins.ts
20719
20821
  var adminPluginRoutes = new hono.Hono();
20720
- adminPluginRoutes.use("*", chunk4SHNHNRP_cjs.requireAuth());
20721
- var AVAILABLE_PLUGINS = Object.values(chunk5ARIHAGN_cjs.PLUGIN_REGISTRY).map((p) => ({
20822
+ adminPluginRoutes.use("*", chunkFTXGZ3BF_cjs.requireAuth());
20823
+ var AVAILABLE_PLUGINS = Object.values(chunkPYZYU7EK_cjs.PLUGIN_REGISTRY).map((p) => ({
20722
20824
  id: p.id,
20723
20825
  name: p.codeName,
20724
20826
  display_name: p.displayName,
@@ -20738,7 +20840,7 @@ adminPluginRoutes.get("/", async (c) => {
20738
20840
  if (user?.role !== "admin") {
20739
20841
  return c.text("Access denied", 403);
20740
20842
  }
20741
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
20843
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
20742
20844
  let installedPlugins = [];
20743
20845
  let stats = { total: 0, active: 0, inactive: 0, errors: 0, uninstalled: 0 };
20744
20846
  try {
@@ -20810,10 +20912,10 @@ adminPluginRoutes.get("/:id", async (c) => {
20810
20912
  if (user?.role !== "admin") {
20811
20913
  return c.redirect("/admin/plugins");
20812
20914
  }
20813
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
20915
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
20814
20916
  let plugin = await pluginService.getPlugin(pluginId);
20815
20917
  if (!plugin) {
20816
- const def = chunk5RSB5SEK_cjs.getPluginDefinition(pluginId);
20918
+ const def = chunkEUJAEB6W_cjs.getPluginDefinition(pluginId);
20817
20919
  if (!def) return c.text("Plugin not found", 404);
20818
20920
  plugin = await pluginService.ensurePlugin(pluginId, {
20819
20921
  displayName: def.displayName ?? pluginId,
@@ -20904,14 +21006,14 @@ adminPluginRoutes.get("/:id/configure", async (c) => {
20904
21006
  const user = c.get("user");
20905
21007
  const pluginId = c.req.param("id");
20906
21008
  if (user?.role !== "admin") return c.redirect("/admin/plugins");
20907
- const def = chunk5RSB5SEK_cjs.getPluginDefinition(pluginId);
21009
+ const def = chunkEUJAEB6W_cjs.getPluginDefinition(pluginId);
20908
21010
  if (!def?.configSchema) return c.text("No schema-driven settings for this plugin", 404);
20909
21011
  const db = c.env.DB;
20910
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
21012
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
20911
21013
  const plugin = await pluginService.getPlugin(pluginId);
20912
21014
  const stored = plugin?.settings ?? {};
20913
- const values = chunk5RSB5SEK_cjs.applySchemaDefaults(def.configSchema, stored);
20914
- const fieldsHtml = chunk5RSB5SEK_cjs.renderSchemaFields(def.configSchema, values);
21015
+ const values = chunkEUJAEB6W_cjs.applySchemaDefaults(def.configSchema, stored);
21016
+ const fieldsHtml = chunkEUJAEB6W_cjs.renderSchemaFields(def.configSchema, values);
20915
21017
  const displayName = plugin?.display_name ?? def.displayName ?? def.id;
20916
21018
  return c.html(`<!DOCTYPE html>
20917
21019
  <html lang="en"><head>
@@ -20938,12 +21040,12 @@ adminPluginRoutes.post("/:id/configure", async (c) => {
20938
21040
  const user = c.get("user");
20939
21041
  const pluginId = c.req.param("id");
20940
21042
  if (user?.role !== "admin") return c.json({ error: "Access denied" }, 403);
20941
- const def = chunk5RSB5SEK_cjs.getPluginDefinition(pluginId);
21043
+ const def = chunkEUJAEB6W_cjs.getPluginDefinition(pluginId);
20942
21044
  if (!def?.configSchema) return c.text("No schema-driven settings for this plugin", 404);
20943
21045
  const form = await c.req.formData();
20944
- const parsed = chunk5RSB5SEK_cjs.parseFormDataToSettings(def.configSchema, form);
21046
+ const parsed = chunkEUJAEB6W_cjs.parseFormDataToSettings(def.configSchema, form);
20945
21047
  const db = c.env.DB;
20946
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
21048
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
20947
21049
  await pluginService.ensurePlugin(pluginId, {
20948
21050
  displayName: def.displayName ?? pluginId,
20949
21051
  version: def.version,
@@ -20967,7 +21069,7 @@ adminPluginRoutes.post("/:id/activate", async (c) => {
20967
21069
  if (user?.role !== "admin") {
20968
21070
  return c.json({ error: "Access denied" }, 403);
20969
21071
  }
20970
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
21072
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
20971
21073
  await pluginService.activatePlugin(pluginId);
20972
21074
  return c.json({ success: true });
20973
21075
  } catch (error) {
@@ -20984,7 +21086,7 @@ adminPluginRoutes.post("/:id/deactivate", async (c) => {
20984
21086
  if (user?.role !== "admin") {
20985
21087
  return c.json({ error: "Access denied" }, 403);
20986
21088
  }
20987
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
21089
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
20988
21090
  await pluginService.deactivatePlugin(pluginId);
20989
21091
  return c.json({ success: true });
20990
21092
  } catch (error) {
@@ -21001,8 +21103,8 @@ adminPluginRoutes.post("/install", async (c) => {
21001
21103
  return c.json({ error: "Access denied" }, 403);
21002
21104
  }
21003
21105
  const body = await c.req.json();
21004
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
21005
- const registryEntry = chunk5ARIHAGN_cjs.findPluginByCodeName(body.name) || chunk5ARIHAGN_cjs.PLUGIN_REGISTRY[body.name] || chunk5ARIHAGN_cjs.PLUGIN_REGISTRY[body.id];
21106
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
21107
+ const registryEntry = chunkPYZYU7EK_cjs.findPluginByCodeName(body.name) || chunkPYZYU7EK_cjs.PLUGIN_REGISTRY[body.name] || chunkPYZYU7EK_cjs.PLUGIN_REGISTRY[body.id];
21006
21108
  if (!registryEntry) {
21007
21109
  return c.json({ error: "Plugin not found in registry" }, 404);
21008
21110
  }
@@ -21035,7 +21137,7 @@ adminPluginRoutes.post("/:id/uninstall", async (c) => {
21035
21137
  if (user?.role !== "admin") {
21036
21138
  return c.json({ error: "Access denied" }, 403);
21037
21139
  }
21038
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
21140
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
21039
21141
  await pluginService.uninstallPlugin(pluginId);
21040
21142
  return c.json({ success: true });
21041
21143
  } catch (error) {
@@ -21053,8 +21155,10 @@ adminPluginRoutes.post("/:id/settings", async (c) => {
21053
21155
  return c.json({ error: "Access denied" }, 403);
21054
21156
  }
21055
21157
  const settings = await c.req.json();
21056
- const pluginService = new chunk5ARIHAGN_cjs.PluginService(db);
21057
- await pluginService.updatePluginSettings(pluginId, settings);
21158
+ const pluginService = new chunkPYZYU7EK_cjs.PluginService(db);
21159
+ const existingPlugin = await pluginService.getPlugin(pluginId);
21160
+ const existingSettings = existingPlugin?.settings ?? {};
21161
+ await pluginService.updatePluginSettings(pluginId, { ...existingSettings, ...settings });
21058
21162
  if (pluginId === "core-auth") {
21059
21163
  try {
21060
21164
  const cacheKv = c.env.CACHE_KV;
@@ -21861,7 +21965,7 @@ function renderLogConfigPage(data) {
21861
21965
 
21862
21966
  // src/routes/admin-logs.ts
21863
21967
  var adminLogsRoutes = new hono.Hono();
21864
- adminLogsRoutes.use("*", chunk4SHNHNRP_cjs.requireAuth());
21968
+ adminLogsRoutes.use("*", chunkFTXGZ3BF_cjs.requireAuth());
21865
21969
  adminLogsRoutes.get("/", async (c) => {
21866
21970
  try {
21867
21971
  const user = c.get("user");
@@ -22853,9 +22957,9 @@ function renderStorageUsage(databaseSizeBytes, mediaSizeBytes) {
22853
22957
  }
22854
22958
 
22855
22959
  // src/routes/admin-dashboard.ts
22856
- var VERSION = chunkAQJEMVAY_cjs.getCoreVersion();
22960
+ var VERSION = chunkQWSR4THH_cjs.getCoreVersion();
22857
22961
  var router = new hono.Hono();
22858
- router.use("*", chunk4SHNHNRP_cjs.requireAuth());
22962
+ router.use("*", chunkFTXGZ3BF_cjs.requireAuth());
22859
22963
  router.get("/", async (c) => {
22860
22964
  const user = c.get("user");
22861
22965
  try {
@@ -24820,7 +24924,7 @@ function renderCollectionFormPage(data) {
24820
24924
  // src/routes/admin-collections.ts
24821
24925
  chunkK623Q6WD_cjs.init_admin_layout_catalyst_template();
24822
24926
  var adminCollectionsRoutes = new hono.Hono();
24823
- adminCollectionsRoutes.use("*", chunk4SHNHNRP_cjs.requireAuth());
24927
+ adminCollectionsRoutes.use("*", chunkFTXGZ3BF_cjs.requireAuth());
24824
24928
  adminCollectionsRoutes.get("/", async (c) => {
24825
24929
  try {
24826
24930
  const user = c.get("user");
@@ -24837,7 +24941,7 @@ adminCollectionsRoutes.get("/", async (c) => {
24837
24941
  results = queryResults.results ?? [];
24838
24942
  } catch (e) {
24839
24943
  }
24840
- const codeCollections = chunk5ARIHAGN_cjs.getCollectionRegistry().list();
24944
+ const codeCollections = chunkPYZYU7EK_cjs.getCollectionRegistry().list();
24841
24945
  const codeCollectionsMap = new Map(
24842
24946
  codeCollections.map((cfg) => {
24843
24947
  const fieldCount = cfg.schema?.properties ? Object.keys(cfg.schema.properties).length : 0;
@@ -24851,7 +24955,7 @@ adminCollectionsRoutes.get("/", async (c) => {
24851
24955
  field_count: fieldCount,
24852
24956
  managed: cfg.managed !== false,
24853
24957
  source_type: "code",
24854
- internal: chunk5ARIHAGN_cjs.isCodeCollectionInternal(cfg),
24958
+ internal: chunkPYZYU7EK_cjs.isCodeCollectionInternal(cfg),
24855
24959
  versioning: cfg.versioning === true
24856
24960
  }];
24857
24961
  })
@@ -24890,7 +24994,7 @@ adminCollectionsRoutes.get("/", async (c) => {
24890
24994
  field_count: fieldCount,
24891
24995
  managed: false,
24892
24996
  source_type: row.source === "code" || row.source === "system" || row.source === "plugin" ? "code" : "user",
24893
- internal: chunk5ARIHAGN_cjs.isDbDocTypeInternal(row.source),
24997
+ internal: chunkPYZYU7EK_cjs.isDbDocTypeInternal(row.source),
24894
24998
  versioning: dbVersioning
24895
24999
  };
24896
25000
  });
@@ -25051,7 +25155,7 @@ export const myPlugin = definePlugin({
25051
25155
  title: "Add a Collection",
25052
25156
  pageTitle: "Add a Collection",
25053
25157
  currentPath: "/admin/collections",
25054
- version: chunkAQJEMVAY_cjs.getCoreVersion(),
25158
+ version: chunkQWSR4THH_cjs.getCoreVersion(),
25055
25159
  user: u ? { name: u.email ?? "Admin", email: u.email ?? "", role: u.role ?? "admin" } : void 0,
25056
25160
  content
25057
25161
  })
@@ -25068,7 +25172,7 @@ adminCollectionsRoutes.get("/:id", async (c) => {
25068
25172
  collection = await stmt.bind(id).first();
25069
25173
  } catch {
25070
25174
  }
25071
- const registryRecord = chunk5ARIHAGN_cjs.getCollectionRegistry().getById(id) ?? chunk5ARIHAGN_cjs.getCollectionRegistry().getByName(id);
25175
+ const registryRecord = chunkPYZYU7EK_cjs.getCollectionRegistry().getById(id) ?? chunkPYZYU7EK_cjs.getCollectionRegistry().getByName(id);
25072
25176
  if (!collection && !registryRecord) {
25073
25177
  const formData2 = {
25074
25178
  isEdit: true,
@@ -25115,9 +25219,9 @@ adminCollectionsRoutes.get("/:id", async (c) => {
25115
25219
  isCodeDriven = true;
25116
25220
  }
25117
25221
  const [tinymceActive, quillActive, mdxeditorActive] = await Promise.all([
25118
- chunk4SHNHNRP_cjs.isPluginActive(db, "tinymce-plugin"),
25119
- chunk4SHNHNRP_cjs.isPluginActive(db, "quill-editor"),
25120
- chunk4SHNHNRP_cjs.isPluginActive(db, "easy-mdx")
25222
+ chunkFTXGZ3BF_cjs.isPluginActive(db, "tinymce-plugin"),
25223
+ chunkFTXGZ3BF_cjs.isPluginActive(db, "quill-editor"),
25224
+ chunkFTXGZ3BF_cjs.isPluginActive(db, "easy-mdx")
25121
25225
  ]);
25122
25226
  const displayName = collection?.display_name ?? registryRecord?.displayName ?? id;
25123
25227
  const formData = {
@@ -25137,9 +25241,9 @@ adminCollectionsRoutes.get("/:id", async (c) => {
25137
25241
  console.error("Error fetching collection:", error);
25138
25242
  const user = c.get("user");
25139
25243
  const [tinymceActive, quillActive, mdxeditorActive] = await Promise.all([
25140
- chunk4SHNHNRP_cjs.isPluginActive(db, "tinymce-plugin"),
25141
- chunk4SHNHNRP_cjs.isPluginActive(db, "quill-editor"),
25142
- chunk4SHNHNRP_cjs.isPluginActive(db, "easy-mdx")
25244
+ chunkFTXGZ3BF_cjs.isPluginActive(db, "tinymce-plugin"),
25245
+ chunkFTXGZ3BF_cjs.isPluginActive(db, "quill-editor"),
25246
+ chunkFTXGZ3BF_cjs.isPluginActive(db, "easy-mdx")
25143
25247
  ]);
25144
25248
  const formData = {
25145
25249
  isEdit: true,
@@ -26088,7 +26192,7 @@ function renderDatabaseToolsSettings(settings) {
26088
26192
 
26089
26193
  // src/routes/admin-settings.ts
26090
26194
  var adminSettingsRoutes = new hono.Hono();
26091
- adminSettingsRoutes.use("*", chunk4SHNHNRP_cjs.requireAuth());
26195
+ adminSettingsRoutes.use("*", chunkFTXGZ3BF_cjs.requireAuth());
26092
26196
  function getMockSettings(user) {
26093
26197
  return {
26094
26198
  general: {
@@ -26191,7 +26295,7 @@ adminSettingsRoutes.get("/database-tools", (c) => {
26191
26295
  adminSettingsRoutes.get("/api/migrations/status", async (c) => {
26192
26296
  try {
26193
26297
  const db = c.env.DB;
26194
- const migrationService = new chunkTQG5FNNR_cjs.MigrationService(db);
26298
+ const migrationService = new chunk3CT3SUR4_cjs.MigrationService(db);
26195
26299
  const status = await migrationService.getMigrationStatus();
26196
26300
  return c.json({
26197
26301
  success: true,
@@ -26231,7 +26335,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
26231
26335
  adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
26232
26336
  try {
26233
26337
  const db = c.env.DB;
26234
- const migrationService = new chunkTQG5FNNR_cjs.MigrationService(db);
26338
+ const migrationService = new chunk3CT3SUR4_cjs.MigrationService(db);
26235
26339
  const validation = await migrationService.validateSchema();
26236
26340
  return c.json({
26237
26341
  success: true,
@@ -26824,16 +26928,16 @@ function renderAPIReferencePage(data) {
26824
26928
  }
26825
26929
 
26826
26930
  // src/routes/admin-api-reference.ts
26827
- var VERSION2 = chunkAQJEMVAY_cjs.getCoreVersion();
26931
+ var VERSION2 = chunkQWSR4THH_cjs.getCoreVersion();
26828
26932
  var router2 = new hono.Hono();
26829
- router2.use("*", chunk4SHNHNRP_cjs.requireAuth());
26933
+ router2.use("*", chunkFTXGZ3BF_cjs.requireAuth());
26830
26934
  router2.get("/", async (c) => {
26831
26935
  const user = c.get("user");
26832
26936
  try {
26833
26937
  const app2 = chunk36Z3AKX3_cjs.getAppInstance();
26834
26938
  const baseEndpoints = chunk36Z3AKX3_cjs.buildRouteList(app2);
26835
26939
  const collectionRoutes = [];
26836
- const collections = chunk5ARIHAGN_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
26940
+ const collections = chunkPYZYU7EK_cjs.getCollectionRegistry().listActive().filter((r) => !r.internal);
26837
26941
  const methodOrder = { GET: 0, POST: 1, PUT: 2, PATCH: 3, DELETE: 4 };
26838
26942
  for (const col of collections) {
26839
26943
  const displayName = col.displayName || col.name;
@@ -26950,5 +27054,5 @@ exports.setVariablesCache = setVariablesCache;
26950
27054
  exports.test_cleanup_default = test_cleanup_default;
26951
27055
  exports.userProfilesPlugin = userProfilesPlugin;
26952
27056
  exports.userRoutes = userRoutes;
26953
- //# sourceMappingURL=chunk-3E7IROND.cjs.map
26954
- //# sourceMappingURL=chunk-3E7IROND.cjs.map
27057
+ //# sourceMappingURL=chunk-JFLZHOQP.cjs.map
27058
+ //# sourceMappingURL=chunk-JFLZHOQP.cjs.map