@sonicjs-cms/core 2.19.0 → 3.0.0-beta.11

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 (230) hide show
  1. package/README.md +52 -52
  2. package/dist/admin-documents-form.template-DDSH6ROU.js +6 -0
  3. package/dist/{admin-layout-catalyst.template-UMTIN66R.js.map → admin-documents-form.template-DDSH6ROU.js.map} +1 -1
  4. package/dist/admin-documents-form.template-LSZKGA5J.cjs +19 -0
  5. package/dist/{admin-layout-catalyst.template-HFD37TY5.cjs.map → admin-documents-form.template-LSZKGA5J.cjs.map} +1 -1
  6. package/dist/{filter-bar.template-DlVYMk-T.d.cts → admin-layout-catalyst.template-DrwDUfsE.d.cts} +25 -1
  7. package/dist/{filter-bar.template-DlVYMk-T.d.ts → admin-layout-catalyst.template-DrwDUfsE.d.ts} +25 -1
  8. package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs +21 -0
  9. package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs.map +1 -0
  10. package/dist/admin-layout-catalyst.template-YQ4EMF2J.js +7 -0
  11. package/dist/admin-layout-catalyst.template-YQ4EMF2J.js.map +1 -0
  12. package/dist/app-Bo0X1OWX.d.ts +1268 -0
  13. package/dist/app-Do66yCcV.d.cts +1268 -0
  14. package/dist/cache-DDARE4QE.js +4 -0
  15. package/dist/cache-DDARE4QE.js.map +1 -0
  16. package/dist/cache-LVYS4BPL.cjs +33 -0
  17. package/dist/cache-LVYS4BPL.cjs.map +1 -0
  18. package/dist/chunk-2CB4KY7I.cjs +771 -0
  19. package/dist/chunk-2CB4KY7I.cjs.map +1 -0
  20. package/dist/{chunk-4NPCDK6B.js → chunk-3PU4WVU6.js} +557 -90
  21. package/dist/chunk-3PU4WVU6.js.map +1 -0
  22. package/dist/chunk-4BTBSXMR.cjs +912 -0
  23. package/dist/chunk-4BTBSXMR.cjs.map +1 -0
  24. package/dist/{chunk-55RDMDOP.js → chunk-5V62WT6M.js} +181 -57
  25. package/dist/chunk-5V62WT6M.js.map +1 -0
  26. package/dist/chunk-6H66MSSL.js +273 -0
  27. package/dist/chunk-6H66MSSL.js.map +1 -0
  28. package/dist/chunk-AI663NBO.js +821 -0
  29. package/dist/chunk-AI663NBO.js.map +1 -0
  30. package/dist/chunk-BLMTL57B.js +767 -0
  31. package/dist/chunk-BLMTL57B.js.map +1 -0
  32. package/dist/{chunk-4ZSNJDLS.cjs → chunk-CRGUD4KC.cjs} +9 -9
  33. package/dist/chunk-CRGUD4KC.cjs.map +1 -0
  34. package/dist/chunk-GCDZZNIN.js +192 -0
  35. package/dist/chunk-GCDZZNIN.js.map +1 -0
  36. package/dist/chunk-HIKBY7MS.cjs +70 -0
  37. package/dist/chunk-HIKBY7MS.cjs.map +1 -0
  38. package/dist/chunk-HPAJKZAQ.js +387 -0
  39. package/dist/chunk-HPAJKZAQ.js.map +1 -0
  40. package/dist/chunk-IESEVHXL.js +66 -0
  41. package/dist/chunk-IESEVHXL.js.map +1 -0
  42. package/dist/chunk-IVPRUGTY.js +242 -0
  43. package/dist/chunk-IVPRUGTY.js.map +1 -0
  44. package/dist/{chunk-JZVHLLSI.cjs → chunk-IXUHXTHW.cjs} +2 -151
  45. package/dist/chunk-IXUHXTHW.cjs.map +1 -0
  46. package/dist/chunk-J6JTWD2A.cjs +100 -0
  47. package/dist/chunk-J6JTWD2A.cjs.map +1 -0
  48. package/dist/chunk-JEQ7FLOD.cjs +199 -0
  49. package/dist/chunk-JEQ7FLOD.cjs.map +1 -0
  50. package/dist/{chunk-ON5ZMSU4.js → chunk-JQISFW6U.js} +3 -3
  51. package/dist/chunk-JQISFW6U.js.map +1 -0
  52. package/dist/chunk-K25XHMM3.js +566 -0
  53. package/dist/chunk-K25XHMM3.js.map +1 -0
  54. package/dist/{chunk-R4FOLLFB.cjs → chunk-K342JMA3.cjs} +8730 -11520
  55. package/dist/chunk-K342JMA3.cjs.map +1 -0
  56. package/dist/{chunk-UYJ6TJHX.cjs → chunk-K623Q6WD.cjs} +181 -56
  57. package/dist/chunk-K623Q6WD.cjs.map +1 -0
  58. package/dist/chunk-KV3CM5RK.cjs +158 -0
  59. package/dist/chunk-KV3CM5RK.cjs.map +1 -0
  60. package/dist/{chunk-ABB34XUS.cjs → chunk-MKKGA3C4.cjs} +667 -19
  61. package/dist/chunk-MKKGA3C4.cjs.map +1 -0
  62. package/dist/chunk-N32OWET6.cjs +327 -0
  63. package/dist/chunk-N32OWET6.cjs.map +1 -0
  64. package/dist/chunk-NUKJ54GA.cjs +245 -0
  65. package/dist/chunk-NUKJ54GA.cjs.map +1 -0
  66. package/dist/{chunk-XWIA3HVX.js → chunk-OBA2RYZN.js} +6 -1249
  67. package/dist/chunk-OBA2RYZN.js.map +1 -0
  68. package/dist/chunk-ORF4CT74.cjs +276 -0
  69. package/dist/chunk-ORF4CT74.cjs.map +1 -0
  70. package/dist/{chunk-TFNTM3OA.js → chunk-PDYRDYXI.js} +645 -15
  71. package/dist/chunk-PDYRDYXI.js.map +1 -0
  72. package/dist/{chunk-OHYBNCVL.cjs → chunk-PXNTCCPE.cjs} +10 -1256
  73. package/dist/chunk-PXNTCCPE.cjs.map +1 -0
  74. package/dist/{chunk-E4YFJBM2.cjs → chunk-QJNKSFDJ.cjs} +876 -829
  75. package/dist/chunk-QJNKSFDJ.cjs.map +1 -0
  76. package/dist/chunk-QLFTG3QJ.js +1828 -0
  77. package/dist/chunk-QLFTG3QJ.js.map +1 -0
  78. package/dist/{chunk-BU7SFHGP.js → chunk-QZGABF2M.js} +3 -149
  79. package/dist/chunk-QZGABF2M.js.map +1 -0
  80. package/dist/chunk-RMRJGMDE.js +323 -0
  81. package/dist/chunk-RMRJGMDE.js.map +1 -0
  82. package/dist/chunk-RNZFGN4R.js +88 -0
  83. package/dist/chunk-RNZFGN4R.js.map +1 -0
  84. package/dist/chunk-RQ6N3FTV.js +900 -0
  85. package/dist/chunk-RQ6N3FTV.js.map +1 -0
  86. package/dist/{chunk-OCL3HMEG.js → chunk-SXLVXD2X.js} +7004 -9807
  87. package/dist/chunk-SXLVXD2X.js.map +1 -0
  88. package/dist/chunk-UHRHZXVR.cjs +408 -0
  89. package/dist/chunk-UHRHZXVR.cjs.map +1 -0
  90. package/dist/chunk-YA3TJ65D.cjs +575 -0
  91. package/dist/chunk-YA3TJ65D.cjs.map +1 -0
  92. package/dist/{chunk-7A4CB7T3.cjs → chunk-YJEBDJDV.cjs} +561 -91
  93. package/dist/chunk-YJEBDJDV.cjs.map +1 -0
  94. package/dist/chunk-YP7GW2G5.cjs +866 -0
  95. package/dist/chunk-YP7GW2G5.cjs.map +1 -0
  96. package/dist/chunk-ZUEIQFE5.js +154 -0
  97. package/dist/chunk-ZUEIQFE5.js.map +1 -0
  98. package/dist/{collection-config-B4PG-AaF.d.cts → collection-config-JgHOpFCG.d.cts} +30 -2
  99. package/dist/{collection-config-B4PG-AaF.d.ts → collection-config-JgHOpFCG.d.ts} +30 -2
  100. package/dist/config-HFXANXCC.js +6 -0
  101. package/dist/config-HFXANXCC.js.map +1 -0
  102. package/dist/config-ON6FNMYX.cjs +19 -0
  103. package/dist/config-ON6FNMYX.cjs.map +1 -0
  104. package/dist/define-plugin-BzNHc1ZI.d.ts +1321 -0
  105. package/dist/define-plugin-IWDKYaVm.d.cts +1321 -0
  106. package/dist/document-projection-TDWRJX3Z.cjs +13 -0
  107. package/dist/document-projection-TDWRJX3Z.cjs.map +1 -0
  108. package/dist/document-projection-YYMC6I4U.js +4 -0
  109. package/dist/document-projection-YYMC6I4U.js.map +1 -0
  110. package/dist/index.cjs +13739 -4328
  111. package/dist/index.cjs.map +1 -1
  112. package/dist/index.d.cts +331 -493
  113. package/dist/index.d.ts +331 -493
  114. package/dist/index.js +13456 -4067
  115. package/dist/index.js.map +1 -1
  116. package/dist/middleware.cjs +38 -32
  117. package/dist/middleware.d.cts +50 -7
  118. package/dist/middleware.d.ts +50 -7
  119. package/dist/middleware.js +9 -3
  120. package/dist/migrations-XQLBY7E5.js +4 -0
  121. package/dist/{migrations-H5IXZNCO.js.map → migrations-XQLBY7E5.js.map} +1 -1
  122. package/dist/migrations-ZXJEUTFA.cjs +13 -0
  123. package/dist/{migrations-566IIPS2.cjs.map → migrations-ZXJEUTFA.cjs.map} +1 -1
  124. package/dist/{plugin-bootstrap-DfVerYV4.d.cts → plugin-bootstrap-B8ThJU21.d.cts} +4315 -1661
  125. package/dist/{plugin-bootstrap-P_ciLp_C.d.ts → plugin-bootstrap-qu8hJgUt.d.ts} +4315 -1661
  126. package/dist/plugins.cjs +171 -12
  127. package/dist/plugins.d.cts +36 -2
  128. package/dist/plugins.d.ts +36 -2
  129. package/dist/plugins.js +5 -2
  130. package/dist/rbac-O73MFKDA.js +5 -0
  131. package/dist/rbac-O73MFKDA.js.map +1 -0
  132. package/dist/rbac-VONLJJKB.cjs +14 -0
  133. package/dist/rbac-VONLJJKB.cjs.map +1 -0
  134. package/dist/routes.cjs +42 -46
  135. package/dist/routes.d.cts +56 -146
  136. package/dist/routes.d.ts +56 -146
  137. package/dist/routes.js +18 -10
  138. package/dist/services.cjs +43 -76
  139. package/dist/services.d.cts +93 -55
  140. package/dist/services.d.ts +93 -55
  141. package/dist/services.js +6 -3
  142. package/dist/{telemetry-B9vIV4wh.d.cts → telemetry-Cku1ax74.d.cts} +1 -1
  143. package/dist/{telemetry-B9vIV4wh.d.ts → telemetry-Cku1ax74.d.ts} +1 -1
  144. package/dist/templates.cjs +17 -29
  145. package/dist/templates.d.cts +2 -89
  146. package/dist/templates.d.ts +2 -89
  147. package/dist/templates.js +3 -3
  148. package/dist/types-Dea1eNxU.d.cts +286 -0
  149. package/dist/types-Dea1eNxU.d.ts +286 -0
  150. package/dist/types.d.cts +2 -2
  151. package/dist/types.d.ts +2 -2
  152. package/dist/utils.cjs +21 -20
  153. package/dist/utils.d.cts +2 -2
  154. package/dist/utils.d.ts +2 -2
  155. package/dist/utils.js +3 -2
  156. package/migrations/0001_core.sql +184 -0
  157. package/migrations/0002_documents.sql +163 -0
  158. package/package.json +12 -7
  159. package/dist/admin-layout-catalyst.template-HFD37TY5.cjs +0 -17
  160. package/dist/admin-layout-catalyst.template-UMTIN66R.js +0 -7
  161. package/dist/app-C9esKLmh.d.cts +0 -112
  162. package/dist/app-C9esKLmh.d.ts +0 -112
  163. package/dist/chunk-4NPCDK6B.js.map +0 -1
  164. package/dist/chunk-4ZSNJDLS.cjs.map +0 -1
  165. package/dist/chunk-55RDMDOP.js.map +0 -1
  166. package/dist/chunk-635JAMSE.cjs +0 -653
  167. package/dist/chunk-635JAMSE.cjs.map +0 -1
  168. package/dist/chunk-7A4CB7T3.cjs.map +0 -1
  169. package/dist/chunk-ABB34XUS.cjs.map +0 -1
  170. package/dist/chunk-BU7SFHGP.js.map +0 -1
  171. package/dist/chunk-E4YFJBM2.cjs.map +0 -1
  172. package/dist/chunk-EXNEW5US.js +0 -648
  173. package/dist/chunk-EXNEW5US.js.map +0 -1
  174. package/dist/chunk-JZV22DEV.js +0 -1783
  175. package/dist/chunk-JZV22DEV.js.map +0 -1
  176. package/dist/chunk-JZVHLLSI.cjs.map +0 -1
  177. package/dist/chunk-OCL3HMEG.js.map +0 -1
  178. package/dist/chunk-OHYBNCVL.cjs.map +0 -1
  179. package/dist/chunk-ON5ZMSU4.js.map +0 -1
  180. package/dist/chunk-QFWHAFEO.js +0 -1843
  181. package/dist/chunk-QFWHAFEO.js.map +0 -1
  182. package/dist/chunk-R4FOLLFB.cjs.map +0 -1
  183. package/dist/chunk-RLMUFFUD.cjs +0 -2219
  184. package/dist/chunk-RLMUFFUD.cjs.map +0 -1
  185. package/dist/chunk-TFNTM3OA.js.map +0 -1
  186. package/dist/chunk-UYJ6TJHX.cjs.map +0 -1
  187. package/dist/chunk-WAEQXGCX.cjs +0 -1898
  188. package/dist/chunk-WAEQXGCX.cjs.map +0 -1
  189. package/dist/chunk-XWIA3HVX.js.map +0 -1
  190. package/dist/chunk-ZYAYUIZE.js +0 -2217
  191. package/dist/chunk-ZYAYUIZE.js.map +0 -1
  192. package/dist/migrations-566IIPS2.cjs +0 -13
  193. package/dist/migrations-H5IXZNCO.js +0 -4
  194. package/dist/plugin-manager-BoM3Q7o7.d.cts +0 -328
  195. package/dist/plugin-manager-Efx9RyDX.d.ts +0 -328
  196. package/migrations/001_initial_schema.sql +0 -170
  197. package/migrations/002_faq_plugin.sql +0 -86
  198. package/migrations/003_stage5_enhancements.sql +0 -121
  199. package/migrations/004_stage6_user_management.sql +0 -183
  200. package/migrations/005_stage7_workflow_automation.sql +0 -294
  201. package/migrations/006_plugin_system.sql +0 -155
  202. package/migrations/007_demo_login_plugin.sql +0 -23
  203. package/migrations/008_fix_slug_validation.sql +0 -22
  204. package/migrations/009_system_logging.sql +0 -57
  205. package/migrations/011_config_managed_collections.sql +0 -15
  206. package/migrations/012_testimonials_plugin.sql +0 -80
  207. package/migrations/013_code_examples_plugin.sql +0 -177
  208. package/migrations/014_fix_plugin_registry.sql +0 -88
  209. package/migrations/015_add_remaining_plugins.sql +0 -89
  210. package/migrations/016_remove_duplicate_cache_plugin.sql +0 -17
  211. package/migrations/017_auth_configurable_fields.sql +0 -49
  212. package/migrations/018_settings_table.sql +0 -23
  213. package/migrations/019_remove_blog_posts_collection.sql +0 -15
  214. package/migrations/020_add_email_plugin.sql +0 -22
  215. package/migrations/021_add_magic_link_auth_plugin.sql +0 -42
  216. package/migrations/022_add_tinymce_plugin.sql +0 -25
  217. package/migrations/023_add_easy_mdx_plugin.sql +0 -25
  218. package/migrations/024_add_quill_editor_plugin.sql +0 -25
  219. package/migrations/025_add_easymde_plugin.sql +0 -25
  220. package/migrations/026_add_otp_login.sql +0 -42
  221. package/migrations/027_fix_slug_field_type.sql +0 -18
  222. package/migrations/028_fix_slug_field_type_in_schemas.sql +0 -30
  223. package/migrations/029_add_forms_system.sql +0 -184
  224. package/migrations/030_add_turnstile_to_forms.sql +0 -14
  225. package/migrations/031_ai_search_plugin.sql +0 -45
  226. package/migrations/032_user_profiles.sql +0 -37
  227. package/migrations/033_form_content_integration.sql +0 -19
  228. package/migrations/034_security_audit_plugin.sql +0 -27
  229. package/migrations/035_user_profiles_data_column.sql +0 -16
  230. package/migrations/036_analytics_events.sql +0 -22
