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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/{chunk-DSXEVMOM.js → chunk-2FCKKOA5.js} +2 -2
  2. package/dist/{chunk-DSXEVMOM.js.map → chunk-2FCKKOA5.js.map} +1 -1
  3. package/dist/{chunk-TQG5FNNR.cjs → chunk-3CT3SUR4.cjs} +2 -2
  4. package/dist/{chunk-TQG5FNNR.cjs.map → chunk-3CT3SUR4.cjs.map} +1 -1
  5. package/dist/{chunk-5UCMLBRQ.js → chunk-6KNTZ67K.js} +121 -17
  6. package/dist/chunk-6KNTZ67K.js.map +1 -0
  7. package/dist/{chunk-W53J3BJ2.js → chunk-73O4GPJ6.js} +3 -3
  8. package/dist/{chunk-W53J3BJ2.js.map → chunk-73O4GPJ6.js.map} +1 -1
  9. package/dist/{chunk-WCA4VENG.js → chunk-CHWT5KBK.js} +5 -5
  10. package/dist/{chunk-WCA4VENG.js.map → chunk-CHWT5KBK.js.map} +1 -1
  11. package/dist/{chunk-RDH6PUOP.js → chunk-DOMXI5PM.js} +2 -2
  12. package/dist/{chunk-RDH6PUOP.js.map → chunk-DOMXI5PM.js.map} +1 -1
  13. package/dist/{chunk-5RSB5SEK.cjs → chunk-EUJAEB6W.cjs} +4 -4
  14. package/dist/{chunk-5RSB5SEK.cjs.map → chunk-EUJAEB6W.cjs.map} +1 -1
  15. package/dist/{chunk-4SHNHNRP.cjs → chunk-FTXGZ3BF.cjs} +15 -15
  16. package/dist/{chunk-4SHNHNRP.cjs.map → chunk-FTXGZ3BF.cjs.map} +1 -1
  17. package/dist/{chunk-MYQ7KZUQ.js → chunk-GB2Q2DNK.js} +4 -4
  18. package/dist/{chunk-MYQ7KZUQ.js.map → chunk-GB2Q2DNK.js.map} +1 -1
  19. package/dist/{chunk-GMZ5TGYP.js → chunk-I2DM27HP.js} +3 -3
  20. package/dist/{chunk-GMZ5TGYP.js.map → chunk-I2DM27HP.js.map} +1 -1
  21. package/dist/{chunk-3E7IROND.cjs → chunk-JFLZHOQP.cjs} +314 -210
  22. package/dist/chunk-JFLZHOQP.cjs.map +1 -0
  23. package/dist/{chunk-DTGCXWWM.cjs → chunk-MGHHPNJN.cjs} +10 -10
  24. package/dist/{chunk-DTGCXWWM.cjs.map → chunk-MGHHPNJN.cjs.map} +1 -1
  25. package/dist/{chunk-5ARIHAGN.cjs → chunk-PYZYU7EK.cjs} +2 -2
  26. package/dist/{chunk-5ARIHAGN.cjs.map → chunk-PYZYU7EK.cjs.map} +1 -1
  27. package/dist/{chunk-AQJEMVAY.cjs → chunk-QWSR4THH.cjs} +3 -3
  28. package/dist/{chunk-AQJEMVAY.cjs.map → chunk-QWSR4THH.cjs.map} +1 -1
  29. package/dist/index.cjs +499 -327
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.js +253 -81
  32. package/dist/index.js.map +1 -1
  33. package/dist/middleware.cjs +33 -33
  34. package/dist/middleware.js +4 -4
  35. package/dist/migrations-HLK2QF4T.js +4 -0
  36. package/dist/{migrations-HZJ6U6SX.js.map → migrations-HLK2QF4T.js.map} +1 -1
  37. package/dist/migrations-UIMA6ZL6.cjs +13 -0
  38. package/dist/{migrations-VQAFXMU7.cjs.map → migrations-UIMA6ZL6.cjs.map} +1 -1
  39. package/dist/plugins.cjs +40 -40
  40. package/dist/plugins.js +3 -3
  41. package/dist/routes.cjs +26 -26
  42. package/dist/routes.js +6 -6
  43. package/dist/services.cjs +18 -18
  44. package/dist/services.js +2 -2
  45. package/dist/utils.cjs +3 -3
  46. package/dist/utils.js +1 -1
  47. package/package.json +1 -1
  48. package/dist/chunk-3E7IROND.cjs.map +0 -1
  49. package/dist/chunk-5UCMLBRQ.js.map +0 -1
  50. package/dist/migrations-HZJ6U6SX.js +0 -4
  51. package/dist/migrations-VQAFXMU7.cjs +0 -13
