@sonicjs-cms/core 2.10.1 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/{chunk-CJYFSKH7.js → chunk-2MXF4RYZ.js} +3 -3
  2. package/dist/{chunk-CJYFSKH7.js.map → chunk-2MXF4RYZ.js.map} +1 -1
  3. package/dist/{chunk-MNFY6DWY.cjs → chunk-56GUBLJE.cjs} +7 -7
  4. package/dist/{chunk-MNFY6DWY.cjs.map → chunk-56GUBLJE.cjs.map} +1 -1
  5. package/dist/{chunk-TWCQVJ6M.cjs → chunk-6BVLPACH.cjs} +37 -2
  6. package/dist/chunk-6BVLPACH.cjs.map +1 -0
  7. package/dist/{chunk-HGKBMUYY.cjs → chunk-ASAEJ4B7.cjs} +252 -125
  8. package/dist/chunk-ASAEJ4B7.cjs.map +1 -0
  9. package/dist/{chunk-5GO3AMON.cjs → chunk-B2ASV5RD.cjs} +8 -8
  10. package/dist/{chunk-5GO3AMON.cjs.map → chunk-B2ASV5RD.cjs.map} +1 -1
  11. package/dist/{chunk-YXTFJPMN.js → chunk-BUU2US2Z.js} +3 -3
  12. package/dist/{chunk-YXTFJPMN.js.map → chunk-BUU2US2Z.js.map} +1 -1
  13. package/dist/{chunk-EAJJHE5F.cjs → chunk-DE5YTNCD.cjs} +2 -2
  14. package/dist/{chunk-EAJJHE5F.cjs.map → chunk-DE5YTNCD.cjs.map} +1 -1
  15. package/dist/{chunk-JFMBYQTC.js → chunk-GKRGDJGG.js} +4 -4
  16. package/dist/{chunk-JFMBYQTC.js.map → chunk-GKRGDJGG.js.map} +1 -1
  17. package/dist/{chunk-FW5CGNM2.js → chunk-H55AYIRI.js} +2 -2
  18. package/dist/{chunk-FW5CGNM2.js.map → chunk-H55AYIRI.js.map} +1 -1
  19. package/dist/{chunk-SDAGUFOF.js → chunk-JTQBNSZX.js} +151 -24
  20. package/dist/chunk-JTQBNSZX.js.map +1 -0
  21. package/dist/{chunk-BUPNX3ZM.js → chunk-NMLFKXWW.js} +37 -2
  22. package/dist/chunk-NMLFKXWW.js.map +1 -0
  23. package/dist/{chunk-E2GKK5HX.cjs → chunk-QLPFENZ2.cjs} +3 -3
  24. package/dist/{chunk-E2GKK5HX.cjs.map → chunk-QLPFENZ2.cjs.map} +1 -1
  25. package/dist/{chunk-KYGRJCZM.cjs → chunk-QTFKZBLC.cjs} +3 -2
  26. package/dist/chunk-QTFKZBLC.cjs.map +1 -0
  27. package/dist/{chunk-LOUJRBXV.js → chunk-QXOZI5Q2.js} +3 -2
  28. package/dist/chunk-QXOZI5Q2.js.map +1 -0
  29. package/dist/index.cjs +685 -114
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +125 -5
  32. package/dist/index.d.ts +125 -5
  33. package/dist/index.js +580 -13
  34. package/dist/index.js.map +1 -1
  35. package/dist/middleware.cjs +29 -29
  36. package/dist/middleware.js +3 -3
  37. package/dist/migrations-UFVJTPVT.js +4 -0
  38. package/dist/{migrations-ADK6YNM2.js.map → migrations-UFVJTPVT.js.map} +1 -1
  39. package/dist/migrations-VNYOSUNE.cjs +13 -0
  40. package/dist/{migrations-EM2D6EG2.cjs.map → migrations-VNYOSUNE.cjs.map} +1 -1
  41. package/dist/{plugin-0Xogrln-.d.cts → plugin-DDYetMF-.d.cts} +1 -0
  42. package/dist/{plugin-0Xogrln-.d.ts → plugin-DDYetMF-.d.ts} +1 -0
  43. package/dist/{plugin-bootstrap-B8PXeGj_.d.cts → plugin-bootstrap-DCXpeQVb.d.cts} +1 -1
  44. package/dist/{plugin-bootstrap-CD63DZ-p.d.ts → plugin-bootstrap-DXBAYaqM.d.ts} +1 -1
  45. package/dist/{plugin-manager-GcIeb226.d.cts → plugin-manager-BoM3Q7o7.d.cts} +1 -1
  46. package/dist/{plugin-manager-Clf2gXwj.d.ts → plugin-manager-Efx9RyDX.d.ts} +1 -1
  47. package/dist/plugins.cjs +10 -10
  48. package/dist/plugins.d.cts +2 -2
  49. package/dist/plugins.d.ts +2 -2
  50. package/dist/plugins.js +2 -2
  51. package/dist/routes.cjs +28 -28
  52. package/dist/routes.js +5 -5
  53. package/dist/services.cjs +23 -23
  54. package/dist/services.d.cts +1 -1
  55. package/dist/services.d.ts +1 -1
  56. package/dist/services.js +2 -2
  57. package/dist/types.cjs +2 -2
  58. package/dist/types.d.cts +1 -1
  59. package/dist/types.d.ts +1 -1
  60. package/dist/types.js +1 -1
  61. package/dist/utils.cjs +11 -11
  62. package/dist/utils.js +1 -1
  63. package/package.json +1 -1
  64. package/dist/chunk-BUPNX3ZM.js.map +0 -1
  65. package/dist/chunk-HGKBMUYY.cjs.map +0 -1
  66. package/dist/chunk-KYGRJCZM.cjs.map +0 -1
  67. package/dist/chunk-LOUJRBXV.js.map +0 -1
  68. package/dist/chunk-SDAGUFOF.js.map +0 -1
  69. package/dist/chunk-TWCQVJ6M.cjs.map +0 -1
  70. package/dist/migrations-ADK6YNM2.js +0 -4
  71. package/dist/migrations-EM2D6EG2.cjs +0 -13