@@ -1,4 +1,6 @@
1
- import { PluginBuilder, manifest_default, TurnstileService } from './chunk-EXNEW5US.js';
1
+ import { definePlugin, HOOK_CAPABILITY_MAP, SonicCapabilityError, setPluginDefinitions } from './chunk-HPAJKZAQ.js';
2
+ import { isKnownHookEvent } from './chunk-RNZFGN4R.js';
3
+ import { getCoreVersion } from './chunk-ZUEIQFE5.js';
2
4
  import { HOOKS } from './chunk-QXOZI5Q2.js';
3
5
  import { __commonJS, __toESM } from './chunk-V4OQ3NZ2.js';
4
6
  import { z } from 'zod';
@@ -2240,7 +2242,7 @@ var PluginValidator = class _PluginValidator {
2240
2242
  "auth",
2241
2243
  "content",
2242
2244
  "media",
2243
- "users",
2245
+ "auth_user",
2244
2246
  "collections"
2245
2247
  ];
2246
2248
  static RESERVED_PATHS = [
@@ -2292,7 +2294,7 @@ var PluginValidator = class _PluginValidator {
2292
2294
  if (!/^[a-z][a-z0-9_]*$/.test(model.tableName)) {
2293
2295
  errors.push(`Invalid table name format: ${model.tableName}`);
2294
2296
  }
2295
- const systemTables = ["users", "collections", "content", "content_versions", "media", "api_tokens"];
2297
+ const systemTables = ["auth_user", "collections", "content", "content_versions", "media", "auth_api_tokens"];
2296
2298
  if (systemTables.includes(model.tableName)) {
2297
2299
  errors.push(`Table name "${model.tableName}" conflicts with system table`);
2298
2300
  }
@@ -3082,6 +3084,638 @@ var PluginManager = class {
3082
3084
  }
3083
3085
  };
3084
3086
 
3087
+ // src/plugins/topo-sort.ts
3088
+ var PluginDependencyCycleError = class extends Error {
3089
+ cycle;
3090
+ constructor(pluginId2, visitStack) {
3091
+ const idx = visitStack.indexOf(pluginId2);
3092
+ const cycle = idx >= 0 ? [...visitStack.slice(idx), pluginId2] : [...visitStack, pluginId2];
3093
+ super(`Plugin dependency cycle detected: ${cycle.join(" \u2192 ")}`);
3094
+ this.name = "PluginDependencyCycleError";
3095
+ this.cycle = cycle;
3096
+ }
3097
+ };
3098
+ function topoSort(plugins, options = {}) {
3099
+ const byId = /* @__PURE__ */ new Map();
3100
+ for (const p of plugins) {
3101
+ const id = pluginId(p);
3102
+ if (id) byId.set(id, p);
3103
+ }
3104
+ const result = [];
3105
+ const visited = /* @__PURE__ */ new Set();
3106
+ const visiting = /* @__PURE__ */ new Set();
3107
+ function visit(p) {
3108
+ const id = pluginId(p) ?? Math.random().toString();
3109
+ if (visited.has(id)) return;
3110
+ if (visiting.has(id)) throw new PluginDependencyCycleError(id, [...visiting]);
3111
+ visiting.add(id);
3112
+ for (const dep of p.dependencies ?? []) {
3113
+ const depPlugin = byId.get(dep);
3114
+ if (!depPlugin) {
3115
+ if (options.strict) {
3116
+ throw new Error(
3117
+ `Plugin "${id}" depends on "${dep}" which is not in the plugin list.`
3118
+ );
3119
+ } else {
3120
+ console.warn(
3121
+ `[plugins] Plugin "${id}" declares dependency "${dep}" which is not registered. The dependency will be skipped \u2014 boot order may be incorrect.`
3122
+ );
3123
+ }
3124
+ continue;
3125
+ }
3126
+ visit(depPlugin);
3127
+ }
3128
+ visiting.delete(id);
3129
+ visited.add(id);
3130
+ result.push(p);
3131
+ }
3132
+ for (const p of plugins) visit(p);
3133
+ return result;
3134
+ }
3135
+ function pluginId(p) {
3136
+ return p.id ?? p.name ?? void 0;
3137
+ }
3138
+
3139
+ // src/plugins/mount.ts
3140
+ var PluginRegisterMustBeSyncError = class extends Error {
3141
+ constructor(pluginName) {
3142
+ super(
3143
+ `Plugin "${pluginName}" register() returned a Promise. register() must be synchronous because Hono's router locks after the first request. Move async work (hook subscriptions, services, crons) to onBoot()/lifecycle hooks.`
3144
+ );
3145
+ this.name = "PluginRegisterMustBeSyncError";
3146
+ }
3147
+ };
3148
+ function sortRoutesByPriority(routes) {
3149
+ return routes.map((route, index) => ({ route, index })).sort((a, b) => {
3150
+ const pa = a.route.priority ?? 0;
3151
+ const pb = b.route.priority ?? 0;
3152
+ if (pb !== pa) return pb - pa;
3153
+ return a.index - b.index;
3154
+ }).map((entry) => entry.route);
3155
+ }
3156
+ function mountPlugin(app, plugin, result) {
3157
+ if (!plugin || typeof plugin !== "object" || !plugin.name) {
3158
+ result?.skipped.push({ plugin: String(plugin?.name ?? "unknown"), reason: "not a valid plugin object" });
3159
+ return;
3160
+ }
3161
+ if (Array.isArray(plugin.routes) && plugin.routes.length > 0) {
3162
+ for (const route of sortRoutesByPriority(plugin.routes)) {
3163
+ if (!route || !route.path || !route.handler) {
3164
+ result?.skipped.push({ plugin: plugin.name, reason: `invalid route entry (missing path or handler)` });
3165
+ continue;
3166
+ }
3167
+ app.route(route.path, route.handler);
3168
+ result?.mounted.push({ plugin: plugin.name, path: route.path });
3169
+ }
3170
+ }
3171
+ if (typeof plugin.register === "function") {
3172
+ const maybePromise = plugin.register(app);
3173
+ if (maybePromise && typeof maybePromise.then === "function") {
3174
+ throw new PluginRegisterMustBeSyncError(plugin.name);
3175
+ }
3176
+ }
3177
+ }
3178
+ function registerPluginRoutes(app, plugins, options = {}) {
3179
+ const result = { mounted: [], skipped: [] };
3180
+ const warnOnDuplicatePath = options.warnOnDuplicatePath ?? (typeof process === "undefined" || process.env?.NODE_ENV !== "production");
3181
+ const seenPaths = /* @__PURE__ */ new Map();
3182
+ const sortByDependencies = options.sortByDependencies ?? true;
3183
+ const sorted = sortByDependencies ? topoSort(plugins.filter((p) => !!p && typeof p === "object"), {
3184
+ strict: options.strict
3185
+ }) : plugins.filter((p) => !!p && typeof p === "object");
3186
+ for (const plugin of sorted) {
3187
+ if (!plugin) continue;
3188
+ const before = result.mounted.length;
3189
+ mountPlugin(app, plugin, result);
3190
+ if (warnOnDuplicatePath) {
3191
+ for (let i = before; i < result.mounted.length; i++) {
3192
+ const entry = result.mounted[i];
3193
+ if (!entry) continue;
3194
+ const { plugin: owner, path } = entry;
3195
+ const prior = seenPaths.get(path);
3196
+ if (prior && prior !== owner) {
3197
+ console.warn(
3198
+ `[plugins] Duplicate route path "${path}" mounted by "${owner}" \u2014 already claimed by "${prior}". The first registration wins; the later one is shadowed.`
3199
+ );
3200
+ } else if (!prior) {
3201
+ seenPaths.set(path, owner);
3202
+ }
3203
+ }
3204
+ }
3205
+ }
3206
+ return result;
3207
+ }
3208
+
3209
+ // src/plugins/wire.ts
3210
+ async function wireRegisteredPlugins(plugins, context, options = {}) {
3211
+ const result = { subscribed: 0, booted: [], errors: [] };
3212
+ const sortByDeps = options.sortByDependencies ?? true;
3213
+ const raw = plugins.filter((p) => !!p && typeof p === "object");
3214
+ const valid = sortByDeps ? topoSort(raw, { strict: options.strict }) : raw;
3215
+ for (const plugin of valid) {
3216
+ const name = plugin.name ?? "unknown";
3217
+ if (!Array.isArray(plugin.hooks) || plugin.hooks.length === 0) continue;
3218
+ for (const hook of plugin.hooks) {
3219
+ if (!hook || typeof hook.name !== "string" || typeof hook.handler !== "function") {
3220
+ result.errors.push({ plugin: name, phase: "subscribe", error: new Error("invalid hook entry") });
3221
+ continue;
3222
+ }
3223
+ if (plugin.capabilities !== void 0 && isKnownHookEvent(hook.name)) {
3224
+ const requiredCap = HOOK_CAPABILITY_MAP[hook.name];
3225
+ if (requiredCap && !plugin.capabilities.includes(requiredCap)) {
3226
+ const capErr = new SonicCapabilityError(requiredCap, name);
3227
+ if (options.strict) {
3228
+ result.errors.push({ plugin: name, phase: "subscribe", error: capErr });
3229
+ } else {
3230
+ console.warn(`[plugins] ${capErr.message} Hook "${hook.name}" will not be registered.`);
3231
+ }
3232
+ continue;
3233
+ }
3234
+ }
3235
+ try {
3236
+ context.hooks.register(hook.name, hook.handler, hook.priority);
3237
+ result.subscribed++;
3238
+ } catch (error) {
3239
+ result.errors.push({ plugin: name, phase: "subscribe", error });
3240
+ }
3241
+ }
3242
+ }
3243
+ for (const plugin of valid) {
3244
+ const name = plugin.name ?? "unknown";
3245
+ if (typeof plugin.onBoot !== "function") continue;
3246
+ try {
3247
+ await plugin.onBoot(context);
3248
+ result.booted.push(name);
3249
+ } catch (error) {
3250
+ result.errors.push({ plugin: name, phase: "onBoot", error });
3251
+ }
3252
+ }
3253
+ if (context.env?.DB) {
3254
+ reflectWiredPlugins(valid, context.env.DB).catch((err) => {
3255
+ console.warn("[plugins] DB reflection failed (non-fatal):", err);
3256
+ });
3257
+ }
3258
+ return result;
3259
+ }
3260
+ async function reflectWiredPlugins(plugins, db) {
3261
+ const now = Date.now();
3262
+ for (const plugin of plugins) {
3263
+ const id = plugin.id ?? plugin.name;
3264
+ if (!id) continue;
3265
+ const displayName = plugin.name ?? id;
3266
+ const version = plugin.version ?? "0.0.0";
3267
+ const description = plugin.description ?? "";
3268
+ const initialStatus = plugin.defaultActive ? "active" : "inactive";
3269
+ try {
3270
+ await db.prepare(
3271
+ `INSERT INTO plugins (id, name, display_name, description, version, author, category,
3272
+ status, is_core, installed_at, last_updated)
3273
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)
3274
+ ON CONFLICT(id) DO UPDATE SET
3275
+ version = excluded.version,
3276
+ display_name = excluded.display_name,
3277
+ last_updated = excluded.last_updated`
3278
+ ).bind(id, id, displayName, description, version, "core", "core", initialStatus, now, now).run();
3279
+ } catch {
3280
+ }
3281
+ }
3282
+ }
3283
+ function createPluginWirer(plugins, ctxFactory) {
3284
+ let started;
3285
+ return () => {
3286
+ if (!started) {
3287
+ const list = typeof plugins === "function" ? plugins() : plugins;
3288
+ started = wireRegisteredPlugins(list, ctxFactory());
3289
+ }
3290
+ return started;
3291
+ };
3292
+ }
3293
+
3294
+ // src/plugins/sdk/register-plugins.ts
3295
+ var import_semver2 = __toESM(require_semver2(), 1);
3296
+
3297
+ // src/services/plugin-menu-singleton.ts
3298
+ var PUZZLE_PIECE = `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M14.5 2A1.5 1.5 0 0013 3.5V4H8.5A1.5 1.5 0 007 5.5V10h-.5a1.5 1.5 0 100 3H7v4.5A1.5 1.5 0 008.5 19H13v-.5a1.5 1.5 0 113 0V19h.5a1.5 1.5 0 001.5-1.5V13h-.5a1.5 1.5 0 110-3h.5V5.5A1.5 1.5 0 0017 4h-.5v-.5A1.5 1.5 0 0014.5 2z"/></svg>`;
3299
+ var MENU_ICON_MAP = {
3300
+ "puzzle-piece": PUZZLE_PIECE,
3301
+ envelope: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z"/><path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"/></svg>`,
3302
+ cog: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" clip-rule="evenodd"/></svg>`,
3303
+ chart: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M2 11a1 1 0 011-1h2a1 1 0 011 1v5a1 1 0 01-1 1H3a1 1 0 01-1-1v-5zM8 7a1 1 0 011-1h2a1 1 0 011 1v9a1 1 0 01-1 1H9a1 1 0 01-1-1V7zM14 4a1 1 0 011-1h2a1 1 0 011 1v12a1 1 0 01-1 1h-2a1 1 0 01-1-1V4z"/></svg>`,
3304
+ sparkles: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9 4.804A7.968 7.968 0 005.5 4c-1.255 0-2.443.29-3.5.804v10A7.969 7.969 0 015.5 14c1.669 0 3.218.51 4.5 1.385A7.962 7.962 0 0114.5 14c1.255 0 2.443.29 3.5.804v-10A7.968 7.968 0 0014.5 4c-1.255 0-2.443.29-3.5.804V12a1 1 0 11-2 0V4.804z"/></svg>`,
3305
+ bolt: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M11.3 1.046A1 1 0 0112 2v5h4a1 1 0 01.82 1.573l-7 10A1 1 0 018 18v-5H4a1 1 0 01-.82-1.573l7-10a1 1 0 011.12-.38z" clip-rule="evenodd"/></svg>`,
3306
+ document: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M4 4a2 2 0 012-2h8a2 2 0 012 2v12a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm3 1h6v2H7V5zm0 4h6v2H7V9zm0 4h4v2H7v-2z" clip-rule="evenodd"/></svg>`,
3307
+ lock: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"/></svg>`,
3308
+ photo: `<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M4 3a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4zm12 12H4l4-8 3 6 2-4 3 6z" clip-rule="evenodd"/></svg>`
3309
+ };
3310
+ function resolveIcon(name) {
3311
+ if (!name) return PUZZLE_PIECE;
3312
+ if (name.startsWith("<svg")) return name;
3313
+ return MENU_ICON_MAP[name] ?? PUZZLE_PIECE;
3314
+ }
3315
+ var menuItems = [];
3316
+ function setPluginMenu(items) {
3317
+ menuItems = [...items];
3318
+ }
3319
+ function getPluginMenu() {
3320
+ return menuItems;
3321
+ }
3322
+ function resetPluginMenu() {
3323
+ menuItems = [];
3324
+ }
3325
+ function resolvePluginMenuItems(user) {
3326
+ const isAdmin = user?.role === "admin";
3327
+ const userPerms = new Set(user?.permissions ?? []);
3328
+ return menuItems.filter((m) => {
3329
+ if (!m.permissions || m.permissions.length === 0) return true;
3330
+ if (isAdmin) return true;
3331
+ return m.permissions.some((p) => userPerms.has(p));
3332
+ }).slice().sort((a, b) => (a.order ?? 100) - (b.order ?? 100)).map((m) => ({
3333
+ label: m.label,
3334
+ path: m.path,
3335
+ icon: resolveIcon(m.icon),
3336
+ order: m.order ?? 100
3337
+ }));
3338
+ }
3339
+
3340
+ // src/plugins/cron.ts
3341
+ function collectCrons(plugins) {
3342
+ const out = [];
3343
+ for (const plugin of plugins) {
3344
+ if (!plugin || !Array.isArray(plugin.crons)) continue;
3345
+ const name = plugin.name ?? "unknown";
3346
+ for (const cron of plugin.crons) {
3347
+ if (cron && typeof cron.schedule === "string" && typeof cron.hookFamily === "string") {
3348
+ out.push({ plugin: name, schedule: cron.schedule, hookFamily: cron.hookFamily });
3349
+ }
3350
+ }
3351
+ }
3352
+ return out;
3353
+ }
3354
+ function collectCronSchedules(plugins) {
3355
+ return [...new Set(collectCrons(plugins).map((c) => c.schedule))];
3356
+ }
3357
+ async function dispatchCronTick(plugins, cron, scheduledTime, context) {
3358
+ const result = { invoked: [], errors: [], unmatched: true };
3359
+ for (const plugin of plugins) {
3360
+ if (!plugin || typeof plugin.onCronTick !== "function" || !Array.isArray(plugin.crons)) continue;
3361
+ const name = plugin.name ?? "unknown";
3362
+ const matches = plugin.crons.filter((c) => c && c.schedule === cron);
3363
+ for (const match of matches) {
3364
+ result.unmatched = false;
3365
+ const event = { cron, scheduledTime, hookFamily: match.hookFamily };
3366
+ try {
3367
+ await plugin.onCronTick(event, context);
3368
+ result.invoked.push({ plugin: name, hookFamily: match.hookFamily });
3369
+ } catch (error) {
3370
+ result.errors.push({ plugin: name, hookFamily: match.hookFamily, error });
3371
+ }
3372
+ }
3373
+ }
3374
+ return result;
3375
+ }
3376
+ function createScheduledHandler(options) {
3377
+ return async (controller, env, ctx) => {
3378
+ if (options.disabled) {
3379
+ return { invoked: [], errors: [], unmatched: true };
3380
+ }
3381
+ if (options.boot) {
3382
+ try {
3383
+ await options.boot(env);
3384
+ } catch (err) {
3385
+ console.error("[cron] boot failed:", err);
3386
+ }
3387
+ }
3388
+ const plugins = typeof options.plugins === "function" ? options.plugins() : options.plugins;
3389
+ const work = dispatchCronTick(plugins, controller.cron, controller.scheduledTime, {
3390
+ hooks: options.getHooks(),
3391
+ env
3392
+ });
3393
+ ctx?.waitUntil?.(work.catch(() => {
3394
+ }));
3395
+ return work;
3396
+ };
3397
+ }
3398
+
3399
+ // src/plugins/sdk/register-plugins.ts
3400
+ var RegisterPluginsError = class extends Error {
3401
+ constructor(reason, details) {
3402
+ super(`registerPlugins(${reason}): ${JSON.stringify(details)}`);
3403
+ this.reason = reason;
3404
+ this.details = details;
3405
+ this.name = "RegisterPluginsError";
3406
+ }
3407
+ };
3408
+ function registerPlugins(app, plugins, host) {
3409
+ const list = plugins.filter((p) => !!p && typeof p === "object");
3410
+ const seen = /* @__PURE__ */ new Set();
3411
+ for (const p of list) {
3412
+ if (!p.id || typeof p.id !== "string")
3413
+ throw new RegisterPluginsError("invalid_id", { plugin: p });
3414
+ if (!import_semver2.default.valid(p.version))
3415
+ throw new RegisterPluginsError("invalid_semver", { id: p.id, version: p.version });
3416
+ if (seen.has(p.id))
3417
+ throw new RegisterPluginsError("duplicate_id", { id: p.id });
3418
+ seen.add(p.id);
3419
+ if (p.sonicjsVersionRange) {
3420
+ try {
3421
+ if (!import_semver2.default.satisfies(getCoreVersion(), p.sonicjsVersionRange)) {
3422
+ console.warn(
3423
+ `[plugins] ${p.id} declares sonicjsVersionRange "${p.sonicjsVersionRange}" but core is "${getCoreVersion()}". Plugin may not work correctly.`
3424
+ );
3425
+ }
3426
+ } catch {
3427
+ }
3428
+ }
3429
+ }
3430
+ let mountResult;
3431
+ try {
3432
+ mountResult = registerPluginRoutes(app, list, {
3433
+ source: host.source,
3434
+ strict: host.strict,
3435
+ ...host.mountOptions
3436
+ });
3437
+ } catch (err) {
3438
+ const pluginId2 = err && typeof err === "object" && "message" in err ? String(err.message).match(/Plugin "([^"]+)"/)?.[1] ?? "unknown" : "unknown";
3439
+ throw new RegisterPluginsError("register_returned_promise", { id: pluginId2, error: String(err) });
3440
+ }
3441
+ const menu = list.flatMap((p) => p.menu ?? []);
3442
+ setPluginMenu(menu);
3443
+ setPluginDefinitions(list);
3444
+ const crons = list.flatMap((p) => p.crons ?? []);
3445
+ const cronSchedules = collectCronSchedules(list);
3446
+ const byId = /* @__PURE__ */ new Map();
3447
+ for (const p of list) {
3448
+ byId.set(p.id, {
3449
+ id: p.id,
3450
+ displayName: p.displayName ?? p.name ?? p.id,
3451
+ version: p.version,
3452
+ capabilities: p.capabilities ?? []
3453
+ });
3454
+ }
3455
+ let wirePromise;
3456
+ const boot = (envOverride) => {
3457
+ if (!wirePromise) {
3458
+ const env = envOverride ?? host.env ?? {};
3459
+ wirePromise = wireRegisteredPlugins(list, { hooks: host.hookSystem, env }, { strict: host.strict });
3460
+ }
3461
+ return wirePromise;
3462
+ };
3463
+ return {
3464
+ byId,
3465
+ order: list.map((p) => p.id),
3466
+ menu,
3467
+ crons,
3468
+ cronSchedules,
3469
+ mountResult,
3470
+ boot
3471
+ };
3472
+ }
3473
+
3474
+ // src/plugins/core-plugins/turnstile-plugin/manifest.json
3475
+ var manifest_default = {
3476
+ id: "turnstile",
3477
+ name: "Cloudflare Turnstile",
3478
+ description: "CAPTCHA-free bot protection using Cloudflare Turnstile. Provides reusable verification for any form.",
3479
+ version: "1.0.0",
3480
+ author: "SonicJS",
3481
+ category: "security",
3482
+ icon: "shield-check",
3483
+ homepage: "https://developers.cloudflare.com/turnstile/",
3484
+ repository: "https://github.com/sonicjs/sonicjs",
3485
+ license: "MIT",
3486
+ permissions: [
3487
+ "settings:write",
3488
+ "admin:access"
3489
+ ],
3490
+ dependencies: [],
3491
+ configSchema: {
3492
+ siteKey: {
3493
+ type: "string",
3494
+ label: "Site Key",
3495
+ description: "Your Cloudflare Turnstile site key (public)",
3496
+ required: true
3497
+ },
3498
+ secretKey: {
3499
+ type: "string",
3500
+ label: "Secret Key",
3501
+ description: "Your Cloudflare Turnstile secret key (private)",
3502
+ required: true,
3503
+ sensitive: true
3504
+ },
3505
+ theme: {
3506
+ type: "select",
3507
+ label: "Widget Theme",
3508
+ description: "Visual theme for the Turnstile widget",
3509
+ default: "auto",
3510
+ options: [
3511
+ {
3512
+ value: "light",
3513
+ label: "Light"
3514
+ },
3515
+ {
3516
+ value: "dark",
3517
+ label: "Dark"
3518
+ },
3519
+ {
3520
+ value: "auto",
3521
+ label: "Auto"
3522
+ }
3523
+ ]
3524
+ },
3525
+ size: {
3526
+ type: "select",
3527
+ label: "Widget Size",
3528
+ description: "Size of the Turnstile widget",
3529
+ default: "normal",
3530
+ options: [
3531
+ {
3532
+ value: "normal",
3533
+ label: "Normal"
3534
+ },
3535
+ {
3536
+ value: "compact",
3537
+ label: "Compact"
3538
+ }
3539
+ ]
3540
+ },
3541
+ mode: {
3542
+ type: "select",
3543
+ label: "Widget Mode",
3544
+ description: "Managed: Adaptive challenge. Non-Interactive: Always visible, minimal friction. Invisible: No visible widget",
3545
+ default: "managed",
3546
+ options: [
3547
+ {
3548
+ value: "managed",
3549
+ label: "Managed (Recommended)"
3550
+ },
3551
+ {
3552
+ value: "non-interactive",
3553
+ label: "Non-Interactive"
3554
+ },
3555
+ {
3556
+ value: "invisible",
3557
+ label: "Invisible"
3558
+ }
3559
+ ]
3560
+ },
3561
+ appearance: {
3562
+ type: "select",
3563
+ label: "Appearance",
3564
+ description: "When the Turnstile challenge is executed. Always: Verifies immediately. Execute: Challenge on form submit. Interaction Only: Only after user interaction",
3565
+ default: "always",
3566
+ options: [
3567
+ {
3568
+ value: "always",
3569
+ label: "Always"
3570
+ },
3571
+ {
3572
+ value: "execute",
3573
+ label: "Execute"
3574
+ },
3575
+ {
3576
+ value: "interaction-only",
3577
+ label: "Interaction Only"
3578
+ }
3579
+ ]
3580
+ },
3581
+ preClearance: {
3582
+ type: "boolean",
3583
+ label: "Enable Pre-clearance",
3584
+ description: "Issue a clearance cookie that bypasses Cloudflare Firewall Rules (as if the user passed a challenge on your proxied site)",
3585
+ default: false
3586
+ },
3587
+ preClearanceLevel: {
3588
+ type: "select",
3589
+ label: "Pre-clearance Level",
3590
+ description: "Controls which Cloudflare Firewall Rules the clearance cookie bypasses. Only applies if Pre-clearance is enabled",
3591
+ default: "managed",
3592
+ options: [
3593
+ {
3594
+ value: "interactive",
3595
+ label: "Interactive - Bypasses Interactive, Managed & JS Challenge Rules"
3596
+ },
3597
+ {
3598
+ value: "managed",
3599
+ label: "Managed - Bypasses Managed & JS Challenge Rules"
3600
+ },
3601
+ {
3602
+ value: "non-interactive",
3603
+ label: "Non-interactive - Bypasses JS Challenge Rules only"
3604
+ }
3605
+ ]
3606
+ },
3607
+ enabled: {
3608
+ type: "boolean",
3609
+ label: "Enable Turnstile",
3610
+ description: "Enable or disable Turnstile verification globally",
3611
+ default: true
3612
+ }
3613
+ },
3614
+ adminMenu: {
3615
+ label: "Turnstile",
3616
+ icon: "shield-check",
3617
+ href: "/admin/plugins/turnstile/settings",
3618
+ parentId: "plugins",
3619
+ order: 100
3620
+ },
3621
+ codeName: "turnstile-plugin",
3622
+ iconEmoji: "\u{1F6E1}\uFE0F",
3623
+ is_core: true,
3624
+ defaultSettings: {
3625
+ siteKey: "",
3626
+ secretKey: "",
3627
+ theme: "auto",
3628
+ size: "normal",
3629
+ mode: "managed",
3630
+ appearance: "always",
3631
+ preClearanceEnabled: false,
3632
+ preClearanceLevel: "managed",
3633
+ enabled: false
3634
+ }
3635
+ };
3636
+
3637
+ // src/plugins/core-plugins/turnstile-plugin/services/turnstile.ts
3638
+ var TurnstileService = class {
3639
+ db;
3640
+ VERIFY_URL = "https://challenges.cloudflare.com/turnstile/v0/siteverify";
3641
+ constructor(db) {
3642
+ this.db = db;
3643
+ }
3644
+ /**
3645
+ * Get Turnstile settings from database
3646
+ */
3647
+ async getSettings() {
3648
+ try {
3649
+ const plugin = await this.db.prepare(`SELECT settings FROM plugins WHERE id = ? LIMIT 1`).bind(manifest_default.id).first();
3650
+ if (!plugin || !plugin.settings) {
3651
+ return null;
3652
+ }
3653
+ return JSON.parse(plugin.settings);
3654
+ } catch (error) {
3655
+ console.error("Error getting Turnstile settings:", error);
3656
+ return null;
3657
+ }
3658
+ }
3659
+ /**
3660
+ * Verify a Turnstile token with Cloudflare
3661
+ */
3662
+ async verifyToken(token, remoteIp) {
3663
+ try {
3664
+ const settings = await this.getSettings();
3665
+ if (!settings) {
3666
+ return { success: false, error: "Turnstile not configured" };
3667
+ }
3668
+ if (!settings.enabled) {
3669
+ return { success: true };
3670
+ }
3671
+ if (!settings.secretKey) {
3672
+ return { success: false, error: "Turnstile secret key not configured" };
3673
+ }
3674
+ const formData = new FormData();
3675
+ formData.append("secret", settings.secretKey);
3676
+ formData.append("response", token);
3677
+ if (remoteIp) {
3678
+ formData.append("remoteip", remoteIp);
3679
+ }
3680
+ const response = await fetch(this.VERIFY_URL, {
3681
+ method: "POST",
3682
+ body: formData
3683
+ });
3684
+ if (!response.ok) {
3685
+ return { success: false, error: "Turnstile verification request failed" };
3686
+ }
3687
+ const result = await response.json();
3688
+ if (!result.success) {
3689
+ const errorCode = result["error-codes"]?.[0] || "unknown-error";
3690
+ return { success: false, error: `Turnstile verification failed: ${errorCode}` };
3691
+ }
3692
+ return { success: true };
3693
+ } catch (error) {
3694
+ console.error("Error verifying Turnstile token:", error);
3695
+ return { success: false, error: "Turnstile verification error" };
3696
+ }
3697
+ }
3698
+ /**
3699
+ * Save Turnstile settings to database
3700
+ */
3701
+ async saveSettings(settings) {
3702
+ try {
3703
+ await this.db.prepare(`UPDATE plugins SET settings = ?, updated_at = ? WHERE id = ?`).bind(JSON.stringify(settings), Date.now(), manifest_default.id).run();
3704
+ console.log("Turnstile settings saved successfully");
3705
+ } catch (error) {
3706
+ console.error("Error saving Turnstile settings:", error);
3707
+ throw new Error("Failed to save Turnstile settings");
3708
+ }
3709
+ }
3710
+ /**
3711
+ * Check if Turnstile is enabled
3712
+ */
3713
+ async isEnabled() {
3714
+ const settings = await this.getSettings();
3715
+ return settings?.enabled === true && !!settings.siteKey && !!settings.secretKey;
3716
+ }
3717
+ };
3718
+
3085
3719
  // src/plugins/core-plugins/turnstile-plugin/middleware/verify.ts