@@ -1,18 +1,18 @@
1
1
  import { isFirstUserRegistration, isRegistrationEnabled, authValidationService } from './chunk-VVYVFCML.js';
2
2
  import { renderDocumentFormPage, renderAlert } from './chunk-RMRJGMDE.js';
3
3
  import { getCacheService, CACHE_CONFIGS, SettingsService, getLogger, getAppInstance, buildRouteList, CATEGORY_INFO } from './chunk-2XAQTPAE.js';
4
- import { DocumentTypeRegistry, requireAuth, requireRole, optionalAuth, isPluginActive, rateLimit, AuthManager, getJwtExpirySecondsFromDb, getJwtRefreshGraceSecondsFromDb, logActivity, generateCsrfToken } from './chunk-WCA4VENG.js';
4
+ import { DocumentTypeRegistry, requireAuth, requireRole, optionalAuth, isPluginActive, rateLimit, AuthManager, getJwtExpirySecondsFromDb, getJwtRefreshGraceSecondsFromDb, logActivity, generateCsrfToken } from './chunk-CHWT5KBK.js';
5
5
  import { DocumentsService, documentSecondsToMs, RbacService } from './chunk-3TMTYJAJ.js';
6
6
  import { nanoid } from './chunk-UWUP2VMT.js';
7
- import { getCollectionRegistry, collectionRecordToRow, loadCollectionConfigs, getVisibleCollections, PluginService, PLUGIN_REGISTRY, findPluginByCodeName, isCodeCollectionInternal, isDbDocTypeInternal, invalidateTenantCache } from './chunk-RDH6PUOP.js';
8
- import { MigrationService } from './chunk-DSXEVMOM.js';
7
+ import { getCollectionRegistry, collectionRecordToRow, loadCollectionConfigs, getVisibleCollections, PluginService, PLUGIN_REGISTRY, findPluginByCodeName, isCodeCollectionInternal, isDbDocTypeInternal, invalidateTenantCache } from './chunk-DOMXI5PM.js';
8
+ import { MigrationService } from './chunk-2FCKKOA5.js';
9
9
  import { renderCheckboxPage, renderAlert as renderAlert$1, renderTable, renderPagination, renderConfirmationDialog, getConfirmationDialogScript, renderAdminLayout, adminLayoutV2, renderForm } from './chunk-OBA2RYZN.js';
10
10
  import { init_admin_layout_catalyst_template, renderAdminLayoutCatalyst } from './chunk-5V62WT6M.js';
11
- import { createServiceSingleton, definePlugin, getPluginDefinition, applySchemaDefaults, renderSchemaFields, parseFormDataToSettings } from './chunk-GMZ5TGYP.js';
11
+ import { createServiceSingleton, definePlugin, getPluginDefinition, applySchemaDefaults, renderSchemaFields, parseFormDataToSettings } from './chunk-I2DM27HP.js';
12
12
  import { hasHookSystem, getTypedHooks } from './chunk-RNZFGN4R.js';
13
13
  import { QueryFilterBuilder, getBlocksFieldConfig, parseBlocksValue } from './chunk-QZGABF2M.js';
14
14
  import { metricsTracker } from './chunk-FICTAGD4.js';
15
- import { getCoreVersion } from './chunk-W53J3BJ2.js';
15
+ import { getCoreVersion } from './chunk-73O4GPJ6.js';
16
16
  import { escapeHtml, sanitizeRichText, sanitizeInput } from './chunk-TQABQWOP.js';
17
17
  import { Hono } from 'hono';
18
18
  import { z } from 'zod';
@@ -2249,12 +2249,17 @@ var MediaDocumentService = class {
2249
2249
  where.push("(json_extract(data, '$.filename') LIKE ? OR json_extract(data, '$.originalName') LIKE ? OR json_extract(data, '$.alt') LIKE ?)");
2250
2250
  params.push(term, term, term);
2251
2251
  }