@@ -1,10 +1,10 @@
1
- import { getCacheService, CACHE_CONFIGS, getLogger, SettingsService, getAppInstance, buildRouteList, CATEGORY_INFO } from './chunk-VJCLJH3X.js';
2
- import { requireAuth, requireRole, isPluginActive, optionalAuth, rateLimit, AuthManager, logActivity, generateCsrfToken } from './chunk-JFMBYQTC.js';
3
- import { PluginService, createContentFromSubmission } from './chunk-BUPNX3ZM.js';
4
- import { MigrationService } from './chunk-FW5CGNM2.js';
1
+ import { getCacheService, CACHE_CONFIGS, SettingsService, getLogger, getAppInstance, buildRouteList, CATEGORY_INFO } from './chunk-VJCLJH3X.js';
2
+ import { requireAuth, requireRole, isPluginActive, optionalAuth, rateLimit, AuthManager, logActivity, generateCsrfToken } from './chunk-GKRGDJGG.js';
3
+ import { PluginService, createContentFromSubmission } from './chunk-NMLFKXWW.js';
4
+ import { MigrationService } from './chunk-H55AYIRI.js';
5
5
  import { init_admin_layout_catalyst_template, renderDesignPage, renderCheckboxPage, renderTestimonialsList, renderCodeExamplesList, renderAlert, renderTable, renderPagination, renderConfirmationDialog, getConfirmationDialogScript, renderAdminLayoutCatalyst, renderAdminLayout, adminLayoutV2, renderForm } from './chunk-JJS7JZCH.js';
6
6
  import { PluginBuilder, TurnstileService } from './chunk-J5WGMRSU.js';