3086
3720
  async function verifyTurnstile(c, next) {
3087
3721
  const db = c.get("db") || c.env?.DB;
@@ -3157,19 +3791,15 @@ function createTurnstileMiddleware(options) {
3157
3791
  }
3158
3792
 
3159
3793
  // src/plugins/core-plugins/turnstile-plugin/index.ts
3160
- new PluginBuilder({
3161
- name: manifest_default.name,
3794
+ definePlugin({
3795
+ id: manifest_default.id,
3162
3796
  version: manifest_default.version,
3797
+ name: manifest_default.name,
3163
3798
  description: manifest_default.description,
3799
+ sonicjsVersionRange: "^3.0.0",
3164
3800
  author: { name: manifest_default.author }
3165
- }).metadata({
3166
- description: manifest_default.description,
3167
- author: { name: manifest_default.author }
3168
- }).addService("turnstile", TurnstileService).addSingleMiddleware("verifyTurnstile", verifyTurnstile, {
3169
- description: "Verify Cloudflare Turnstile token",
3170
- global: false
3171
- }).build();
3801
+ });
3172
3802
 
3173
- export { HookSystemImpl, HookUtils, PluginManager, PluginRegistryImpl, PluginValidator, ScopedHookSystem, createTurnstileMiddleware, verifyTurnstile };
3174
- //# sourceMappingURL=chunk-TFNTM3OA.js.map
3175
- //# sourceMappingURL=chunk-TFNTM3OA.js.map
3803
+ export { HookSystemImpl, HookUtils, PluginDependencyCycleError, PluginManager, PluginRegisterMustBeSyncError, PluginRegistryImpl, PluginValidator, RegisterPluginsError, ScopedHookSystem, TurnstileService, collectCronSchedules, collectCrons, createPluginWirer, createScheduledHandler, createTurnstileMiddleware, dispatchCronTick, getPluginMenu, mountPlugin, registerPluginRoutes, registerPlugins, resetPluginMenu, resolvePluginMenuItems, setPluginMenu, topoSort, verifyTurnstile, wireRegisteredPlugins };
3804
+ //# sourceMappingURL=chunk-PDYRDYXI.js.map
3805
+ //# sourceMappingURL=chunk-PDYRDYXI.js.map