2252
- const listed = await this.db.prepare(`SELECT * FROM documents WHERE ${where.join(" AND ")} ORDER BY updated_at DESC LIMIT ? OFFSET ?`).bind(...params, limit, offset).all();
2252
+ const [listed, countResult] = await Promise.all([
2253
+ this.db.prepare(`SELECT * FROM documents WHERE ${where.join(" AND ")} ORDER BY updated_at DESC LIMIT ? OFFSET ?`).bind(...params, limit, offset).all(),
2254
+ this.db.prepare(`SELECT COUNT(*) AS total FROM documents WHERE ${where.join(" AND ")}`).bind(...params).first()
2255
+ ]);
2253
2256
  const files = (listed.results ?? []).map(rowToMinimalDoc);
2257
+ const total = countResult?.total ?? 0;
2254
2258
  const folderAgg = await this.db.prepare(`SELECT q_media_folder AS folder, COUNT(*) AS count, SUM(q_media_size) AS totalSize FROM documents WHERE ${base} GROUP BY q_media_folder ORDER BY q_media_folder`).bind(this.tenantId).all();
2255
2259
  const typeAgg = await this.db.prepare(`SELECT CASE WHEN q_media_mime LIKE 'image/%' THEN 'images' WHEN q_media_mime LIKE 'video/%' THEN 'videos' WHEN q_media_mime IN ('application/pdf', 'text/plain') THEN 'documents' ELSE 'other' END AS type, COUNT(*) AS count FROM documents WHERE ${base} GROUP BY type`).bind(this.tenantId).all();
2256
2260
  return {
2257
2261
  files,
2262
+ total,
2258
2263
  folders: (folderAgg.results ?? []).map((f) => ({ folder: f.folder, count: f.count, totalSize: f.totalSize ?? 0 })),
2259
2264
  types: (typeAgg.results ?? []).map((t) => ({ type: t.type, count: t.count }))
2260
2265
  };
@@ -3394,7 +3399,7 @@ adminApiRoutes.patch("/collections/:id", collectionsReadOnly);
3394
3399
  adminApiRoutes.delete("/collections/:id", collectionsReadOnly);
