@sonicjs-cms/core 2.16.1 → 2.17.0

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 (61) hide show
  1. package/dist/{app-D9L3mrC-.d.cts → app-C9esKLmh.d.cts} +2 -0
  2. package/dist/{app-D9L3mrC-.d.ts → app-C9esKLmh.d.ts} +2 -0
  3. package/dist/{chunk-U6FOL6EO.cjs → chunk-4HCUJ3MG.cjs} +34 -6
  4. package/dist/chunk-4HCUJ3MG.cjs.map +1 -0
  5. package/dist/{chunk-JF5RQXPN.js → chunk-6F57Z6SD.js} +3 -3
  6. package/dist/{chunk-JF5RQXPN.js.map → chunk-6F57Z6SD.js.map} +1 -1
  7. package/dist/{chunk-W33MHOPA.js → chunk-FDXNIZ6N.js} +34 -6
  8. package/dist/chunk-FDXNIZ6N.js.map +1 -0
  9. package/dist/{chunk-HU4MN74Q.cjs → chunk-FSWP4FBW.cjs} +2 -2
  10. package/dist/{chunk-HU4MN74Q.cjs.map → chunk-FSWP4FBW.cjs.map} +1 -1
  11. package/dist/{chunk-MZS33LLH.cjs → chunk-J5MYHM6Z.cjs} +352 -176
  12. package/dist/chunk-J5MYHM6Z.cjs.map +1 -0
  13. package/dist/{chunk-BAMJVG33.js → chunk-LZJLWW7E.js} +227 -51
  14. package/dist/chunk-LZJLWW7E.js.map +1 -0
  15. package/dist/{chunk-PUZMLXOJ.js → chunk-NMJT6BJR.js} +2 -2
  16. package/dist/{chunk-PUZMLXOJ.js.map → chunk-NMJT6BJR.js.map} +1 -1
  17. package/dist/{chunk-V76ERLX6.cjs → chunk-QBLBIAVZ.cjs} +3 -3
  18. package/dist/{chunk-V76ERLX6.cjs.map → chunk-QBLBIAVZ.cjs.map} +1 -1
  19. package/dist/{chunk-TBJY2FF7.js → chunk-QFWHAFEO.js} +22 -2
  20. package/dist/chunk-QFWHAFEO.js.map +1 -0
  21. package/dist/{chunk-7HHIZQNE.cjs → chunk-RE3NVA23.cjs} +155 -17
  22. package/dist/chunk-RE3NVA23.cjs.map +1 -0
  23. package/dist/{chunk-KYAF33AF.js → chunk-S7K4FRJ2.js} +149 -14
  24. package/dist/chunk-S7K4FRJ2.js.map +1 -0
  25. package/dist/{chunk-NZWFCUDA.cjs → chunk-WAEQXGCX.cjs} +22 -2
  26. package/dist/chunk-WAEQXGCX.cjs.map +1 -0
  27. package/dist/index.cjs +194 -186
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +1 -1
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.js +30 -22
  32. package/dist/index.js.map +1 -1
  33. package/dist/middleware.cjs +41 -29
  34. package/dist/middleware.d.cts +38 -4
  35. package/dist/middleware.d.ts +38 -4
  36. package/dist/middleware.js +3 -3
  37. package/dist/migrations-HQI62CAO.js +4 -0
  38. package/dist/{migrations-WCEBO5QQ.js.map → migrations-HQI62CAO.js.map} +1 -1
  39. package/dist/migrations-ZYPYVSXI.cjs +13 -0
  40. package/dist/{migrations-MYQI2KAJ.cjs.map → migrations-ZYPYVSXI.cjs.map} +1 -1
  41. package/dist/routes.cjs +29 -29
  42. package/dist/routes.d.cts +1 -1
  43. package/dist/routes.d.ts +1 -1
  44. package/dist/routes.js +6 -6
  45. package/dist/services.cjs +39 -39
  46. package/dist/services.d.cts +12 -0
  47. package/dist/services.d.ts +12 -0
  48. package/dist/services.js +3 -3
  49. package/dist/utils.cjs +11 -11
  50. package/dist/utils.js +1 -1
  51. package/package.json +1 -1
  52. package/dist/chunk-7HHIZQNE.cjs.map +0 -1
  53. package/dist/chunk-BAMJVG33.js.map +0 -1
  54. package/dist/chunk-KYAF33AF.js.map +0 -1
  55. package/dist/chunk-MZS33LLH.cjs.map +0 -1
  56. package/dist/chunk-NZWFCUDA.cjs.map +0 -1
  57. package/dist/chunk-TBJY2FF7.js.map +0 -1
  58. package/dist/chunk-U6FOL6EO.cjs.map +0 -1
  59. package/dist/chunk-W33MHOPA.js.map +0 -1
  60. package/dist/migrations-MYQI2KAJ.cjs +0 -13
  61. package/dist/migrations-WCEBO5QQ.js +0 -4
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var chunkNZWFCUDA_cjs = require('./chunk-NZWFCUDA.cjs');
4
- var chunk7HHIZQNE_cjs = require('./chunk-7HHIZQNE.cjs');
5
- var chunkU6FOL6EO_cjs = require('./chunk-U6FOL6EO.cjs');
6
- var chunkHU4MN74Q_cjs = require('./chunk-HU4MN74Q.cjs');
3
+ var chunkWAEQXGCX_cjs = require('./chunk-WAEQXGCX.cjs');
4
+ var chunkRE3NVA23_cjs = require('./chunk-RE3NVA23.cjs');
5
+ var chunk4HCUJ3MG_cjs = require('./chunk-4HCUJ3MG.cjs');
6
+ var chunkFSWP4FBW_cjs = require('./chunk-FSWP4FBW.cjs');
7
7
  var chunkOHYBNCVL_cjs = require('./chunk-OHYBNCVL.cjs');
8
8
  var chunkUYJ6TJHX_cjs = require('./chunk-UYJ6TJHX.cjs');
9
9
  var chunk635JAMSE_cjs = require('./chunk-635JAMSE.cjs');
10
- var chunkV76ERLX6_cjs = require('./chunk-V76ERLX6.cjs');
10
+ var chunkQBLBIAVZ_cjs = require('./chunk-QBLBIAVZ.cjs');
11
11
  var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
12
12
  var chunkMNWKYY5E_cjs = require('./chunk-MNWKYY5E.cjs');
13
13
  var hono = require('hono');
@@ -189,7 +189,7 @@ apiContentCrudRoutes.get("/:id", async (c) => {
189
189
  }, 500);
190
190
  }
191
191
  });
192
- apiContentCrudRoutes.post("/", chunk7HHIZQNE_cjs.requireAuth(), chunk7HHIZQNE_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
192
+ apiContentCrudRoutes.post("/", chunkRE3NVA23_cjs.requireAuth(), chunkRE3NVA23_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
193
193
  try {
194
194
  const db = c.env.DB;
195
195
  const user = c.get("user");
@@ -230,7 +230,7 @@ apiContentCrudRoutes.post("/", chunk7HHIZQNE_cjs.requireAuth(), chunk7HHIZQNE_cj
230
230
  now,
231
231
  now
232
232
  ).run();
233
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.api);
233
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.api);
234
234
  await cache.invalidate(`content:list:${collectionId}:*`);
235
235
  await cache.invalidate("content-filtered:*");
236
236
  const getStmt = db.prepare("SELECT * FROM content WHERE id = ?");
@@ -255,7 +255,7 @@ apiContentCrudRoutes.post("/", chunk7HHIZQNE_cjs.requireAuth(), chunk7HHIZQNE_cj
255
255
  }, 500);
256
256
  }
257
257
  });
