@sonicjs-cms/core 2.0.1 → 2.0.3

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 (65) hide show
  1. package/dist/{chunk-O46XKBFM.js → chunk-3LZ6TLPC.js} +14 -24
  2. package/dist/chunk-3LZ6TLPC.js.map +1 -0
  3. package/dist/{chunk-SRCY43RN.cjs → chunk-3NVJ6W27.cjs} +2 -2
  4. package/dist/chunk-3NVJ6W27.cjs.map +1 -0
  5. package/dist/{chunk-ALOS2CBJ.cjs → chunk-3SPQ3J4N.cjs} +14 -24
  6. package/dist/chunk-3SPQ3J4N.cjs.map +1 -0
  7. package/dist/chunk-4BJGEGX5.cjs +236 -0
  8. package/dist/chunk-4BJGEGX5.cjs.map +1 -0
  9. package/dist/{chunk-EGFHFM4N.cjs → chunk-5APKEYFK.cjs} +5 -5
  10. package/dist/{chunk-EGFHFM4N.cjs.map → chunk-5APKEYFK.cjs.map} +1 -1
  11. package/dist/{chunk-5FDDDD4J.cjs → chunk-5B3VMVEX.cjs} +559 -390
  12. package/dist/chunk-5B3VMVEX.cjs.map +1 -0
  13. package/dist/chunk-CDBVZEWR.js.map +1 -1
  14. package/dist/{chunk-BITQ4MFX.js → chunk-EAELJXRV.js} +93 -115
  15. package/dist/chunk-EAELJXRV.js.map +1 -0
  16. package/dist/chunk-FICTAGD4.js +59 -0
  17. package/dist/chunk-FICTAGD4.js.map +1 -0
  18. package/dist/{chunk-FVMV5DKA.cjs → chunk-HJZOA2O5.cjs} +93 -115
  19. package/dist/chunk-HJZOA2O5.cjs.map +1 -0
  20. package/dist/chunk-LEG4KNFP.cjs.map +1 -1
  21. package/dist/{chunk-5XTB4FE5.js → chunk-LH4Z7QID.js} +2 -2
  22. package/dist/chunk-LH4Z7QID.js.map +1 -0
  23. package/dist/chunk-M6FPVS7E.js +214 -0
  24. package/dist/chunk-M6FPVS7E.js.map +1 -0
  25. package/dist/{chunk-QSF34IYQ.js → chunk-PPUKPNTP.js} +401 -232
  26. package/dist/chunk-PPUKPNTP.js.map +1 -0
  27. package/dist/chunk-RCQ2HIQD.cjs +61 -0
  28. package/dist/chunk-RCQ2HIQD.cjs.map +1 -0
  29. package/dist/{chunk-P2PTTBO5.js → chunk-RYQCT2IV.js} +3 -3
  30. package/dist/{chunk-P2PTTBO5.js.map → chunk-RYQCT2IV.js.map} +1 -1
  31. package/dist/{chunk-NK6FN5R5.cjs → chunk-UL32L2KV.cjs} +3 -60
  32. package/dist/chunk-UL32L2KV.cjs.map +1 -0
  33. package/dist/{chunk-OL2OE3VJ.js → chunk-XJETEIRU.js} +4 -60
  34. package/dist/chunk-XJETEIRU.js.map +1 -0
  35. package/dist/index.cjs +145 -130
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.js +19 -15
  38. package/dist/index.js.map +1 -1
  39. package/dist/middleware.cjs +26 -21
  40. package/dist/middleware.js +2 -1
  41. package/dist/plugins.cjs +7 -7
  42. package/dist/plugins.js +1 -1
  43. package/dist/routes.cjs +26 -25
  44. package/dist/routes.js +6 -5
  45. package/dist/services.cjs +7 -7
  46. package/dist/services.js +1 -1
  47. package/dist/templates.cjs +18 -18
  48. package/dist/templates.js +2 -2
  49. package/dist/utils.cjs +16 -15
  50. package/dist/utils.js +2 -1
  51. package/package.json +1 -1
  52. package/dist/chunk-5FDDDD4J.cjs.map +0 -1
  53. package/dist/chunk-5XTB4FE5.js.map +0 -1
  54. package/dist/chunk-ALOS2CBJ.cjs.map +0 -1
  55. package/dist/chunk-BITQ4MFX.js.map +0 -1
  56. package/dist/chunk-FVMV5DKA.cjs.map +0 -1
  57. package/dist/chunk-KM4AJFXI.cjs +0 -101
  58. package/dist/chunk-KM4AJFXI.cjs.map +0 -1
  59. package/dist/chunk-NK6FN5R5.cjs.map +0 -1
  60. package/dist/chunk-O46XKBFM.js.map +0 -1
  61. package/dist/chunk-OL2OE3VJ.js.map +0 -1
  62. package/dist/chunk-QSF34IYQ.js.map +0 -1
  63. package/dist/chunk-SRCY43RN.cjs.map +0 -1
  64. package/dist/chunk-TY3NHEBN.js +0 -80
  65. package/dist/chunk-TY3NHEBN.js.map +0 -1
@@ -1,10 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var chunkSRCY43RN_cjs = require('./chunk-SRCY43RN.cjs');
4
- var chunkKM4AJFXI_cjs = require('./chunk-KM4AJFXI.cjs');
3
+ var chunk3NVJ6W27_cjs = require('./chunk-3NVJ6W27.cjs');
4
+ var chunk4BJGEGX5_cjs = require('./chunk-4BJGEGX5.cjs');
5
5
  var chunkLEG4KNFP_cjs = require('./chunk-LEG4KNFP.cjs');
6
- var chunkALOS2CBJ_cjs = require('./chunk-ALOS2CBJ.cjs');
7
- var chunkNK6FN5R5_cjs = require('./chunk-NK6FN5R5.cjs');
6
+ var chunk3SPQ3J4N_cjs = require('./chunk-3SPQ3J4N.cjs');
7
+ var chunkUL32L2KV_cjs = require('./chunk-UL32L2KV.cjs');
8
+ var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
8
9
  var hono = require('hono');
9
10
  var cors = require('hono/cors');
10
11
  var zod = require('zod');
@@ -42,7 +43,7 @@ apiContentCrudRoutes.get("/:id", async (c) => {
42
43
  }, 500);
43
44
  }
44
45
  });