3395
3400
  adminApiRoutes.get("/migrations/status", async (c) => {
3396
3401
  try {
3397
- const { MigrationService: MigrationService2 } = await import('./migrations-HZJ6U6SX.js');
3402
+ const { MigrationService: MigrationService2 } = await import('./migrations-HLK2QF4T.js');
3398
3403
  const db = c.env.DB;
3399
3404
  const migrationService = new MigrationService2(db);
3400
3405
  const status = await migrationService.getMigrationStatus();
@@ -3437,7 +3442,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
3437
3442
  });
3438
3443
  adminApiRoutes.get("/migrations/validate", async (c) => {
3439
3444
  try {
3440
- const { MigrationService: MigrationService2 } = await import('./migrations-HZJ6U6SX.js');
3445
+ const { MigrationService: MigrationService2 } = await import('./migrations-HLK2QF4T.js');
3441
3446
  const db = c.env.DB;
3442
3447
  const migrationService = new MigrationService2(db);
3443
3448
  const validation = await migrationService.validateSchema();
@@ -17815,7 +17820,7 @@ adminMediaRoutes.get("/", async (c) => {
17815
17820
  const limit = 24;
17816
17821
  const offset = (page - 1) * limit;
17817
17822
  const mediaSvc = new MediaDocumentService(c.env.DB, getRequestTenant(c));
17818
- const { files, folders: folderAgg, types: typeAgg } = await mediaSvc.list({ folder, type, limit, offset });
17823
+ const { files, total, folders: folderAgg, types: typeAgg } = await mediaSvc.list({ folder, type, limit, offset });
17819
17824
  const mediaFiles = files.map((doc) => mediaDocToFile(doc));
17820
17825
  const pageData = {
17821
17826
  files: mediaFiles,
@@ -17825,8 +17830,8 @@ adminMediaRoutes.get("/", async (c) => {
17825
17830
  currentType: type,
17826
17831
  currentView: view,
17827
17832
  currentPage: page,
17828
- totalFiles: mediaFiles.length,
17829
- hasNextPage: mediaFiles.length === limit,
17833
+ totalFiles: total,
17834
+ hasNextPage: offset + mediaFiles.length < total,
17830
17835
  user: {
17831
17836
  name: user.email,
17832
17837
  email: user.email,
@@ -17866,12 +17871,14 @@ adminMediaRoutes.get("/selector", async (c) => {
17866
17871
  <input
17867
17872
  type="search"
17868
17873
  id="media-selector-search"
17874
+ name="search"
17869
17875
  placeholder="Search files..."
17870
17876
  class="w-full rounded-lg bg-white dark:bg-zinc-800 px-4 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow"
17871
17877
  hx-get="/admin/media/selector"
17872
17878
  hx-trigger="keyup changed delay:300ms"
17873
17879
  hx-target="#media-selector-grid"
17874
- hx-include="[name='search']"
17880
+ hx-swap="outerHTML"
17881
+ hx-select="#media-selector-grid"
17875
17882
  >
17876
17883
  </div>
17877
17884
 
@@ -19338,7 +19345,7 @@ function escapeHtmlAttr(value) {
19338
19345
  }
19339
19346
  function renderPluginSettingsPage(data) {
19340
19347
  const { plugin, activity = [], user } = data;
19341
- const hasUserSettings = Object.keys(plugin.settings || {}).some((k) => !k.startsWith("_"));
19348
+ const hasUserSettings = plugin.id in pluginSettingsComponents || Object.keys(plugin.settings || {}).some((k) => !k.startsWith("_"));
19342
19349
  const defaultTab = hasUserSettings ? "settings" : "info";
19343
19350
  const pageContent = `
19344
19351
  <div class="w-full px-4 sm:px-6 lg:px-8 py-6">
@@ -19989,7 +19996,8 @@ function formatTimestamp(timestamp) {
19989
19996
  }
19990
19997
  var pluginSettingsComponents = {
19991
19998
  "otp-login": renderOTPLoginSettingsContent,
19992
- "email": renderEmailSettingsContent
19999
+ "email": renderEmailSettingsContent,
20000
+ "oauth-providers": renderOAuthProvidersSettingsContent
19993
20001
  };
19994
20002
  function renderOTPLoginSettingsContent(plugin, settings) {
19995
20003
  const siteName = settings.siteName || "SonicJS";
@@ -20712,6 +20720,100 @@ defineUserProfile({
20712
20720
  </div>
20713
20721
  `;
20714
20722
  }
20723
+ function renderOAuthProvidersSettingsContent(_plugin, settings) {
20724
+ const providers = settings.providers || {};
20725
+ const github = providers.github || {};
20726
+ const google = providers.google || {};
20727
+ const inputClass = "w-full px-3 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none text-white";
20728
+ function renderProviderCard(name, label, icon, data) {
20729
+ const clientId = escapeHtmlAttr(data.clientId || "");
20730
+ const clientSecret = escapeHtmlAttr(data.clientSecret || "");
20731
+ const enabled = data.enabled === true;
20732
+ return `
20733
+ <div class="backdrop-blur-md bg-white/5 rounded-xl border border-white/10 p-6">
20734
+ <div class="flex items-center justify-between mb-4">
20735
+ <h3 class="text-lg font-semibold text-white flex items-center gap-2">
20736
+ <span>${icon}</span> ${label}
20737
+ </h3>
20738
+ <label class="relative inline-flex items-center cursor-pointer">
20739
+ <input type="checkbox" id="oauth_${name}_enabled" ${enabled ? "checked" : ""} class="sr-only peer">
20740
+ <div class="w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600"></div>
20741
+ <span class="ml-2 text-sm text-gray-300">Enabled</span>
20742
+ </label>
20743
+ </div>
20744
+ <div class="space-y-4">
20745
+ <div>
20746
+ <label for="oauth_${name}_clientId" class="block text-sm font-medium text-gray-300 mb-2">Client ID</label>
20747
+ <input type="text" id="oauth_${name}_clientId" value="${clientId}" placeholder="${label} OAuth Client ID" class="${inputClass}">
20748
+ </div>
20749
+ <div>
20750
+ <label for="oauth_${name}_clientSecret" class="block text-sm font-medium text-gray-300 mb-2">Client Secret</label>
20751
+ <input type="password" id="oauth_${name}_clientSecret" value="${clientSecret}" placeholder="${label} OAuth Client Secret" class="${inputClass}">
20752
+ </div>
20753
+ </div>
20754
+ </div>
20755
+ `;
20756
+ }
20757
+ return `
20758
+ <div class="space-y-6">
20759
+ <div class="bg-blue-500/10 border border-blue-500/20 rounded-lg p-4">
20760
+ <p class="text-blue-200 text-sm">
20761
+ Configure OAuth provider credentials below. Credentials are stored securely and used server-side only.
20762
+ Make sure to add the callback URL <code class="text-blue-300">/auth/oauth/[provider]/callback</code> to your OAuth app's allowed redirect URIs.
20763
+ </p>
20764
+ </div>
20765
+
20766
+ ${renderProviderCard("github", "GitHub", "\u{1F419}", github)}
20767
+ ${renderProviderCard("google", "Google", "\u{1F535}", google)}
20768
+ </div>
20769
+
20770
+ <script>
20771
+ (function () {
20772
+ const origSave = window.saveSettings;
20773
+ window.saveSettings = async function () {
20774
+ const settings = {
20775
+ providers: {
20776
+ github: {
20777
+ clientId: document.getElementById('oauth_github_clientId').value,
20778
+ clientSecret: document.getElementById('oauth_github_clientSecret').value,
20779
+ enabled: document.getElementById('oauth_github_enabled').checked,
20780
+ },
20781
+ google: {
20782
+ clientId: document.getElementById('oauth_google_clientId').value,
20783
+ clientSecret: document.getElementById('oauth_google_clientSecret').value,
20784
+ enabled: document.getElementById('oauth_google_enabled').checked,
20785
+ },
20786
+ }
20787
+ };
20788
+
20789
+ const saveButton = document.getElementById('save-button');
20790
+ saveButton.disabled = true;
20791
+ saveButton.textContent = 'Saving...';
20792
+
20793
+ try {
20794
+ const response = await fetch('/admin/plugins/oauth-providers/settings', {
20795
+ method: 'POST',
20796
+ headers: { 'Content-Type': 'application/json' },
20797
+ body: JSON.stringify(settings),
20798
+ });
20799
+ const result = await response.json();
20800
+ if (result.success) {
20801
+ showNotification('Settings saved successfully', 'success');
20802
+ setTimeout(() => location.reload(), 1000);
20803
+ } else {
20804
+ throw new Error(result.error || 'Failed to save settings');
20805
+ }
20806
+ } catch (error) {
20807
+ showNotification(error.message, 'error');
20808
+ } finally {
20809
+ saveButton.disabled = false;
20810
+ saveButton.textContent = 'Save Settings';
20811
+ }
20812
+ };
20813
+ })();
20814
+ </script>
20815
+ `;
20816
+ }
20715
20817
 
20716
20818
  // src/routes/admin-plugins.ts
20717
20819
  var adminPluginRoutes = new Hono();
@@ -21052,7 +21154,9 @@ adminPluginRoutes.post("/:id/settings", async (c) => {
21052
21154
  }
21053
21155
  const settings = await c.req.json();
21054
21156
  const pluginService = new PluginService(db);
21055
- await pluginService.updatePluginSettings(pluginId, settings);
21157
+ const existingPlugin = await pluginService.getPlugin(pluginId);
21158
+ const existingSettings = existingPlugin?.settings ?? {};
21159
+ await pluginService.updatePluginSettings(pluginId, { ...existingSettings, ...settings });
21056
21160
  if (pluginId === "core-auth") {
21057
21161
  try {
21058
21162
  const cacheKv = c.env.CACHE_KV;
@@ -26905,5 +27009,5 @@ var ROUTES_INFO = {
26905
27009
  };
26906
27010
 
26907
27011
  export { DocumentRepository, ROUTES_INFO, TenantService, VALID_MEMBER_ROLES, adminCheckboxRoutes, adminCollectionsRoutes, adminDocumentsRoutes, adminLogsRoutes, adminMediaRoutes, adminPluginRoutes, adminSettingsRoutes, admin_api_default, admin_content_default, apiDocumentsRoutes, api_content_crud_default, api_default, api_media_default, api_system_default, auth_default, createDocumentSchema, createUserProfilesPlugin, defineUserProfile, denyIfNotAllowed, dispatchHookEvent, getConfirmationDialogScript2 as getConfirmationDialogScript, getCustomData, getEmailService, getUserProfileConfig, getVariablesCached, hasEmailService, invalidateVariablesCache, isValidMemberRole, lexicalEditorPlugin, renderConfirmationDialog2 as renderConfirmationDialog, renderTable2 as renderTable, resolveDocScope, resolveVariablesInObject, router, router2, setEmailService, setVariablesCache, test_cleanup_default, userProfilesPlugin, userRoutes };
26908
- //# sourceMappingURL=chunk-5UCMLBRQ.js.map
26909
- //# sourceMappingURL=chunk-5UCMLBRQ.js.map
27012
+ //# sourceMappingURL=chunk-6KNTZ67K.js.map
27013
+ //# sourceMappingURL=chunk-6KNTZ67K.js.map