7
- import { QueryFilterBuilder, getCoreVersion, getBlocksFieldConfig, parseBlocksValue } from './chunk-YXTFJPMN.js';
7
+ import { QueryFilterBuilder, getCoreVersion, getBlocksFieldConfig, parseBlocksValue } from './chunk-BUU2US2Z.js';
8
8
  import { metricsTracker } from './chunk-FICTAGD4.js';
9
9
  import { escapeHtml, sanitizeRichText, sanitizeInput } from './chunk-TQABQWOP.js';
10
10
  import { Hono } from 'hono';
@@ -59,6 +59,69 @@ function normalizePublicContentFilter(filter, userRole) {
59
59
  });
60
60
  return normalizedFilter;
61
61
  }
62
+
63
+ // src/plugins/core-plugins/global-variables-plugin/variable-resolver.ts
64
+ var TOKEN_PATTERN = /\{([a-z0-9_]+)\}/g;
65
+ function resolveVariables(text, variables) {
66
+ if (!text || variables.size === 0) return text;
67
+ return text.replace(TOKEN_PATTERN, (match, key) => {
68
+ const value = variables.get(key);
69
+ return value !== void 0 ? value : match;
70
+ });
71
+ }
72
+ function resolveVariablesInObject(obj, variables) {
73
+ if (!obj || variables.size === 0) return obj;
74
+ if (typeof obj === "string") {
75
+ return resolveVariables(obj, variables);
76
+ }
77
+ if (Array.isArray(obj)) {
78
+ return obj.map((item) => resolveVariablesInObject(item, variables));
79
+ }
80
+ if (typeof obj === "object") {
81
+ const result = {};
82
+ for (const [key, value] of Object.entries(obj)) {
83
+ result[key] = resolveVariablesInObject(value, variables);
84
+ }
85
+ return result;
86
+ }
87
+ return obj;
88
+ }
89
+ var variableCache = null;
90
+ var cacheTimestamp = 0;
91
+ var CACHE_TTL_MS = 3e5;
92
+ function getVariablesCached() {
93
+ const now = Date.now();
94
+ if (variableCache && now - cacheTimestamp < CACHE_TTL_MS) {
95
+ return variableCache;
96
+ }
97
+ return null;
98
+ }
99
+ function setVariablesCache(map) {
100
+ variableCache = map;
101
+ cacheTimestamp = Date.now();
102
+ }
103
+ async function resolveContentVariables(contentData, db) {
104
+ if (!db || !contentData) return contentData;
105
+ try {
106
+ let variables = getVariablesCached();
107
+ if (!variables) {
108
+ const { results } = await db.prepare(
109
+ "SELECT key, value FROM global_variables WHERE is_active = 1"
110
+ ).all();
111
+ variables = /* @__PURE__ */ new Map();
112
+ for (const row of results || []) {
113
+ variables.set(row.key, row.value);
114
+ }
115
+ setVariablesCache(variables);
116
+ }
117
+ if (variables.size === 0) return contentData;
118
+ return resolveVariablesInObject(contentData, variables);
119
+ } catch {
120
+ return contentData;
121
+ }
122
+ }
123
+
124
+ // src/routes/api-content-crud.ts
62
125
  var apiContentCrudRoutes = new Hono();