45
- apiContentCrudRoutes.post("/", chunkKM4AJFXI_cjs.requireAuth(), async (c) => {
46
+ apiContentCrudRoutes.post("/", chunk4BJGEGX5_cjs.requireAuth(), async (c) => {
46
47
  try {
47
48
  const db = c.env.DB;
48
49
  const user = c.get("user");
@@ -83,7 +84,7 @@ apiContentCrudRoutes.post("/", chunkKM4AJFXI_cjs.requireAuth(), async (c) => {
83
84
  now,
84
85
  now
85
86
  ).run();
86
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.api);
87
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.api);
87
88
  await cache.invalidate(`content:list:${collectionId}:*`);
88
89
  await cache.invalidate("content-filtered:*");
89
90
  const getStmt = db.prepare("SELECT * FROM content WHERE id = ?");
@@ -108,7 +109,7 @@ apiContentCrudRoutes.post("/", chunkKM4AJFXI_cjs.requireAuth(), async (c) => {
108
109
  }, 500);
109
110
  }
110
111
  });
111
- apiContentCrudRoutes.put("/:id", chunkKM4AJFXI_cjs.requireAuth(), async (c) => {
112
+ apiContentCrudRoutes.put("/:id", chunk4BJGEGX5_cjs.requireAuth(), async (c) => {
112
113
  try {
113
114
  const id = c.req.param("id");
114
115
  const db = c.env.DB;
@@ -146,7 +147,7 @@ apiContentCrudRoutes.put("/:id", chunkKM4AJFXI_cjs.requireAuth(), async (c) => {
146
147
  WHERE id = ?
147
148
  `);
148
149
  await updateStmt.bind(...params).run();
149
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.api);
150
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.api);
150
151
  await cache.delete(cache.generateKey("content", id));
151
152
  await cache.invalidate(`content:list:${existing.collection_id}:*`);
152
153
  await cache.invalidate("content-filtered:*");
@@ -172,7 +173,7 @@ apiContentCrudRoutes.put("/:id", chunkKM4AJFXI_cjs.requireAuth(), async (c) => {
172
173
  }, 500);
173
174
  }
174
175
  });
175
- apiContentCrudRoutes.delete("/:id", chunkKM4AJFXI_cjs.requireAuth(), async (c) => {
176
+ apiContentCrudRoutes.delete("/:id", chunk4BJGEGX5_cjs.requireAuth(), async (c) => {
176
177
  try {
177
178
  const id = c.req.param("id");
178
179
  const db = c.env.DB;
@@ -183,7 +184,7 @@ apiContentCrudRoutes.delete("/:id", chunkKM4AJFXI_cjs.requireAuth(), async (c) =
183
184
  }
184
185
  const deleteStmt = db.prepare("DELETE FROM content WHERE id = ?");
185
186
  await deleteStmt.bind(id).run();
186
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.api);
187
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.api);
187
188
  await cache.delete(cache.generateKey("content", id));
188
189
  await cache.invalidate(`content:list:${existing.collection_id}:*`);
189
190
  await cache.invalidate("content-filtered:*");
@@ -208,7 +209,7 @@ apiRoutes.use("*", async (c, next) => {
208
209
  c.header("X-Response-Time", `${totalTime}ms`);
209
210
  });
210
211
  apiRoutes.use("*", async (c, next) => {
211
- const cacheEnabled = await chunkKM4AJFXI_cjs.isPluginActive(c.env.DB, "core-cache");
212
+ const cacheEnabled = await chunk4BJGEGX5_cjs.isPluginActive(c.env.DB, "core-cache");
212
213
  c.set("cacheEnabled", cacheEnabled);
213
214
  await next();
214
215
  });
@@ -256,7 +257,7 @@ apiRoutes.get("/collections", async (c) => {
256
257
  try {
257
258
  const db = c.env.DB;
258
259
  const cacheEnabled = c.get("cacheEnabled");
259
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.api);
260
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.api);
260
261
  const cacheKey = cache.generateKey("collections", "all");
261
262
  if (cacheEnabled) {
262
263
  const cacheResult = await cache.getWithSource(cacheKey);
@@ -333,12 +334,12 @@ apiRoutes.get("/content", async (c) => {
333
334
  });
334
335
  }
335
336
  }
336
- const filter = chunkNK6FN5R5_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
337
+ const filter = chunkUL32L2KV_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
337
338
  if (!filter.limit) {
338
339
  filter.limit = 50;
339
340
  }
340
341
  filter.limit = Math.min(filter.limit, 1e3);
341
- const builder = new chunkNK6FN5R5_cjs.QueryFilterBuilder();
342
+ const builder = new chunkUL32L2KV_cjs.QueryFilterBuilder();
342
343
  const queryResult = builder.build("content", filter);
343
344
  if (queryResult.errors.length > 0) {
344
345
  return c.json({
@@ -347,7 +348,7 @@ apiRoutes.get("/content", async (c) => {
347
348
  }, 400);
348
349
  }
349
350
  const cacheEnabled = c.get("cacheEnabled");
350
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.api);
351
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.api);
351
352
  const cacheKey = cache.generateKey("content-filtered", JSON.stringify({ filter, query: queryResult.sql }));
352
353
  if (cacheEnabled) {
353
354
  const cacheResult = await cache.getWithSource(cacheKey);
@@ -425,7 +426,7 @@ apiRoutes.get("/collections/:collection/content", async (c) => {
425
426
  if (!collectionResult) {
426
427
  return c.json({ error: "Collection not found" }, 404);
427
428
  }
428
- const filter = chunkNK6FN5R5_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
429
+ const filter = chunkUL32L2KV_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
429
430
  if (!filter.where) {
430
431
  filter.where = { and: [] };
431
432
  }
@@ -441,7 +442,7 @@ apiRoutes.get("/collections/:collection/content", async (c) => {
441
442
  filter.limit = 50;
442
443
  }
443
444
  filter.limit = Math.min(filter.limit, 1e3);
444
- const builder = new chunkNK6FN5R5_cjs.QueryFilterBuilder();
445
+ const builder = new chunkUL32L2KV_cjs.QueryFilterBuilder();
445
446
  const queryResult = builder.build("content", filter);
446
447
  if (queryResult.errors.length > 0) {
447
448
  return c.json({
@@ -450,7 +451,7 @@ apiRoutes.get("/collections/:collection/content", async (c) => {
450
451
  }, 400);
451
452
  }
452
453
  const cacheEnabled = c.get("cacheEnabled");
453
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.api);
454
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.api);
454
455
  const cacheKey = cache.generateKey("collection-content-filtered", `${collection}:${JSON.stringify({ filter, query: queryResult.sql })}`);
455
456
  if (cacheEnabled) {
456
457
  const cacheResult = await cache.getWithSource(cacheKey);
@@ -566,7 +567,7 @@ var fileValidationSchema = zod.z.object({
566
567
  // 50MB max
567
568
  });
568
569
  var apiMediaRoutes = new hono.Hono();
569
- apiMediaRoutes.use("*", chunkKM4AJFXI_cjs.requireAuth());
570
+ apiMediaRoutes.use("*", chunk4BJGEGX5_cjs.requireAuth());
570
571
  apiMediaRoutes.post("/upload", async (c) => {
571
572
  try {
572
573
  const user = c.get("user");
@@ -1301,8 +1302,8 @@ apiSystemRoutes.get("/env", (c) => {
1301
1302
  });
1302
1303
  var api_system_default = apiSystemRoutes;
1303
1304
  var adminApiRoutes = new hono.Hono();
1304
- adminApiRoutes.use("*", chunkKM4AJFXI_cjs.requireAuth());
1305
- adminApiRoutes.use("*", chunkKM4AJFXI_cjs.requireRole(["admin", "editor"]));
1305
+ adminApiRoutes.use("*", chunk4BJGEGX5_cjs.requireAuth());
1306
+ adminApiRoutes.use("*", chunk4BJGEGX5_cjs.requireRole(["admin", "editor"]));
1306
1307
  adminApiRoutes.get("/stats", async (c) => {
1307
1308
  try {
1308
1309
  const db = c.env.DB;
@@ -1754,8 +1755,8 @@ function renderLoginPage(data, demoLoginActive = false) {
1754
1755
  <div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
1755
1756
  <div class="bg-zinc-900 shadow-sm ring-1 ring-white/10 rounded-xl px-6 py-8 sm:px-10">
1756
1757
  <!-- Alerts -->
1757
- ${data.error ? `<div class="mb-6">${chunkALOS2CBJ_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
1758
- ${data.message ? `<div class="mb-6">${chunkALOS2CBJ_cjs.renderAlert({ type: "success", message: data.message })}</div>` : ""}
1758
+ ${data.error ? `<div class="mb-6">${chunk3SPQ3J4N_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
1759
+ ${data.message ? `<div class="mb-6">${chunk3SPQ3J4N_cjs.renderAlert({ type: "success", message: data.message })}</div>` : ""}
1759
1760
 
1760
1761
  <!-- Form Response (HTMX target) -->
1761
1762
  <div id="form-response" class="mb-6"></div>
@@ -1919,7 +1920,7 @@ function renderRegisterPage(data) {
1919
1920
  <div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
1920
1921
  <div class="bg-zinc-900 shadow-sm ring-1 ring-white/10 rounded-xl px-6 py-8 sm:px-10">
1921
1922
  <!-- Alerts -->
1922
- ${data.error ? `<div class="mb-6">${chunkALOS2CBJ_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
1923
+ ${data.error ? `<div class="mb-6">${chunk3SPQ3J4N_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
1923
1924
 
1924
1925
  <!-- Form -->
1925
1926
  <form
@@ -2032,9 +2033,36 @@ function renderRegisterPage(data) {
2032
2033
  </html>
2033
2034
  `;
2034
2035
  }
2035
-
2036
- // src/services/auth-validation.ts
2037
- var authValidationService = {};
2036
+ var authValidationService = {
2037
+ /**
2038
+ * Build registration schema dynamically based on auth settings
2039
+ * For now, returns a static schema with standard fields
2040
+ */
2041
+ async buildRegistrationSchema(_db) {
2042
+ return zod.z.object({
2043
+ email: zod.z.string().email("Valid email is required"),
2044
+ password: zod.z.string().min(8, "Password must be at least 8 characters"),
2045
+ username: zod.z.string().min(3, "Username must be at least 3 characters").optional(),
2046
+ firstName: zod.z.string().min(1, "First name is required").optional(),
2047
+ lastName: zod.z.string().min(1, "Last name is required").optional()
2048
+ });
2049
+ },
2050
+ /**
2051
+ * Generate default values for optional fields
2052
+ */
2053
+ generateDefaultValue(field, data) {
2054
+ switch (field) {
2055
+ case "username":
2056
+ return data.email ? data.email.split("@")[0] : `user${Date.now()}`;
2057
+ case "firstName":
2058
+ return "User";
2059
+ case "lastName":
2060
+ return data.email ? data.email.split("@")[0] : "Account";
2061
+ default:
2062
+ return "";
2063
+ }
2064
+ }
2065
+ };
2038
2066
 
2039
2067
  // src/routes/auth.ts
2040
2068
  var authRoutes = new hono.Hono();
@@ -2091,7 +2119,7 @@ authRoutes.post(
2091
2119
  if (existingUser) {
2092
2120
  return c.json({ error: "User with this email or username already exists" }, 400);
2093
2121
  }
2094
- const passwordHash = await chunkKM4AJFXI_cjs.AuthManager.hashPassword(password);
2122
+ const passwordHash = await chunk4BJGEGX5_cjs.AuthManager.hashPassword(password);
2095
2123
  const userId = crypto.randomUUID();
2096
2124
  const now = /* @__PURE__ */ new Date();
2097
2125
  await db.prepare(`
@@ -2111,7 +2139,7 @@ authRoutes.post(
2111
2139
  now.getTime(),
2112
2140
  now.getTime()
2113
2141
  ).run();
2114
- const token = await chunkKM4AJFXI_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer");
2142
+ const token = await chunk4BJGEGX5_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer");
2115
2143
  cookie.setCookie(c, "auth_token", token, {
2116
2144
  httpOnly: true,
2117
2145
  secure: true,
@@ -2146,7 +2174,7 @@ authRoutes.post("/login", async (c) => {
2146
2174
  const { email, password } = validation.data;
2147
2175
  const db = c.env.DB;
2148
2176
  const normalizedEmail = email.toLowerCase();
2149
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.user);
2177
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.user);
2150
2178
  let user = await cache.get(cache.generateKey("user", `email:${normalizedEmail}`));
2151
2179
  if (!user) {
2152
2180
  user = await db.prepare("SELECT * FROM users WHERE email = ? AND is_active = 1").bind(normalizedEmail).first();
@@ -2158,11 +2186,11 @@ authRoutes.post("/login", async (c) => {
2158
2186
  if (!user) {
2159
2187
  return c.json({ error: "Invalid email or password" }, 401);
2160
2188
  }
2161
- const isValidPassword = await chunkKM4AJFXI_cjs.AuthManager.verifyPassword(password, user.password_hash);
2189
+ const isValidPassword = await chunk4BJGEGX5_cjs.AuthManager.verifyPassword(password, user.password_hash);
2162
2190
  if (!isValidPassword) {
2163
2191
  return c.json({ error: "Invalid email or password" }, 401);
2164
2192
  }
2165
- const token = await chunkKM4AJFXI_cjs.AuthManager.generateToken(user.id, user.email, user.role);
2193
+ const token = await chunk4BJGEGX5_cjs.AuthManager.generateToken(user.id, user.email, user.role);
2166
2194
  cookie.setCookie(c, "auth_token", token, {
2167
2195
  httpOnly: true,
2168
2196
  secure: true,
@@ -2211,7 +2239,7 @@ authRoutes.get("/logout", (c) => {
2211
2239
  });
2212
2240
  return c.redirect("/auth/login?message=You have been logged out successfully");
2213
2241
  });
2214
- authRoutes.get("/me", chunkKM4AJFXI_cjs.requireAuth(), async (c) => {
2242
+ authRoutes.get("/me", chunk4BJGEGX5_cjs.requireAuth(), async (c) => {
2215
2243
  try {
2216
2244
  const user = c.get("user");
2217
2245
  if (!user) {
@@ -2228,13 +2256,13 @@ authRoutes.get("/me", chunkKM4AJFXI_cjs.requireAuth(), async (c) => {
2228
2256
  return c.json({ error: "Failed to get user" }, 500);
2229
2257
  }
2230
2258
  });
2231
- authRoutes.post("/refresh", chunkKM4AJFXI_cjs.requireAuth(), async (c) => {
2259
+ authRoutes.post("/refresh", chunk4BJGEGX5_cjs.requireAuth(), async (c) => {
2232
2260
  try {
2233
2261
  const user = c.get("user");
2234
2262
  if (!user) {
2235
2263
  return c.json({ error: "Not authenticated" }, 401);
2236
2264
  }
2237
- const token = await chunkKM4AJFXI_cjs.AuthManager.generateToken(user.userId, user.email, user.role);
2265
+ const token = await chunk4BJGEGX5_cjs.AuthManager.generateToken(user.userId, user.email, user.role);
2238
2266
  cookie.setCookie(c, "auth_token", token, {
2239
2267
  httpOnly: true,
2240
2268
  secure: true,
@@ -2284,7 +2312,7 @@ authRoutes.post("/register/form", async (c) => {
2284
2312
  </div>
2285
2313
  `);
2286
2314
  }
2287
- const passwordHash = await chunkKM4AJFXI_cjs.AuthManager.hashPassword(password);
2315
+ const passwordHash = await chunk4BJGEGX5_cjs.AuthManager.hashPassword(password);
2288
2316
  const userId = crypto.randomUUID();
2289
2317
  const now = /* @__PURE__ */ new Date();
2290
2318
  await db.prepare(`
@@ -2304,7 +2332,7 @@ authRoutes.post("/register/form", async (c) => {
2304
2332
  now.getTime(),
2305
2333
  now.getTime()
2306
2334
  ).run();
2307
- const token = await chunkKM4AJFXI_cjs.AuthManager.generateToken(userId, normalizedEmail, "admin");
2335
+ const token = await chunk4BJGEGX5_cjs.AuthManager.generateToken(userId, normalizedEmail, "admin");
2308
2336
  cookie.setCookie(c, "auth_token", token, {
2309
2337
  httpOnly: true,
2310
2338
  secure: false,
@@ -2355,7 +2383,7 @@ authRoutes.post("/login/form", async (c) => {
2355
2383
  </div>
2356
2384
  `);
2357
2385
  }
2358
- const isValidPassword = await chunkKM4AJFXI_cjs.AuthManager.verifyPassword(password, user.password_hash);
2386
+ const isValidPassword = await chunk4BJGEGX5_cjs.AuthManager.verifyPassword(password, user.password_hash);
2359
2387
  if (!isValidPassword) {
2360
2388
  return c.html(html.html`
2361
2389
  <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
@@ -2363,7 +2391,7 @@ authRoutes.post("/login/form", async (c) => {
2363
2391
  </div>
2364
2392
  `);
2365
2393
  }
2366
- const token = await chunkKM4AJFXI_cjs.AuthManager.generateToken(user.id, user.email, user.role);
2394
+ const token = await chunk4BJGEGX5_cjs.AuthManager.generateToken(user.id, user.email, user.role);
2367
2395
  cookie.setCookie(c, "auth_token", token, {
2368
2396
  httpOnly: true,
2369
2397
  secure: false,
@@ -2432,7 +2460,7 @@ authRoutes.post("/seed-admin", async (c) => {
2432
2460
  }
2433
2461
  });
2434
2462
  }
2435
- const passwordHash = await chunkKM4AJFXI_cjs.AuthManager.hashPassword("admin123");
2463
+ const passwordHash = await chunk4BJGEGX5_cjs.AuthManager.hashPassword("admin123");
2436
2464
  const userId = "admin-user-id";
2437
2465
  const now = Date.now();
2438
2466
  const adminEmail = "admin@sonicjs.com".toLowerCase();
@@ -2652,7 +2680,7 @@ authRoutes.post("/accept-invitation", async (c) => {
2652
2680
  if (existingUsername) {
2653
2681
  return c.json({ error: "Username is already taken" }, 400);
2654
2682
  }
2655
- const passwordHash = await chunkKM4AJFXI_cjs.AuthManager.hashPassword(password);
2683
+ const passwordHash = await chunk4BJGEGX5_cjs.AuthManager.hashPassword(password);
2656
2684
  const updateStmt = db.prepare(`
2657
2685
  UPDATE users SET
2658
2686
  username = ?,
@@ -2671,7 +2699,7 @@ authRoutes.post("/accept-invitation", async (c) => {
2671
2699
  Date.now(),
2672
2700
  invitedUser.id
2673
2701
  ).run();
2674
- const authToken = await chunkKM4AJFXI_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role);
2702
+ const authToken = await chunk4BJGEGX5_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role);
2675
2703
  cookie.setCookie(c, "auth_token", authToken, {
2676
2704
  httpOnly: true,
2677
2705
  secure: true,
@@ -2901,7 +2929,7 @@ authRoutes.post("/reset-password", async (c) => {
2901
2929
  if (Date.now() > user.password_reset_expires) {
2902
2930
  return c.json({ error: "Reset token has expired" }, 400);
2903
2931
  }
2904
- const newPasswordHash = await chunkKM4AJFXI_cjs.AuthManager.hashPassword(password);
2932
+ const newPasswordHash = await chunk4BJGEGX5_cjs.AuthManager.hashPassword(password);
2905
2933
  try {
2906
2934
  const historyStmt = db.prepare(`
2907
2935
  INSERT INTO password_history (id, user_id, password_hash, created_at)
@@ -2938,7 +2966,7 @@ authRoutes.post("/reset-password", async (c) => {
2938
2966
  var auth_default = authRoutes;
2939
2967
 
2940
2968
  // src/templates/pages/admin-content-form.template.ts
2941
- chunkALOS2CBJ_cjs.init_admin_layout_catalyst_template();
2969
+ chunk3SPQ3J4N_cjs.init_admin_layout_catalyst_template();
2942
2970
 
2943
2971
  // src/templates/components/dynamic-field.template.ts
2944
2972
  function renderDynamicField(field, options = {}) {
@@ -3342,8 +3370,8 @@ function renderContentFormPage(data) {
3342
3370
  <!-- Form Content -->
3343
3371
  <div class="px-6 py-6">
3344
3372
  <div id="form-messages">
3345
- ${data.error ? chunkALOS2CBJ_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
3346
- ${data.success ? chunkALOS2CBJ_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
3373
+ ${data.error ? chunk3SPQ3J4N_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
3374
+ ${data.success ? chunk3SPQ3J4N_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
3347
3375
  </div>
3348
3376
 
3349
3377
  <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
@@ -3578,7 +3606,7 @@ function renderContentFormPage(data) {
3578
3606
  </div>
3579
3607
 
3580
3608
  <!-- Confirmation Dialogs -->
3581
- ${chunkALOS2CBJ_cjs.renderConfirmationDialog({
3609
+ ${chunk3SPQ3J4N_cjs.renderConfirmationDialog({
3582
3610
  id: "duplicate-content-confirm",
3583
3611
  title: "Duplicate Content",
3584
3612
  message: "Create a copy of this content?",
@@ -3589,7 +3617,7 @@ function renderContentFormPage(data) {
3589
3617
  onConfirm: "performDuplicateContent()"
3590
3618
  })}
3591
3619
 
3592
- ${chunkALOS2CBJ_cjs.renderConfirmationDialog({
3620
+ ${chunk3SPQ3J4N_cjs.renderConfirmationDialog({
3593
3621
  id: "delete-content-confirm",
3594
3622
  title: "Delete Content",
3595
3623
  message: "Are you sure you want to delete this content? This action cannot be undone.",
@@ -3600,7 +3628,7 @@ function renderContentFormPage(data) {
3600
3628
  onConfirm: `performDeleteContent('${data.id}')`
3601
3629
  })}
3602
3630
 
3603
- ${chunkALOS2CBJ_cjs.getConfirmationDialogScript()}
3631
+ ${chunk3SPQ3J4N_cjs.getConfirmationDialogScript()}
3604
3632
 
3605
3633
  <!-- TinyMCE CDN -->
3606
3634
  <script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
@@ -3888,11 +3916,11 @@ function renderContentFormPage(data) {
3888
3916
  content: pageContent,
3889
3917
  version: data.version
3890
3918
  };
3891
- return chunkALOS2CBJ_cjs.renderAdminLayoutCatalyst(layoutData);
3919
+ return chunk3SPQ3J4N_cjs.renderAdminLayoutCatalyst(layoutData);
3892
3920
  }
3893
3921
 
3894
3922
  // src/templates/pages/admin-content-list.template.ts
3895
- chunkALOS2CBJ_cjs.init_admin_layout_catalyst_template();
3923
+ chunk3SPQ3J4N_cjs.init_admin_layout_catalyst_template();
3896
3924
  function renderContentListPage(data) {
3897
3925
  const urlParams = new URLSearchParams();
3898
3926
  if (data.modelName && data.modelName !== "all") urlParams.set("model", data.modelName);
@@ -4288,8 +4316,8 @@ function renderContentListPage(data) {
4288
4316
 
4289
4317
  <!-- Content List -->
4290
4318
  <div id="content-list">
4291
- ${chunkALOS2CBJ_cjs.renderTable(tableData)}
4292
- ${chunkALOS2CBJ_cjs.renderPagination(paginationData)}
4319
+ ${chunk3SPQ3J4N_cjs.renderTable(tableData)}
4320
+ ${chunk3SPQ3J4N_cjs.renderPagination(paginationData)}
4293
4321
  </div>
4294
4322
 
4295
4323
  </div>
@@ -4498,7 +4526,7 @@ function renderContentListPage(data) {
4498
4526
  </script>
4499
4527
 
4500
4528
  <!-- Confirmation Dialog for Bulk Actions -->
4501
- ${chunkALOS2CBJ_cjs.renderConfirmationDialog({
4529
+ ${chunk3SPQ3J4N_cjs.renderConfirmationDialog({
4502
4530
  id: "bulk-action-confirm",
4503
4531
  title: "Confirm Bulk Action",
4504
4532
  message: "Are you sure you want to perform this action? This operation will affect multiple items.",
@@ -4510,7 +4538,7 @@ function renderContentListPage(data) {
4510
4538
  })}
4511
4539
 
4512
4540
  <!-- Confirmation Dialog Script -->
4513
- ${chunkALOS2CBJ_cjs.getConfirmationDialogScript()}
4541
+ ${chunk3SPQ3J4N_cjs.getConfirmationDialogScript()}
4514
4542
  `;
4515
4543
  const layoutData = {
4516
4544
  title: "Content Management",
@@ -4520,7 +4548,7 @@ function renderContentListPage(data) {
4520
4548
  version: data.version,
4521
4549
  content: pageContent
4522
4550
  };
4523
- return chunkALOS2CBJ_cjs.renderAdminLayoutCatalyst(layoutData);
4551
+ return chunk3SPQ3J4N_cjs.renderAdminLayoutCatalyst(layoutData);
4524
4552
  }
4525
4553
 
4526
4554
  // src/templates/components/version-history.template.ts
@@ -4706,8 +4734,9 @@ var isPluginActive2 = () => false;
4706
4734
 
4707
4735
  // src/routes/admin-content.ts
4708
4736
  var adminContentRoutes = new hono.Hono();
4737
+ adminContentRoutes.use("*", chunk4BJGEGX5_cjs.requireAuth());
4709
4738
  async function getCollectionFields(db, collectionId) {
4710
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.collection);
4739
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.collection);
4711
4740
  return cache.getOrSet(
4712
4741
  cache.generateKey("fields", collectionId),
4713
4742
  async () => {
@@ -4731,7 +4760,7 @@ async function getCollectionFields(db, collectionId) {
4731
4760
  );
4732
4761
  }
4733
4762
  async function getCollection(db, collectionId) {
4734
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.collection);
4763
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.collection);
4735
4764
  return cache.getOrSet(
4736
4765
  cache.generateKey("collection", collectionId),
4737
4766
  async () => {
@@ -4987,7 +5016,7 @@ adminContentRoutes.get("/:id/edit", async (c) => {
4987
5016
  const db = c.env.DB;
4988
5017
  const url = new URL(c.req.url);
4989
5018
  const referrerParams = url.searchParams.get("ref") || "";
4990
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.content);
5019
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.content);
4991
5020
  const content = await cache.getOrSet(
4992
5021
  cache.generateKey("content", id),
4993
5022
  async () => {
@@ -5177,7 +5206,7 @@ adminContentRoutes.post("/", async (c) => {
5177
5206
  now,
5178
5207
  now
5179
5208
  ).run();
5180
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.content);
5209
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.content);
5181
5210
  await cache.invalidate(`content:list:${collectionId}:*`);
5182
5211
  const versionStmt = db.prepare(`
5183
5212
  INSERT INTO content_versions (id, content_id, version, data, author_id, created_at)
@@ -5325,7 +5354,7 @@ adminContentRoutes.put("/:id", async (c) => {
5325
5354
  now,
5326
5355
  id
5327
5356
  ).run();
5328
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.content);
5357
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.content);
5329
5358
  await cache.delete(cache.generateKey("content", id));
5330
5359
  await cache.invalidate(`content:list:${existingContent.collection_id}:*`);
5331
5360
  const existingData = JSON.parse(existingContent.data || "{}");
@@ -5618,7 +5647,7 @@ adminContentRoutes.post("/bulk-action", async (c) => {
5618
5647
  } else {
5619
5648
  return c.json({ success: false, error: "Invalid action" });
5620
5649
  }
5621
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.content);
5650
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.content);
5622
5651
  for (const contentId of ids) {
5623
5652
  await cache.delete(cache.generateKey("content", contentId));
5624
5653
  }
@@ -5646,7 +5675,7 @@ adminContentRoutes.delete("/:id", async (c) => {
5646
5675
  WHERE id = ?
5647
5676
  `);
5648
5677
  await deleteStmt.bind(now, id).run();
5649
- const cache = chunkSRCY43RN_cjs.getCacheService(chunkSRCY43RN_cjs.CACHE_CONFIGS.content);
5678
+ const cache = chunk3NVJ6W27_cjs.getCacheService(chunk3NVJ6W27_cjs.CACHE_CONFIGS.content);
5650
5679
  await cache.delete(cache.generateKey("content", id));
5651
5680
  await cache.invalidate("content:list:*");
5652
5681
  return c.html(`
@@ -5838,170 +5867,157 @@ ${JSON.stringify(data, null, 2)}
5838
5867
  var admin_content_default = adminContentRoutes;
5839
5868
 
5840
5869
  // src/templates/pages/admin-profile.template.ts
5870
+ chunk3SPQ3J4N_cjs.init_admin_layout_catalyst_template();
5841
5871
  function renderProfilePage(data) {
5842
5872
  const pageContent = `
5843
- <div class="w-full px-4 sm:px-6 lg:px-8 py-6">
5873
+ <div class="space-y-8">
5844
5874
  <!-- Header -->
5845
- <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6">
5875
+ <div class="sm:flex sm:items-center sm:justify-between">
5846
5876
  <div>
5847
- <h1 class="text-2xl font-semibold text-white">User Profile</h1>
5848
- <p class="mt-2 text-sm text-gray-300">Manage your account settings and preferences</p>
5877
+ <h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">User Profile</h1>
5878
+ <p class="mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400">
5879
+ Manage your account settings and preferences
5880
+ </p>
5849
5881
  </div>
5850
5882
  </div>
5851
5883
 
5852
- <!-- Breadcrumb -->
5853
- <nav class="flex mb-6" aria-label="Breadcrumb">
5854
- <ol class="flex items-center space-x-3">
5855
- <li>
5856
- <a href="/admin" class="text-gray-300 hover:text-white transition-colors">
5857
- <svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
5858
- <path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"/>
5859
- </svg>
5860
- </a>
5861
- </li>
5862
- <li class="flex items-center">
5863
- <svg class="h-5 w-5 text-gray-400 mx-2" fill="currentColor" viewBox="0 0 20 20">
5864
- <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/>
5865
- </svg>
5866
- <span class="text-sm font-medium text-gray-200">Profile</span>
5867
- </li>
5868
- </ol>
5869
- </nav>
5870
-
5871
5884
  <!-- Alert Messages -->
5872
- ${data.error ? chunkALOS2CBJ_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
5873
- ${data.success ? chunkALOS2CBJ_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
5885
+ ${data.error ? chunk3SPQ3J4N_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
5886
+ ${data.success ? chunk3SPQ3J4N_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
5874
5887
 
5875
5888
  <!-- Profile Form -->
5876
- <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
5889
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
5877
5890
  <!-- Main Profile Form -->
5878
5891
  <div class="lg:col-span-2">
5879
- <div class="backdrop-blur-xl bg-white/10 rounded-3xl border border-white/20 shadow-2xl overflow-hidden">
5892
+ <div class="rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10">
5880
5893
  <!-- Form Header -->
5881
- <div class="relative px-8 py-6 border-b border-white/10">
5882
- <div class="absolute inset-0 bg-gradient-to-r from-blue-600/10 via-purple-600/10 to-pink-600/10"></div>
5883
- <div class="relative flex items-center gap-3">
5884
- <div class="w-12 h-12 rounded-xl bg-white/10 backdrop-blur-sm flex items-center justify-center">
5885
- <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5894
+ <div class="px-6 py-5 border-b border-zinc-950/5 dark:border-white/5">
5895
+ <div class="flex items-center gap-x-3">
5896
+ <div class="flex h-10 w-10 items-center justify-center rounded-lg bg-zinc-950 dark:bg-white">
5897
+ <svg class="h-5 w-5 text-white dark:text-zinc-950" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5886
5898
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
5887
5899
  </svg>
5888
5900
  </div>
5889
5901
  <div>
5890
- <h2 class="text-xl font-semibold text-white">Profile Information</h2>
5891
- <p class="text-sm text-gray-300">Update your account details and preferences</p>
5902
+ <h2 class="text-base font-semibold text-zinc-950 dark:text-white">Profile Information</h2>
5903
+ <p class="text-sm text-zinc-500 dark:text-zinc-400">Update your account details</p>
5892
5904
  </div>
5893
5905
  </div>
5894
5906
  </div>
5895
5907
 
5896
5908
  <!-- Form Content -->
5897
- <form id="profile-form" hx-put="/admin/profile" hx-target="#form-messages" class="p-8 space-y-6">
5909
+ <form id="profile-form" hx-put="/admin/profile" hx-target="#form-messages" class="p-6 space-y-6">
5898
5910
  <div id="form-messages"></div>
5899
5911
 
5900
5912
  <!-- Basic Information -->
5901
5913
  <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
5902
5914
  <div>
5903
- <label class="block text-sm font-medium text-gray-300 mb-2">First Name</label>
5904
- <input
5905
- type="text"
5906
- name="first_name"
5915
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">First Name</label>
5916
+ <input
5917
+ type="text"
5918
+ name="first_name"
5907
5919
  value="${data.profile.first_name}"
5908
5920
  required
5909
- class="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30 focus:ring-2 focus:ring-white/20 transition-all"
5921
+ class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
5910
5922
  placeholder="Enter your first name"
5911
5923
  >
5912
5924
  </div>
5913
5925
  <div>
5914
- <label class="block text-sm font-medium text-gray-300 mb-2">Last Name</label>
5915
- <input
5916
- type="text"
5917
- name="last_name"
5926
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Last Name</label>
5927
+ <input
5928
+ type="text"
5929
+ name="last_name"
5918
5930
  value="${data.profile.last_name}"
5919
5931
  required
5920
- class="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30 focus:ring-2 focus:ring-white/20 transition-all"
5932
+ class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
5921
5933
  placeholder="Enter your last name"
5922
5934
  >
5923
5935
  </div>
5924
5936
  </div>
5925
5937
 
5926
5938
  <div>
5927
- <label class="block text-sm font-medium text-gray-300 mb-2">Username</label>
5928
- <input
5929
- type="text"
5930
- name="username"
5939
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Username</label>
5940
+ <input
5941
+ type="text"
5942
+ name="username"
5931
5943
  value="${data.profile.username}"
5932
5944
  required
5933
- class="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30 focus:ring-2 focus:ring-white/20 transition-all"
5945
+ class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
5934
5946
  placeholder="Enter your username"
5935
5947
  >
5936
5948
  </div>
5937
5949
 
5938
5950
  <div>
5939
- <label class="block text-sm font-medium text-gray-300 mb-2">Email Address</label>
5940
- <input
5941
- type="email"
5942
- name="email"
5951
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Email Address</label>
5952
+ <input
5953
+ type="email"
5954
+ name="email"
5943
5955
  value="${data.profile.email}"
5944
5956
  required
5945
- class="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30 focus:ring-2 focus:ring-white/20 transition-all"
5957
+ class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
5946
5958
  placeholder="Enter your email address"
5947
5959
  >
5948
5960
  </div>
5949
5961
 
5950
5962
  <div>
5951
- <label class="block text-sm font-medium text-gray-300 mb-2">Phone Number</label>
5952
- <input
5953
- type="tel"
5954
- name="phone"
5963
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Phone Number</label>
5964
+ <input
5965
+ type="tel"
5966
+ name="phone"
5955
5967
  value="${data.profile.phone || ""}"
5956
- class="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30 focus:ring-2 focus:ring-white/20 transition-all"
5968
+ class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
5957
5969
  placeholder="Enter your phone number"
5958
5970
  >
5959
5971
  </div>
5960
5972
 
5961
5973
  <div>
5962
- <label class="block text-sm font-medium text-gray-300 mb-2">Bio</label>
5963
- <textarea
5964
- name="bio"
5974
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Bio</label>
5975
+ <textarea
5976
+ name="bio"
5965
5977
  rows="3"
5966
- class="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30 focus:ring-2 focus:ring-white/20 transition-all resize-none"
5978
+ class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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 resize-none"
5967
5979
  placeholder="Tell us about yourself..."
5968
5980
  >${data.profile.bio || ""}</textarea>
5969
5981
  </div>
5970
5982
 
5971
5983
  <!-- Preferences -->
5972
- <div class="pt-6 border-t border-white/10">
5973
- <h3 class="text-lg font-semibold text-white mb-4">Preferences</h3>
5974
-
5984
+ <div class="pt-6 border-t border-zinc-950/5 dark:border-white/5">
5985
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Preferences</h3>
5986
+
5975
5987
  <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
5976
5988
  <div>
5977
- <label class="block text-sm font-medium text-gray-300 mb-2">Timezone</label>
5978
- <select
5979
- name="timezone"
5980
- class="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30 focus:ring-2 focus:ring-white/20 transition-all"
5981
- >
5982
- ${data.timezones.map((tz) => `
5983
- <option value="${tz.value}" ${tz.value === data.profile.timezone ? "selected" : ""}>${tz.label}</option>
5984
- `).join("")}
5985
- </select>
5989
+ <label for="timezone" class="block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2">Timezone</label>
5990
+ <div class="grid grid-cols-1">
5991
+ <select id="timezone" name="timezone" class="col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-zinc-500/30 dark:outline-zinc-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-zinc-500 dark:focus-visible:outline-zinc-400 sm:text-sm/6">
5992
+ ${data.timezones.map((tz) => `
5993
+ <option value="${tz.value}" ${tz.value === data.profile.timezone ? "selected" : ""}>${tz.label}</option>
5994
+ `).join("")}
5995
+ </select>
5996
+ <svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" class="pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-zinc-600 dark:text-zinc-400 sm:size-4">
5997
+ <path d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" fill-rule="evenodd" />
5998
+ </svg>
5999
+ </div>
5986
6000
  </div>
5987
6001
  <div>
5988
- <label class="block text-sm font-medium text-gray-300 mb-2">Language</label>
5989
- <select
5990
- name="language"
5991
- class="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30 focus:ring-2 focus:ring-white/20 transition-all"
5992
- >
5993
- ${data.languages.map((lang) => `
5994
- <option value="${lang.value}" ${lang.value === data.profile.language ? "selected" : ""}>${lang.label}</option>
5995
- `).join("")}
5996
- </select>
6002
+ <label for="language" class="block text-sm/6 font-medium text-zinc-950 dark:text-white mb-2">Language</label>
6003
+ <div class="grid grid-cols-1">
6004
+ <select id="language" name="language" class="col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-zinc-500/30 dark:outline-zinc-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-zinc-500 dark:focus-visible:outline-zinc-400 sm:text-sm/6">
6005
+ ${data.languages.map((lang) => `
6006
+ <option value="${lang.value}" ${lang.value === data.profile.language ? "selected" : ""}>${lang.label}</option>
6007
+ `).join("")}
6008
+ </select>
6009
+ <svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" class="pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-zinc-600 dark:text-zinc-400 sm:size-4">
6010
+ <path d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" fill-rule="evenodd" />
6011
+ </svg>
6012
+ </div>
5997
6013
  </div>
5998
6014
  </div>
5999
6015
  </div>
6000
6016
 
6001
6017
  <!-- Notifications -->
6002
- <div class="pt-6 border-t border-white/10">
6003
- <h3 class="text-lg font-semibold text-white mb-4">Notifications</h3>
6004
-
6018
+ <div class="pt-6 border-t border-zinc-950/5 dark:border-white/5">
6019
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Notifications</h3>
6020
+
6005
6021
  <div class="space-y-5">
6006
6022
  <div class="flex gap-3">
6007
6023
  <div class="flex h-6 shrink-0 items-center">
@@ -6012,27 +6028,30 @@ function renderProfilePage(data) {
6012
6028
  name="email_notifications"
6013
6029
  value="1"
6014
6030
  ${data.profile.email_notifications ? "checked" : ""}
6015
- class="col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 indeterminate:border-indigo-500 indeterminate:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 disabled:checked:bg-zinc-950/10 dark:disabled:checked:bg-white/10 forced-colors:appearance-auto"
6031
+ class="col-start-1 row-start-1 appearance-none rounded border border-zinc-950/10 dark:border-white/10 bg-white dark:bg-white/5 checked:border-indigo-500 checked:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:border-zinc-950/5 dark:disabled:border-white/5 disabled:bg-zinc-950/10 dark:disabled:bg-white/10 forced-colors:appearance-auto"
6016
6032
  />
6017
6033
  <svg viewBox="0 0 14 14" fill="none" class="pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-zinc-950/25 dark:group-has-[:disabled]:stroke-white/25">
6018
6034
  <path d="M3 8L6 11L11 3.5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="opacity-0 group-has-[:checked]:opacity-100" />
6019
- <path d="M3 7H11" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="opacity-0 group-has-[:indeterminate]:opacity-100" />
6020
6035
  </svg>
6021
6036
  </div>
6022
6037
  </div>
6023
6038
  <div class="text-sm/6">
6024
6039
  <label for="email_notifications" class="font-medium text-zinc-950 dark:text-white">Email notifications</label>
6040
+ <p class="text-zinc-500 dark:text-zinc-400">Receive email updates about new features and product announcements.</p>
6025
6041
  </div>
6026
6042
  </div>
6027
6043
  </div>
6028
6044
  </div>
6029
6045
 
6030
6046
  <!-- Submit Button -->
6031
- <div class="pt-6 border-t border-white/10">
6032
- <button
6047
+ <div class="pt-6 border-t border-zinc-950/5 dark:border-white/5">
6048
+ <button
6033
6049
  type="submit"
6034
- class="w-full px-6 py-3 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-semibold rounded-xl hover:from-blue-700 hover:to-purple-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:ring-offset-transparent transition-all"
6050
+ class="inline-flex justify-center items-center gap-x-2 rounded-lg bg-zinc-950 dark:bg-white px-4 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-950 dark:focus-visible:outline-white transition-colors"
6035
6051
  >
6052
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6053
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
6054
+ </svg>
6036
6055
  Update Profile
6037
6056
  </button>
6038
6057
  </div>
@@ -6043,86 +6062,96 @@ function renderProfilePage(data) {
6043
6062
  <!-- Profile Sidebar -->
6044
6063
  <div class="lg:col-span-1 space-y-6">
6045
6064
  <!-- Avatar -->
6046
- <div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl p-6">
6047
- <h3 class="text-lg font-semibold text-white mb-4">Profile Picture</h3>
6048
-
6065
+ <div class="rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6">
6066
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Profile Picture</h3>
6067
+
6049
6068
  <div class="text-center">
6050
- <div class="w-24 h-24 rounded-full mx-auto mb-4 overflow-hidden bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
6069
+ <div class="w-24 h-24 rounded-full mx-auto mb-4 overflow-hidden bg-gradient-to-br from-cyan-400 to-purple-400 flex items-center justify-center ring-4 ring-zinc-950/5 dark:ring-white/10">
6051
6070
  ${data.profile.avatar_url ? `<img src="${data.profile.avatar_url}" alt="Profile picture" class="w-full h-full object-cover">` : `<span class="text-2xl font-bold text-white">${data.profile.first_name.charAt(0)}${data.profile.last_name.charAt(0)}</span>`}
6052
6071
  </div>
6053
-
6072
+
6054
6073
  <form id="avatar-form" hx-post="/admin/profile/avatar" hx-target="#avatar-messages" hx-encoding="multipart/form-data">
6055
- <input
6056
- type="file"
6057
- name="avatar"
6074
+ <input
6075
+ type="file"
6076
+ name="avatar"
6058
6077
  accept="image/*"
6059
6078
  class="hidden"
6060
6079
  id="avatar-input"
6061
6080
  onchange="document.getElementById('avatar-form').dispatchEvent(new Event('submit'))"
6062
6081
  >
6063
- <label
6082
+ <label
6064
6083
  for="avatar-input"
6065
- class="inline-block px-4 py-2 bg-white/10 text-white rounded-xl border border-white/20 hover:bg-white/20 transition-all cursor-pointer"
6084
+ class="inline-flex items-center gap-x-2 rounded-lg bg-white dark:bg-zinc-800 px-4 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors cursor-pointer"
6066
6085
  >
6086
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6087
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"/>
6088
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"/>
6089
+ </svg>
6067
6090
  Change Picture
6068
6091
  </label>
6069
6092
  </form>
6070
-
6093
+
6071
6094
  <div id="avatar-messages" class="mt-3"></div>
6072
6095
  </div>
6073
6096
  </div>
6074
6097
 
6075
6098
  <!-- Account Info -->
6076
- <div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl p-6">
6077
- <h3 class="text-lg font-semibold text-white mb-4">Account Information</h3>
6078
-
6079
- <div class="space-y-3 text-sm">
6099
+ <div class="rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6">
6100
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Account Information</h3>
6101
+
6102
+ <dl class="space-y-3 text-sm">
6080
6103
  <div>
6081
- <span class="text-gray-400">Role:</span>
6082
- <span class="text-white ml-2 capitalize">${data.profile.role}</span>
6104
+ <dt class="text-zinc-500 dark:text-zinc-400">Role</dt>
6105
+ <dd class="mt-1">
6106
+ <span class="inline-flex items-center rounded-md bg-blue-50 dark:bg-blue-500/10 px-2 py-1 text-xs font-medium text-blue-700 dark:text-blue-400 ring-1 ring-inset ring-blue-700/10 dark:ring-blue-400/20 capitalize">
6107
+ ${data.profile.role}
6108
+ </span>
6109
+ </dd>
6083
6110
  </div>
6084
6111
  <div>
6085
- <span class="text-gray-400">Member Since:</span>
6086
- <span class="text-white ml-2">${new Date(data.profile.created_at).toLocaleDateString()}</span>
6112
+ <dt class="text-zinc-500 dark:text-zinc-400">Member Since</dt>
6113
+ <dd class="mt-1 text-zinc-950 dark:text-white">${new Date(data.profile.created_at).toLocaleDateString()}</dd>
6087
6114
  </div>
6088
6115
  ${data.profile.last_login_at ? `
6089
6116
  <div>
6090
- <span class="text-gray-400">Last Login:</span>
6091
- <span class="text-white ml-2">${new Date(data.profile.last_login_at).toLocaleDateString()}</span>
6117
+ <dt class="text-zinc-500 dark:text-zinc-400">Last Login</dt>
6118
+ <dd class="mt-1 text-zinc-950 dark:text-white">${new Date(data.profile.last_login_at).toLocaleDateString()}</dd>
6092
6119
  </div>
6093
6120
  ` : ""}
6094
6121
  <div>
6095
- <span class="text-gray-400">Two-Factor Auth:</span>
6096
- <span class="text-white ml-2">${data.profile.two_factor_enabled ? "Enabled" : "Disabled"}</span>
6122
+ <dt class="text-zinc-500 dark:text-zinc-400">Two-Factor Auth</dt>
6123
+ <dd class="mt-1">
6124
+ ${data.profile.two_factor_enabled ? '<span class="inline-flex items-center rounded-md bg-green-50 dark:bg-green-500/10 px-2 py-1 text-xs font-medium text-green-700 dark:text-green-400 ring-1 ring-inset ring-green-600/20 dark:ring-green-500/20">Enabled</span>' : '<span class="inline-flex items-center rounded-md bg-zinc-50 dark:bg-zinc-800 px-2 py-1 text-xs font-medium text-zinc-600 dark:text-zinc-400 ring-1 ring-inset ring-zinc-500/10 dark:ring-zinc-400/20">Disabled</span>'}
6125
+ </dd>
6097
6126
  </div>
6098
- </div>
6127
+ </dl>
6099
6128
  </div>
6100
6129
 
6101
6130
  <!-- Security Actions -->
6102
- <div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl p-6">
6103
- <h3 class="text-lg font-semibold text-white mb-4">Security</h3>
6104
-
6105
- <div class="space-y-3">
6106
- <button
6131
+ <div class="rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6">
6132
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Security</h3>
6133
+
6134
+ <div class="space-y-2">
6135
+ <button
6107
6136
  type="button"
6108
6137
  onclick="showChangePasswordModal()"
6109
- class="w-full text-left px-3 py-2 text-sm text-gray-300 hover:text-white hover:bg-white/10 rounded-xl transition-all"
6138
+ class="w-full text-left flex items-center gap-x-3 px-3 py-2 text-sm text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-800/50 rounded-lg transition-colors"
6110
6139
  >
6111
- <svg class="w-4 h-4 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6140
+ <svg class="w-4 h-4 text-zinc-500 dark:text-zinc-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6112
6141
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-3.586l4.293-4.293A6 6 0 0119 9z"/>
6113
6142
  </svg>
6114
- Change Password
6143
+ <span class="font-medium">Change Password</span>
6115
6144
  </button>
6116
-
6117
- <button
6145
+
6146
+ <button
6118
6147
  type="button"
6119
6148
  onclick="toggle2FA()"
6120
- class="w-full text-left px-3 py-2 text-sm text-gray-300 hover:text-white hover:bg-white/10 rounded-xl transition-all"
6149
+ class="w-full text-left flex items-center gap-x-3 px-3 py-2 text-sm text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-800/50 rounded-lg transition-colors"
6121
6150
  >
6122
- <svg class="w-4 h-4 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6151
+ <svg class="w-4 h-4 text-zinc-500 dark:text-zinc-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6123
6152
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
6124
6153
  </svg>
6125
- ${data.profile.two_factor_enabled ? "Disable" : "Enable"} 2FA
6154
+ <span class="font-medium">${data.profile.two_factor_enabled ? "Disable" : "Enable"} 2FA</span>
6126
6155
  </button>
6127
6156
  </div>
6128
6157
  </div>
@@ -6131,67 +6160,73 @@ function renderProfilePage(data) {
6131
6160
  </div>
6132
6161
 
6133
6162
  <!-- Change Password Modal -->
6134
- <div id="password-modal" class="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 hidden">
6135
- <div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl w-full max-w-md mx-4">
6136
- <div class="relative px-6 py-4 border-b border-white/10">
6137
- <div class="absolute inset-0 bg-gradient-to-r from-blue-600/10 via-purple-600/10 to-pink-600/10"></div>
6138
- <div class="relative flex items-center justify-between">
6139
- <h3 class="text-lg font-semibold text-white">Change Password</h3>
6140
- <button onclick="closePasswordModal()" class="text-gray-300 hover:text-white">
6141
- <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6163
+ <div id="password-modal" class="fixed inset-0 bg-zinc-950/50 backdrop-blur-sm flex items-center justify-center z-50 hidden">
6164
+ <div class="rounded-xl bg-white dark:bg-zinc-900 shadow-2xl ring-1 ring-zinc-950/5 dark:ring-white/10 w-full max-w-md mx-4">
6165
+ <div class="px-6 py-5 border-b border-zinc-950/5 dark:border-white/5">
6166
+ <div class="flex items-center justify-between">
6167
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white">Change Password</h3>
6168
+ <button onclick="closePasswordModal()" class="text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white transition-colors">
6169
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6142
6170
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
6143
6171
  </svg>
6144
6172
  </button>
6145
6173
  </div>
6146
6174
  </div>
6147
-
6175
+
6148
6176
  <form id="password-form" hx-post="/admin/profile/password" hx-target="#password-messages" class="p-6 space-y-4">
6149
6177
  <div id="password-messages"></div>
6150
-
6178
+
6151
6179
  <div>
6152
- <label class="block text-sm font-medium text-gray-300 mb-2">Current Password</label>
6153
- <input
6154
- type="password"
6155
- name="current_password"
6180
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Current Password</label>
6181
+ <input
6182
+ type="password"
6183
+ name="current_password"
6156
6184
  required
6157
- class="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30 focus:ring-2 focus:ring-white/20 transition-all"
6185
+ class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
6186
+ placeholder="Enter current password"
6158
6187
  >
6159
6188
  </div>
6160
6189
 
6161
6190
  <div>
6162
- <label class="block text-sm font-medium text-gray-300 mb-2">New Password</label>
6163
- <input
6164
- type="password"
6165
- name="new_password"
6191
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">New Password</label>
6192
+ <input
6193
+ type="password"
6194
+ name="new_password"
6166
6195
  required
6167
6196
  minlength="8"
6168
- class="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30 focus:ring-2 focus:ring-white/20 transition-all"
6197
+ class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
6198
+ placeholder="Enter new password"
6169
6199
  >
6200
+ <p class="mt-1 text-xs text-zinc-500 dark:text-zinc-400">Must be at least 8 characters</p>
6170
6201
  </div>
6171
6202
 
6172
6203
  <div>
6173
- <label class="block text-sm font-medium text-gray-300 mb-2">Confirm New Password</label>
6174
- <input
6175
- type="password"
6176
- name="confirm_password"
6204
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Confirm New Password</label>
6205
+ <input
6206
+ type="password"
6207
+ name="confirm_password"
6177
6208
  required
6178
6209
  minlength="8"
6179
- class="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-xl text-white focus:outline-none focus:bg-white/10 focus:border-white/30 focus:ring-2 focus:ring-white/20 transition-all"
6210
+ class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
6211
+ placeholder="Confirm new password"
6180
6212
  >
6181
6213
  </div>
6182
6214
 
6183
- <div class="flex justify-end space-x-3 pt-4 border-t border-white/10">
6184
- <button
6185
- type="button"
6215
+ <div class="flex justify-end gap-x-3 pt-4 border-t border-zinc-950/5 dark:border-white/5">
6216
+ <button
6217
+ type="button"
6186
6218
  onclick="closePasswordModal()"
6187
- class="px-4 py-2 bg-white/10 text-white rounded-xl border border-white/20 hover:bg-white/20 transition-all"
6219
+ class="rounded-lg bg-white dark:bg-zinc-800 px-4 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors"
6188
6220
  >
6189
6221
  Cancel
6190
6222
  </button>
6191
- <button
6223
+ <button
6192
6224
  type="submit"
6193
- class="px-4 py-2 bg-gradient-to-r from-blue-600 to-purple-600 text-white font-medium rounded-xl hover:from-blue-700 hover:to-purple-700 transition-all"
6225
+ class="inline-flex items-center gap-x-2 rounded-lg bg-zinc-950 dark:bg-white px-4 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors"
6194
6226
  >
6227
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6228
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
6229
+ </svg>
6195
6230
  Update Password
6196
6231
  </button>
6197
6232
  </div>
@@ -6234,9 +6269,10 @@ function renderProfilePage(data) {
6234
6269
  pageTitle: "Profile",
6235
6270
  currentPath: "/admin/profile",
6236
6271
  user: data.user,
6272
+ version: data.version,
6237
6273
  content: pageContent
6238
6274
  };
6239
- return chunkALOS2CBJ_cjs.renderAdminLayout(layoutData);
6275
+ return chunk3SPQ3J4N_cjs.renderAdminLayoutCatalyst(layoutData);
6240
6276
  }
6241
6277
 
6242
6278
  // src/templates/components/alert.template.ts
@@ -6519,7 +6555,7 @@ function renderActivityLogsPage(data) {
6519
6555
  user: data.user,
6520
6556
  content: pageContent
6521
6557
  };
6522
- return chunkALOS2CBJ_cjs.renderAdminLayout(layoutData);
6558
+ return chunk3SPQ3J4N_cjs.renderAdminLayout(layoutData);
6523
6559
  }
6524
6560
  function getActionBadgeClass(action) {
6525
6561
  if (action.includes("login") || action.includes("logout")) {
@@ -6539,7 +6575,7 @@ function formatAction(action) {
6539
6575
  }
6540
6576
 
6541
6577
  // src/templates/pages/admin-user-edit.template.ts
6542
- chunkALOS2CBJ_cjs.init_admin_layout_catalyst_template();
6578
+ chunk3SPQ3J4N_cjs.init_admin_layout_catalyst_template();
6543
6579
 
6544
6580
  // src/templates/components/confirmation-dialog.template.ts
6545
6581
  function renderConfirmationDialog2(options) {
@@ -6660,8 +6696,8 @@ function renderUserEditPage(data) {
6660
6696
 
6661
6697
  <!-- Alert Messages -->
6662
6698
  <div id="form-messages">
6663
- ${data.error ? chunkALOS2CBJ_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
6664
- ${data.success ? chunkALOS2CBJ_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
6699
+ ${data.error ? chunk3SPQ3J4N_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
6700
+ ${data.success ? chunk3SPQ3J4N_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
6665
6701
  </div>
6666
6702
 
6667
6703
  <!-- User Edit Form -->
@@ -6680,7 +6716,7 @@ function renderUserEditPage(data) {
6680
6716
  <input
6681
6717
  type="text"
6682
6718
  name="first_name"
6683
- value="${chunkNK6FN5R5_cjs.escapeHtml(data.userToEdit.firstName || "")}"
6719
+ value="${chunkUL32L2KV_cjs.escapeHtml(data.userToEdit.firstName || "")}"
6684
6720
  required
6685
6721
  class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
6686
6722
  />
@@ -6691,7 +6727,7 @@ function renderUserEditPage(data) {
6691
6727
  <input
6692
6728
  type="text"
6693
6729
  name="last_name"
6694
- value="${chunkNK6FN5R5_cjs.escapeHtml(data.userToEdit.lastName || "")}"
6730
+ value="${chunkUL32L2KV_cjs.escapeHtml(data.userToEdit.lastName || "")}"
6695
6731
  required
6696
6732
  class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
6697
6733
  />
@@ -6702,7 +6738,7 @@ function renderUserEditPage(data) {
6702
6738
  <input
6703
6739
  type="text"
6704
6740
  name="username"
6705
- value="${chunkNK6FN5R5_cjs.escapeHtml(data.userToEdit.username || "")}"
6741
+ value="${chunkUL32L2KV_cjs.escapeHtml(data.userToEdit.username || "")}"
6706
6742
  required
6707
6743
  class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
6708
6744
  />
@@ -6713,7 +6749,7 @@ function renderUserEditPage(data) {
6713
6749
  <input
6714
6750
  type="email"
6715
6751
  name="email"
6716
- value="${chunkNK6FN5R5_cjs.escapeHtml(data.userToEdit.email || "")}"
6752
+ value="${chunkUL32L2KV_cjs.escapeHtml(data.userToEdit.email || "")}"
6717
6753
  required
6718
6754
  class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
6719
6755
  />
@@ -6724,7 +6760,7 @@ function renderUserEditPage(data) {
6724
6760
  <input
6725
6761
  type="tel"
6726
6762
  name="phone"
6727
- value="${chunkNK6FN5R5_cjs.escapeHtml(data.userToEdit.phone || "")}"
6763
+ value="${chunkUL32L2KV_cjs.escapeHtml(data.userToEdit.phone || "")}"
6728
6764
  class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
6729
6765
  />
6730
6766
  </div>
@@ -6738,7 +6774,7 @@ function renderUserEditPage(data) {
6738
6774
  class="col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-zinc-500/30 dark:outline-zinc-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-zinc-500 dark:focus-visible:outline-zinc-400 sm:text-sm/6"
6739
6775
  >
6740
6776
  ${data.roles.map((role) => `
6741
- <option value="${chunkNK6FN5R5_cjs.escapeHtml(role.value)}" ${data.userToEdit.role === role.value ? "selected" : ""}>${chunkNK6FN5R5_cjs.escapeHtml(role.label)}</option>
6777
+ <option value="${chunkUL32L2KV_cjs.escapeHtml(role.value)}" ${data.userToEdit.role === role.value ? "selected" : ""}>${chunkUL32L2KV_cjs.escapeHtml(role.label)}</option>
6742
6778
  `).join("")}
6743
6779
  </select>
6744
6780
  <svg viewBox="0 0 16 16" fill="currentColor" data-slot="icon" aria-hidden="true" class="pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-zinc-600 dark:text-zinc-400 sm:size-4">
@@ -6754,7 +6790,7 @@ function renderUserEditPage(data) {
6754
6790
  name="bio"
6755
6791
  rows="3"
6756
6792
  class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 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"
6757
- >${chunkNK6FN5R5_cjs.escapeHtml(data.userToEdit.bio || "")}</textarea>
6793
+ >${chunkUL32L2KV_cjs.escapeHtml(data.userToEdit.bio || "")}</textarea>
6758
6794
  </div>
6759
6795
  </div>
6760
6796
 
@@ -6954,11 +6990,11 @@ function renderUserEditPage(data) {
6954
6990
  user: data.user,
6955
6991
  content: pageContent
6956
6992
  };
6957
- return chunkALOS2CBJ_cjs.renderAdminLayoutCatalyst(layoutData);
6993
+ return chunk3SPQ3J4N_cjs.renderAdminLayoutCatalyst(layoutData);
6958
6994
  }
6959
6995
 
6960
6996
  // src/templates/pages/admin-user-new.template.ts
6961
- chunkALOS2CBJ_cjs.init_admin_layout_catalyst_template();
6997
+ chunk3SPQ3J4N_cjs.init_admin_layout_catalyst_template();
6962
6998
  function renderUserNewPage(data) {
6963
6999
  const pageContent = `
6964
7000
  <div>
@@ -6997,8 +7033,8 @@ function renderUserNewPage(data) {
6997
7033
 
6998
7034
  <!-- Alert Messages -->
6999
7035
  <div id="form-messages">
7000
- ${data.error ? chunkALOS2CBJ_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
7001
- ${data.success ? chunkALOS2CBJ_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
7036
+ ${data.error ? chunk3SPQ3J4N_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
7037
+ ${data.success ? chunk3SPQ3J4N_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
7002
7038
  </div>
7003
7039
 
7004
7040
  <!-- User New Form -->
@@ -7242,11 +7278,11 @@ function renderUserNewPage(data) {
7242
7278
  user: data.user,
7243
7279
  content: pageContent
7244
7280
  };
7245
- return chunkALOS2CBJ_cjs.renderAdminLayoutCatalyst(layoutData);
7281
+ return chunk3SPQ3J4N_cjs.renderAdminLayoutCatalyst(layoutData);
7246
7282
  }
7247
7283
 
7248
7284
  // src/templates/pages/admin-users-list.template.ts
7249
- chunkALOS2CBJ_cjs.init_admin_layout_catalyst_template();
7285
+ chunk3SPQ3J4N_cjs.init_admin_layout_catalyst_template();
7250
7286
  function renderUsersListPage(data) {
7251
7287
  const columns = [
7252
7288
  {
@@ -7397,8 +7433,8 @@ function renderUsersListPage(data) {
7397
7433
  </div>
7398
7434
 
7399
7435
  <!-- Alert Messages -->
7400
- ${data.error ? chunkALOS2CBJ_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
7401
- ${data.success ? chunkALOS2CBJ_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
7436
+ ${data.error ? chunk3SPQ3J4N_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
7437
+ ${data.success ? chunk3SPQ3J4N_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
7402
7438
 
7403
7439
  <!-- Stats -->
7404
7440
  <div class="mb-6">
@@ -7575,10 +7611,10 @@ function renderUsersListPage(data) {
7575
7611
  </div>
7576
7612
 
7577
7613
  <!-- Users Table -->
7578
- ${chunkALOS2CBJ_cjs.renderTable(tableData)}
7614
+ ${chunk3SPQ3J4N_cjs.renderTable(tableData)}
7579
7615
 
7580
7616
  <!-- Pagination -->
7581
- ${data.pagination ? chunkALOS2CBJ_cjs.renderPagination(data.pagination) : ""}
7617
+ ${data.pagination ? chunk3SPQ3J4N_cjs.renderPagination(data.pagination) : ""}
7582
7618
  </div>
7583
7619
 
7584
7620
  <script>
@@ -7649,12 +7685,15 @@ function renderUsersListPage(data) {
7649
7685
  version: data.version,
7650
7686
  content: pageContent
7651
7687
  };
7652
- return chunkALOS2CBJ_cjs.renderAdminLayoutCatalyst(layoutData);
7688
+ return chunk3SPQ3J4N_cjs.renderAdminLayoutCatalyst(layoutData);
7653
7689
  }
7654
7690
 
7655
7691
  // src/routes/admin-users.ts
7656
7692
  var userRoutes = new hono.Hono();
7657
- userRoutes.use("*", chunkKM4AJFXI_cjs.requireAuth());
7693
+ userRoutes.use("*", chunk4BJGEGX5_cjs.requireAuth());
7694
+ userRoutes.get("/", (c) => {
7695
+ return c.redirect("/admin/dashboard");
7696
+ });
7658
7697
  var TIMEZONES = [
7659
7698
  { value: "UTC", label: "UTC" },
7660
7699
  { value: "America/New_York", label: "Eastern Time" },
@@ -7750,12 +7789,12 @@ userRoutes.put("/profile", async (c) => {
7750
7789
  const db = c.env.DB;
7751
7790
  try {
7752
7791
  const formData = await c.req.formData();
7753
- const firstName = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("first_name")?.toString());
7754
- const lastName = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("last_name")?.toString());
7755
- const username = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("username")?.toString());
7792
+ const firstName = chunkUL32L2KV_cjs.sanitizeInput(formData.get("first_name")?.toString());
7793
+ const lastName = chunkUL32L2KV_cjs.sanitizeInput(formData.get("last_name")?.toString());
7794
+ const username = chunkUL32L2KV_cjs.sanitizeInput(formData.get("username")?.toString());
7756
7795
  const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
7757
- const phone = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
7758
- const bio = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
7796
+ const phone = chunkUL32L2KV_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
7797
+ const bio = chunkUL32L2KV_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
7759
7798
  const timezone = formData.get("timezone")?.toString() || "UTC";
7760
7799
  const language = formData.get("language")?.toString() || "en";
7761
7800
  const emailNotifications = formData.get("email_notifications") === "1";
@@ -7806,7 +7845,7 @@ userRoutes.put("/profile", async (c) => {
7806
7845
  Date.now(),
7807
7846
  user.userId
7808
7847
  ).run();
7809
- await chunkKM4AJFXI_cjs.logActivity(
7848
+ await chunk4BJGEGX5_cjs.logActivity(
7810
7849
  db,
7811
7850
  user.userId,
7812
7851
  "profile.update",
@@ -7865,7 +7904,7 @@ userRoutes.post("/profile/avatar", async (c) => {
7865
7904
  WHERE id = ?
7866
7905
  `);
7867
7906
  await updateStmt.bind(avatarUrl, Date.now(), user.userId).run();
7868
- await chunkKM4AJFXI_cjs.logActivity(
7907
+ await chunk4BJGEGX5_cjs.logActivity(
7869
7908
  db,
7870
7909
  user.userId,
7871
7910
  "profile.avatar_update",
@@ -7929,7 +7968,7 @@ userRoutes.post("/profile/password", async (c) => {
7929
7968
  dismissible: true
7930
7969
  }));
7931
7970
  }
7932
- const validPassword = await chunkKM4AJFXI_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
7971
+ const validPassword = await chunk4BJGEGX5_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
7933
7972
  if (!validPassword) {
7934
7973
  return c.html(renderAlert2({
7935
7974
  type: "error",
@@ -7937,7 +7976,7 @@ userRoutes.post("/profile/password", async (c) => {
7937
7976
  dismissible: true
7938
7977
  }));
7939
7978
  }
7940
- const newPasswordHash = await chunkKM4AJFXI_cjs.AuthManager.hashPassword(newPassword);
7979
+ const newPasswordHash = await chunk4BJGEGX5_cjs.AuthManager.hashPassword(newPassword);
7941
7980
  const historyStmt = db.prepare(`
7942
7981
  INSERT INTO password_history (id, user_id, password_hash, created_at)
7943
7982
  VALUES (?, ?, ?, ?)
@@ -7953,7 +7992,7 @@ userRoutes.post("/profile/password", async (c) => {
7953
7992
  WHERE id = ?
7954
7993
  `);
7955
7994
  await updateStmt.bind(newPasswordHash, Date.now(), user.userId).run();
7956
- await chunkKM4AJFXI_cjs.logActivity(
7995
+ await chunk4BJGEGX5_cjs.logActivity(
7957
7996
  db,
7958
7997
  user.userId,
7959
7998
  "profile.password_change",
@@ -7977,7 +8016,7 @@ userRoutes.post("/profile/password", async (c) => {
7977
8016
  }));
7978
8017
  }
7979
8018
  });
7980
- userRoutes.get("/users", chunkKM4AJFXI_cjs.requirePermission("users.read"), async (c) => {
8019
+ userRoutes.get("/users", async (c) => {
7981
8020
  const db = c.env.DB;
7982
8021
  const user = c.get("user");
7983
8022
  try {
@@ -8020,7 +8059,7 @@ userRoutes.get("/users", chunkKM4AJFXI_cjs.requirePermission("users.read"), asyn
8020
8059
  `);
8021
8060
  const countResult = await countStmt.bind(...params).first();
8022
8061
  const totalUsers = countResult?.total || 0;
8023
- await chunkKM4AJFXI_cjs.logActivity(
8062
+ await chunk4BJGEGX5_cjs.logActivity(
8024
8063
  db,
8025
8064
  user.userId,
8026
8065
  "users.list_view",
@@ -8096,7 +8135,7 @@ userRoutes.get("/users", chunkKM4AJFXI_cjs.requirePermission("users.read"), asyn
8096
8135
  }), 500);
8097
8136
  }
8098
8137
  });
8099
- userRoutes.get("/users/new", chunkKM4AJFXI_cjs.requirePermission("users.create"), async (c) => {
8138
+ userRoutes.get("/users/new", async (c) => {
8100
8139
  const user = c.get("user");
8101
8140
  try {
8102
8141
  const pageData = {
@@ -8117,17 +8156,17 @@ userRoutes.get("/users/new", chunkKM4AJFXI_cjs.requirePermission("users.create")
8117
8156
  }), 500);
8118
8157
  }
8119
8158
  });
8120
- userRoutes.post("/users/new", chunkKM4AJFXI_cjs.requirePermission("users.create"), async (c) => {
8159
+ userRoutes.post("/users/new", async (c) => {
8121
8160
  const db = c.env.DB;
8122
8161
  const user = c.get("user");
8123
8162
  try {
8124
8163
  const formData = await c.req.formData();
8125
- const firstName = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("first_name")?.toString());
8126
- const lastName = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("last_name")?.toString());
8127
- const username = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("username")?.toString());
8164
+ const firstName = chunkUL32L2KV_cjs.sanitizeInput(formData.get("first_name")?.toString());
8165
+ const lastName = chunkUL32L2KV_cjs.sanitizeInput(formData.get("last_name")?.toString());
8166
+ const username = chunkUL32L2KV_cjs.sanitizeInput(formData.get("username")?.toString());
8128
8167
  const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
8129
- const phone = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
8130
- const bio = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
8168
+ const phone = chunkUL32L2KV_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
8169
+ const bio = chunkUL32L2KV_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
8131
8170
  const role = formData.get("role")?.toString() || "viewer";
8132
8171
  const password = formData.get("password")?.toString() || "";
8133
8172
  const confirmPassword = formData.get("confirm_password")?.toString() || "";
@@ -8174,7 +8213,7 @@ userRoutes.post("/users/new", chunkKM4AJFXI_cjs.requirePermission("users.create"
8174
8213
  dismissible: true
8175
8214
  }));
8176
8215
  }
8177
- const passwordHash = await chunkKM4AJFXI_cjs.AuthManager.hashPassword(password);
8216
+ const passwordHash = await chunk4BJGEGX5_cjs.AuthManager.hashPassword(password);
8178
8217
  const userId = globalThis.crypto.randomUUID();
8179
8218
  const createStmt = db.prepare(`
8180
8219
  INSERT INTO users (
@@ -8197,7 +8236,7 @@ userRoutes.post("/users/new", chunkKM4AJFXI_cjs.requirePermission("users.create"
8197
8236
  Date.now(),
8198
8237
  Date.now()
8199
8238
  ).run();
8200
- await chunkKM4AJFXI_cjs.logActivity(
8239
+ await chunk4BJGEGX5_cjs.logActivity(
8201
8240
  db,
8202
8241
  user.userId,
8203
8242
  "user!.create",
@@ -8217,7 +8256,7 @@ userRoutes.post("/users/new", chunkKM4AJFXI_cjs.requirePermission("users.create"
8217
8256
  }));
8218
8257
  }
8219
8258
  });
8220
- userRoutes.get("/users/:id", chunkKM4AJFXI_cjs.requirePermission("users.read"), async (c) => {
8259
+ userRoutes.get("/users/:id", async (c) => {
8221
8260
  if (c.req.path.endsWith("/edit")) {
8222
8261
  return c.notFound();
8223
8262
  }
@@ -8235,7 +8274,7 @@ userRoutes.get("/users/:id", chunkKM4AJFXI_cjs.requirePermission("users.read"),
8235
8274
  if (!userRecord) {
8236
8275
  return c.json({ error: "User not found" }, 404);
8237
8276
  }
8238
- await chunkKM4AJFXI_cjs.logActivity(
8277
+ await chunk4BJGEGX5_cjs.logActivity(
8239
8278
  db,
8240
8279
  user.userId,
8241
8280
  "user!.view",
@@ -8268,7 +8307,7 @@ userRoutes.get("/users/:id", chunkKM4AJFXI_cjs.requirePermission("users.read"),
8268
8307
  return c.json({ error: "Failed to fetch user" }, 500);
8269
8308
  }
8270
8309
  });
8271
- userRoutes.get("/users/:id/edit", chunkKM4AJFXI_cjs.requirePermission("users.update"), async (c) => {
8310
+ userRoutes.get("/users/:id/edit", async (c) => {
8272
8311
  const db = c.env.DB;
8273
8312
  const user = c.get("user");
8274
8313
  const userId = c.req.param("id");
@@ -8322,18 +8361,18 @@ userRoutes.get("/users/:id/edit", chunkKM4AJFXI_cjs.requirePermission("users.upd
8322
8361
  }), 500);
8323
8362
  }
8324
8363
  });
8325
- userRoutes.put("/users/:id", chunkKM4AJFXI_cjs.requirePermission("users.update"), async (c) => {
8364
+ userRoutes.put("/users/:id", async (c) => {
8326
8365
  const db = c.env.DB;
8327
8366
  const user = c.get("user");
8328
8367
  const userId = c.req.param("id");
8329
8368
  try {
8330
8369
  const formData = await c.req.formData();
8331
- const firstName = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("first_name")?.toString());
8332
- const lastName = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("last_name")?.toString());
8333
- const username = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("username")?.toString());
8370
+ const firstName = chunkUL32L2KV_cjs.sanitizeInput(formData.get("first_name")?.toString());
8371
+ const lastName = chunkUL32L2KV_cjs.sanitizeInput(formData.get("last_name")?.toString());
8372
+ const username = chunkUL32L2KV_cjs.sanitizeInput(formData.get("username")?.toString());
8334
8373
  const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
8335
- const phone = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
8336
- const bio = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
8374
+ const phone = chunkUL32L2KV_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
8375
+ const bio = chunkUL32L2KV_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
8337
8376
  const role = formData.get("role")?.toString() || "viewer";
8338
8377
  const isActive = formData.get("is_active") === "1";
8339
8378
  const emailVerified = formData.get("email_verified") === "1";
@@ -8384,7 +8423,7 @@ userRoutes.put("/users/:id", chunkKM4AJFXI_cjs.requirePermission("users.update")
8384
8423
  Date.now(),
8385
8424
  userId
8386
8425
  ).run();
8387
- await chunkKM4AJFXI_cjs.logActivity(
8426
+ await chunk4BJGEGX5_cjs.logActivity(
8388
8427
  db,
8389
8428
  user.userId,
8390
8429
  "user!.update",
@@ -8408,7 +8447,7 @@ userRoutes.put("/users/:id", chunkKM4AJFXI_cjs.requirePermission("users.update")
8408
8447
  }));
8409
8448
  }
8410
8449
  });
8411
- userRoutes.delete("/users/:id", chunkKM4AJFXI_cjs.requirePermission("users.delete"), async (c) => {
8450
+ userRoutes.delete("/users/:id", async (c) => {
8412
8451
  const db = c.env.DB;
8413
8452
  const user = c.get("user");
8414
8453
  const userId = c.req.param("id");
@@ -8430,7 +8469,7 @@ userRoutes.delete("/users/:id", chunkKM4AJFXI_cjs.requirePermission("users.delet
8430
8469
  DELETE FROM users WHERE id = ?
8431
8470
  `);
8432
8471
  await deleteStmt.bind(userId).run();
8433
- await chunkKM4AJFXI_cjs.logActivity(
8472
+ await chunk4BJGEGX5_cjs.logActivity(
8434
8473
  db,
8435
8474
  user.userId,
8436
8475
  "user!.hard_delete",
@@ -8449,7 +8488,7 @@ userRoutes.delete("/users/:id", chunkKM4AJFXI_cjs.requirePermission("users.delet
8449
8488
  UPDATE users SET is_active = 0, updated_at = ? WHERE id = ?
8450
8489
  `);
8451
8490
  await deleteStmt.bind(Date.now(), userId).run();
8452
- await chunkKM4AJFXI_cjs.logActivity(
8491
+ await chunk4BJGEGX5_cjs.logActivity(
8453
8492
  db,
8454
8493
  user.userId,
8455
8494
  "user!.soft_delete",
@@ -8469,15 +8508,15 @@ userRoutes.delete("/users/:id", chunkKM4AJFXI_cjs.requirePermission("users.delet
8469
8508
  return c.json({ error: "Failed to delete user" }, 500);
8470
8509
  }
8471
8510
  });
8472
- userRoutes.post("/invite-user", chunkKM4AJFXI_cjs.requirePermission("users.create"), async (c) => {
8511
+ userRoutes.post("/invite-user", async (c) => {
8473
8512
  const db = c.env.DB;
8474
8513
  const user = c.get("user");
8475
8514
  try {
8476
8515
  const formData = await c.req.formData();
8477
8516
  const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
8478
8517
  const role = formData.get("role")?.toString()?.trim() || "viewer";
8479
- const firstName = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("first_name")?.toString());
8480
- const lastName = chunkNK6FN5R5_cjs.sanitizeInput(formData.get("last_name")?.toString());
8518
+ const firstName = chunkUL32L2KV_cjs.sanitizeInput(formData.get("first_name")?.toString());
8519
+ const lastName = chunkUL32L2KV_cjs.sanitizeInput(formData.get("last_name")?.toString());
8481
8520
  if (!email || !firstName || !lastName) {
8482
8521
  return c.json({ error: "Email, first name, and last name are required" }, 400);
8483
8522
  }
@@ -8516,7 +8555,7 @@ userRoutes.post("/invite-user", chunkKM4AJFXI_cjs.requirePermission("users.creat
8516
8555
  Date.now(),
8517
8556
  Date.now()
8518
8557
  ).run();
8519
- await chunkKM4AJFXI_cjs.logActivity(
8558
+ await chunk4BJGEGX5_cjs.logActivity(
8520
8559
  db,
8521
8560
  user.userId,
8522
8561
  "user!.invite_sent",
@@ -8545,7 +8584,7 @@ userRoutes.post("/invite-user", chunkKM4AJFXI_cjs.requirePermission("users.creat
8545
8584
  return c.json({ error: "Failed to send user invitation" }, 500);
8546
8585
  }
8547
8586
  });
8548
- userRoutes.post("/resend-invitation/:id", chunkKM4AJFXI_cjs.requirePermission("users.create"), async (c) => {
8587
+ userRoutes.post("/resend-invitation/:id", async (c) => {
8549
8588
  const db = c.env.DB;
8550
8589
  const user = c.get("user");
8551
8590
  const userId = c.req.param("id");
@@ -8573,7 +8612,7 @@ userRoutes.post("/resend-invitation/:id", chunkKM4AJFXI_cjs.requirePermission("u
8573
8612
  Date.now(),
8574
8613
  userId
8575
8614
  ).run();
8576
- await chunkKM4AJFXI_cjs.logActivity(
8615
+ await chunk4BJGEGX5_cjs.logActivity(
8577
8616
  db,
8578
8617
  user.userId,
8579
8618
  "user!.invitation_resent",
@@ -8594,7 +8633,7 @@ userRoutes.post("/resend-invitation/:id", chunkKM4AJFXI_cjs.requirePermission("u
8594
8633
  return c.json({ error: "Failed to resend invitation" }, 500);
8595
8634
  }
8596
8635
  });
8597
- userRoutes.delete("/cancel-invitation/:id", chunkKM4AJFXI_cjs.requirePermission("users.delete"), async (c) => {
8636
+ userRoutes.delete("/cancel-invitation/:id", async (c) => {
8598
8637
  const db = c.env.DB;
8599
8638
  const user = c.get("user");
8600
8639
  const userId = c.req.param("id");
@@ -8609,7 +8648,7 @@ userRoutes.delete("/cancel-invitation/:id", chunkKM4AJFXI_cjs.requirePermission(
8609
8648
  }
8610
8649
  const deleteStmt = db.prepare(`DELETE FROM users WHERE id = ?`);
8611
8650
  await deleteStmt.bind(userId).run();
8612
- await chunkKM4AJFXI_cjs.logActivity(
8651
+ await chunk4BJGEGX5_cjs.logActivity(
8613
8652
  db,
8614
8653
  user.userId,
8615
8654
  "user!.invitation_cancelled",
@@ -8628,7 +8667,7 @@ userRoutes.delete("/cancel-invitation/:id", chunkKM4AJFXI_cjs.requirePermission(
8628
8667
  return c.json({ error: "Failed to cancel invitation" }, 500);
8629
8668
  }
8630
8669
  });
8631
- userRoutes.get("/activity-logs", chunkKM4AJFXI_cjs.requirePermission("activity.read"), async (c) => {
8670
+ userRoutes.get("/activity-logs", async (c) => {
8632
8671
  const db = c.env.DB;
8633
8672
  const user = c.get("user");
8634
8673
  try {
@@ -8692,7 +8731,7 @@ userRoutes.get("/activity-logs", chunkKM4AJFXI_cjs.requirePermission("activity.r
8692
8731
  ...log,
8693
8732
  details: log.details ? JSON.parse(log.details) : null
8694
8733
  }));
8695
- await chunkKM4AJFXI_cjs.logActivity(
8734
+ await chunk4BJGEGX5_cjs.logActivity(
8696
8735
  db,
8697
8736
  user.userId,
8698
8737
  "activity.logs_viewed",
@@ -8734,7 +8773,7 @@ userRoutes.get("/activity-logs", chunkKM4AJFXI_cjs.requirePermission("activity.r
8734
8773
  return c.html(renderActivityLogsPage(pageData));
8735
8774
  }
8736
8775
  });
8737
- userRoutes.get("/activity-logs/export", chunkKM4AJFXI_cjs.requirePermission("activity.read"), async (c) => {
8776
+ userRoutes.get("/activity-logs/export", async (c) => {
8738
8777
  const db = c.env.DB;
8739
8778
  const user = c.get("user");
8740
8779
  try {
@@ -8799,7 +8838,7 @@ userRoutes.get("/activity-logs/export", chunkKM4AJFXI_cjs.requirePermission("act
8799
8838
  csvRows.push(row.join(","));
8800
8839
  }
8801
8840
  const csvContent = csvRows.join("\n");
8802
- await chunkKM4AJFXI_cjs.logActivity(
8841
+ await chunk4BJGEGX5_cjs.logActivity(
8803
8842
  db,
8804
8843
  user.userId,
8805
8844
  "activity.logs_exported",
@@ -9017,7 +9056,7 @@ function getFileIcon(mimeType) {
9017
9056
  }
9018
9057
 
9019
9058
  // src/templates/pages/admin-media-library.template.ts
9020
- chunkALOS2CBJ_cjs.init_admin_layout_catalyst_template();
9059
+ chunk3SPQ3J4N_cjs.init_admin_layout_catalyst_template();
9021
9060
  function renderMediaLibraryPage(data) {
9022
9061
  const pageContent = `
9023
9062
  <div>
@@ -9949,7 +9988,7 @@ function renderMediaLibraryPage(data) {
9949
9988
  version: data.version,
9950
9989
  content: pageContent
9951
9990
  };
9952
- return chunkALOS2CBJ_cjs.renderAdminLayoutCatalyst(layoutData);
9991
+ return chunk3SPQ3J4N_cjs.renderAdminLayoutCatalyst(layoutData);
9953
9992
  }
9954
9993
 
9955
9994
  // src/templates/components/media-file-details.template.ts
@@ -10135,6 +10174,7 @@ var fileValidationSchema2 = zod.z.object({
10135
10174
  // 50MB max
10136
10175
  });
10137
10176
  var adminMediaRoutes = new hono.Hono();
10177
+ adminMediaRoutes.use("*", chunk4BJGEGX5_cjs.requireAuth());
10138
10178
  adminMediaRoutes.get("/", async (c) => {
10139
10179
  try {
10140
10180
  const user = c.get("user");
@@ -10867,7 +10907,7 @@ function formatFileSize(bytes) {
10867
10907
  }
10868
10908
 
10869
10909
  // src/templates/pages/admin-plugins-list.template.ts
10870
- chunkALOS2CBJ_cjs.init_admin_layout_catalyst_template();
10910
+ chunk3SPQ3J4N_cjs.init_admin_layout_catalyst_template();
10871
10911
  function renderPluginsListPage(data) {
10872
10912
  const pageContent = `
10873
10913
  <div>
@@ -11241,7 +11281,7 @@ function renderPluginsListPage(data) {
11241
11281
  version: data.version,
11242
11282
  content: pageContent
11243
11283
  };
11244
- return chunkALOS2CBJ_cjs.renderAdminLayoutCatalyst(layoutData);
11284
+ return chunk3SPQ3J4N_cjs.renderAdminLayoutCatalyst(layoutData);
11245
11285
  }
11246
11286
  function renderPluginCard(plugin) {
11247
11287
  const statusColors = {
@@ -11891,7 +11931,7 @@ function renderPluginSettingsPage(data) {
11891
11931
  user,
11892
11932
  content: pageContent
11893
11933
  };
11894
- return chunkALOS2CBJ_cjs.renderAdminLayout(layoutData);
11934
+ return chunk3SPQ3J4N_cjs.renderAdminLayout(layoutData);
11895
11935
  }
11896
11936
  function renderStatusBadge(status) {
11897
11937
  const statusColors = {
@@ -12154,6 +12194,7 @@ function formatTimestamp(timestamp) {
12154
12194
 
12155
12195
  // src/routes/admin-plugins.ts
12156
12196
  var adminPluginRoutes = new hono.Hono();
12197
+ adminPluginRoutes.use("*", chunk4BJGEGX5_cjs.requireAuth());
12157
12198
  adminPluginRoutes.get("/", async (c) => {
12158
12199
  try {
12159
12200
  const user = c.get("user");
@@ -12488,7 +12529,7 @@ function formatLastUpdated(timestamp) {
12488
12529
  }
12489
12530
 
12490
12531
  // src/templates/pages/admin-logs-list.template.ts
12491
- chunkALOS2CBJ_cjs.init_admin_layout_catalyst_template();
12532
+ chunk3SPQ3J4N_cjs.init_admin_layout_catalyst_template();
12492
12533
  function renderLogsListPage(data) {
12493
12534
  const { logs, pagination, filters, user } = data;
12494
12535
  const content = `
@@ -12799,7 +12840,7 @@ function renderLogsListPage(data) {
12799
12840
  user,
12800
12841
  content
12801
12842
  };
12802
- return chunkALOS2CBJ_cjs.renderAdminLayoutCatalyst(layoutData);
12843
+ return chunk3SPQ3J4N_cjs.renderAdminLayoutCatalyst(layoutData);
12803
12844
  }
12804
12845
  function renderLogDetailsPage(data) {
12805
12846
  const { log, user } = data;
@@ -13011,7 +13052,7 @@ function renderLogDetailsPage(data) {
13011
13052
  </div>
13012
13053
  </div>
13013
13054
  `;
13014
- return chunkALOS2CBJ_cjs.adminLayoutV2({
13055
+ return chunk3SPQ3J4N_cjs.adminLayoutV2({
13015
13056
  title: `Log Details - ${log.id}`,
13016
13057
  user,
13017
13058
  content
@@ -13254,7 +13295,7 @@ function renderLogConfigPage(data) {
13254
13295
 
13255
13296
  <script src="https://unpkg.com/htmx.org@1.9.6"></script>
13256
13297
  `;
13257
- return chunkALOS2CBJ_cjs.adminLayoutV2({
13298
+ return chunk3SPQ3J4N_cjs.adminLayoutV2({
13258
13299
  title: "Log Configuration",
13259
13300
  user,
13260
13301
  content
@@ -13263,10 +13304,11 @@ function renderLogConfigPage(data) {
13263
13304
 
13264
13305
  // src/routes/admin-logs.ts
13265
13306
  var adminLogsRoutes = new hono.Hono();
13307
+ adminLogsRoutes.use("*", chunk4BJGEGX5_cjs.requireAuth());
13266
13308
  adminLogsRoutes.get("/", async (c) => {
13267
13309
  try {
13268
13310
  const user = c.get("user");
13269
- const logger = chunkSRCY43RN_cjs.getLogger(c.env.DB);
13311
+ const logger = chunk3NVJ6W27_cjs.getLogger(c.env.DB);
13270
13312
  const query = c.req.query();
13271
13313
  const page = parseInt(query.page || "1");
13272
13314
  const limit = parseInt(query.limit || "50");
@@ -13346,7 +13388,7 @@ adminLogsRoutes.get("/:id", async (c) => {
13346
13388
  try {
13347
13389
  const id = c.req.param("id");
13348
13390
  const user = c.get("user");
13349
- const logger = chunkSRCY43RN_cjs.getLogger(c.env.DB);
13391
+ const logger = chunk3NVJ6W27_cjs.getLogger(c.env.DB);
13350
13392
  const { logs } = await logger.getLogs({
13351
13393
  limit: 1,
13352
13394
  offset: 0,
@@ -13383,7 +13425,7 @@ adminLogsRoutes.get("/:id", async (c) => {
13383
13425
  adminLogsRoutes.get("/config", async (c) => {
13384
13426
  try {
13385
13427
  const user = c.get("user");
13386
- const logger = chunkSRCY43RN_cjs.getLogger(c.env.DB);
13428
+ const logger = chunk3NVJ6W27_cjs.getLogger(c.env.DB);
13387
13429
  const configs = await logger.getAllConfigs();
13388
13430
  const pageData = {
13389
13431
  configs,
@@ -13407,7 +13449,7 @@ adminLogsRoutes.post("/config/:category", async (c) => {
13407
13449
  const level = formData.get("level");
13408
13450
  const retention = parseInt(formData.get("retention"));
13409
13451
  const maxSize = parseInt(formData.get("max_size"));
13410
- const logger = chunkSRCY43RN_cjs.getLogger(c.env.DB);
13452
+ const logger = chunk3NVJ6W27_cjs.getLogger(c.env.DB);
13411
13453
  await logger.updateConfig(category, {
13412
13454
  enabled,
13413
13455
  level,
@@ -13436,7 +13478,7 @@ adminLogsRoutes.get("/export", async (c) => {
13436
13478
  const category = query.category;
13437
13479
  const startDate = query.start_date;
13438
13480
  const endDate = query.end_date;
13439
- const logger = chunkSRCY43RN_cjs.getLogger(c.env.DB);
13481
+ const logger = chunk3NVJ6W27_cjs.getLogger(c.env.DB);
13440
13482
  const filter = {
13441
13483
  limit: 1e4,
13442
13484
  // Export up to 10k logs
@@ -13517,7 +13559,7 @@ adminLogsRoutes.post("/cleanup", async (c) => {
13517
13559
  error: "Unauthorized. Admin access required."
13518
13560
  }, 403);
13519
13561
  }
13520
- const logger = chunkSRCY43RN_cjs.getLogger(c.env.DB);
13562
+ const logger = chunk3NVJ6W27_cjs.getLogger(c.env.DB);
13521
13563
  await logger.cleanupByRetention();
13522
13564
  return c.html(html.html`
13523
13565
  <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded">
@@ -13539,7 +13581,7 @@ adminLogsRoutes.post("/search", async (c) => {
13539
13581
  const search = formData.get("search");
13540
13582
  const level = formData.get("level");
13541
13583
  const category = formData.get("category");
13542
- const logger = chunkSRCY43RN_cjs.getLogger(c.env.DB);
13584
+ const logger = chunk3NVJ6W27_cjs.getLogger(c.env.DB);
13543
13585
  const filter = {
13544
13586
  limit: 20,
13545
13587
  offset: 0,
@@ -13634,7 +13676,7 @@ adminDesignRoutes.get("/", (c) => {
13634
13676
  role: user.role
13635
13677
  } : void 0
13636
13678
  };
13637
- return c.html(chunkALOS2CBJ_cjs.renderDesignPage(pageData));
13679
+ return c.html(chunk3SPQ3J4N_cjs.renderDesignPage(pageData));
13638
13680
  });
13639
13681
  var adminCheckboxRoutes = new hono.Hono();
13640
13682
  adminCheckboxRoutes.get("/", (c) => {
@@ -13646,7 +13688,7 @@ adminCheckboxRoutes.get("/", (c) => {
13646
13688
  role: user.role
13647
13689
  } : void 0
13648
13690
  };
13649
- return c.html(chunkALOS2CBJ_cjs.renderCheckboxPage(pageData));
13691
+ return c.html(chunk3SPQ3J4N_cjs.renderCheckboxPage(pageData));
13650
13692
  });
13651
13693
 
13652
13694
  // src/templates/pages/admin-faq-form.template.ts
@@ -13674,7 +13716,7 @@ function renderFAQForm(data) {
13674
13716
  </div>
13675
13717
  </div>
13676
13718
 
13677
- ${message ? chunkALOS2CBJ_cjs.renderAlert({ type: messageType || "info", message, dismissible: true }) : ""}
13719
+ ${message ? chunk3SPQ3J4N_cjs.renderAlert({ type: messageType || "info", message, dismissible: true }) : ""}
13678
13720
 
13679
13721
  <!-- Form -->
13680
13722
  <div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl">
@@ -13887,7 +13929,7 @@ function renderFAQForm(data) {
13887
13929
  user: data.user,
13888
13930
  content: pageContent
13889
13931
  };
13890
- return chunkALOS2CBJ_cjs.renderAdminLayout(layoutData);
13932
+ return chunk3SPQ3J4N_cjs.renderAdminLayout(layoutData);
13891
13933
  }
13892
13934
  function escapeHtml4(unsafe) {
13893
13935
  return unsafe.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
@@ -13912,7 +13954,7 @@ adminFAQRoutes.get("/", async (c) => {
13912
13954
  const offset = (currentPage - 1) * limit;
13913
13955
  const db = c.env?.DB;
13914
13956
  if (!db) {
13915
- return c.html(chunkALOS2CBJ_cjs.renderFAQList({
13957
+ return c.html(chunk3SPQ3J4N_cjs.renderFAQList({
13916
13958
  faqs: [],
13917
13959
  totalCount: 0,
13918
13960
  currentPage: 1,
@@ -13952,7 +13994,7 @@ adminFAQRoutes.get("/", async (c) => {
13952
13994
  `;
13953
13995
  const { results: faqs } = await db.prepare(dataQuery).bind(...params, limit, offset).all();
13954
13996
  const totalPages = Math.ceil(totalCount / limit);
13955
- return c.html(chunkALOS2CBJ_cjs.renderFAQList({
13997
+ return c.html(chunk3SPQ3J4N_cjs.renderFAQList({
13956
13998
  faqs: faqs || [],
13957
13999
  totalCount,
13958
14000
  currentPage,
@@ -13966,7 +14008,7 @@ adminFAQRoutes.get("/", async (c) => {
13966
14008
  } catch (error) {
13967
14009
  console.error("Error fetching FAQs:", error);
13968
14010
  const user = c.get("user");
13969
- return c.html(chunkALOS2CBJ_cjs.renderFAQList({
14011
+ return c.html(chunk3SPQ3J4N_cjs.renderFAQList({
13970
14012
  faqs: [],
13971
14013
  totalCount: 0,
13972
14014
  currentPage: 1,
@@ -14279,7 +14321,7 @@ function renderTestimonialsForm(data) {
14279
14321
  </div>
14280
14322
  </div>
14281
14323
 
14282
- ${message ? chunkALOS2CBJ_cjs.renderAlert({ type: messageType || "info", message, dismissible: true }) : ""}
14324
+ ${message ? chunk3SPQ3J4N_cjs.renderAlert({ type: messageType || "info", message, dismissible: true }) : ""}
14283
14325
 
14284
14326
  <!-- Form -->
14285
14327
  <div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl">
@@ -14508,7 +14550,7 @@ function renderTestimonialsForm(data) {
14508
14550
  user: data.user,
14509
14551
  content: pageContent
14510
14552
  };
14511
- return chunkALOS2CBJ_cjs.renderAdminLayout(layoutData);
14553
+ return chunk3SPQ3J4N_cjs.renderAdminLayout(layoutData);
14512
14554
  }
14513
14555
  function escapeHtml5(unsafe) {
14514
14556
  return unsafe.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
@@ -14534,7 +14576,7 @@ adminTestimonialsRoutes.get("/", async (c) => {
14534
14576
  const offset = (currentPage - 1) * limit;
14535
14577
  const db = c.env?.DB;
14536
14578
  if (!db) {
14537
- return c.html(chunkALOS2CBJ_cjs.renderTestimonialsList({
14579
+ return c.html(chunk3SPQ3J4N_cjs.renderTestimonialsList({
14538
14580
  testimonials: [],
14539
14581
  totalCount: 0,
14540
14582
  currentPage: 1,
@@ -14574,7 +14616,7 @@ adminTestimonialsRoutes.get("/", async (c) => {
14574
14616
  `;
14575
14617
  const { results: testimonials } = await db.prepare(dataQuery).bind(...params, limit, offset).all();
14576
14618
  const totalPages = Math.ceil(totalCount / limit);
14577
- return c.html(chunkALOS2CBJ_cjs.renderTestimonialsList({
14619
+ return c.html(chunk3SPQ3J4N_cjs.renderTestimonialsList({
14578
14620
  testimonials: testimonials || [],
14579
14621
  totalCount,
14580
14622
  currentPage,
@@ -14588,7 +14630,7 @@ adminTestimonialsRoutes.get("/", async (c) => {
14588
14630
  } catch (error) {
14589
14631
  console.error("Error fetching testimonials:", error);
14590
14632
  const user = c.get("user");
14591
- return c.html(chunkALOS2CBJ_cjs.renderTestimonialsList({
14633
+ return c.html(chunk3SPQ3J4N_cjs.renderTestimonialsList({
14592
14634
  testimonials: [],
14593
14635
  totalCount: 0,
14594
14636
  currentPage: 1,
@@ -14907,7 +14949,7 @@ function renderCodeExamplesForm(data) {
14907
14949
  </div>
14908
14950
  </div>
14909
14951
 
14910
- ${message ? chunkALOS2CBJ_cjs.renderAlert({ type: messageType || "info", message, dismissible: true }) : ""}
14952
+ ${message ? chunk3SPQ3J4N_cjs.renderAlert({ type: messageType || "info", message, dismissible: true }) : ""}
14911
14953
 
14912
14954
  <!-- Form -->
14913
14955
  <div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl">
@@ -15177,7 +15219,7 @@ function renderCodeExamplesForm(data) {
15177
15219
  user: data.user,
15178
15220
  content: pageContent
15179
15221
  };
15180
- return chunkALOS2CBJ_cjs.renderAdminLayout(layoutData);
15222
+ return chunk3SPQ3J4N_cjs.renderAdminLayout(layoutData);
15181
15223
  }
15182
15224
  function escapeHtml6(unsafe) {
15183
15225
  return unsafe.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
@@ -15204,7 +15246,7 @@ adminCodeExamplesRoutes.get("/", async (c) => {
15204
15246
  const offset = (currentPage - 1) * limit;
15205
15247
  const db = c.env?.DB;
15206
15248
  if (!db) {
15207
- return c.html(chunkALOS2CBJ_cjs.renderCodeExamplesList({
15249
+ return c.html(chunk3SPQ3J4N_cjs.renderCodeExamplesList({
15208
15250
  codeExamples: [],
15209
15251
  totalCount: 0,
15210
15252
  currentPage: 1,
@@ -15244,7 +15286,7 @@ adminCodeExamplesRoutes.get("/", async (c) => {
15244
15286
  `;
15245
15287
  const { results: codeExamples } = await db.prepare(dataQuery).bind(...params, limit, offset).all();
15246
15288
  const totalPages = Math.ceil(totalCount / limit);
15247
- return c.html(chunkALOS2CBJ_cjs.renderCodeExamplesList({
15289
+ return c.html(chunk3SPQ3J4N_cjs.renderCodeExamplesList({
15248
15290
  codeExamples: codeExamples || [],
15249
15291
  totalCount,
15250
15292
  currentPage,
@@ -15258,7 +15300,7 @@ adminCodeExamplesRoutes.get("/", async (c) => {
15258
15300
  } catch (error) {
15259
15301
  console.error("Error fetching code examples:", error);
15260
15302
  const user = c.get("user");
15261
- return c.html(chunkALOS2CBJ_cjs.renderCodeExamplesList({
15303
+ return c.html(chunk3SPQ3J4N_cjs.renderCodeExamplesList({
15262
15304
  codeExamples: [],
15263
15305
  totalCount: 0,
15264
15306
  currentPage: 1,
@@ -15647,7 +15689,7 @@ function renderDashboardPage(data) {
15647
15689
  version: data.version,
15648
15690
  content: pageContent
15649
15691
  };
15650
- return chunkALOS2CBJ_cjs.renderAdminLayout(layoutData);
15692
+ return chunk3SPQ3J4N_cjs.renderAdminLayout(layoutData);
15651
15693
  }
15652
15694
  function renderStatsCards(stats) {
15653
15695
  const cards = [
@@ -15745,7 +15787,7 @@ function renderAnalyticsChart() {
15745
15787
 
15746
15788
  <!-- Hidden div to trigger HTMX polling -->
15747
15789
  <div
15748
- hx-get="/admin/api/metrics"
15790
+ hx-get="/admin/dashboard/api/metrics"
15749
15791
  hx-trigger="every 1s"
15750
15792
  hx-swap="none"
15751
15793
  style="display: none;"
@@ -15848,9 +15890,12 @@ function renderAnalyticsChart() {
15848
15890
 
15849
15891
  // Listen for metrics updates from HTMX
15850
15892
  window.addEventListener('htmx:afterRequest', function(event) {
15851
- if (event.detail.pathInfo.requestPath === '/admin/api/metrics') {
15893
+ console.log('[Dashboard] HTMX request completed:', event.detail.pathInfo.requestPath);
15894
+
15895
+ if (event.detail.pathInfo.requestPath === '/admin/dashboard/api/metrics') {
15852
15896
  try {
15853
15897
  const metrics = JSON.parse(event.detail.xhr.responseText);
15898
+ console.log('[Dashboard] Metrics received:', metrics);
15854
15899
 
15855
15900
  // Update current RPS display
15856
15901
  const rpsElement = document.getElementById('current-rps');
@@ -15871,8 +15916,9 @@ function renderAnalyticsChart() {
15871
15916
  chart.data.labels = newLabels;
15872
15917
 
15873
15918
  chart.update('none'); // Update without animation for smoother real-time updates
15919
+ console.log('[Dashboard] Chart updated with RPS:', metrics.requestsPerSecond);
15874
15920
  } catch (e) {
15875
- console.error('Error updating metrics:', e);
15921
+ console.error('[Dashboard] Error updating metrics:', e);
15876
15922
  }
15877
15923
  }
15878
15924
  });
@@ -16191,9 +16237,9 @@ function renderStorageUsage(databaseSizeBytes, mediaSizeBytes) {
16191
16237
  }
16192
16238
 
16193
16239
  // src/routes/admin-dashboard.ts
16194
- var VERSION = chunkNK6FN5R5_cjs.getCoreVersion();
16240
+ var VERSION = chunkUL32L2KV_cjs.getCoreVersion();
16195
16241
  var router = new hono.Hono();
16196
- router.use("*", chunkKM4AJFXI_cjs.requireAuth());
16242
+ router.use("*", chunk4BJGEGX5_cjs.requireAuth());
16197
16243
  router.get("/", async (c) => {
16198
16244
  const user = c.get("user");
16199
16245
  try {
@@ -16219,7 +16265,7 @@ router.get("/", async (c) => {
16219
16265
  return c.html(renderDashboardPage(pageData));
16220
16266
  }
16221
16267
  });
16222
- router.get("/dashboard/stats", async (c) => {
16268
+ router.get("/stats", async (c) => {
16223
16269
  try {
16224
16270
  const db = c.env.DB;
16225
16271
  let collectionsCount = 0;
@@ -16269,7 +16315,7 @@ router.get("/dashboard/stats", async (c) => {
16269
16315
  return c.html('<div class="text-red-500">Failed to load statistics</div>');
16270
16316
  }
16271
16317
  });
16272
- router.get("/dashboard/storage", async (c) => {
16318
+ router.get("/storage", async (c) => {
16273
16319
  try {
16274
16320
  const db = c.env.DB;
16275
16321
  let databaseSize = 0;
@@ -16294,7 +16340,7 @@ router.get("/dashboard/storage", async (c) => {
16294
16340
  return c.html('<div class="text-red-500">Failed to load storage information</div>');
16295
16341
  }
16296
16342
  });
16297
- router.get("/dashboard/recent-activity", async (c) => {
16343
+ router.get("/recent-activity", async (c) => {
16298
16344
  try {
16299
16345
  const db = c.env.DB;
16300
16346
  const limit = parseInt(c.req.query("limit") || "5");
@@ -16346,25 +16392,14 @@ router.get("/dashboard/recent-activity", async (c) => {
16346
16392
  }
16347
16393
  });
16348
16394
  router.get("/api/metrics", async (c) => {
16349
- try {
16350
- const { metricsTracker } = await import('../utils/metrics-tracker');
16351
- return c.json({
16352
- requestsPerSecond: metricsTracker.getRequestsPerSecond(),
16353
- totalRequests: metricsTracker.getTotalRequests(),
16354
- averageRPS: metricsTracker.getAverageRPS(),
16355
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
16356
- });
16357
- } catch (error) {
16358
- console.error("Error fetching metrics:", error);
16359
- return c.json({
16360
- requestsPerSecond: 0,
16361
- totalRequests: 0,
16362
- averageRPS: 0,
16363
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
16364
- });
16365
- }
16395
+ return c.json({
16396
+ requestsPerSecond: chunkRCQ2HIQD_cjs.metricsTracker.getRequestsPerSecond(),
16397
+ totalRequests: chunkRCQ2HIQD_cjs.metricsTracker.getTotalRequests(),
16398
+ averageRPS: Number(chunkRCQ2HIQD_cjs.metricsTracker.getAverageRPS().toFixed(2)),
16399
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
16400
+ });
16366
16401
  });
16367
- router.get("/dashboard/system-status", async (c) => {
16402
+ router.get("/system-status", async (c) => {
16368
16403
  try {
16369
16404
  const html9 = `
16370
16405
  <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
@@ -16429,7 +16464,7 @@ router.get("/dashboard/system-status", async (c) => {
16429
16464
  });
16430
16465
 
16431
16466
  // src/templates/pages/admin-collections-list.template.ts
16432
- chunkALOS2CBJ_cjs.init_admin_layout_catalyst_template();
16467
+ chunk3SPQ3J4N_cjs.init_admin_layout_catalyst_template();
16433
16468
 
16434
16469
  // src/templates/components/table.template.ts
16435
16470
  function renderTable2(data) {
@@ -16903,11 +16938,11 @@ function renderCollectionsListPage(data) {
16903
16938
  version: data.version,
16904
16939
  content: pageContent
16905
16940
  };
16906
- return chunkALOS2CBJ_cjs.renderAdminLayoutCatalyst(layoutData);
16941
+ return chunk3SPQ3J4N_cjs.renderAdminLayoutCatalyst(layoutData);
16907
16942
  }
16908
16943
 
16909
16944
  // src/templates/pages/admin-collections-form.template.ts
16910
- chunkALOS2CBJ_cjs.init_admin_layout_catalyst_template();
16945
+ chunk3SPQ3J4N_cjs.init_admin_layout_catalyst_template();
16911
16946
  function renderCollectionFormPage(data) {
16912
16947
  const isEdit = data.isEdit || !!data.id;
16913
16948
  const title = isEdit ? "Edit Collection" : "Create New Collection";
@@ -17136,7 +17171,7 @@ function renderCollectionFormPage(data) {
17136
17171
  }
17137
17172
  </style>
17138
17173
 
17139
- ${chunkALOS2CBJ_cjs.renderForm(formData)}
17174
+ ${chunk3SPQ3J4N_cjs.renderForm(formData)}
17140
17175
 
17141
17176
  ${isEdit && !data.managed ? `
17142
17177
  <!-- Fields Management Section -->
@@ -17680,12 +17715,13 @@ function renderCollectionFormPage(data) {
17680
17715
  version: data.version,
17681
17716
  content: pageContent
17682
17717
  };
17683
- return chunkALOS2CBJ_cjs.renderAdminLayoutCatalyst(layoutData);
17718
+ return chunk3SPQ3J4N_cjs.renderAdminLayoutCatalyst(layoutData);
17684
17719
  }
17685
17720
 
17686
17721
  // src/routes/admin-collections.ts
17687
17722
  var adminCollectionsRoutes = new hono.Hono();
17688
- adminCollectionsRoutes.get("/collections", async (c) => {
17723
+ adminCollectionsRoutes.use("*", chunk4BJGEGX5_cjs.requireAuth());
17724
+ adminCollectionsRoutes.get("/", async (c) => {
17689
17725
  try {
17690
17726
  const user = c.get("user");
17691
17727
  const db = c.env.DB;
@@ -17740,7 +17776,7 @@ adminCollectionsRoutes.get("/collections", async (c) => {
17740
17776
  return c.html(html.html`<p>Error loading collections</p>`);
17741
17777
  }
17742
17778
  });
17743
- adminCollectionsRoutes.get("/collections/new", (c) => {
17779
+ adminCollectionsRoutes.get("/new", (c) => {
17744
17780
  const user = c.get("user");
17745
17781
  const formData = {
17746
17782
  isEdit: false,
@@ -17753,7 +17789,7 @@ adminCollectionsRoutes.get("/collections/new", (c) => {
17753
17789
  };
17754
17790
  return c.html(renderCollectionFormPage(formData));
17755
17791
  });
17756
- adminCollectionsRoutes.post("/collections", async (c) => {
17792
+ adminCollectionsRoutes.post("/", async (c) => {
17757
17793
  try {
17758
17794
  const formData = await c.req.formData();
17759
17795
  const name = formData.get("name");
@@ -17872,7 +17908,7 @@ adminCollectionsRoutes.post("/collections", async (c) => {
17872
17908
  }
17873
17909
  }
17874
17910
  });
17875
- adminCollectionsRoutes.get("/collections/:id", async (c) => {
17911
+ adminCollectionsRoutes.get("/:id", async (c) => {
17876
17912
  try {
17877
17913
  const id = c.req.param("id");
17878
17914
  const user = c.get("user");
@@ -17940,7 +17976,7 @@ adminCollectionsRoutes.get("/collections/:id", async (c) => {
17940
17976
  return c.html(renderCollectionFormPage(formData));
17941
17977
  }
17942
17978
  });
17943
- adminCollectionsRoutes.put("/collections/:id", async (c) => {
17979
+ adminCollectionsRoutes.put("/:id", async (c) => {
17944
17980
  try {
17945
17981
  const id = c.req.param("id");
17946
17982
  const formData = await c.req.formData();
@@ -17974,7 +18010,7 @@ adminCollectionsRoutes.put("/collections/:id", async (c) => {
17974
18010
  `);
17975
18011
  }
17976
18012
  });
17977
- adminCollectionsRoutes.delete("/collections/:id", async (c) => {
18013
+ adminCollectionsRoutes.delete("/:id", async (c) => {
17978
18014
  try {
17979
18015
  const id = c.req.param("id");
17980
18016
  const db = c.env.DB;
@@ -18005,7 +18041,7 @@ adminCollectionsRoutes.delete("/collections/:id", async (c) => {
18005
18041
  `);
18006
18042
  }
18007
18043
  });
18008
- adminCollectionsRoutes.post("/collections/:id/fields", async (c) => {
18044
+ adminCollectionsRoutes.post("/:id/fields", async (c) => {
18009
18045
  try {
18010
18046
  const collectionId = c.req.param("id");
18011
18047
  const formData = await c.req.formData();
@@ -18058,7 +18094,7 @@ adminCollectionsRoutes.post("/collections/:id/fields", async (c) => {
18058
18094
  return c.json({ success: false, error: "Failed to add field." });
18059
18095
  }
18060
18096
  });
18061
- adminCollectionsRoutes.put("/collections/:collectionId/fields/:fieldId", async (c) => {
18097
+ adminCollectionsRoutes.put("/:collectionId/fields/:fieldId", async (c) => {
18062
18098
  try {
18063
18099
  const fieldId = c.req.param("fieldId");
18064
18100
  const formData = await c.req.formData();
@@ -18082,7 +18118,7 @@ adminCollectionsRoutes.put("/collections/:collectionId/fields/:fieldId", async (
18082
18118
  return c.json({ success: false, error: "Failed to update field." });
18083
18119
  }
18084
18120
  });
18085
- adminCollectionsRoutes.delete("/collections/:collectionId/fields/:fieldId", async (c) => {
18121
+ adminCollectionsRoutes.delete("/:collectionId/fields/:fieldId", async (c) => {
18086
18122
  try {
18087
18123
  const fieldId = c.req.param("fieldId");
18088
18124
  const db = c.env.DB;
@@ -18094,7 +18130,7 @@ adminCollectionsRoutes.delete("/collections/:collectionId/fields/:fieldId", asyn
18094
18130
  return c.json({ success: false, error: "Failed to delete field." });
18095
18131
  }
18096
18132
  });
18097
- adminCollectionsRoutes.post("/collections/:collectionId/fields/reorder", async (c) => {
18133
+ adminCollectionsRoutes.post("/:collectionId/fields/reorder", async (c) => {
18098
18134
  try {
18099
18135
  const body = await c.req.json();
18100
18136
  const fieldIds = body.fieldIds;
@@ -18114,7 +18150,7 @@ adminCollectionsRoutes.post("/collections/:collectionId/fields/reorder", async (
18114
18150
  });
18115
18151
 
18116
18152
  // src/templates/pages/admin-settings.template.ts
18117
- chunkALOS2CBJ_cjs.init_admin_layout_catalyst_template();
18153
+ chunk3SPQ3J4N_cjs.init_admin_layout_catalyst_template();
18118
18154
  function renderSettingsPage(data) {
18119
18155
  const activeTab = data.activeTab || "general";
18120
18156
  const pageContent = `
@@ -18215,7 +18251,7 @@ function renderSettingsPage(data) {
18215
18251
  // Migration functions
18216
18252
  window.refreshMigrationStatus = async function() {
18217
18253
  try {
18218
- const response = await fetch('/admin/api/migrations/status');
18254
+ const response = await fetch('/admin/settings/api/migrations/status');
18219
18255
  const result = await response.json();
18220
18256
 
18221
18257
  if (result.success) {
@@ -18243,7 +18279,7 @@ function renderSettingsPage(data) {
18243
18279
  btn.innerHTML = 'Running...';
18244
18280
 
18245
18281
  try {
18246
- const response = await fetch('/admin/api/migrations/run', {
18282
+ const response = await fetch('/admin/settings/api/migrations/run', {
18247
18283
  method: 'POST'
18248
18284
  });
18249
18285
  const result = await response.json();
@@ -18264,7 +18300,7 @@ function renderSettingsPage(data) {
18264
18300
 
18265
18301
  window.validateSchema = async function() {
18266
18302
  try {
18267
- const response = await fetch('/admin/api/migrations/validate');
18303
+ const response = await fetch('/admin/settings/api/migrations/validate');
18268
18304
  const result = await response.json();
18269
18305
 
18270
18306
  if (result.success) {
@@ -18342,7 +18378,7 @@ function renderSettingsPage(data) {
18342
18378
  // Database Tools functions
18343
18379
  window.refreshDatabaseStats = async function() {
18344
18380
  try {
18345
- const response = await fetch('/admin/database-tools/api/stats');
18381
+ const response = await fetch('/admin/settings/api/database-tools/stats');
18346
18382
  const result = await response.json();
18347
18383
 
18348
18384
  if (result.success) {
@@ -18363,7 +18399,7 @@ function renderSettingsPage(data) {
18363
18399
  btn.innerHTML = 'Creating Backup...';
18364
18400
 
18365
18401
  try {
18366
- const response = await fetch('/admin/database-tools/api/backup', {
18402
+ const response = await fetch('/admin/settings/api/database-tools/backup', {
18367
18403
  method: 'POST'
18368
18404
  });
18369
18405
  const result = await response.json();
@@ -18402,7 +18438,7 @@ function renderSettingsPage(data) {
18402
18438
  btn.innerHTML = 'Truncating...';
18403
18439
 
18404
18440
  try {
18405
- const response = await fetch('/admin/database-tools/api/truncate', {
18441
+ const response = await fetch('/admin/settings/api/database-tools/truncate', {
18406
18442
  method: 'POST',
18407
18443
  headers: {
18408
18444
  'Content-Type': 'application/json'
@@ -18433,7 +18469,7 @@ function renderSettingsPage(data) {
18433
18469
 
18434
18470
  window.validateDatabase = async function() {
18435
18471
  try {
18436
- const response = await fetch('/admin/database-tools/api/validate');
18472
+ const response = await fetch('/admin/settings/api/database-tools/validate');
18437
18473
  const result = await response.json();
18438
18474
 
18439
18475
  if (result.success) {
@@ -18524,7 +18560,7 @@ function renderSettingsPage(data) {
18524
18560
  version: data.version,
18525
18561
  content: pageContent
18526
18562
  };
18527
- return chunkALOS2CBJ_cjs.renderAdminLayoutCatalyst(layoutData);
18563
+ return chunk3SPQ3J4N_cjs.renderAdminLayoutCatalyst(layoutData);
18528
18564
  }
18529
18565
  function renderTabButton(tabId, label, iconPath, activeTab) {
18530
18566
  const isActive = activeTab === tabId;
@@ -19287,7 +19323,7 @@ function renderMigrationSettings(settings) {
19287
19323
  if (typeof refreshMigrationStatus === 'undefined') {
19288
19324
  window.refreshMigrationStatus = async function() {
19289
19325
  try {
19290
- const response = await fetch('/admin/api/migrations/status');
19326
+ const response = await fetch('/admin/settings/api/migrations/status');
19291
19327
  const result = await response.json();
19292
19328
 
19293
19329
  if (result.success) {
@@ -19541,6 +19577,7 @@ function renderDatabaseToolsSettings(settings) {
19541
19577
 
19542
19578
  // src/routes/admin-settings.ts
19543
19579
  var adminSettingsRoutes = new hono.Hono();
19580
+ adminSettingsRoutes.use("*", chunk4BJGEGX5_cjs.requireAuth());
19544
19581
  function getMockSettings(user) {
19545
19582
  return {
19546
19583
  general: {
@@ -19599,10 +19636,10 @@ function getMockSettings(user) {
19599
19636
  }
19600
19637
  };
19601
19638
  }
19602
- adminSettingsRoutes.get("/settings", (c) => {
19639
+ adminSettingsRoutes.get("/", (c) => {
19603
19640
  return c.redirect("/admin/settings/general");
19604
19641
  });
19605
- adminSettingsRoutes.get("/settings/general", (c) => {
19642
+ adminSettingsRoutes.get("/general", (c) => {
19606
19643
  const user = c.get("user");
19607
19644
  const pageData = {
19608
19645
  user: user ? {
@@ -19616,7 +19653,7 @@ adminSettingsRoutes.get("/settings/general", (c) => {
19616
19653
  };
19617
19654
  return c.html(renderSettingsPage(pageData));
19618
19655
  });
19619
- adminSettingsRoutes.get("/settings/appearance", (c) => {
19656
+ adminSettingsRoutes.get("/appearance", (c) => {
19620
19657
  const user = c.get("user");
19621
19658
  const pageData = {
19622
19659
  user: user ? {
@@ -19630,7 +19667,7 @@ adminSettingsRoutes.get("/settings/appearance", (c) => {
19630
19667
  };
19631
19668
  return c.html(renderSettingsPage(pageData));
19632
19669
  });
19633
- adminSettingsRoutes.get("/settings/security", (c) => {
19670
+ adminSettingsRoutes.get("/security", (c) => {
19634
19671
  const user = c.get("user");
19635
19672
  const pageData = {
19636
19673
  user: user ? {
@@ -19644,7 +19681,7 @@ adminSettingsRoutes.get("/settings/security", (c) => {
19644
19681
  };
19645
19682
  return c.html(renderSettingsPage(pageData));
19646
19683
  });
19647
- adminSettingsRoutes.get("/settings/notifications", (c) => {
19684
+ adminSettingsRoutes.get("/notifications", (c) => {
19648
19685
  const user = c.get("user");
19649
19686
  const pageData = {
19650
19687
  user: user ? {
@@ -19658,7 +19695,7 @@ adminSettingsRoutes.get("/settings/notifications", (c) => {
19658
19695
  };
19659
19696
  return c.html(renderSettingsPage(pageData));
19660
19697
  });
19661
- adminSettingsRoutes.get("/settings/storage", (c) => {
19698
+ adminSettingsRoutes.get("/storage", (c) => {
19662
19699
  const user = c.get("user");
19663
19700
  const pageData = {
19664
19701
  user: user ? {
@@ -19672,7 +19709,7 @@ adminSettingsRoutes.get("/settings/storage", (c) => {
19672
19709
  };
19673
19710
  return c.html(renderSettingsPage(pageData));
19674
19711
  });
19675
- adminSettingsRoutes.get("/settings/migrations", (c) => {
19712
+ adminSettingsRoutes.get("/migrations", (c) => {
19676
19713
  const user = c.get("user");
19677
19714
  const pageData = {
19678
19715
  user: user ? {
@@ -19686,7 +19723,7 @@ adminSettingsRoutes.get("/settings/migrations", (c) => {
19686
19723
  };
19687
19724
  return c.html(renderSettingsPage(pageData));
19688
19725
  });
19689
- adminSettingsRoutes.get("/settings/database-tools", (c) => {
19726
+ adminSettingsRoutes.get("/database-tools", (c) => {
19690
19727
  const user = c.get("user");
19691
19728
  const pageData = {
19692
19729
  user: user ? {
@@ -19759,7 +19796,139 @@ adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
19759
19796
  }, 500);
19760
19797
  }
19761
19798
  });
19762
- adminSettingsRoutes.post("/settings", async (c) => {
19799
+ adminSettingsRoutes.get("/api/database-tools/stats", async (c) => {
19800
+ try {
19801
+ const db = c.env.DB;
19802
+ const tablesQuery = await db.prepare(`
19803
+ SELECT name FROM sqlite_master
19804
+ WHERE type='table'
19805
+ AND name NOT LIKE 'sqlite_%'
19806
+ AND name NOT LIKE '_cf_%'
19807
+ ORDER BY name
19808
+ `).all();
19809
+ const tables = tablesQuery.results || [];
19810
+ let totalRows = 0;
19811
+ const tableStats = await Promise.all(
19812
+ tables.map(async (table) => {
19813
+ try {
19814
+ const countResult = await db.prepare(`SELECT COUNT(*) as count FROM ${table.name}`).first();
19815
+ const rowCount = countResult?.count || 0;
19816
+ totalRows += rowCount;
19817
+ return {
19818
+ name: table.name,
19819
+ rowCount
19820
+ };
19821
+ } catch (error) {
19822
+ console.error(`Error counting rows in ${table.name}:`, error);
19823
+ return {
19824
+ name: table.name,
19825
+ rowCount: 0
19826
+ };
19827
+ }
19828
+ })
19829
+ );
19830
+ const estimatedSizeBytes = totalRows * 1024;
19831
+ const databaseSizeMB = (estimatedSizeBytes / (1024 * 1024)).toFixed(2);
19832
+ return c.json({
19833
+ success: true,
19834
+ data: {
19835
+ totalTables: tables.length,
19836
+ totalRows,
19837
+ databaseSize: `${databaseSizeMB} MB (estimated)`,
19838
+ tables: tableStats
19839
+ }
19840
+ });
19841
+ } catch (error) {
19842
+ console.error("Error fetching database stats:", error);
19843
+ return c.json({
19844
+ success: false,
19845
+ error: "Failed to fetch database statistics"
19846
+ }, 500);
19847
+ }
19848
+ });
19849
+ adminSettingsRoutes.get("/api/database-tools/validate", async (c) => {
19850
+ try {
19851
+ const db = c.env.DB;
19852
+ const integrityResult = await db.prepare("PRAGMA integrity_check").first();
19853
+ const isValid = integrityResult?.integrity_check === "ok";
19854
+ return c.json({
19855
+ success: true,
19856
+ data: {
19857
+ valid: isValid,
19858
+ message: isValid ? "Database integrity check passed" : "Database integrity check failed"
19859
+ }
19860
+ });
19861
+ } catch (error) {
19862
+ console.error("Error validating database:", error);
19863
+ return c.json({
19864
+ success: false,
19865
+ error: "Failed to validate database"
19866
+ }, 500);
19867
+ }
19868
+ });
19869
+ adminSettingsRoutes.post("/api/database-tools/backup", async (c) => {
19870
+ try {
19871
+ const user = c.get("user");
19872
+ if (!user || user.role !== "admin") {
19873
+ return c.json({
19874
+ success: false,
19875
+ error: "Unauthorized. Admin access required."
19876
+ }, 403);
19877
+ }
19878
+ return c.json({
19879
+ success: true,
19880
+ message: "Database backup feature coming soon. Use Cloudflare Dashboard for backups."
19881
+ });
19882
+ } catch (error) {
19883
+ console.error("Error creating backup:", error);
19884
+ return c.json({
19885
+ success: false,
19886
+ error: "Failed to create backup"
19887
+ }, 500);
19888
+ }
19889
+ });
19890
+ adminSettingsRoutes.post("/api/database-tools/truncate", async (c) => {
19891
+ try {
19892
+ const user = c.get("user");
19893
+ if (!user || user.role !== "admin") {
19894
+ return c.json({
19895
+ success: false,
19896
+ error: "Unauthorized. Admin access required."
19897
+ }, 403);
19898
+ }
19899
+ const body = await c.req.json();
19900
+ const tablesToTruncate = body.tables || [];
19901
+ if (!Array.isArray(tablesToTruncate) || tablesToTruncate.length === 0) {
19902
+ return c.json({
19903
+ success: false,
19904
+ error: "No tables specified for truncation"
19905
+ }, 400);
19906
+ }
19907
+ const db = c.env.DB;
19908
+ const results = [];
19909
+ for (const tableName of tablesToTruncate) {
19910
+ try {
19911
+ await db.prepare(`DELETE FROM ${tableName}`).run();
19912
+ results.push({ table: tableName, success: true });
19913
+ } catch (error) {
19914
+ console.error(`Error truncating ${tableName}:`, error);
19915
+ results.push({ table: tableName, success: false, error: String(error) });
19916
+ }
19917
+ }
19918
+ return c.json({
19919
+ success: true,
19920
+ message: `Truncated ${results.filter((r) => r.success).length} of ${tablesToTruncate.length} tables`,
19921
+ results
19922
+ });
19923
+ } catch (error) {
19924
+ console.error("Error truncating tables:", error);
19925
+ return c.json({
19926
+ success: false,
19927
+ error: "Failed to truncate tables"
19928
+ }, 500);
19929
+ }
19930
+ });
19931
+ adminSettingsRoutes.post("/", async (c) => {
19763
19932
  try {
19764
19933
  const formData = await c.req.formData();
19765
19934
  return c.html(html.html`
@@ -19830,5 +19999,5 @@ exports.api_system_default = api_system_default;
19830
19999
  exports.auth_default = auth_default;
19831
20000
  exports.router = router;
19832
20001
  exports.userRoutes = userRoutes;
19833
- //# sourceMappingURL=chunk-5FDDDD4J.cjs.map
19834
- //# sourceMappingURL=chunk-5FDDDD4J.cjs.map
20002
+ //# sourceMappingURL=chunk-5B3VMVEX.cjs.map
20003
+ //# sourceMappingURL=chunk-5B3VMVEX.cjs.map