258
- apiContentCrudRoutes.put("/:id", chunk7HHIZQNE_cjs.requireAuth(), chunk7HHIZQNE_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
258
+ apiContentCrudRoutes.put("/:id", chunkRE3NVA23_cjs.requireAuth(), chunkRE3NVA23_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
259
259
  try {
260
260
  const id = c.req.param("id");
261
261
  const db = c.env.DB;
@@ -293,7 +293,7 @@ apiContentCrudRoutes.put("/:id", chunk7HHIZQNE_cjs.requireAuth(), chunk7HHIZQNE_
293
293
  WHERE id = ?
294
294
  `);
295
295
  await updateStmt.bind(...params).run();
296
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.api);
296
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.api);
297
297
  await cache.delete(cache.generateKey("content", id));
298
298
  await cache.invalidate(`content:list:${existing.collection_id}:*`);
299
299
  await cache.invalidate("content-filtered:*");
@@ -319,7 +319,7 @@ apiContentCrudRoutes.put("/:id", chunk7HHIZQNE_cjs.requireAuth(), chunk7HHIZQNE_
319
319
  }, 500);
320
320
  }
321
321
  });
322
- apiContentCrudRoutes.delete("/:id", chunk7HHIZQNE_cjs.requireAuth(), chunk7HHIZQNE_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
322
+ apiContentCrudRoutes.delete("/:id", chunkRE3NVA23_cjs.requireAuth(), chunkRE3NVA23_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
323
323
  try {
324
324
  const id = c.req.param("id");
325
325
  const db = c.env.DB;
@@ -330,7 +330,7 @@ apiContentCrudRoutes.delete("/:id", chunk7HHIZQNE_cjs.requireAuth(), chunk7HHIZQ
330
330
  }
331
331
  const deleteStmt = db.prepare("DELETE FROM content WHERE id = ?");
332
332
  await deleteStmt.bind(id).run();
333
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.api);
333
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.api);
334
334
  await cache.delete(cache.generateKey("content", id));
335
335
  await cache.invalidate(`content:list:${existing.collection_id}:*`);
336
336
  await cache.invalidate("content-filtered:*");
@@ -355,7 +355,7 @@ apiRoutes.use("*", async (c, next) => {
355
355
  c.header("X-Response-Time", `${totalTime}ms`);
356
356
  });
357
357
  apiRoutes.use("*", async (c, next) => {
358
- const cacheEnabled = await chunk7HHIZQNE_cjs.isPluginActive(c.env.DB, "core-cache");
358
+ const cacheEnabled = await chunkRE3NVA23_cjs.isPluginActive(c.env.DB, "core-cache");
359
359
  c.set("cacheEnabled", cacheEnabled);
360
360
  await next();
361
361
  });
@@ -792,7 +792,7 @@ apiRoutes.get("/collections", async (c) => {
792
792
  try {
793
793
  const db = c.env.DB;
794
794
  const cacheEnabled = c.get("cacheEnabled");
795
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.api);
795
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.api);
796
796
  const cacheKey = cache.generateKey("collections", "all");
797
797
  if (cacheEnabled) {
798
798
  const cacheResult = await cache.getWithSource(cacheKey);
@@ -846,7 +846,7 @@ apiRoutes.get("/collections", async (c) => {
846
846
  return c.json({ error: "Failed to fetch collections" }, 500);
847
847
  }
848
848
  });
849
- apiRoutes.get("/content", chunk7HHIZQNE_cjs.optionalAuth(), async (c) => {
849
+ apiRoutes.get("/content", chunkRE3NVA23_cjs.optionalAuth(), async (c) => {
850
850
  const executionStart = Date.now();
851
851
  try {
852
852
  const db = c.env.DB;
@@ -869,13 +869,13 @@ apiRoutes.get("/content", chunk7HHIZQNE_cjs.optionalAuth(), async (c) => {
869
869
  });
870
870
  }
871
871
  }
872
- const filter = chunkV76ERLX6_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
872
+ const filter = chunkQBLBIAVZ_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
873
873
  const normalizedFilter = normalizePublicContentFilter(filter, c.get("user")?.role);
874
874
  if (!normalizedFilter.limit) {
875
875
  normalizedFilter.limit = 50;
876
876
  }
877
877
  normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
878
- const builder3 = new chunkV76ERLX6_cjs.QueryFilterBuilder();
878
+ const builder3 = new chunkQBLBIAVZ_cjs.QueryFilterBuilder();
879
879
  const queryResult = builder3.build("content", normalizedFilter);
880
880
  if (queryResult.errors.length > 0) {
881
881
  return c.json({
@@ -884,7 +884,7 @@ apiRoutes.get("/content", chunk7HHIZQNE_cjs.optionalAuth(), async (c) => {
884
884
  }, 400);
885
885
  }
886
886
  const cacheEnabled = c.get("cacheEnabled");
887
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.api);
887
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.api);
888
888
  const cacheKey = cache.generateKey("content-filtered", JSON.stringify({ filter: normalizedFilter, query: queryResult.sql }));
889
889
  if (cacheEnabled) {
890
890
  const cacheResult = await cache.getWithSource(cacheKey);
@@ -947,7 +947,7 @@ apiRoutes.get("/content", chunk7HHIZQNE_cjs.optionalAuth(), async (c) => {
947
947
  }, 500);
948
948
  }
949
949
  });
950
- apiRoutes.get("/collections/:collection/content", chunk7HHIZQNE_cjs.optionalAuth(), async (c) => {
950
+ apiRoutes.get("/collections/:collection/content", chunkRE3NVA23_cjs.optionalAuth(), async (c) => {
951
951
  const executionStart = Date.now();
952
952
  try {
953
953
  const collection = c.req.param("collection");
@@ -958,7 +958,7 @@ apiRoutes.get("/collections/:collection/content", chunk7HHIZQNE_cjs.optionalAuth
958
958
  if (!collectionResult) {
959
959
  return c.json({ error: "Collection not found" }, 404);
960
960
  }
961
- const filter = chunkV76ERLX6_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
961
+ const filter = chunkQBLBIAVZ_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
962
962
  const normalizedFilter = normalizePublicContentFilter(filter, c.get("user")?.role);
963
963
  if (!normalizedFilter.where) {
964
964
  normalizedFilter.where = { and: [] };
@@ -975,7 +975,7 @@ apiRoutes.get("/collections/:collection/content", chunk7HHIZQNE_cjs.optionalAuth
975
975
  normalizedFilter.limit = 50;
976
976
  }
977
977
  normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
978
- const builder3 = new chunkV76ERLX6_cjs.QueryFilterBuilder();
978
+ const builder3 = new chunkQBLBIAVZ_cjs.QueryFilterBuilder();
979
979
  const queryResult = builder3.build("content", normalizedFilter);
980
980
  if (queryResult.errors.length > 0) {
981
981
  return c.json({
@@ -984,7 +984,7 @@ apiRoutes.get("/collections/:collection/content", chunk7HHIZQNE_cjs.optionalAuth
984
984
  }, 400);
985
985
  }
986
986
  const cacheEnabled = c.get("cacheEnabled");
987
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.api);
987
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.api);
988
988
  const cacheKey = cache.generateKey("collection-content-filtered", `${collection}:${JSON.stringify({ filter: normalizedFilter, query: queryResult.sql })}`);
989
989
  if (cacheEnabled) {
990
990
  const cacheResult = await cache.getWithSource(cacheKey);
@@ -1096,7 +1096,7 @@ var fileValidationSchema = zod.z.object({
1096
1096
  // 50MB max
1097
1097
  });
1098
1098
  var apiMediaRoutes = new hono.Hono();
1099
- apiMediaRoutes.use("*", chunk7HHIZQNE_cjs.requireAuth());
1099
+ apiMediaRoutes.use("*", chunkRE3NVA23_cjs.requireAuth());
1100
1100
  apiMediaRoutes.post("/upload", async (c) => {
1101
1101
  try {
1102
1102
  const user = c.get("user");
@@ -1840,8 +1840,8 @@ apiSystemRoutes.get("/env", (c) => {
1840
1840
  });
1841
1841
  var api_system_default = apiSystemRoutes;
1842
1842
  var adminApiRoutes = new hono.Hono();
1843
- adminApiRoutes.use("*", chunk7HHIZQNE_cjs.requireAuth());
1844
- adminApiRoutes.use("*", chunk7HHIZQNE_cjs.requireRole(["admin", "editor"]));
1843
+ adminApiRoutes.use("*", chunkRE3NVA23_cjs.requireAuth());
1844
+ adminApiRoutes.use("*", chunkRE3NVA23_cjs.requireRole(["admin", "editor"]));
1845
1845
  adminApiRoutes.get("/stats", async (c) => {
1846
1846
  try {
1847
1847
  const db = c.env.DB;
@@ -2353,7 +2353,7 @@ adminApiRoutes.delete("/collections/:id", async (c) => {
2353
2353
  });
2354
2354
  adminApiRoutes.get("/migrations/status", async (c) => {
2355
2355
  try {
2356
- const { MigrationService: MigrationService2 } = await import('./migrations-MYQI2KAJ.cjs');
2356
+ const { MigrationService: MigrationService2 } = await import('./migrations-ZYPYVSXI.cjs');
2357
2357
  const db = c.env.DB;
2358
2358
  const migrationService = new MigrationService2(db);
2359
2359
  const status = await migrationService.getMigrationStatus();
@@ -2378,7 +2378,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
2378
2378
  error: "Unauthorized. Admin access required."
2379
2379
  }, 403);
2380
2380
  }
2381
- const { MigrationService: MigrationService2 } = await import('./migrations-MYQI2KAJ.cjs');
2381
+ const { MigrationService: MigrationService2 } = await import('./migrations-ZYPYVSXI.cjs');
2382
2382
  const db = c.env.DB;
2383
2383
  const migrationService = new MigrationService2(db);
2384
2384
  const result = await migrationService.runPendingMigrations();
@@ -2400,7 +2400,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
2400
2400
  });
2401
2401
  adminApiRoutes.get("/migrations/validate", async (c) => {
2402
2402
  try {
2403
- const { MigrationService: MigrationService2 } = await import('./migrations-MYQI2KAJ.cjs');
2403
+ const { MigrationService: MigrationService2 } = await import('./migrations-ZYPYVSXI.cjs');
2404
2404
  const db = c.env.DB;
2405
2405
  const migrationService = new MigrationService2(db);
2406
2406
  const validation = await migrationService.validateSchema();
@@ -5150,16 +5150,17 @@ var userProfilesPlugin = createUserProfilesPlugin();
5150
5150
 
5151
5151
  // src/routes/auth.ts
5152
5152
  var JWT_SECRET_FALLBACK = "your-super-secret-jwt-key-change-in-production";
5153
- async function setCsrfCookie(c) {
5153
+ async function setCsrfCookie(c, maxAge) {
5154
5154
  const secret = c.env?.JWT_SECRET || JWT_SECRET_FALLBACK;
5155
5155
  const isDev = c.env?.ENVIRONMENT === "development" || !c.env?.ENVIRONMENT;
5156
- const csrfToken = await chunk7HHIZQNE_cjs.generateCsrfToken(secret);
5156
+ const csrfToken = await chunkRE3NVA23_cjs.generateCsrfToken(secret);
5157
+ const cookieMaxAge = await chunkRE3NVA23_cjs.getJwtExpirySecondsFromDb(c.env?.DB, c.env);
5157
5158
  cookie.setCookie(c, "csrf_token", csrfToken, {
5158
5159
  httpOnly: false,
5159
5160
  secure: !isDev,
5160
5161
  sameSite: "Strict",
5161
5162
  path: "/",
5162
- maxAge: 86400
5163
+ maxAge: cookieMaxAge
5163
5164
  });
5164
5165
  }
5165
5166
  function clearCsrfCookie(c) {
@@ -5210,7 +5211,7 @@ var loginSchema = zod.z.object({
5210
5211
  });
5211
5212
  authRoutes.post(
5212
5213
  "/register",
5213
- chunk7HHIZQNE_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
5214
+ chunkRE3NVA23_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
5214
5215
  async (c) => {
5215
5216
  try {
5216
5217
  const db = c.env.DB;
@@ -5247,7 +5248,7 @@ authRoutes.post(
5247
5248
  if (existingUser) {
5248
5249
  return c.json({ error: "User with this email or username already exists" }, 400);
5249
5250
  }
5250
- const passwordHash = await chunk7HHIZQNE_cjs.AuthManager.hashPassword(password);
5251
+ const passwordHash = await chunkRE3NVA23_cjs.AuthManager.hashPassword(password);
5251
5252
  const userId = crypto.randomUUID();
5252
5253
  const now = /* @__PURE__ */ new Date();
5253
5254
  await db.prepare(`
@@ -5281,13 +5282,13 @@ authRoutes.post(
5281
5282
  await saveCustomData(db, userId, sanitized);
5282
5283
  }
5283
5284
  }
5284
- const token = await chunk7HHIZQNE_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer", c.env.JWT_SECRET);
5285
+ const tokenTtl = await chunkRE3NVA23_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
5286
+ const token = await chunkRE3NVA23_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer", c.env.JWT_SECRET, tokenTtl);
5285
5287
  cookie.setCookie(c, "auth_token", token, {
5286
5288
  httpOnly: true,
5287
5289
  secure: true,
5288
5290
  sameSite: "Strict",
5289
- maxAge: 60 * 60 * 24
5290
- // 24 hours
5291
+ maxAge: tokenTtl
5291
5292
  });
5292
5293
  await setCsrfCookie(c);
5293
5294
  return c.json({
@@ -5315,7 +5316,7 @@ authRoutes.post(
5315
5316
  );
5316
5317
  authRoutes.post(
5317
5318
  "/login",
5318
- chunk7HHIZQNE_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
5319
+ chunkRE3NVA23_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
5319
5320
  async (c) => {
5320
5321
  try {
5321
5322
  const body = await c.req.json();
@@ -5326,7 +5327,7 @@ authRoutes.post(
5326
5327
  const { email, password } = validation.data;
5327
5328
  const db = c.env.DB;
5328
5329
  const normalizedEmail = email.toLowerCase();
5329
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.user);
5330
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.user);
5330
5331
  let user = await cache.get(cache.generateKey("user", `email:${normalizedEmail}`));
5331
5332
  if (!user) {
5332
5333
  user = await db.prepare("SELECT * FROM users WHERE email = ? AND is_active = 1").bind(normalizedEmail).first();
@@ -5338,25 +5339,25 @@ authRoutes.post(
5338
5339
  if (!user) {
5339
5340
  return c.json({ error: "Invalid email or password" }, 401);
5340
5341
  }
5341
- const isValidPassword = await chunk7HHIZQNE_cjs.AuthManager.verifyPassword(password, user.password_hash);
5342
+ const isValidPassword = await chunkRE3NVA23_cjs.AuthManager.verifyPassword(password, user.password_hash);
5342
5343
  if (!isValidPassword) {
5343
5344
  return c.json({ error: "Invalid email or password" }, 401);
5344
5345
  }
5345
- if (chunk7HHIZQNE_cjs.AuthManager.isLegacyHash(user.password_hash)) {
5346
+ if (chunkRE3NVA23_cjs.AuthManager.isLegacyHash(user.password_hash)) {
5346
5347
  try {
5347
- const newHash = await chunk7HHIZQNE_cjs.AuthManager.hashPassword(password);
5348
+ const newHash = await chunkRE3NVA23_cjs.AuthManager.hashPassword(password);
5348
5349
  await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(newHash, Date.now(), user.id).run();
5349
5350
  } catch (rehashError) {
5350
5351
  console.error("Password rehash failed (non-fatal):", rehashError);
5351
5352
  }
5352
5353
  }
5353
- const token = await chunk7HHIZQNE_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET);
5354
+ const tokenTtl = await chunkRE3NVA23_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
5355
+ const token = await chunkRE3NVA23_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET, tokenTtl);
5354
5356
  cookie.setCookie(c, "auth_token", token, {
5355
5357
  httpOnly: true,
5356
5358
  secure: true,
5357
5359
  sameSite: "Strict",
5358
- maxAge: 60 * 60 * 24
5359
- // 24 hours
5360
+ maxAge: tokenTtl
5360
5361
  });
5361
5362
  await setCsrfCookie(c);
5362
5363
  await db.prepare("UPDATE users SET last_login_at = ? WHERE id = ?").bind((/* @__PURE__ */ new Date()).getTime(), user.id).run();
@@ -5403,7 +5404,7 @@ authRoutes.get("/logout", (c) => {
5403
5404
  clearCsrfCookie(c);
5404
5405
  return c.redirect("/auth/login?message=You have been logged out successfully");
5405
5406
  });
5406
- authRoutes.get("/me", chunk7HHIZQNE_cjs.requireAuth(), async (c) => {
5407
+ authRoutes.get("/me", chunkRE3NVA23_cjs.requireAuth(), async (c) => {
5407
5408
  try {
5408
5409
  const user = c.get("user");
5409
5410
  if (!user) {
@@ -5420,30 +5421,48 @@ authRoutes.get("/me", chunk7HHIZQNE_cjs.requireAuth(), async (c) => {
5420
5421
  return c.json({ error: "Failed to get user" }, 500);
5421
5422
  }
5422
5423
  });
5423
- authRoutes.post("/refresh", chunk7HHIZQNE_cjs.requireAuth(), async (c) => {
5424
- try {
5425
- const user = c.get("user");
5426
- if (!user) {
5427
- return c.json({ error: "Not authenticated" }, 401);
5424
+ authRoutes.post(
5425
+ "/refresh",
5426
+ chunkRE3NVA23_cjs.rateLimit({ max: 60, windowMs: 60 * 1e3, keyPrefix: "refresh" }),
5427
+ async (c) => {
5428
+ try {
5429
+ let token = c.req.header("Authorization")?.replace("Bearer ", "");
5430
+ if (!token) token = cookie.getCookie(c, "auth_token");
5431
+ if (!token) {
5432
+ return c.json({ error: "Authentication required" }, 401);
5433
+ }
5434
+ const db = c.env.DB;
5435
+ const grace = await chunkRE3NVA23_cjs.getJwtRefreshGraceSecondsFromDb(db, c.env);
5436
+ const payload = await chunkRE3NVA23_cjs.AuthManager.verifyToken(token, c.env.JWT_SECRET, grace);
5437
+ if (!payload) {
5438
+ return c.json({ error: "Invalid or expired token" }, 401);
5439
+ }
5440
+ const row = await db.prepare("SELECT id, email, role, is_active FROM users WHERE id = ?").bind(payload.userId).first();
5441
+ if (!row || !row.is_active) {
5442
+ return c.json({ error: "User is not active" }, 401);
5443
+ }
5444
+ const tokenTtl = await chunkRE3NVA23_cjs.getJwtExpirySecondsFromDb(db, c.env);
5445
+ const newToken = await chunkRE3NVA23_cjs.AuthManager.generateToken(row.id, row.email, row.role, c.env.JWT_SECRET, tokenTtl);
5446
+ cookie.setCookie(c, "auth_token", newToken, {
5447
+ httpOnly: true,
5448
+ secure: true,
5449
+ sameSite: "Strict",
5450
+ maxAge: tokenTtl
5451
+ });
5452
+ await setCsrfCookie(c);
5453
+ return c.json({
5454
+ token: newToken,
5455
+ expiresIn: tokenTtl
5456
+ });
5457
+ } catch (error) {
5458
+ console.error("Token refresh error:", error);
5459
+ return c.json({ error: "Token refresh failed" }, 500);
5428
5460
  }
5429
- const token = await chunk7HHIZQNE_cjs.AuthManager.generateToken(user.userId, user.email, user.role, c.env.JWT_SECRET);
5430
- cookie.setCookie(c, "auth_token", token, {
5431
- httpOnly: true,
5432
- secure: true,
5433
- sameSite: "Strict",
5434
- maxAge: 60 * 60 * 24
5435
- // 24 hours
5436
- });
5437
- await setCsrfCookie(c);
5438
- return c.json({ token });
5439
- } catch (error) {
5440
- console.error("Token refresh error:", error);
5441
- return c.json({ error: "Token refresh failed" }, 500);
5442
5461
  }
5443
- });
5462
+ );
5444
5463
  authRoutes.post(
5445
5464
  "/register/form",
5446
- chunk7HHIZQNE_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
5465
+ chunkRE3NVA23_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
5447
5466
  async (c) => {
5448
5467
  try {
5449
5468
  const db = c.env.DB;
@@ -5490,7 +5509,7 @@ authRoutes.post(
5490
5509
  </div>
5491
5510
  `);
5492
5511
  }
5493
- const passwordHash = await chunk7HHIZQNE_cjs.AuthManager.hashPassword(password);
5512
+ const passwordHash = await chunkRE3NVA23_cjs.AuthManager.hashPassword(password);
5494
5513
  const role = isFirstUser ? "admin" : "viewer";
5495
5514
  const userId = crypto.randomUUID();
5496
5515
  const now = /* @__PURE__ */ new Date();
@@ -5525,14 +5544,14 @@ authRoutes.post(
5525
5544
  await saveCustomData(db, userId, sanitized);
5526
5545
  }
5527
5546
  }
5528
- const token = await chunk7HHIZQNE_cjs.AuthManager.generateToken(userId, normalizedEmail, role, c.env.JWT_SECRET);
5547
+ const tokenTtl = await chunkRE3NVA23_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
5548
+ const token = await chunkRE3NVA23_cjs.AuthManager.generateToken(userId, normalizedEmail, role, c.env.JWT_SECRET, tokenTtl);
5529
5549
  cookie.setCookie(c, "auth_token", token, {
5530
5550
  httpOnly: true,
5531
5551
  secure: false,
5532
5552
  // Set to true in production with HTTPS
5533
5553
  sameSite: "Strict",
5534
- maxAge: 60 * 60 * 24
5535
- // 24 hours
5554
+ maxAge: tokenTtl
5536
5555
  });
5537
5556
  await setCsrfCookie(c);
5538
5557
  const redirectUrl = role === "admin" ? "/admin/dashboard" : "/admin/dashboard";
@@ -5558,7 +5577,7 @@ authRoutes.post(
5558
5577
  );
5559
5578
  authRoutes.post(
5560
5579
  "/login/form",
5561
- chunk7HHIZQNE_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
5580
+ chunkRE3NVA23_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
5562
5581
  async (c) => {
5563
5582
  try {
5564
5583
  const formData = await c.req.formData();
@@ -5582,7 +5601,7 @@ authRoutes.post(
5582
5601
  </div>
5583
5602
  `);
5584
5603
  }
5585
- const isValidPassword = await chunk7HHIZQNE_cjs.AuthManager.verifyPassword(password, user.password_hash);
5604
+ const isValidPassword = await chunkRE3NVA23_cjs.AuthManager.verifyPassword(password, user.password_hash);
5586
5605
  if (!isValidPassword) {
5587
5606
  return c.html(html.html`
5588
5607
  <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
@@ -5590,22 +5609,22 @@ authRoutes.post(
5590
5609
  </div>
5591
5610
  `);
5592
5611
  }
5593
- if (chunk7HHIZQNE_cjs.AuthManager.isLegacyHash(user.password_hash)) {
5612
+ if (chunkRE3NVA23_cjs.AuthManager.isLegacyHash(user.password_hash)) {
5594
5613
  try {
5595
- const newHash = await chunk7HHIZQNE_cjs.AuthManager.hashPassword(password);
5614
+ const newHash = await chunkRE3NVA23_cjs.AuthManager.hashPassword(password);
5596
5615
  await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(newHash, Date.now(), user.id).run();
5597
5616
  } catch (rehashError) {
5598
5617
  console.error("Password rehash failed (non-fatal):", rehashError);
5599
5618
  }
5600
5619
  }
5601
- const token = await chunk7HHIZQNE_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET);
5620
+ const tokenTtl = await chunkRE3NVA23_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
5621
+ const token = await chunkRE3NVA23_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET, tokenTtl);
5602
5622
  cookie.setCookie(c, "auth_token", token, {
5603
5623
  httpOnly: true,
5604
5624
  secure: false,
5605
5625
  // Set to true in production with HTTPS
5606
5626
  sameSite: "Strict",
5607
- maxAge: 60 * 60 * 24
5608
- // 24 hours
5627
+ maxAge: tokenTtl
5609
5628
  });
5610
5629
  await setCsrfCookie(c);
5611
5630
  await db.prepare("UPDATE users SET last_login_at = ? WHERE id = ?").bind((/* @__PURE__ */ new Date()).getTime(), user.id).run();
@@ -5640,7 +5659,7 @@ authRoutes.post(
5640
5659
  );
5641
5660
  authRoutes.post(
5642
5661
  "/seed-admin",
5643
- chunk7HHIZQNE_cjs.rateLimit({ max: 10, windowMs: 60 * 1e3, keyPrefix: "seed-admin" }),
5662
+ chunkRE3NVA23_cjs.rateLimit({ max: 10, windowMs: 60 * 1e3, keyPrefix: "seed-admin" }),
5644
5663
  async (c) => {
5645
5664
  try {
5646
5665
  const db = c.env.DB;
@@ -5662,7 +5681,7 @@ authRoutes.post(
5662
5681
  `).run();
5663
5682
  const existingAdmin = await db.prepare("SELECT id FROM users WHERE email = ? OR username = ?").bind("admin@sonicjs.com", "admin").first();
5664
5683
  if (existingAdmin) {
5665
- const passwordHash2 = await chunk7HHIZQNE_cjs.AuthManager.hashPassword("sonicjs!");
5684
+ const passwordHash2 = await chunkRE3NVA23_cjs.AuthManager.hashPassword("sonicjs!");
5666
5685
  await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(passwordHash2, Date.now(), existingAdmin.id).run();
5667
5686
  return c.json({
5668
5687
  message: "Admin user already exists (password updated)",
@@ -5674,7 +5693,7 @@ authRoutes.post(
5674
5693
  }
5675
5694
  });
5676
5695
  }
5677
- const passwordHash = await chunk7HHIZQNE_cjs.AuthManager.hashPassword("sonicjs!");
5696
+ const passwordHash = await chunkRE3NVA23_cjs.AuthManager.hashPassword("sonicjs!");
5678
5697
  const userId = "admin-user-id";
5679
5698
  const now = Date.now();
5680
5699
  const adminEmail = "admin@sonicjs.com".toLowerCase();
@@ -5895,7 +5914,7 @@ authRoutes.post("/accept-invitation", async (c) => {
5895
5914
  if (existingUsername) {
5896
5915
  return c.json({ error: "Username is already taken" }, 400);
5897
5916
  }
5898
- const passwordHash = await chunk7HHIZQNE_cjs.AuthManager.hashPassword(password);
5917
+ const passwordHash = await chunkRE3NVA23_cjs.AuthManager.hashPassword(password);
5899
5918
  const updateStmt = db.prepare(`
5900
5919
  UPDATE users SET
5901
5920
  username = ?,
@@ -5914,13 +5933,13 @@ authRoutes.post("/accept-invitation", async (c) => {
5914
5933
  Date.now(),
5915
5934
  invitedUser.id
5916
5935
  ).run();
5917
- const authToken = await chunk7HHIZQNE_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role, c.env.JWT_SECRET);
5936
+ const tokenTtl = await chunkRE3NVA23_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
5937
+ const authToken = await chunkRE3NVA23_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role, c.env.JWT_SECRET, tokenTtl);
5918
5938
  cookie.setCookie(c, "auth_token", authToken, {
5919
5939
  httpOnly: true,
5920
5940
  secure: true,
5921
5941
  sameSite: "Strict",
5922
- maxAge: 60 * 60 * 24
5923
- // 24 hours
5942
+ maxAge: tokenTtl
5924
5943
  });
5925
5944
  await setCsrfCookie(c);
5926
5945
  return c.redirect("/admin/dashboard?welcome=true");
@@ -5931,7 +5950,7 @@ authRoutes.post("/accept-invitation", async (c) => {
5931
5950
  });
5932
5951
  authRoutes.post(
5933
5952
  "/request-password-reset",
5934
- chunk7HHIZQNE_cjs.rateLimit({ max: 3, windowMs: 15 * 60 * 1e3, keyPrefix: "password-reset" }),
5953
+ chunkRE3NVA23_cjs.rateLimit({ max: 3, windowMs: 15 * 60 * 1e3, keyPrefix: "password-reset" }),
5935
5954
  async (c) => {
5936
5955
  try {
5937
5956
  const formData = await c.req.formData();
@@ -6149,7 +6168,7 @@ authRoutes.post("/reset-password", async (c) => {
6149
6168
  if (Date.now() > user.password_reset_expires) {
6150
6169
  return c.json({ error: "Reset token has expired" }, 400);
6151
6170
  }
6152
- const newPasswordHash = await chunk7HHIZQNE_cjs.AuthManager.hashPassword(password);
6171
+ const newPasswordHash = await chunkRE3NVA23_cjs.AuthManager.hashPassword(password);
6153
6172
  try {
6154
6173
  const historyStmt = db.prepare(`
6155
6174
  INSERT INTO password_history (id, user_id, password_hash, created_at)
@@ -9525,9 +9544,9 @@ function parseFieldValue(field, formData, options = {}) {
9525
9544
  const { skipValidation = false } = options;
9526
9545
  const value = formData.get(field.field_name);
9527
9546
  const errors = [];
9528
- const blocksConfig = chunkV76ERLX6_cjs.getBlocksFieldConfig(field.field_options);
9547
+ const blocksConfig = chunkQBLBIAVZ_cjs.getBlocksFieldConfig(field.field_options);
9529
9548
  if (blocksConfig) {
9530
- const parsed = chunkV76ERLX6_cjs.parseBlocksValue(value, blocksConfig);
9549
+ const parsed = chunkQBLBIAVZ_cjs.parseBlocksValue(value, blocksConfig);
9531
9550
  if (!skipValidation && field.is_required && parsed.value.length === 0) {
9532
9551
  parsed.errors.push(`${field.field_label} is required`);
9533
9552
  }
@@ -9637,9 +9656,9 @@ function extractFieldData(fields, formData, options = {}) {
9637
9656
  }
9638
9657
  return { data, errors };
9639
9658
  }
9640
- adminContentRoutes.use("*", chunk7HHIZQNE_cjs.requireAuth());
9659
+ adminContentRoutes.use("*", chunkRE3NVA23_cjs.requireAuth());
9641
9660
  async function getCollectionFields(db, collectionId) {
9642
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.collection);
9661
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.collection);
9643
9662
  return cache.getOrSet(
9644
9663
  cache.generateKey("fields", collectionId),
9645
9664
  async () => {
@@ -9688,7 +9707,7 @@ async function getCollectionFields(db, collectionId) {
9688
9707
  );
9689
9708
  }
9690
9709
  async function getCollection(db, collectionId) {
9691
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.collection);
9710
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.collection);
9692
9711
  return cache.getOrSet(
9693
9712
  cache.generateKey("collection", collectionId),
9694
9713
  async () => {
@@ -9914,21 +9933,21 @@ adminContentRoutes.get("/new", async (c) => {
9914
9933
  const tinymceEnabled = await isPluginActive2(db, "tinymce-plugin");
9915
9934
  let tinymceSettings;
9916
9935
  if (tinymceEnabled) {
9917
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
9936
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
9918
9937
  const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
9919
9938
  tinymceSettings = tinymcePlugin2?.settings;
9920
9939
  }
9921
9940
  const quillEnabled = await isPluginActive2(db, "quill-editor");
9922
9941
  let quillSettings;
9923
9942
  if (quillEnabled) {
9924
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
9943
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
9925
9944
  const quillPlugin = await pluginService.getPlugin("quill-editor");
9926
9945
  quillSettings = quillPlugin?.settings;
9927
9946
  }
9928
9947
  const mdxeditorEnabled = await isPluginActive2(db, "easy-mdx");
9929
9948
  let mdxeditorSettings;
9930
9949
  if (mdxeditorEnabled) {
9931
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
9950
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
9932
9951
  const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
9933
9952
  mdxeditorSettings = mdxeditorPlugin?.settings;
9934
9953
  }
@@ -9978,7 +9997,7 @@ adminContentRoutes.get("/:id/edit", async (c) => {
9978
9997
  const db = c.env.DB;
9979
9998
  const url = new URL(c.req.url);
9980
9999
  const referrerParams = url.searchParams.get("ref") || "";
9981
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.content);
10000
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.content);
9982
10001
  const content = await cache.getOrSet(
9983
10002
  cache.generateKey("content", id),
9984
10003
  async () => {
@@ -10019,21 +10038,21 @@ adminContentRoutes.get("/:id/edit", async (c) => {
10019
10038
  const tinymceEnabled = await isPluginActive2(db, "tinymce-plugin");
10020
10039
  let tinymceSettings;
10021
10040
  if (tinymceEnabled) {
10022
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
10041
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
10023
10042
  const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
10024
10043
  tinymceSettings = tinymcePlugin2?.settings;
10025
10044
  }
10026
10045
  const quillEnabled = await isPluginActive2(db, "quill-editor");
10027
10046
  let quillSettings;
10028
10047
  if (quillEnabled) {
10029
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
10048
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
10030
10049
  const quillPlugin = await pluginService.getPlugin("quill-editor");
10031
10050
  quillSettings = quillPlugin?.settings;
10032
10051
  }
10033
10052
  const mdxeditorEnabled = await isPluginActive2(db, "easy-mdx");
10034
10053
  let mdxeditorSettings;
10035
10054
  if (mdxeditorEnabled) {
10036
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
10055
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
10037
10056
  const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
10038
10057
  mdxeditorSettings = mdxeditorPlugin?.settings;
10039
10058
  }
@@ -10154,7 +10173,7 @@ adminContentRoutes.post("/", async (c) => {
10154
10173
  now,
10155
10174
  now
10156
10175
  ).run();
10157
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.content);
10176
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.content);
10158
10177
  await cache.invalidate(`content:list:${collectionId}:*`);
10159
10178
  const versionStmt = db.prepare(`
10160
10179
  INSERT INTO content_versions (id, content_id, version, data, author_id, created_at)
@@ -10273,7 +10292,7 @@ adminContentRoutes.put("/:id", async (c) => {
10273
10292
  now,
10274
10293
  id
10275
10294
  ).run();
10276
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.content);
10295
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.content);
10277
10296
  await cache.delete(cache.generateKey("content", id));
10278
10297
  await cache.invalidate(`content:list:${existingContent.collection_id}:*`);
10279
10298
  const existingData = JSON.parse(existingContent.data || "{}");
@@ -10328,7 +10347,7 @@ adminContentRoutes.put("/:id", async (c) => {
10328
10347
  `);
10329
10348
  }
10330
10349
  });
10331
- adminContentRoutes.post("/preview", chunk7HHIZQNE_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
10350
+ adminContentRoutes.post("/preview", chunkRE3NVA23_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
10332
10351
  try {
10333
10352
  const formData = await c.req.formData();
10334
10353
  const collectionId = formData.get("collection_id");
@@ -10550,7 +10569,7 @@ adminContentRoutes.post("/bulk-action", async (c) => {
10550
10569
  } else {
10551
10570
  return c.json({ success: false, error: "Invalid action" });
10552
10571
  }
10553
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.content);
10572
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.content);
10554
10573
  for (const contentId of ids) {
10555
10574
  await cache.delete(cache.generateKey("content", contentId));
10556
10575
  }
@@ -10578,7 +10597,7 @@ adminContentRoutes.delete("/:id", async (c) => {
10578
10597
  WHERE id = ?
10579
10598
  `);
10580
10599
  await deleteStmt.bind(now, id).run();
10581
- const cache = chunkNZWFCUDA_cjs.getCacheService(chunkNZWFCUDA_cjs.CACHE_CONFIGS.content);
10600
+ const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.content);
10582
10601
  await cache.delete(cache.generateKey("content", id));
10583
10602
  await cache.invalidate("content:list:*");
10584
10603
  return c.html(`
@@ -10706,7 +10725,7 @@ adminContentRoutes.post("/:id/restore/:version", async (c) => {
10706
10725
  return c.json({ success: false, error: "Failed to restore version" });
10707
10726
  }
10708
10727
  });
10709
- adminContentRoutes.get("/:id/version/:version/preview", chunk7HHIZQNE_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
10728
+ adminContentRoutes.get("/:id/version/:version/preview", chunkRE3NVA23_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
10710
10729
  try {
10711
10730
  const id = c.req.param("id");
10712
10731
  const version = parseInt(c.req.param("version") || "0");
@@ -12707,14 +12726,14 @@ function renderUsersListPage(data) {
12707
12726
 
12708
12727
  // src/routes/admin-users.ts
12709
12728
  var userRoutes = new hono.Hono();
12710
- userRoutes.use("*", chunk7HHIZQNE_cjs.requireAuth());
12711
- userRoutes.use("/users/*", chunk7HHIZQNE_cjs.requireRole(["admin"]));
12712
- userRoutes.use("/users", chunk7HHIZQNE_cjs.requireRole(["admin"]));
12713
- userRoutes.use("/invite-user", chunk7HHIZQNE_cjs.requireRole(["admin"]));
12714
- userRoutes.use("/resend-invitation/*", chunk7HHIZQNE_cjs.requireRole(["admin"]));
12715
- userRoutes.use("/cancel-invitation/*", chunk7HHIZQNE_cjs.requireRole(["admin"]));
12716
- userRoutes.use("/activity-logs", chunk7HHIZQNE_cjs.requireRole(["admin"]));
12717
- userRoutes.use("/activity-logs/*", chunk7HHIZQNE_cjs.requireRole(["admin"]));
12729
+ userRoutes.use("*", chunkRE3NVA23_cjs.requireAuth());
12730
+ userRoutes.use("/users/*", chunkRE3NVA23_cjs.requireRole(["admin"]));
12731
+ userRoutes.use("/users", chunkRE3NVA23_cjs.requireRole(["admin"]));
12732
+ userRoutes.use("/invite-user", chunkRE3NVA23_cjs.requireRole(["admin"]));
12733
+ userRoutes.use("/resend-invitation/*", chunkRE3NVA23_cjs.requireRole(["admin"]));
12734
+ userRoutes.use("/cancel-invitation/*", chunkRE3NVA23_cjs.requireRole(["admin"]));
12735
+ userRoutes.use("/activity-logs", chunkRE3NVA23_cjs.requireRole(["admin"]));
12736
+ userRoutes.use("/activity-logs/*", chunkRE3NVA23_cjs.requireRole(["admin"]));
12718
12737
  userRoutes.get("/", (c) => {
12719
12738
  return c.redirect("/admin/dashboard");
12720
12739
  });
@@ -12884,7 +12903,7 @@ userRoutes.put("/profile", async (c) => {
12884
12903
  }
12885
12904
  await saveCustomData(db, user.userId, sanitized);
12886
12905
  }
12887
- await chunk7HHIZQNE_cjs.logActivity(
12906
+ await chunkRE3NVA23_cjs.logActivity(
12888
12907
  db,
12889
12908
  user.userId,
12890
12909
  "profile.update",
@@ -12947,7 +12966,7 @@ userRoutes.post("/profile/avatar", async (c) => {
12947
12966
  SELECT first_name, last_name FROM users WHERE id = ?
12948
12967
  `);
12949
12968
  const userData = await userStmt.bind(user.userId).first();
12950
- await chunk7HHIZQNE_cjs.logActivity(
12969
+ await chunkRE3NVA23_cjs.logActivity(
12951
12970
  db,
12952
12971
  user.userId,
12953
12972
  "profile.avatar_update",
@@ -13018,7 +13037,7 @@ userRoutes.post("/profile/password", async (c) => {
13018
13037
  dismissible: true
13019
13038
  }));
13020
13039
  }
13021
- const validPassword = await chunk7HHIZQNE_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
13040
+ const validPassword = await chunkRE3NVA23_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
13022
13041
  if (!validPassword) {
13023
13042
  return c.html(renderAlert2({
13024
13043
  type: "error",
@@ -13026,7 +13045,7 @@ userRoutes.post("/profile/password", async (c) => {
13026
13045
  dismissible: true
13027
13046
  }));
13028
13047
  }
13029
- const newPasswordHash = await chunk7HHIZQNE_cjs.AuthManager.hashPassword(newPassword);
13048
+ const newPasswordHash = await chunkRE3NVA23_cjs.AuthManager.hashPassword(newPassword);
13030
13049
  const historyStmt = db.prepare(`
13031
13050
  INSERT INTO password_history (id, user_id, password_hash, created_at)
13032
13051
  VALUES (?, ?, ?, ?)
@@ -13042,7 +13061,7 @@ userRoutes.post("/profile/password", async (c) => {
13042
13061
  WHERE id = ?
13043
13062
  `);
13044
13063
  await updateStmt.bind(newPasswordHash, Date.now(), user.userId).run();
13045
- await chunk7HHIZQNE_cjs.logActivity(
13064
+ await chunkRE3NVA23_cjs.logActivity(
13046
13065
  db,
13047
13066
  user.userId,
13048
13067
  "profile.password_change",
@@ -13109,7 +13128,7 @@ userRoutes.get("/users", async (c) => {
13109
13128
  `);
13110
13129
  const countResult = await countStmt.bind(...params).first();
13111
13130
  const totalUsers = countResult?.total || 0;
13112
- await chunk7HHIZQNE_cjs.logActivity(
13131
+ await chunkRE3NVA23_cjs.logActivity(
13113
13132
  db,
13114
13133
  user.userId,
13115
13134
  "users.list_view",
@@ -13267,7 +13286,7 @@ userRoutes.post("/users/new", async (c) => {
13267
13286
  dismissible: true
13268
13287
  }));
13269
13288
  }
13270
- const passwordHash = await chunk7HHIZQNE_cjs.AuthManager.hashPassword(password);
13289
+ const passwordHash = await chunkRE3NVA23_cjs.AuthManager.hashPassword(password);
13271
13290
  const userId = crypto.randomUUID();
13272
13291
  const createStmt = db.prepare(`
13273
13292
  INSERT INTO users (
@@ -13290,7 +13309,7 @@ userRoutes.post("/users/new", async (c) => {
13290
13309
  Date.now(),
13291
13310
  Date.now()
13292
13311
  ).run();
13293
- await chunk7HHIZQNE_cjs.logActivity(
13312
+ await chunkRE3NVA23_cjs.logActivity(
13294
13313
  db,
13295
13314
  user.userId,
13296
13315
  "user!.create",
@@ -13329,7 +13348,7 @@ userRoutes.get("/users/:id", async (c) => {
13329
13348
  if (!userRecord) {
13330
13349
  return c.json({ error: "User not found" }, 404);
13331
13350
  }
13332
- await chunk7HHIZQNE_cjs.logActivity(
13351
+ await chunkRE3NVA23_cjs.logActivity(
13333
13352
  db,
13334
13353
  user.userId,
13335
13354
  "user!.view",
@@ -13555,7 +13574,7 @@ userRoutes.put("/users/:id", async (c) => {
13555
13574
  userId
13556
13575
  ).run();
13557
13576
  if (newPassword) {
13558
- const passwordHash = await chunk7HHIZQNE_cjs.AuthManager.hashPassword(newPassword);
13577
+ const passwordHash = await chunkRE3NVA23_cjs.AuthManager.hashPassword(newPassword);
13559
13578
  const updatePasswordStmt = db.prepare(`
13560
13579
  UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?
13561
13580
  `);
@@ -13609,7 +13628,7 @@ userRoutes.put("/users/:id", async (c) => {
13609
13628
  ).run();
13610
13629
  }
13611
13630
  }
13612
- await chunk7HHIZQNE_cjs.logActivity(
13631
+ await chunkRE3NVA23_cjs.logActivity(
13613
13632
  db,
13614
13633
  user.userId,
13615
13634
  "user.update",
@@ -13654,7 +13673,7 @@ userRoutes.post("/users/:id/toggle", async (c) => {
13654
13673
  UPDATE users SET is_active = ?, updated_at = ? WHERE id = ?
13655
13674
  `);
13656
13675
  await toggleStmt.bind(active ? 1 : 0, Date.now(), userId).run();
13657
- await chunk7HHIZQNE_cjs.logActivity(
13676
+ await chunkRE3NVA23_cjs.logActivity(
13658
13677
  db,
13659
13678
  user.userId,
13660
13679
  active ? "user.activate" : "user.deactivate",
@@ -13695,7 +13714,7 @@ userRoutes.delete("/users/:id", async (c) => {
13695
13714
  DELETE FROM users WHERE id = ?
13696
13715
  `);
13697
13716
  await deleteStmt.bind(userId).run();
13698
- await chunk7HHIZQNE_cjs.logActivity(
13717
+ await chunkRE3NVA23_cjs.logActivity(
13699
13718
  db,
13700
13719
  user.userId,
13701
13720
  "user!.hard_delete",
@@ -13714,7 +13733,7 @@ userRoutes.delete("/users/:id", async (c) => {
13714
13733
  UPDATE users SET is_active = 0, updated_at = ? WHERE id = ?
13715
13734
  `);
13716
13735
  await deleteStmt.bind(Date.now(), userId).run();
13717
- await chunk7HHIZQNE_cjs.logActivity(
13736
+ await chunkRE3NVA23_cjs.logActivity(
13718
13737
  db,
13719
13738
  user.userId,
13720
13739
  "user!.soft_delete",
@@ -13780,7 +13799,7 @@ userRoutes.post("/invite-user", async (c) => {
13780
13799
  Date.now(),
13781
13800
  Date.now()
13782
13801
  ).run();
13783
- await chunk7HHIZQNE_cjs.logActivity(
13802
+ await chunkRE3NVA23_cjs.logActivity(
13784
13803
  db,
13785
13804
  user.userId,
13786
13805
  "user!.invite_sent",
@@ -13837,7 +13856,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
13837
13856
  Date.now(),
13838
13857
  userId
13839
13858
  ).run();
13840
- await chunk7HHIZQNE_cjs.logActivity(
13859
+ await chunkRE3NVA23_cjs.logActivity(
13841
13860
  db,
13842
13861
  user.userId,
13843
13862
  "user!.invitation_resent",
@@ -13873,7 +13892,7 @@ userRoutes.delete("/cancel-invitation/:id", async (c) => {
13873
13892
  }
13874
13893
  const deleteStmt = db.prepare(`DELETE FROM users WHERE id = ?`);
13875
13894
  await deleteStmt.bind(userId).run();
13876
- await chunk7HHIZQNE_cjs.logActivity(
13895
+ await chunkRE3NVA23_cjs.logActivity(
13877
13896
  db,
13878
13897
  user.userId,
13879
13898
  "user!.invitation_cancelled",
@@ -13956,7 +13975,7 @@ userRoutes.get("/activity-logs", async (c) => {
13956
13975
  ...log,
13957
13976
  details: log.details ? JSON.parse(log.details) : null
13958
13977
  }));
13959
- await chunk7HHIZQNE_cjs.logActivity(
13978
+ await chunkRE3NVA23_cjs.logActivity(
13960
13979
  db,
13961
13980
  user.userId,
13962
13981
  "activity.logs_viewed",
@@ -14063,7 +14082,7 @@ userRoutes.get("/activity-logs/export", async (c) => {
14063
14082
  csvRows.push(row.join(","));
14064
14083
  }
14065
14084
  const csvContent = csvRows.join("\n");
14066
- await chunk7HHIZQNE_cjs.logActivity(
14085
+ await chunkRE3NVA23_cjs.logActivity(
14067
14086
  db,
14068
14087
  user.userId,
14069
14088
  "activity.logs_exported",
@@ -15402,7 +15421,7 @@ var fileValidationSchema2 = zod.z.object({
15402
15421
  // 50MB max
15403
15422
  });
15404
15423
  var adminMediaRoutes = new hono.Hono();
15405
- adminMediaRoutes.use("*", chunk7HHIZQNE_cjs.requireAuth());
15424
+ adminMediaRoutes.use("*", chunkRE3NVA23_cjs.requireAuth());
15406
15425
  adminMediaRoutes.get("/", async (c) => {
15407
15426
  try {
15408
15427
  const user = c.get("user");
@@ -15988,7 +16007,7 @@ adminMediaRoutes.put("/:id", async (c) => {
15988
16007
  `);
15989
16008
  }
15990
16009
  });
15991
- adminMediaRoutes.delete("/cleanup", chunk7HHIZQNE_cjs.requireRole("admin"), async (c) => {
16010
+ adminMediaRoutes.delete("/cleanup", chunkRE3NVA23_cjs.requireRole("admin"), async (c) => {
15992
16011
  try {
15993
16012
  const db = c.env.DB;
15994
16013
  const allMediaStmt = db.prepare("SELECT id, r2_key, filename FROM media WHERE deleted_at IS NULL");
@@ -18213,8 +18232,8 @@ function renderEmailSettingsContent(plugin, settings) {
18213
18232
 
18214
18233
  // src/routes/admin-plugins.ts
18215
18234
  var adminPluginRoutes = new hono.Hono();
18216
- adminPluginRoutes.use("*", chunk7HHIZQNE_cjs.requireAuth());
18217
- var AVAILABLE_PLUGINS = Object.values(chunkU6FOL6EO_cjs.PLUGIN_REGISTRY).map((p) => ({
18235
+ adminPluginRoutes.use("*", chunkRE3NVA23_cjs.requireAuth());
18236
+ var AVAILABLE_PLUGINS = Object.values(chunk4HCUJ3MG_cjs.PLUGIN_REGISTRY).map((p) => ({
18218
18237
  id: p.id,
18219
18238
  name: p.codeName,
18220
18239
  display_name: p.displayName,
@@ -18234,7 +18253,7 @@ adminPluginRoutes.get("/", async (c) => {
18234
18253
  if (user?.role !== "admin") {
18235
18254
  return c.text("Access denied", 403);
18236
18255
  }
18237
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
18256
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
18238
18257
  let installedPlugins = [];
18239
18258
  let stats = { total: 0, active: 0, inactive: 0, errors: 0, uninstalled: 0 };
18240
18259
  try {
@@ -18306,7 +18325,7 @@ adminPluginRoutes.get("/:id", async (c) => {
18306
18325
  if (user?.role !== "admin") {
18307
18326
  return c.redirect("/admin/plugins");
18308
18327
  }
18309
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
18328
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
18310
18329
  const plugin = await pluginService.getPlugin(pluginId);
18311
18330
  if (!plugin) {
18312
18331
  return c.text("Plugin not found", 404);
@@ -18314,7 +18333,7 @@ adminPluginRoutes.get("/:id", async (c) => {
18314
18333
  const activity = await pluginService.getPluginActivity(pluginId, 20);
18315
18334
  let enrichedSettings = plugin.settings || {};
18316
18335
  if (pluginId === "otp-login") {
18317
- const settingsService = new chunkNZWFCUDA_cjs.SettingsService(db);
18336
+ const settingsService = new chunkWAEQXGCX_cjs.SettingsService(db);
18318
18337
  const generalSettings = await settingsService.getGeneralSettings();
18319
18338
  const siteName = generalSettings.siteName || "SonicJS";
18320
18339
  const emailPlugin = await db.prepare(`
@@ -18382,7 +18401,7 @@ adminPluginRoutes.post("/:id/activate", async (c) => {
18382
18401
  if (user?.role !== "admin") {
18383
18402
  return c.json({ error: "Access denied" }, 403);
18384
18403
  }
18385
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
18404
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
18386
18405
  await pluginService.activatePlugin(pluginId);
18387
18406
  return c.json({ success: true });
18388
18407
  } catch (error) {
@@ -18399,7 +18418,7 @@ adminPluginRoutes.post("/:id/deactivate", async (c) => {
18399
18418
  if (user?.role !== "admin") {
18400
18419
  return c.json({ error: "Access denied" }, 403);
18401
18420
  }
18402
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
18421
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
18403
18422
  await pluginService.deactivatePlugin(pluginId);
18404
18423
  return c.json({ success: true });
18405
18424
  } catch (error) {
@@ -18416,8 +18435,8 @@ adminPluginRoutes.post("/install", async (c) => {
18416
18435
  return c.json({ error: "Access denied" }, 403);
18417
18436
  }
18418
18437
  const body = await c.req.json();
18419
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
18420
- const registryEntry = chunkU6FOL6EO_cjs.findPluginByCodeName(body.name) || chunkU6FOL6EO_cjs.PLUGIN_REGISTRY[body.name] || chunkU6FOL6EO_cjs.PLUGIN_REGISTRY[body.id];
18438
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
18439
+ const registryEntry = chunk4HCUJ3MG_cjs.findPluginByCodeName(body.name) || chunk4HCUJ3MG_cjs.PLUGIN_REGISTRY[body.name] || chunk4HCUJ3MG_cjs.PLUGIN_REGISTRY[body.id];
18421
18440
  if (!registryEntry) {
18422
18441
  return c.json({ error: "Plugin not found in registry" }, 404);
18423
18442
  }
@@ -18450,7 +18469,7 @@ adminPluginRoutes.post("/:id/uninstall", async (c) => {
18450
18469
  if (user?.role !== "admin") {
18451
18470
  return c.json({ error: "Access denied" }, 403);
18452
18471
  }
18453
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
18472
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
18454
18473
  await pluginService.uninstallPlugin(pluginId);
18455
18474
  return c.json({ success: true });
18456
18475
  } catch (error) {
@@ -18468,7 +18487,7 @@ adminPluginRoutes.post("/:id/settings", async (c) => {
18468
18487
  return c.json({ error: "Access denied" }, 403);
18469
18488
  }
18470
18489
  const settings = await c.req.json();
18471
- const pluginService = new chunkU6FOL6EO_cjs.PluginService(db);
18490
+ const pluginService = new chunk4HCUJ3MG_cjs.PluginService(db);
18472
18491
  await pluginService.updatePluginSettings(pluginId, settings);
18473
18492
  if (pluginId === "core-auth") {
18474
18493
  try {
@@ -19276,11 +19295,11 @@ function renderLogConfigPage(data) {
19276
19295
 
19277
19296
  // src/routes/admin-logs.ts
19278
19297
  var adminLogsRoutes = new hono.Hono();
19279
- adminLogsRoutes.use("*", chunk7HHIZQNE_cjs.requireAuth());
19298
+ adminLogsRoutes.use("*", chunkRE3NVA23_cjs.requireAuth());
19280
19299
  adminLogsRoutes.get("/", async (c) => {
19281
19300
  try {
19282
19301
  const user = c.get("user");
19283
- const logger = chunkNZWFCUDA_cjs.getLogger(c.env.DB);
19302
+ const logger = chunkWAEQXGCX_cjs.getLogger(c.env.DB);
19284
19303
  const query = c.req.query();
19285
19304
  const page = parseInt(query.page || "1");
19286
19305
  const limit = parseInt(query.limit || "50");
@@ -19360,7 +19379,7 @@ adminLogsRoutes.get("/:id", async (c) => {
19360
19379
  try {
19361
19380
  const id = c.req.param("id");
19362
19381
  const user = c.get("user");
19363
- const logger = chunkNZWFCUDA_cjs.getLogger(c.env.DB);
19382
+ const logger = chunkWAEQXGCX_cjs.getLogger(c.env.DB);
19364
19383
  const { logs } = await logger.getLogs({
19365
19384
  limit: 1,
19366
19385
  offset: 0,
@@ -19397,7 +19416,7 @@ adminLogsRoutes.get("/:id", async (c) => {
19397
19416
  adminLogsRoutes.get("/config", async (c) => {
19398
19417
  try {
19399
19418
  const user = c.get("user");
19400
- const logger = chunkNZWFCUDA_cjs.getLogger(c.env.DB);
19419
+ const logger = chunkWAEQXGCX_cjs.getLogger(c.env.DB);
19401
19420
  const configs = await logger.getAllConfigs();
19402
19421
  const pageData = {
19403
19422
  configs,
@@ -19421,7 +19440,7 @@ adminLogsRoutes.post("/config/:category", async (c) => {
19421
19440
  const level = formData.get("level");
19422
19441
  const retention = parseInt(formData.get("retention"));
19423
19442
  const maxSize = parseInt(formData.get("max_size"));
19424
- const logger = chunkNZWFCUDA_cjs.getLogger(c.env.DB);
19443
+ const logger = chunkWAEQXGCX_cjs.getLogger(c.env.DB);
19425
19444
  await logger.updateConfig(category, {
19426
19445
  enabled,
19427
19446
  level,
@@ -19450,7 +19469,7 @@ adminLogsRoutes.get("/export", async (c) => {
19450
19469
  const category = query.category;
19451
19470
  const startDate = query.start_date;
19452
19471
  const endDate = query.end_date;
19453
- const logger = chunkNZWFCUDA_cjs.getLogger(c.env.DB);
19472
+ const logger = chunkWAEQXGCX_cjs.getLogger(c.env.DB);
19454
19473
  const filter = {
19455
19474
  limit: 1e4,
19456
19475
  // Export up to 10k logs
@@ -19531,7 +19550,7 @@ adminLogsRoutes.post("/cleanup", async (c) => {
19531
19550
  error: "Unauthorized. Admin access required."
19532
19551
  }, 403);
19533
19552
  }
19534
- const logger = chunkNZWFCUDA_cjs.getLogger(c.env.DB);
19553
+ const logger = chunkWAEQXGCX_cjs.getLogger(c.env.DB);
19535
19554
  await logger.cleanupByRetention();
19536
19555
  return c.html(html.html`
19537
19556
  <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded">
@@ -19553,7 +19572,7 @@ adminLogsRoutes.post("/search", async (c) => {
19553
19572
  const search = formData.get("search");
19554
19573
  const level = formData.get("level");
19555
19574
  const category = formData.get("category");
19556
- const logger = chunkNZWFCUDA_cjs.getLogger(c.env.DB);
19575
+ const logger = chunkWAEQXGCX_cjs.getLogger(c.env.DB);
19557
19576
  const filter = {
19558
19577
  limit: 20,
19559
19578
  offset: 0,
@@ -21604,9 +21623,9 @@ function renderStorageUsage(databaseSizeBytes, mediaSizeBytes) {
21604
21623
  }
21605
21624
 
21606
21625
  // src/routes/admin-dashboard.ts
21607
- var VERSION = chunkV76ERLX6_cjs.getCoreVersion();
21626
+ var VERSION = chunkQBLBIAVZ_cjs.getCoreVersion();
21608
21627
  var router = new hono.Hono();
21609
- router.use("*", chunk7HHIZQNE_cjs.requireAuth());
21628
+ router.use("*", chunkRE3NVA23_cjs.requireAuth());
21610
21629
  router.get("/", async (c) => {
21611
21630
  const user = c.get("user");
21612
21631
  try {
@@ -23425,10 +23444,10 @@ function renderCollectionFormPage(data) {
23425
23444
 
23426
23445
  // src/routes/admin-collections.ts
23427
23446
  var adminCollectionsRoutes = new hono.Hono();
23428
- adminCollectionsRoutes.use("*", chunk7HHIZQNE_cjs.requireAuth());
23429
- adminCollectionsRoutes.post("*", chunk7HHIZQNE_cjs.requireRole(["admin"]));
23430
- adminCollectionsRoutes.put("*", chunk7HHIZQNE_cjs.requireRole(["admin"]));
23431
- adminCollectionsRoutes.delete("*", chunk7HHIZQNE_cjs.requireRole(["admin"]));
23447
+ adminCollectionsRoutes.use("*", chunkRE3NVA23_cjs.requireAuth());
23448
+ adminCollectionsRoutes.post("*", chunkRE3NVA23_cjs.requireRole(["admin"]));
23449
+ adminCollectionsRoutes.put("*", chunkRE3NVA23_cjs.requireRole(["admin"]));
23450
+ adminCollectionsRoutes.delete("*", chunkRE3NVA23_cjs.requireRole(["admin"]));
23432
23451
  adminCollectionsRoutes.get("/", async (c) => {
23433
23452
  try {
23434
23453
  const user = c.get("user");
@@ -24241,6 +24260,43 @@ function renderSettingsPage(data) {
24241
24260
  }
24242
24261
  }
24243
24262
 
24263
+ async function saveSecuritySettings() {
24264
+ const formData = new FormData();
24265
+ const expiry = document.getElementById('jwtExpiresIn');
24266
+ const grace = document.getElementById('jwtRefreshGraceSeconds');
24267
+ if (expiry) formData.append('jwtExpiresIn', expiry.value);
24268
+ if (grace) formData.append('jwtRefreshGraceSeconds', grace.value);
24269
+
24270
+ const saveBtn = document.querySelector('button[onclick="saveSecuritySettings()"]');
24271
+ const originalText = saveBtn ? saveBtn.innerHTML : '';
24272
+ if (saveBtn) {
24273
+ saveBtn.innerHTML = '<svg class="animate-spin -ml-0.5 mr-1.5 h-5 w-5 inline" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>Saving...';
24274
+ saveBtn.disabled = true;
24275
+ }
24276
+
24277
+ try {
24278
+ const response = await fetch('/admin/settings/security', {
24279
+ method: 'POST',
24280
+ body: formData
24281
+ });
24282
+ const result = await response.json();
24283
+ if (result.success) {
24284
+ showNotification(result.message || 'Security settings saved successfully!', 'success');
24285
+ } else {
24286
+ showNotification(result.error || 'Failed to save security settings', 'error');
24287
+ }
24288
+ } catch (error) {
24289
+ console.error('Error saving security settings:', error);
24290
+ showNotification('Failed to save security settings. Please try again.', 'error');
24291
+ } finally {
24292
+ if (saveBtn) {
24293
+ saveBtn.innerHTML = originalText;
24294
+ saveBtn.disabled = false;
24295
+ }
24296
+ }
24297
+ }
24298
+ window.saveSecuritySettings = saveSecuritySettings;
24299
+
24244
24300
  // Migration functions
24245
24301
  window.refreshMigrationStatus = async function() {
24246
24302
  try {
@@ -24823,9 +24879,71 @@ function renderAppearanceSettings(settings) {
24823
24879
  `;
24824
24880
  }
24825
24881
  function renderSecuritySettings(settings) {
24882
+ const jwtExpiresIn = settings?.jwtExpiresIn ?? "30d";
24883
+ const jwtRefreshGraceSeconds = typeof settings?.jwtRefreshGraceSeconds === "number" ? settings.jwtRefreshGraceSeconds : 60 * 60 * 24 * 7;
24826
24884
  return `
24827
24885
  <div class="space-y-6">
24828
- <!-- WIP Notice -->
24886
+ <!-- Session / JWT card (live) -->
24887
+ <div class="rounded-lg bg-white dark:bg-white/5 p-6 ring-1 ring-inset ring-zinc-950/5 dark:ring-white/10">
24888
+ <h3 class="text-lg/7 font-semibold text-zinc-950 dark:text-white">Session / JWT</h3>
24889
+ <p class="mt-1 text-sm/6 text-zinc-500 dark:text-zinc-400">
24890
+ Configure how long a signed-in session lasts and how long an expired token can still be refreshed.
24891
+ The <code class="text-xs">JWT_EXPIRES_IN</code> and <code class="text-xs">JWT_REFRESH_GRACE_SECONDS</code>
24892
+ environment variables, when set, override the values below.
24893
+ </p>
24894
+
24895
+ <div class="mt-6 grid grid-cols-1 md:grid-cols-2 gap-6">
24896
+ <div>
24897
+ <label for="jwtExpiresIn" class="block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2">
24898
+ JWT Expiration
24899
+ </label>
24900
+ <input
24901
+ type="text"
24902
+ id="jwtExpiresIn"
24903
+ name="jwtExpiresIn"
24904
+ value="${jwtExpiresIn}"
24905
+ placeholder="30d"
24906
+ class="w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm/6 text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400"
24907
+ />
24908
+ <p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">
24909
+ Accepts <code>30d</code>, <code>12h</code>, <code>3600s</code>, or bare seconds. Default: 30 days.
24910
+ </p>
24911
+ </div>
24912
+
24913
+ <div>
24914
+ <label for="jwtRefreshGraceSeconds" class="block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2">
24915
+ Refresh Grace Window (seconds)
24916
+ </label>
24917
+ <input
24918
+ type="number"
24919
+ id="jwtRefreshGraceSeconds"
24920
+ name="jwtRefreshGraceSeconds"
24921
+ value="${jwtRefreshGraceSeconds}"
24922
+ min="0"
24923
+ max="7776000"
24924
+ class="w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm/6 text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400"
24925
+ />
24926
+ <p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">
24927
+ How long an expired token can still be exchanged at <code>/auth/refresh</code>. Default: 604800 (7 days).
24928
+ </p>
24929
+ </div>
24930
+ </div>
24931
+
24932
+ <div class="mt-6 pt-4 border-t border-zinc-950/5 dark:border-white/10 flex justify-end">
24933
+ <button
24934
+ type="button"
24935
+ onclick="saveSecuritySettings()"
24936
+ class="inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm"
24937
+ >
24938
+ <svg class="-ml-0.5 mr-1.5 h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
24939
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
24940
+ </svg>
24941
+ Save Session Settings
24942
+ </button>
24943
+ </div>
24944
+ </div>
24945
+
24946
+ <!-- WIP Notice for remaining fields -->
24829
24947
  <div class="rounded-lg bg-blue-50 dark:bg-blue-950/20 p-6 ring-1 ring-inset ring-blue-600/20 dark:ring-blue-500/30">
24830
24948
  <div class="flex items-start space-x-3">
24831
24949
  <svg class="w-6 h-6 text-blue-600 dark:text-blue-400 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -24834,7 +24952,7 @@ function renderSecuritySettings(settings) {
24834
24952
  <div class="flex-1">
24835
24953
  <h4 class="text-base/7 font-semibold text-blue-900 dark:text-blue-300">Work in Progress</h4>
24836
24954
  <p class="mt-1 text-sm/6 text-blue-700 dark:text-blue-200">
24837
- This settings section is currently under development and provided for reference and design feedback only. Changes made here will not be saved.
24955
+ The fields below are under development and provided for reference and design feedback only. Changes made here will not be saved.
24838
24956
  </p>
24839
24957
  </div>
24840
24958
  </div>
@@ -25624,7 +25742,7 @@ function renderDatabaseToolsSettings(settings) {
25624
25742
 
25625
25743
  // src/routes/admin-settings.ts
25626
25744
  var adminSettingsRoutes = new hono.Hono();
25627
- adminSettingsRoutes.use("*", chunk7HHIZQNE_cjs.requireAuth());
25745
+ adminSettingsRoutes.use("*", chunkRE3NVA23_cjs.requireAuth());
25628
25746
  function getMockSettings(user) {
25629
25747
  return {
25630
25748
  general: {
@@ -25689,7 +25807,7 @@ adminSettingsRoutes.get("/", (c) => {
25689
25807
  adminSettingsRoutes.get("/general", async (c) => {
25690
25808
  const user = c.get("user");
25691
25809
  const db = c.env.DB;
25692
- const settingsService = new chunkNZWFCUDA_cjs.SettingsService(db);
25810
+ const settingsService = new chunkWAEQXGCX_cjs.SettingsService(db);
25693
25811
  const generalSettings = await settingsService.getGeneralSettings(user?.email);
25694
25812
  const mockSettings = getMockSettings(user);
25695
25813
  mockSettings.general = generalSettings;
@@ -25719,15 +25837,24 @@ adminSettingsRoutes.get("/appearance", (c) => {
25719
25837
  };
25720
25838
  return c.html(renderSettingsPage(pageData));
25721
25839
  });
25722
- adminSettingsRoutes.get("/security", (c) => {
25840
+ adminSettingsRoutes.get("/security", async (c) => {
25723
25841
  const user = c.get("user");
25842
+ const db = c.env.DB;
25843
+ const settingsService = new chunkWAEQXGCX_cjs.SettingsService(db);
25844
+ const persisted = await settingsService.getSecuritySettings();
25845
+ const mockSettings = getMockSettings(user);
25846
+ mockSettings.security = {
25847
+ ...mockSettings.security,
25848
+ jwtExpiresIn: persisted.jwtExpiresIn,
25849
+ jwtRefreshGraceSeconds: persisted.jwtRefreshGraceSeconds
25850
+ };
25724
25851
  const pageData = {
25725
25852
  user: user ? {
25726
25853
  name: user.email,
25727
25854
  email: user.email,
25728
25855
  role: user.role
25729
25856
  } : void 0,
25730
- settings: getMockSettings(user),
25857
+ settings: mockSettings,
25731
25858
  activeTab: "security",
25732
25859
  version: c.get("appVersion")
25733
25860
  };
@@ -25792,7 +25919,7 @@ adminSettingsRoutes.get("/database-tools", (c) => {
25792
25919
  adminSettingsRoutes.get("/api/migrations/status", async (c) => {
25793
25920
  try {
25794
25921
  const db = c.env.DB;
25795
- const migrationService = new chunkHU4MN74Q_cjs.MigrationService(db);
25922
+ const migrationService = new chunkFSWP4FBW_cjs.MigrationService(db);
25796
25923
  const status = await migrationService.getMigrationStatus();
25797
25924
  return c.json({
25798
25925
  success: true,
@@ -25816,7 +25943,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
25816
25943
  }, 403);
25817
25944
  }
25818
25945
  const db = c.env.DB;
25819
- const migrationService = new chunkHU4MN74Q_cjs.MigrationService(db);
25946
+ const migrationService = new chunkFSWP4FBW_cjs.MigrationService(db);
25820
25947
  const result = await migrationService.runPendingMigrations();
25821
25948
  return c.json({
25822
25949
  success: result.success,
@@ -25834,7 +25961,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
25834
25961
  adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
25835
25962
  try {
25836
25963
  const db = c.env.DB;
25837
- const migrationService = new chunkHU4MN74Q_cjs.MigrationService(db);
25964
+ const migrationService = new chunkFSWP4FBW_cjs.MigrationService(db);
25838
25965
  const validation = await migrationService.validateSchema();
25839
25966
  return c.json({
25840
25967
  success: true,
@@ -26003,7 +26130,7 @@ adminSettingsRoutes.post("/general", async (c) => {
26003
26130
  }
26004
26131
  const formData = await c.req.formData();
26005
26132
  const db = c.env.DB;
26006
- const settingsService = new chunkNZWFCUDA_cjs.SettingsService(db);
26133
+ const settingsService = new chunkWAEQXGCX_cjs.SettingsService(db);
26007
26134
  const settings = {
26008
26135
  siteName: formData.get("siteName"),
26009
26136
  siteDescription: formData.get("siteDescription"),
@@ -26038,6 +26165,55 @@ adminSettingsRoutes.post("/general", async (c) => {
26038
26165
  }, 500);
26039
26166
  }
26040
26167
  });
26168
+ adminSettingsRoutes.post("/security", async (c) => {
26169
+ try {
26170
+ const user = c.get("user");
26171
+ if (!user || user.role !== "admin") {
26172
+ return c.json({
26173
+ success: false,
26174
+ error: "Unauthorized. Admin access required."
26175
+ }, 403);
26176
+ }
26177
+ const formData = await c.req.formData();
26178
+ const db = c.env.DB;
26179
+ const settingsService = new chunkWAEQXGCX_cjs.SettingsService(db);
26180
+ const jwtExpiresInRaw = formData.get("jwtExpiresIn")?.trim() || "";
26181
+ const graceRaw = formData.get("jwtRefreshGraceSeconds")?.trim() || "";
26182
+ if (!/^\d+(?:s|m|h|d)?$/i.test(jwtExpiresInRaw)) {
26183
+ return c.json({
26184
+ success: false,
26185
+ error: "JWT expiration must be a number optionally suffixed with s/m/h/d (e.g. 30d, 12h, 3600)."
26186
+ }, 400);
26187
+ }
26188
+ const graceSeconds = Number.parseInt(graceRaw, 10);
26189
+ if (!Number.isFinite(graceSeconds) || graceSeconds < 0 || graceSeconds > 60 * 60 * 24 * 90) {
26190
+ return c.json({
26191
+ success: false,
26192
+ error: "Refresh grace must be an integer between 0 and 7776000 seconds (90 days)."
26193
+ }, 400);
26194
+ }
26195
+ const success = await settingsService.saveSecuritySettings({
26196
+ jwtExpiresIn: jwtExpiresInRaw,
26197
+ jwtRefreshGraceSeconds: graceSeconds
26198
+ });
26199
+ if (success) {
26200
+ return c.json({
26201
+ success: true,
26202
+ message: "Security settings saved successfully!"
26203
+ });
26204
+ }
26205
+ return c.json({
26206
+ success: false,
26207
+ error: "Failed to save settings"
26208
+ }, 500);
26209
+ } catch (error) {
26210
+ console.error("Error saving security settings:", error);
26211
+ return c.json({
26212
+ success: false,
26213
+ error: "Failed to save settings. Please try again."
26214
+ }, 500);
26215
+ }
26216
+ });
26041
26217
  adminSettingsRoutes.post("/", async (c) => {
26042
26218
  return c.redirect("/admin/settings/general");
26043
26219
  });
@@ -27724,7 +27900,7 @@ function renderFormCreatePage(data) {
27724
27900
 
27725
27901
  // src/routes/admin-forms.ts
27726
27902
  var adminFormsRoutes = new hono.Hono();
27727
- adminFormsRoutes.use("*", chunk7HHIZQNE_cjs.requireAuth());
27903
+ adminFormsRoutes.use("*", chunkRE3NVA23_cjs.requireAuth());
27728
27904
  adminFormsRoutes.get("/", async (c) => {
27729
27905
  try {
27730
27906
  const user = c.get("user");
@@ -28529,7 +28705,7 @@ publicFormsRoutes.post("/:identifier/submit", async (c) => {
28529
28705
  `).bind(now, form.id).run();
28530
28706
  let contentId = null;
28531
28707
  try {
28532
- contentId = await chunkU6FOL6EO_cjs.createContentFromSubmission(
28708
+ contentId = await chunk4HCUJ3MG_cjs.createContentFromSubmission(
28533
28709
  db,
28534
28710
  sanitizedData,
28535
28711
  { id: form.id, name: form.name, display_name: form.display_name },
@@ -28703,7 +28879,7 @@ function renderAPIReferencePage(data) {
28703
28879
  >
28704
28880
  <option value="">All Categories</option>
28705
28881
  ${categories.map((category) => {
28706
- const info = chunkNZWFCUDA_cjs.CATEGORY_INFO[category];
28882
+ const info = chunkWAEQXGCX_cjs.CATEGORY_INFO[category];
28707
28883
  const title = info ? info.title : category;
28708
28884
  return `<option value="${category}">${title}</option>`;
28709
28885
  }).join("\n ")}
@@ -28720,7 +28896,7 @@ function renderAPIReferencePage(data) {
28720
28896
  <!-- API Categories -->
28721
28897
  <div class="space-y-6">
28722
28898
  ${Object.entries(endpointsByCategory).map(([category, endpoints]) => {
28723
- const info = chunkNZWFCUDA_cjs.CATEGORY_INFO[category] || { title: category, description: "", icon: "&#x1f4cb;" };
28899
+ const info = chunkWAEQXGCX_cjs.CATEGORY_INFO[category] || { title: category, description: "", icon: "&#x1f4cb;" };
28724
28900
  return `
28725
28901
  <div class="api-category" data-category="${category}">
28726
28902
  <div class="rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden">
@@ -28897,14 +29073,14 @@ function renderAPIReferencePage(data) {
28897
29073
  }
28898
29074
 
28899
29075
  // src/routes/admin-api-reference.ts
28900
- var VERSION2 = chunkV76ERLX6_cjs.getCoreVersion();
29076
+ var VERSION2 = chunkQBLBIAVZ_cjs.getCoreVersion();
28901
29077
  var router2 = new hono.Hono();
28902
- router2.use("*", chunk7HHIZQNE_cjs.requireAuth());
29078
+ router2.use("*", chunkRE3NVA23_cjs.requireAuth());
28903
29079
  router2.get("/", async (c) => {
28904
29080
  const user = c.get("user");
28905
29081
  try {
28906
- const app2 = chunkNZWFCUDA_cjs.getAppInstance();
28907
- const endpoints = chunkNZWFCUDA_cjs.buildRouteList(app2);
29082
+ const app2 = chunkWAEQXGCX_cjs.getAppInstance();
29083
+ const endpoints = chunkWAEQXGCX_cjs.buildRouteList(app2);
28908
29084
  const pageData = {
28909
29085
  endpoints,
28910
29086
  user: user ? {
@@ -28990,5 +29166,5 @@ exports.router2 = router2;
28990
29166
  exports.test_cleanup_default = test_cleanup_default;
28991
29167
  exports.userProfilesPlugin = userProfilesPlugin;
28992
29168
  exports.userRoutes = userRoutes;
28993
- //# sourceMappingURL=chunk-MZS33LLH.cjs.map
28994
- //# sourceMappingURL=chunk-MZS33LLH.cjs.map
29169
+ //# sourceMappingURL=chunk-J5MYHM6Z.cjs.map
29170
+ //# sourceMappingURL=chunk-J5MYHM6Z.cjs.map