63
126
  apiContentCrudRoutes.get("/check-slug", async (c) => {
64
127
  try {
@@ -110,6 +173,10 @@ apiContentCrudRoutes.get("/:id", async (c) => {
110
173
  created_at: content.created_at,
111
174
  updated_at: content.updated_at
112
175
  };
176
+ const resolveVars = c.req.query("resolve_variables") !== "false";
177
+ if (resolveVars) {
178
+ transformedContent.data = await resolveContentVariables(transformedContent.data, db);
179
+ }
113
180
  return c.json({ data: transformedContent });
114
181
  } catch (error) {
115
182
  console.error("Error fetching content:", error);
@@ -2283,7 +2350,7 @@ adminApiRoutes.delete("/collections/:id", async (c) => {
2283
2350
  });
2284
2351
  adminApiRoutes.get("/migrations/status", async (c) => {
2285
2352
  try {
2286
- const { MigrationService: MigrationService2 } = await import('./migrations-ADK6YNM2.js');
2353
+ const { MigrationService: MigrationService2 } = await import('./migrations-UFVJTPVT.js');
2287
2354
  const db = c.env.DB;
2288
2355
  const migrationService = new MigrationService2(db);
2289
2356
  const status = await migrationService.getMigrationStatus();
@@ -2308,7 +2375,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
2308
2375
  error: "Unauthorized. Admin access required."
2309
2376
  }, 403);
2310
2377
  }
2311
- const { MigrationService: MigrationService2 } = await import('./migrations-ADK6YNM2.js');
2378
+ const { MigrationService: MigrationService2 } = await import('./migrations-UFVJTPVT.js');
2312
2379
  const db = c.env.DB;
2313
2380
  const migrationService = new MigrationService2(db);
2314
2381
  const result = await migrationService.runPendingMigrations();
@@ -2327,7 +2394,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
2327
2394
  });
2328
2395
  adminApiRoutes.get("/migrations/validate", async (c) => {
2329
2396
  try {
2330
- const { MigrationService: MigrationService2 } = await import('./migrations-ADK6YNM2.js');
2397
+ const { MigrationService: MigrationService2 } = await import('./migrations-UFVJTPVT.js');
2331
2398
  const db = c.env.DB;
2332
2399
  const migrationService = new MigrationService2(db);
2333
2400
  const validation = await migrationService.validateSchema();
@@ -8139,7 +8206,15 @@ function renderContentFormPage(data) {
8139
8206
  fetch(\`/admin/content/\${contentId}/versions\`)
8140
8207
  .then(response => response.text())
8141
8208
  .then(html => {
8142
- document.getElementById('version-history-content').innerHTML = html;
8209
+ const container = document.getElementById('version-history-content');
8210
+ container.innerHTML = html;
8211
+ // Script tags inserted via innerHTML are not executed by the browser,
8212
+ // so we need to manually create and append them for execution.
8213
+ container.querySelectorAll('script').forEach(oldScript => {
8214
+ const newScript = document.createElement('script');
8215
+ newScript.textContent = oldScript.textContent;
8216
+ oldScript.replaceWith(newScript);
8217
+ });
8143
8218
  })
8144
8219
  .catch(error => {
8145
8220
  console.error('Error loading version history:', error);
@@ -11420,6 +11495,36 @@ function renderUserEditPage(data) {
11420
11495
  </div>
11421
11496
  </div>
11422
11497
 
11498
+ <!-- Set Password -->
11499
+ <div class="mb-8">
11500
+ <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Set Password</h3>
11501
+ <p class="text-sm text-zinc-500 dark:text-zinc-400 mb-4">Leave blank to keep the current password</p>
11502
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
11503
+ <div>
11504
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">New Password</label>
11505
+ <input
11506
+ type="password"
11507
+ name="new_password"
11508
+ minlength="8"
11509
+ placeholder="Minimum 8 characters"
11510
+ autocomplete="new-password"
11511
+ 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"
11512
+ />
11513
+ </div>
11514
+ <div>
11515
+ <label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Confirm Password</label>
11516
+ <input
11517
+ type="password"
11518
+ name="confirm_password"
11519
+ minlength="8"
11520
+ placeholder="Repeat new password"
11521
+ autocomplete="new-password"
11522
+ 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"
11523
+ />
11524
+ </div>
11525
+ </div>
11526
+ </div>
11527
+
11423
11528
  <!-- Account Status -->
11424
11529
  <div class="mb-8">
11425
11530
  <h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Account Status</h3>
@@ -12741,6 +12846,7 @@ userRoutes.get("/users", async (c) => {
12741
12846
  formattedLastLogin: u.last_login_at ? new Date(u.last_login_at).toLocaleDateString() : void 0,
12742
12847
  formattedCreatedAt: new Date(u.created_at).toLocaleDateString()
12743
12848
  }));
12849
+ const successMessage = c.req.query("success") || void 0;
12744
12850
  const pageData = {
12745
12851
  users,
12746
12852
  currentPage: page,
@@ -12749,6 +12855,7 @@ userRoutes.get("/users", async (c) => {
12749
12855
  searchFilter: search,
12750
12856
  roleFilter,
12751
12857
  statusFilter,
12858
+ success: successMessage,
12752
12859
  pagination: {
12753
12860
  currentPage: page,
12754
12861
  totalPages: Math.ceil(totalUsers / limit),
@@ -12892,7 +12999,8 @@ userRoutes.post("/users/new", async (c) => {
12892
12999
  c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
12893
13000
  c.req.header("user-agent")
12894
13001
  );
12895
- return c.redirect(`/admin/users/${userId}/edit?success=User created successfully`);
13002
+ c.header("HX-Redirect", "/admin/users?success=User created successfully");
13003
+ return c.body(null, 200);
12896
13004
  } catch (error) {
12897
13005
  console.error("User creation error:", error);
12898
13006
  return c.html(renderAlert2({
@@ -13038,6 +13146,8 @@ userRoutes.put("/users/:id", async (c) => {
13038
13146
  const role = validRoles.includes(roleInput) ? roleInput : "viewer";
13039
13147
  const isActive = formData.get("is_active") === "1";
13040
13148
  const emailVerified = formData.get("email_verified") === "1";
13149
+ const newPassword = formData.get("new_password")?.toString() || "";
13150
+ const confirmPassword = formData.get("confirm_password")?.toString() || "";
13041
13151
  const profileDisplayName = sanitizeInput(formData.get("profile_display_name")?.toString()) || null;
13042
13152
  const profileBio = sanitizeInput(formData.get("profile_bio")?.toString()) || null;
13043
13153
  const profileCompany = sanitizeInput(formData.get("profile_company")?.toString()) || null;
@@ -13061,6 +13171,22 @@ userRoutes.put("/users/:id", async (c) => {
13061
13171
  dismissible: true
13062
13172
  }));
13063
13173
  }
13174
+ if (newPassword) {
13175
+ if (newPassword.length < 8) {
13176
+ return c.html(renderAlert2({
13177
+ type: "error",
13178
+ message: "Password must be at least 8 characters long.",
13179
+ dismissible: true
13180
+ }));
13181
+ }
13182
+ if (newPassword !== confirmPassword) {
13183
+ return c.html(renderAlert2({
13184
+ type: "error",
13185
+ message: "Passwords do not match.",
13186
+ dismissible: true
13187
+ }));
13188
+ }
13189
+ }
13064
13190
  if (profileWebsite) {
13065
13191
  try {
13066
13192
  new URL(profileWebsite);
@@ -13103,6 +13229,13 @@ userRoutes.put("/users/:id", async (c) => {
13103
13229
  Date.now(),
13104
13230
  userId
13105
13231
  ).run();
13232
+ if (newPassword) {
13233
+ const passwordHash = await AuthManager.hashPassword(newPassword);
13234
+ const updatePasswordStmt = db.prepare(`
13235
+ UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?
13236
+ `);
13237
+ await updatePasswordStmt.bind(passwordHash, Date.now(), userId).run();
13238
+ }
13106
13239
  const hasProfileData = profileDisplayName || profileBio || profileCompany || profileJobTitle || profileWebsite || profileLocation || profileDateOfBirth;
13107
13240
  if (hasProfileData) {
13108
13241
  const now = Date.now();
@@ -13153,7 +13286,7 @@ userRoutes.put("/users/:id", async (c) => {
13153
13286
  "user.update",
13154
13287
  "users",
13155
13288
  userId,
13156
- { fields: ["first_name", "last_name", "username", "email", "phone", "role", "is_active", "email_verified", "profile"] },
13289
+ { fields: ["first_name", "last_name", "username", "email", "phone", "role", "is_active", "email_verified", "profile", ...newPassword ? ["password"] : []] },
13157
13290
  c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
13158
13291
  c.req.header("user-agent")
13159
13292
  );
@@ -17253,6 +17386,7 @@ function renderOTPLoginSettingsContent(plugin, settings) {
17253
17386
  const maxAttempts = settings.maxAttempts || 3;
17254
17387
  const rateLimitPerHour = settings.rateLimitPerHour || 5;
17255
17388
  const allowNewUserRegistration = settings.allowNewUserRegistration || false;
17389
+ const logoUrl = settings.logoUrl || "";
17256
17390
  return `
17257
17391
  <div class="space-y-6">
17258
17392
  <!-- Test OTP Section -->
@@ -17436,6 +17570,7 @@ function renderOTPLoginSettingsContent(plugin, settings) {
17436
17570
 
17437
17571
  <div class="bg-white rounded-lg overflow-hidden shadow-lg">
17438
17572
  <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px 20px; text-align: center;">
17573
+ ${logoUrl ? `<img src="${logoUrl}" alt="Logo" style="max-width: 150px; height: auto; margin: 0 auto 16px;">` : ""}
17439
17574
  <h3 style="margin: 0 0 8px 0; font-size: 24px; font-weight: 600;">Your Login Code</h3>
17440
17575
  <p style="margin: 0; opacity: 0.95; font-size: 14px;">Enter this code to sign in to ${siteName}</p>
17441
17576
  </div>
@@ -17960,17 +18095,9 @@ adminPluginRoutes.get("/:id", async (c) => {
17960
18095
  const activity = await pluginService.getPluginActivity(pluginId, 20);
17961
18096
  let enrichedSettings = plugin.settings || {};
17962
18097
  if (pluginId === "otp-login") {
17963
- const generalSettings = await db.prepare(`
17964
- SELECT value FROM settings WHERE key = 'general'
17965
- `).first();
17966
- let siteName = "SonicJS";
17967
- if (generalSettings?.value) {
17968
- try {
17969
- const parsed = JSON.parse(generalSettings.value);
17970
- siteName = parsed.siteName || "SonicJS";
17971
- } catch (e) {
17972
- }
17973
- }
18098
+ const settingsService = new SettingsService(db);
18099
+ const generalSettings = await settingsService.getGeneralSettings();
18100
+ const siteName = generalSettings.siteName || "SonicJS";
17974
18101
  const emailPlugin = await db.prepare(`
17975
18102
  SELECT settings FROM plugins WHERE id = 'email'
17976
18103
  `).first();
@@ -28852,5 +28979,5 @@ var ROUTES_INFO = {
28852
28979
  };
28853
28980
 
28854
28981
  export { ROUTES_INFO, adminCheckboxRoutes, adminCollectionsRoutes, adminDesignRoutes, adminFormsRoutes, adminLogsRoutes, adminMediaRoutes, adminPluginRoutes, adminSettingsRoutes, admin_api_default, admin_code_examples_default, admin_content_default, admin_testimonials_default, api_content_crud_default, api_default, api_media_default, api_system_default, auth_default, getConfirmationDialogScript2 as getConfirmationDialogScript, public_forms_default, renderConfirmationDialog2 as renderConfirmationDialog, router, router2, test_cleanup_default, userRoutes };
28855
- //# sourceMappingURL=chunk-SDAGUFOF.js.map
28856
- //# sourceMappingURL=chunk-SDAGUFOF.js.map
28982
+ //# sourceMappingURL=chunk-JTQBNSZX.js.map
28983
+ //# sourceMappingURL=chunk-JTQBNSZX.js.map