@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.
- package/README.md +52 -52
- package/dist/admin-documents-form.template-DDSH6ROU.js +6 -0
- package/dist/{admin-layout-catalyst.template-UMTIN66R.js.map → admin-documents-form.template-DDSH6ROU.js.map} +1 -1
- package/dist/admin-documents-form.template-LSZKGA5J.cjs +19 -0
- package/dist/{admin-layout-catalyst.template-HFD37TY5.cjs.map → admin-documents-form.template-LSZKGA5J.cjs.map} +1 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.cts → admin-layout-catalyst.template-DrwDUfsE.d.cts} +25 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.ts → admin-layout-catalyst.template-DrwDUfsE.d.ts} +25 -1
- package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs +21 -0
- package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs.map +1 -0
- package/dist/admin-layout-catalyst.template-YQ4EMF2J.js +7 -0
- package/dist/admin-layout-catalyst.template-YQ4EMF2J.js.map +1 -0
- package/dist/app-Bo0X1OWX.d.ts +1268 -0
- package/dist/app-Do66yCcV.d.cts +1268 -0
- package/dist/cache-DDARE4QE.js +4 -0
- package/dist/cache-DDARE4QE.js.map +1 -0
- package/dist/cache-LVYS4BPL.cjs +33 -0
- package/dist/cache-LVYS4BPL.cjs.map +1 -0
- package/dist/chunk-2CB4KY7I.cjs +771 -0
- package/dist/chunk-2CB4KY7I.cjs.map +1 -0
- package/dist/{chunk-4NPCDK6B.js → chunk-3PU4WVU6.js} +557 -90
- package/dist/chunk-3PU4WVU6.js.map +1 -0
- package/dist/chunk-4BTBSXMR.cjs +912 -0
- package/dist/chunk-4BTBSXMR.cjs.map +1 -0
- package/dist/{chunk-55RDMDOP.js → chunk-5V62WT6M.js} +181 -57
- package/dist/chunk-5V62WT6M.js.map +1 -0
- package/dist/chunk-6H66MSSL.js +273 -0
- package/dist/chunk-6H66MSSL.js.map +1 -0
- package/dist/chunk-AI663NBO.js +821 -0
- package/dist/chunk-AI663NBO.js.map +1 -0
- package/dist/chunk-BLMTL57B.js +767 -0
- package/dist/chunk-BLMTL57B.js.map +1 -0
- package/dist/{chunk-4ZSNJDLS.cjs → chunk-CRGUD4KC.cjs} +9 -9
- package/dist/chunk-CRGUD4KC.cjs.map +1 -0
- package/dist/chunk-GCDZZNIN.js +192 -0
- package/dist/chunk-GCDZZNIN.js.map +1 -0
- package/dist/chunk-HIKBY7MS.cjs +70 -0
- package/dist/chunk-HIKBY7MS.cjs.map +1 -0
- package/dist/chunk-HPAJKZAQ.js +387 -0
- package/dist/chunk-HPAJKZAQ.js.map +1 -0
- package/dist/chunk-IESEVHXL.js +66 -0
- package/dist/chunk-IESEVHXL.js.map +1 -0
- package/dist/chunk-IVPRUGTY.js +242 -0
- package/dist/chunk-IVPRUGTY.js.map +1 -0
- package/dist/{chunk-JZVHLLSI.cjs → chunk-IXUHXTHW.cjs} +2 -151
- package/dist/chunk-IXUHXTHW.cjs.map +1 -0
- package/dist/chunk-J6JTWD2A.cjs +100 -0
- package/dist/chunk-J6JTWD2A.cjs.map +1 -0
- package/dist/chunk-JEQ7FLOD.cjs +199 -0
- package/dist/chunk-JEQ7FLOD.cjs.map +1 -0
- package/dist/{chunk-ON5ZMSU4.js → chunk-JQISFW6U.js} +3 -3
- package/dist/chunk-JQISFW6U.js.map +1 -0
- package/dist/chunk-K25XHMM3.js +566 -0
- package/dist/chunk-K25XHMM3.js.map +1 -0
- package/dist/{chunk-R4FOLLFB.cjs → chunk-K342JMA3.cjs} +8730 -11520
- package/dist/chunk-K342JMA3.cjs.map +1 -0
- package/dist/{chunk-UYJ6TJHX.cjs → chunk-K623Q6WD.cjs} +181 -56
- package/dist/chunk-K623Q6WD.cjs.map +1 -0
- package/dist/chunk-KV3CM5RK.cjs +158 -0
- package/dist/chunk-KV3CM5RK.cjs.map +1 -0
- package/dist/{chunk-ABB34XUS.cjs → chunk-MKKGA3C4.cjs} +667 -19
- package/dist/chunk-MKKGA3C4.cjs.map +1 -0
- package/dist/chunk-N32OWET6.cjs +327 -0
- package/dist/chunk-N32OWET6.cjs.map +1 -0
- package/dist/chunk-NUKJ54GA.cjs +245 -0
- package/dist/chunk-NUKJ54GA.cjs.map +1 -0
- package/dist/{chunk-XWIA3HVX.js → chunk-OBA2RYZN.js} +6 -1249
- package/dist/chunk-OBA2RYZN.js.map +1 -0
- package/dist/chunk-ORF4CT74.cjs +276 -0
- package/dist/chunk-ORF4CT74.cjs.map +1 -0
- package/dist/{chunk-TFNTM3OA.js → chunk-PDYRDYXI.js} +645 -15
- package/dist/chunk-PDYRDYXI.js.map +1 -0
- package/dist/{chunk-OHYBNCVL.cjs → chunk-PXNTCCPE.cjs} +10 -1256
- package/dist/chunk-PXNTCCPE.cjs.map +1 -0
- package/dist/{chunk-E4YFJBM2.cjs → chunk-QJNKSFDJ.cjs} +876 -829
- package/dist/chunk-QJNKSFDJ.cjs.map +1 -0
- package/dist/chunk-QLFTG3QJ.js +1828 -0
- package/dist/chunk-QLFTG3QJ.js.map +1 -0
- package/dist/{chunk-BU7SFHGP.js → chunk-QZGABF2M.js} +3 -149
- package/dist/chunk-QZGABF2M.js.map +1 -0
- package/dist/chunk-RMRJGMDE.js +323 -0
- package/dist/chunk-RMRJGMDE.js.map +1 -0
- package/dist/chunk-RNZFGN4R.js +88 -0
- package/dist/chunk-RNZFGN4R.js.map +1 -0
- package/dist/chunk-RQ6N3FTV.js +900 -0
- package/dist/chunk-RQ6N3FTV.js.map +1 -0
- package/dist/{chunk-OCL3HMEG.js → chunk-SXLVXD2X.js} +7004 -9807
- package/dist/chunk-SXLVXD2X.js.map +1 -0
- package/dist/chunk-UHRHZXVR.cjs +408 -0
- package/dist/chunk-UHRHZXVR.cjs.map +1 -0
- package/dist/chunk-YA3TJ65D.cjs +575 -0
- package/dist/chunk-YA3TJ65D.cjs.map +1 -0
- package/dist/{chunk-7A4CB7T3.cjs → chunk-YJEBDJDV.cjs} +561 -91
- package/dist/chunk-YJEBDJDV.cjs.map +1 -0
- package/dist/chunk-YP7GW2G5.cjs +866 -0
- package/dist/chunk-YP7GW2G5.cjs.map +1 -0
- package/dist/chunk-ZUEIQFE5.js +154 -0
- package/dist/chunk-ZUEIQFE5.js.map +1 -0
- package/dist/{collection-config-B4PG-AaF.d.cts → collection-config-JgHOpFCG.d.cts} +30 -2
- package/dist/{collection-config-B4PG-AaF.d.ts → collection-config-JgHOpFCG.d.ts} +30 -2
- package/dist/config-HFXANXCC.js +6 -0
- package/dist/config-HFXANXCC.js.map +1 -0
- package/dist/config-ON6FNMYX.cjs +19 -0
- package/dist/config-ON6FNMYX.cjs.map +1 -0
- package/dist/define-plugin-BzNHc1ZI.d.ts +1321 -0
- package/dist/define-plugin-IWDKYaVm.d.cts +1321 -0
- package/dist/document-projection-TDWRJX3Z.cjs +13 -0
- package/dist/document-projection-TDWRJX3Z.cjs.map +1 -0
- package/dist/document-projection-YYMC6I4U.js +4 -0
- package/dist/document-projection-YYMC6I4U.js.map +1 -0
- package/dist/index.cjs +13739 -4328
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +331 -493
- package/dist/index.d.ts +331 -493
- package/dist/index.js +13456 -4067
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +38 -32
- package/dist/middleware.d.cts +50 -7
- package/dist/middleware.d.ts +50 -7
- package/dist/middleware.js +9 -3
- package/dist/migrations-XQLBY7E5.js +4 -0
- package/dist/{migrations-H5IXZNCO.js.map → migrations-XQLBY7E5.js.map} +1 -1
- package/dist/migrations-ZXJEUTFA.cjs +13 -0
- package/dist/{migrations-566IIPS2.cjs.map → migrations-ZXJEUTFA.cjs.map} +1 -1
- package/dist/{plugin-bootstrap-DfVerYV4.d.cts → plugin-bootstrap-B8ThJU21.d.cts} +4315 -1661
- package/dist/{plugin-bootstrap-P_ciLp_C.d.ts → plugin-bootstrap-qu8hJgUt.d.ts} +4315 -1661
- package/dist/plugins.cjs +171 -12
- package/dist/plugins.d.cts +36 -2
- package/dist/plugins.d.ts +36 -2
- package/dist/plugins.js +5 -2
- package/dist/rbac-O73MFKDA.js +5 -0
- package/dist/rbac-O73MFKDA.js.map +1 -0
- package/dist/rbac-VONLJJKB.cjs +14 -0
- package/dist/rbac-VONLJJKB.cjs.map +1 -0
- package/dist/routes.cjs +42 -46
- package/dist/routes.d.cts +56 -146
- package/dist/routes.d.ts +56 -146
- package/dist/routes.js +18 -10
- package/dist/services.cjs +43 -76
- package/dist/services.d.cts +93 -55
- package/dist/services.d.ts +93 -55
- package/dist/services.js +6 -3
- package/dist/{telemetry-B9vIV4wh.d.cts → telemetry-Cku1ax74.d.cts} +1 -1
- package/dist/{telemetry-B9vIV4wh.d.ts → telemetry-Cku1ax74.d.ts} +1 -1
- package/dist/templates.cjs +17 -29
- package/dist/templates.d.cts +2 -89
- package/dist/templates.d.ts +2 -89
- package/dist/templates.js +3 -3
- package/dist/types-Dea1eNxU.d.cts +286 -0
- package/dist/types-Dea1eNxU.d.ts +286 -0
- package/dist/types.d.cts +2 -2
- package/dist/types.d.ts +2 -2
- package/dist/utils.cjs +21 -20
- package/dist/utils.d.cts +2 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +3 -2
- package/migrations/0001_core.sql +184 -0
- package/migrations/0002_documents.sql +163 -0
- package/package.json +12 -7
- package/dist/admin-layout-catalyst.template-HFD37TY5.cjs +0 -17
- package/dist/admin-layout-catalyst.template-UMTIN66R.js +0 -7
- package/dist/app-C9esKLmh.d.cts +0 -112
- package/dist/app-C9esKLmh.d.ts +0 -112
- package/dist/chunk-4NPCDK6B.js.map +0 -1
- package/dist/chunk-4ZSNJDLS.cjs.map +0 -1
- package/dist/chunk-55RDMDOP.js.map +0 -1
- package/dist/chunk-635JAMSE.cjs +0 -653
- package/dist/chunk-635JAMSE.cjs.map +0 -1
- package/dist/chunk-7A4CB7T3.cjs.map +0 -1
- package/dist/chunk-ABB34XUS.cjs.map +0 -1
- package/dist/chunk-BU7SFHGP.js.map +0 -1
- package/dist/chunk-E4YFJBM2.cjs.map +0 -1
- package/dist/chunk-EXNEW5US.js +0 -648
- package/dist/chunk-EXNEW5US.js.map +0 -1
- package/dist/chunk-JZV22DEV.js +0 -1783
- package/dist/chunk-JZV22DEV.js.map +0 -1
- package/dist/chunk-JZVHLLSI.cjs.map +0 -1
- package/dist/chunk-OCL3HMEG.js.map +0 -1
- package/dist/chunk-OHYBNCVL.cjs.map +0 -1
- package/dist/chunk-ON5ZMSU4.js.map +0 -1
- package/dist/chunk-QFWHAFEO.js +0 -1843
- package/dist/chunk-QFWHAFEO.js.map +0 -1
- package/dist/chunk-R4FOLLFB.cjs.map +0 -1
- package/dist/chunk-RLMUFFUD.cjs +0 -2219
- package/dist/chunk-RLMUFFUD.cjs.map +0 -1
- package/dist/chunk-TFNTM3OA.js.map +0 -1
- package/dist/chunk-UYJ6TJHX.cjs.map +0 -1
- package/dist/chunk-WAEQXGCX.cjs +0 -1898
- package/dist/chunk-WAEQXGCX.cjs.map +0 -1
- package/dist/chunk-XWIA3HVX.js.map +0 -1
- package/dist/chunk-ZYAYUIZE.js +0 -2217
- package/dist/chunk-ZYAYUIZE.js.map +0 -1
- package/dist/migrations-566IIPS2.cjs +0 -13
- package/dist/migrations-H5IXZNCO.js +0 -4
- package/dist/plugin-manager-BoM3Q7o7.d.cts +0 -328
- package/dist/plugin-manager-Efx9RyDX.d.ts +0 -328
- package/migrations/001_initial_schema.sql +0 -170
- package/migrations/002_faq_plugin.sql +0 -86
- package/migrations/003_stage5_enhancements.sql +0 -121
- package/migrations/004_stage6_user_management.sql +0 -183
- package/migrations/005_stage7_workflow_automation.sql +0 -294
- package/migrations/006_plugin_system.sql +0 -155
- package/migrations/007_demo_login_plugin.sql +0 -23
- package/migrations/008_fix_slug_validation.sql +0 -22
- package/migrations/009_system_logging.sql +0 -57
- package/migrations/011_config_managed_collections.sql +0 -15
- package/migrations/012_testimonials_plugin.sql +0 -80
- package/migrations/013_code_examples_plugin.sql +0 -177
- package/migrations/014_fix_plugin_registry.sql +0 -88
- package/migrations/015_add_remaining_plugins.sql +0 -89
- package/migrations/016_remove_duplicate_cache_plugin.sql +0 -17
- package/migrations/017_auth_configurable_fields.sql +0 -49
- package/migrations/018_settings_table.sql +0 -23
- package/migrations/019_remove_blog_posts_collection.sql +0 -15
- package/migrations/020_add_email_plugin.sql +0 -22
- package/migrations/021_add_magic_link_auth_plugin.sql +0 -42
- package/migrations/022_add_tinymce_plugin.sql +0 -25
- package/migrations/023_add_easy_mdx_plugin.sql +0 -25
- package/migrations/024_add_quill_editor_plugin.sql +0 -25
- package/migrations/025_add_easymde_plugin.sql +0 -25
- package/migrations/026_add_otp_login.sql +0 -42
- package/migrations/027_fix_slug_field_type.sql +0 -18
- package/migrations/028_fix_slug_field_type_in_schemas.sql +0 -30
- package/migrations/029_add_forms_system.sql +0 -184
- package/migrations/030_add_turnstile_to_forms.sql +0 -14
- package/migrations/031_ai_search_plugin.sql +0 -45
- package/migrations/032_user_profiles.sql +0 -37
- package/migrations/033_form_content_integration.sql +0 -19
- package/migrations/034_security_audit_plugin.sql +0 -27
- package/migrations/035_user_profiles_data_column.sql +0 -16
- package/migrations/036_analytics_events.sql +0 -22
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkUHRHZXVR_cjs = require('./chunk-UHRHZXVR.cjs');
|
|
4
|
+
var chunkJ6JTWD2A_cjs = require('./chunk-J6JTWD2A.cjs');
|
|
5
|
+
var chunkKV3CM5RK_cjs = require('./chunk-KV3CM5RK.cjs');
|
|
4
6
|
var chunkQTFKZBLC_cjs = require('./chunk-QTFKZBLC.cjs');
|
|
5
7
|
var chunkIGJUBJBW_cjs = require('./chunk-IGJUBJBW.cjs');
|
|
6
8
|
var zod = require('zod');
|
|
@@ -2242,7 +2244,7 @@ var PluginValidator = class _PluginValidator {
|
|
|
2242
2244
|
"auth",
|
|
2243
2245
|
"content",
|
|
2244
2246
|
"media",
|
|
2245
|
-
"
|
|
2247
|
+
"auth_user",
|
|
2246
2248
|
"collections"
|
|
2247
2249
|
];
|
|
2248
2250
|
static RESERVED_PATHS = [
|
|
@@ -2294,7 +2296,7 @@ var PluginValidator = class _PluginValidator {
|
|
|
2294
2296
|
if (!/^[a-z][a-z0-9_]*$/.test(model.tableName)) {
|
|
2295
2297
|
errors.push(`Invalid table name format: ${model.tableName}`);
|
|
2296
2298
|
}
|
|
2297
|
-
const systemTables = ["
|
|
2299
|
+
const systemTables = ["auth_user", "collections", "content", "content_versions", "media", "auth_api_tokens"];
|
|
2298
2300
|
if (systemTables.includes(model.tableName)) {
|
|
2299
2301
|
errors.push(`Table name "${model.tableName}" conflicts with system table`);
|
|
2300
2302
|
}
|
|
@@ -3084,6 +3086,638 @@ var PluginManager = class {
|
|
|
3084
3086
|
}
|
|
3085
3087
|
};
|
|
3086
3088
|
|
|
3089
|
+
// src/plugins/topo-sort.ts
|
|
3090
|
+
var PluginDependencyCycleError = class extends Error {
|
|
3091
|
+
cycle;
|
|
3092
|
+
constructor(pluginId2, visitStack) {
|
|
3093
|
+
const idx = visitStack.indexOf(pluginId2);
|
|
3094
|
+
const cycle = idx >= 0 ? [...visitStack.slice(idx), pluginId2] : [...visitStack, pluginId2];
|
|
3095
|
+
super(`Plugin dependency cycle detected: ${cycle.join(" \u2192 ")}`);
|
|
3096
|
+
this.name = "PluginDependencyCycleError";
|
|
3097
|
+
this.cycle = cycle;
|
|
3098
|
+
}
|
|
3099
|
+
};
|
|
3100
|
+
function topoSort(plugins, options = {}) {
|
|
3101
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3102
|
+
for (const p of plugins) {
|
|
3103
|
+
const id = pluginId(p);
|
|
3104
|
+
if (id) byId.set(id, p);
|
|
3105
|
+
}
|
|
3106
|
+
const result = [];
|
|
3107
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3108
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
3109
|
+
function visit(p) {
|
|
3110
|
+
const id = pluginId(p) ?? Math.random().toString();
|
|
3111
|
+
if (visited.has(id)) return;
|
|
3112
|
+
if (visiting.has(id)) throw new PluginDependencyCycleError(id, [...visiting]);
|
|
3113
|
+
visiting.add(id);
|
|
3114
|
+
for (const dep of p.dependencies ?? []) {
|
|
3115
|
+
const depPlugin = byId.get(dep);
|
|
3116
|
+
if (!depPlugin) {
|
|
3117
|
+
if (options.strict) {
|
|
3118
|
+
throw new Error(
|
|
3119
|
+
`Plugin "${id}" depends on "${dep}" which is not in the plugin list.`
|
|
3120
|
+
);
|
|
3121
|
+
} else {
|
|
3122
|
+
console.warn(
|
|
3123
|
+
`[plugins] Plugin "${id}" declares dependency "${dep}" which is not registered. The dependency will be skipped \u2014 boot order may be incorrect.`
|
|
3124
|
+
);
|
|
3125
|
+
}
|
|
3126
|
+
continue;
|
|
3127
|
+
}
|
|
3128
|
+
visit(depPlugin);
|
|
3129
|
+
}
|
|
3130
|
+
visiting.delete(id);
|
|
3131
|
+
visited.add(id);
|
|
3132
|
+
result.push(p);
|
|
3133
|
+
}
|
|
3134
|
+
for (const p of plugins) visit(p);
|
|
3135
|
+
return result;
|
|
3136
|
+
}
|
|
3137
|
+
function pluginId(p) {
|
|
3138
|
+
return p.id ?? p.name ?? void 0;
|
|
3139
|
+
}
|
|
3140
|
+
|
|
3141
|
+
// src/plugins/mount.ts
|
|
3142
|
+
var PluginRegisterMustBeSyncError = class extends Error {
|
|
3143
|
+
constructor(pluginName) {
|
|
3144
|
+
super(
|
|
3145
|
+
`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.`
|
|
3146
|
+
);
|
|
3147
|
+
this.name = "PluginRegisterMustBeSyncError";
|
|
3148
|
+
}
|
|
3149
|
+
};
|
|
3150
|
+
function sortRoutesByPriority(routes) {
|
|
3151
|
+
return routes.map((route, index) => ({ route, index })).sort((a, b) => {
|
|
3152
|
+
const pa = a.route.priority ?? 0;
|
|
3153
|
+
const pb = b.route.priority ?? 0;
|
|
3154
|
+
if (pb !== pa) return pb - pa;
|
|
3155
|
+
return a.index - b.index;
|
|
3156
|
+
}).map((entry) => entry.route);
|
|
3157
|
+
}
|
|
3158
|
+
function mountPlugin(app, plugin, result) {
|
|
3159
|
+
if (!plugin || typeof plugin !== "object" || !plugin.name) {
|
|
3160
|
+
result?.skipped.push({ plugin: String(plugin?.name ?? "unknown"), reason: "not a valid plugin object" });
|
|
3161
|
+
return;
|
|
3162
|
+
}
|
|
3163
|
+
if (Array.isArray(plugin.routes) && plugin.routes.length > 0) {
|
|
3164
|
+
for (const route of sortRoutesByPriority(plugin.routes)) {
|
|
3165
|
+
if (!route || !route.path || !route.handler) {
|
|
3166
|
+
result?.skipped.push({ plugin: plugin.name, reason: `invalid route entry (missing path or handler)` });
|
|
3167
|
+
continue;
|
|
3168
|
+
}
|
|
3169
|
+
app.route(route.path, route.handler);
|
|
3170
|
+
result?.mounted.push({ plugin: plugin.name, path: route.path });
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3173
|
+
if (typeof plugin.register === "function") {
|
|
3174
|
+
const maybePromise = plugin.register(app);
|
|
3175
|
+
if (maybePromise && typeof maybePromise.then === "function") {
|
|
3176
|
+
throw new PluginRegisterMustBeSyncError(plugin.name);
|
|
3177
|
+
}
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
function registerPluginRoutes(app, plugins, options = {}) {
|
|
3181
|
+
const result = { mounted: [], skipped: [] };
|
|
3182
|
+
const warnOnDuplicatePath = options.warnOnDuplicatePath ?? (typeof process === "undefined" || process.env?.NODE_ENV !== "production");
|
|
3183
|
+
const seenPaths = /* @__PURE__ */ new Map();
|
|
3184
|
+
const sortByDependencies = options.sortByDependencies ?? true;
|
|
3185
|
+
const sorted = sortByDependencies ? topoSort(plugins.filter((p) => !!p && typeof p === "object"), {
|
|
3186
|
+
strict: options.strict
|
|
3187
|
+
}) : plugins.filter((p) => !!p && typeof p === "object");
|
|
3188
|
+
for (const plugin of sorted) {
|
|
3189
|
+
if (!plugin) continue;
|
|
3190
|
+
const before = result.mounted.length;
|
|
3191
|
+
mountPlugin(app, plugin, result);
|
|
3192
|
+
if (warnOnDuplicatePath) {
|
|
3193
|
+
for (let i = before; i < result.mounted.length; i++) {
|
|
3194
|
+
const entry = result.mounted[i];
|
|
3195
|
+
if (!entry) continue;
|
|
3196
|
+
const { plugin: owner, path } = entry;
|
|
3197
|
+
const prior = seenPaths.get(path);
|
|
3198
|
+
if (prior && prior !== owner) {
|
|
3199
|
+
console.warn(
|
|
3200
|
+
`[plugins] Duplicate route path "${path}" mounted by "${owner}" \u2014 already claimed by "${prior}". The first registration wins; the later one is shadowed.`
|
|
3201
|
+
);
|
|
3202
|
+
} else if (!prior) {
|
|
3203
|
+
seenPaths.set(path, owner);
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
return result;
|
|
3209
|
+
}
|
|
3210
|
+
|
|
3211
|
+
// src/plugins/wire.ts
|
|
3212
|
+
async function wireRegisteredPlugins(plugins, context, options = {}) {
|
|
3213
|
+
const result = { subscribed: 0, booted: [], errors: [] };
|
|
3214
|
+
const sortByDeps = options.sortByDependencies ?? true;
|
|
3215
|
+
const raw = plugins.filter((p) => !!p && typeof p === "object");
|
|
3216
|
+
const valid = sortByDeps ? topoSort(raw, { strict: options.strict }) : raw;
|
|
3217
|
+
for (const plugin of valid) {
|
|
3218
|
+
const name = plugin.name ?? "unknown";
|
|
3219
|
+
if (!Array.isArray(plugin.hooks) || plugin.hooks.length === 0) continue;
|
|
3220
|
+
for (const hook of plugin.hooks) {
|
|
3221
|
+
if (!hook || typeof hook.name !== "string" || typeof hook.handler !== "function") {
|
|
3222
|
+
result.errors.push({ plugin: name, phase: "subscribe", error: new Error("invalid hook entry") });
|
|
3223
|
+
continue;
|
|
3224
|
+
}
|
|
3225
|
+
if (plugin.capabilities !== void 0 && chunkJ6JTWD2A_cjs.isKnownHookEvent(hook.name)) {
|
|
3226
|
+
const requiredCap = chunkUHRHZXVR_cjs.HOOK_CAPABILITY_MAP[hook.name];
|
|
3227
|
+
if (requiredCap && !plugin.capabilities.includes(requiredCap)) {
|
|
3228
|
+
const capErr = new chunkUHRHZXVR_cjs.SonicCapabilityError(requiredCap, name);
|
|
3229
|
+
if (options.strict) {
|
|
3230
|
+
result.errors.push({ plugin: name, phase: "subscribe", error: capErr });
|
|
3231
|
+
} else {
|
|
3232
|
+
console.warn(`[plugins] ${capErr.message} Hook "${hook.name}" will not be registered.`);
|
|
3233
|
+
}
|
|
3234
|
+
continue;
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
try {
|
|
3238
|
+
context.hooks.register(hook.name, hook.handler, hook.priority);
|
|
3239
|
+
result.subscribed++;
|
|
3240
|
+
} catch (error) {
|
|
3241
|
+
result.errors.push({ plugin: name, phase: "subscribe", error });
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
for (const plugin of valid) {
|
|
3246
|
+
const name = plugin.name ?? "unknown";
|
|
3247
|
+
if (typeof plugin.onBoot !== "function") continue;
|
|
3248
|
+
try {
|
|
3249
|
+
await plugin.onBoot(context);
|
|
3250
|
+
result.booted.push(name);
|
|
3251
|
+
} catch (error) {
|
|
3252
|
+
result.errors.push({ plugin: name, phase: "onBoot", error });
|
|
3253
|
+
}
|
|
3254
|
+
}
|
|
3255
|
+
if (context.env?.DB) {
|
|
3256
|
+
reflectWiredPlugins(valid, context.env.DB).catch((err) => {
|
|
3257
|
+
console.warn("[plugins] DB reflection failed (non-fatal):", err);
|
|
3258
|
+
});
|
|
3259
|
+
}
|
|
3260
|
+
return result;
|
|
3261
|
+
}
|
|
3262
|
+
async function reflectWiredPlugins(plugins, db) {
|
|
3263
|
+
const now = Date.now();
|
|
3264
|
+
for (const plugin of plugins) {
|
|
3265
|
+
const id = plugin.id ?? plugin.name;
|
|
3266
|
+
if (!id) continue;
|
|
3267
|
+
const displayName = plugin.name ?? id;
|
|
3268
|
+
const version = plugin.version ?? "0.0.0";
|
|
3269
|
+
const description = plugin.description ?? "";
|
|
3270
|
+
const initialStatus = plugin.defaultActive ? "active" : "inactive";
|
|
3271
|
+
try {
|
|
3272
|
+
await db.prepare(
|
|
3273
|
+
`INSERT INTO plugins (id, name, display_name, description, version, author, category,
|
|
3274
|
+
status, is_core, installed_at, last_updated)
|
|
3275
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)
|
|
3276
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
3277
|
+
version = excluded.version,
|
|
3278
|
+
display_name = excluded.display_name,
|
|
3279
|
+
last_updated = excluded.last_updated`
|
|
3280
|
+
).bind(id, id, displayName, description, version, "core", "core", initialStatus, now, now).run();
|
|
3281
|
+
} catch {
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
}
|
|
3285
|
+
function createPluginWirer(plugins, ctxFactory) {
|
|
3286
|
+
let started;
|
|
3287
|
+
return () => {
|
|
3288
|
+
if (!started) {
|
|
3289
|
+
const list = typeof plugins === "function" ? plugins() : plugins;
|
|
3290
|
+
started = wireRegisteredPlugins(list, ctxFactory());
|
|
3291
|
+
}
|
|
3292
|
+
return started;
|
|
3293
|
+
};
|
|
3294
|
+
}
|
|
3295
|
+
|
|
3296
|
+
// src/plugins/sdk/register-plugins.ts
|
|
3297
|
+
var import_semver2 = chunkIGJUBJBW_cjs.__toESM(require_semver2(), 1);
|
|
3298
|
+
|
|
3299
|
+
// src/services/plugin-menu-singleton.ts
|
|
3300
|
+
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>`;
|
|
3301
|
+
var MENU_ICON_MAP = {
|
|
3302
|
+
"puzzle-piece": PUZZLE_PIECE,
|
|
3303
|
+
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>`,
|
|
3304
|
+
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>`,
|
|
3305
|
+
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>`,
|
|
3306
|
+
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>`,
|
|
3307
|
+
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>`,
|
|
3308
|
+
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>`,
|
|
3309
|
+
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>`,
|
|
3310
|
+
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>`
|
|
3311
|
+
};
|
|
3312
|
+
function resolveIcon(name) {
|
|
3313
|
+
if (!name) return PUZZLE_PIECE;
|
|
3314
|
+
if (name.startsWith("<svg")) return name;
|
|
3315
|
+
return MENU_ICON_MAP[name] ?? PUZZLE_PIECE;
|
|
3316
|
+
}
|
|
3317
|
+
var menuItems = [];
|
|
3318
|
+
function setPluginMenu(items) {
|
|
3319
|
+
menuItems = [...items];
|
|
3320
|
+
}
|
|
3321
|
+
function getPluginMenu() {
|
|
3322
|
+
return menuItems;
|
|
3323
|
+
}
|
|
3324
|
+
function resetPluginMenu() {
|
|
3325
|
+
menuItems = [];
|
|
3326
|
+
}
|
|
3327
|
+
function resolvePluginMenuItems(user) {
|
|
3328
|
+
const isAdmin = user?.role === "admin";
|
|
3329
|
+
const userPerms = new Set(user?.permissions ?? []);
|
|
3330
|
+
return menuItems.filter((m) => {
|
|
3331
|
+
if (!m.permissions || m.permissions.length === 0) return true;
|
|
3332
|
+
if (isAdmin) return true;
|
|
3333
|
+
return m.permissions.some((p) => userPerms.has(p));
|
|
3334
|
+
}).slice().sort((a, b) => (a.order ?? 100) - (b.order ?? 100)).map((m) => ({
|
|
3335
|
+
label: m.label,
|
|
3336
|
+
path: m.path,
|
|
3337
|
+
icon: resolveIcon(m.icon),
|
|
3338
|
+
order: m.order ?? 100
|
|
3339
|
+
}));
|
|
3340
|
+
}
|
|
3341
|
+
|
|
3342
|
+
// src/plugins/cron.ts
|
|
3343
|
+
function collectCrons(plugins) {
|
|
3344
|
+
const out = [];
|
|
3345
|
+
for (const plugin of plugins) {
|
|
3346
|
+
if (!plugin || !Array.isArray(plugin.crons)) continue;
|
|
3347
|
+
const name = plugin.name ?? "unknown";
|
|
3348
|
+
for (const cron of plugin.crons) {
|
|
3349
|
+
if (cron && typeof cron.schedule === "string" && typeof cron.hookFamily === "string") {
|
|
3350
|
+
out.push({ plugin: name, schedule: cron.schedule, hookFamily: cron.hookFamily });
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
return out;
|
|
3355
|
+
}
|
|
3356
|
+
function collectCronSchedules(plugins) {
|
|
3357
|
+
return [...new Set(collectCrons(plugins).map((c) => c.schedule))];
|
|
3358
|
+
}
|
|
3359
|
+
async function dispatchCronTick(plugins, cron, scheduledTime, context) {
|
|
3360
|
+
const result = { invoked: [], errors: [], unmatched: true };
|
|
3361
|
+
for (const plugin of plugins) {
|
|
3362
|
+
if (!plugin || typeof plugin.onCronTick !== "function" || !Array.isArray(plugin.crons)) continue;
|
|
3363
|
+
const name = plugin.name ?? "unknown";
|
|
3364
|
+
const matches = plugin.crons.filter((c) => c && c.schedule === cron);
|
|
3365
|
+
for (const match of matches) {
|
|
3366
|
+
result.unmatched = false;
|
|
3367
|
+
const event = { cron, scheduledTime, hookFamily: match.hookFamily };
|
|
3368
|
+
try {
|
|
3369
|
+
await plugin.onCronTick(event, context);
|
|
3370
|
+
result.invoked.push({ plugin: name, hookFamily: match.hookFamily });
|
|
3371
|
+
} catch (error) {
|
|
3372
|
+
result.errors.push({ plugin: name, hookFamily: match.hookFamily, error });
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
return result;
|
|
3377
|
+
}
|
|
3378
|
+
function createScheduledHandler(options) {
|
|
3379
|
+
return async (controller, env, ctx) => {
|
|
3380
|
+
if (options.disabled) {
|
|
3381
|
+
return { invoked: [], errors: [], unmatched: true };
|
|
3382
|
+
}
|
|
3383
|
+
if (options.boot) {
|
|
3384
|
+
try {
|
|
3385
|
+
await options.boot(env);
|
|
3386
|
+
} catch (err) {
|
|
3387
|
+
console.error("[cron] boot failed:", err);
|
|
3388
|
+
}
|
|
3389
|
+
}
|
|
3390
|
+
const plugins = typeof options.plugins === "function" ? options.plugins() : options.plugins;
|
|
3391
|
+
const work = dispatchCronTick(plugins, controller.cron, controller.scheduledTime, {
|
|
3392
|
+
hooks: options.getHooks(),
|
|
3393
|
+
env
|
|
3394
|
+
});
|
|
3395
|
+
ctx?.waitUntil?.(work.catch(() => {
|
|
3396
|
+
}));
|
|
3397
|
+
return work;
|
|
3398
|
+
};
|
|
3399
|
+
}
|
|
3400
|
+
|
|
3401
|
+
// src/plugins/sdk/register-plugins.ts
|
|
3402
|
+
var RegisterPluginsError = class extends Error {
|
|
3403
|
+
constructor(reason, details) {
|
|
3404
|
+
super(`registerPlugins(${reason}): ${JSON.stringify(details)}`);
|
|
3405
|
+
this.reason = reason;
|
|
3406
|
+
this.details = details;
|
|
3407
|
+
this.name = "RegisterPluginsError";
|
|
3408
|
+
}
|
|
3409
|
+
};
|
|
3410
|
+
function registerPlugins(app, plugins, host) {
|
|
3411
|
+
const list = plugins.filter((p) => !!p && typeof p === "object");
|
|
3412
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3413
|
+
for (const p of list) {
|
|
3414
|
+
if (!p.id || typeof p.id !== "string")
|
|
3415
|
+
throw new RegisterPluginsError("invalid_id", { plugin: p });
|
|
3416
|
+
if (!import_semver2.default.valid(p.version))
|
|
3417
|
+
throw new RegisterPluginsError("invalid_semver", { id: p.id, version: p.version });
|
|
3418
|
+
if (seen.has(p.id))
|
|
3419
|
+
throw new RegisterPluginsError("duplicate_id", { id: p.id });
|
|
3420
|
+
seen.add(p.id);
|
|
3421
|
+
if (p.sonicjsVersionRange) {
|
|
3422
|
+
try {
|
|
3423
|
+
if (!import_semver2.default.satisfies(chunkKV3CM5RK_cjs.getCoreVersion(), p.sonicjsVersionRange)) {
|
|
3424
|
+
console.warn(
|
|
3425
|
+
`[plugins] ${p.id} declares sonicjsVersionRange "${p.sonicjsVersionRange}" but core is "${chunkKV3CM5RK_cjs.getCoreVersion()}". Plugin may not work correctly.`
|
|
3426
|
+
);
|
|
3427
|
+
}
|
|
3428
|
+
} catch {
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
}
|
|
3432
|
+
let mountResult;
|
|
3433
|
+
try {
|
|
3434
|
+
mountResult = registerPluginRoutes(app, list, {
|
|
3435
|
+
source: host.source,
|
|
3436
|
+
strict: host.strict,
|
|
3437
|
+
...host.mountOptions
|
|
3438
|
+
});
|
|
3439
|
+
} catch (err) {
|
|
3440
|
+
const pluginId2 = err && typeof err === "object" && "message" in err ? String(err.message).match(/Plugin "([^"]+)"/)?.[1] ?? "unknown" : "unknown";
|
|
3441
|
+
throw new RegisterPluginsError("register_returned_promise", { id: pluginId2, error: String(err) });
|
|
3442
|
+
}
|
|
3443
|
+
const menu = list.flatMap((p) => p.menu ?? []);
|
|
3444
|
+
setPluginMenu(menu);
|
|
3445
|
+
chunkUHRHZXVR_cjs.setPluginDefinitions(list);
|
|
3446
|
+
const crons = list.flatMap((p) => p.crons ?? []);
|
|
3447
|
+
const cronSchedules = collectCronSchedules(list);
|
|
3448
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3449
|
+
for (const p of list) {
|
|
3450
|
+
byId.set(p.id, {
|
|
3451
|
+
id: p.id,
|
|
3452
|
+
displayName: p.displayName ?? p.name ?? p.id,
|
|
3453
|
+
version: p.version,
|
|
3454
|
+
capabilities: p.capabilities ?? []
|
|
3455
|
+
});
|
|
3456
|
+
}
|
|
3457
|
+
let wirePromise;
|
|
3458
|
+
const boot = (envOverride) => {
|
|
3459
|
+
if (!wirePromise) {
|
|
3460
|
+
const env = envOverride ?? host.env ?? {};
|
|
3461
|
+
wirePromise = wireRegisteredPlugins(list, { hooks: host.hookSystem, env }, { strict: host.strict });
|
|
3462
|
+
}
|
|
3463
|
+
return wirePromise;
|
|
3464
|
+
};
|
|
3465
|
+
return {
|
|
3466
|
+
byId,
|
|
3467
|
+
order: list.map((p) => p.id),
|
|
3468
|
+
menu,
|
|
3469
|
+
crons,
|
|
3470
|
+
cronSchedules,
|
|
3471
|
+
mountResult,
|
|
3472
|
+
boot
|
|
3473
|
+
};
|
|
3474
|
+
}
|
|
3475
|
+
|
|
3476
|
+
// src/plugins/core-plugins/turnstile-plugin/manifest.json
|
|
3477
|
+
var manifest_default = {
|
|
3478
|
+
id: "turnstile",
|
|
3479
|
+
name: "Cloudflare Turnstile",
|
|
3480
|
+
description: "CAPTCHA-free bot protection using Cloudflare Turnstile. Provides reusable verification for any form.",
|
|
3481
|
+
version: "1.0.0",
|
|
3482
|
+
author: "SonicJS",
|
|
3483
|
+
category: "security",
|
|
3484
|
+
icon: "shield-check",
|
|
3485
|
+
homepage: "https://developers.cloudflare.com/turnstile/",
|
|
3486
|
+
repository: "https://github.com/sonicjs/sonicjs",
|
|
3487
|
+
license: "MIT",
|
|
3488
|
+
permissions: [
|
|
3489
|
+
"settings:write",
|
|
3490
|
+
"admin:access"
|
|
3491
|
+
],
|
|
3492
|
+
dependencies: [],
|
|
3493
|
+
configSchema: {
|
|
3494
|
+
siteKey: {
|
|
3495
|
+
type: "string",
|
|
3496
|
+
label: "Site Key",
|
|
3497
|
+
description: "Your Cloudflare Turnstile site key (public)",
|
|
3498
|
+
required: true
|
|
3499
|
+
},
|
|
3500
|
+
secretKey: {
|
|
3501
|
+
type: "string",
|
|
3502
|
+
label: "Secret Key",
|
|
3503
|
+
description: "Your Cloudflare Turnstile secret key (private)",
|
|
3504
|
+
required: true,
|
|
3505
|
+
sensitive: true
|
|
3506
|
+
},
|
|
3507
|
+
theme: {
|
|
3508
|
+
type: "select",
|
|
3509
|
+
label: "Widget Theme",
|
|
3510
|
+
description: "Visual theme for the Turnstile widget",
|
|
3511
|
+
default: "auto",
|
|
3512
|
+
options: [
|
|
3513
|
+
{
|
|
3514
|
+
value: "light",
|
|
3515
|
+
label: "Light"
|
|
3516
|
+
},
|
|
3517
|
+
{
|
|
3518
|
+
value: "dark",
|
|
3519
|
+
label: "Dark"
|
|
3520
|
+
},
|
|
3521
|
+
{
|
|
3522
|
+
value: "auto",
|
|
3523
|
+
label: "Auto"
|
|
3524
|
+
}
|
|
3525
|
+
]
|
|
3526
|
+
},
|
|
3527
|
+
size: {
|
|
3528
|
+
type: "select",
|
|
3529
|
+
label: "Widget Size",
|
|
3530
|
+
description: "Size of the Turnstile widget",
|
|
3531
|
+
default: "normal",
|
|
3532
|
+
options: [
|
|
3533
|
+
{
|
|
3534
|
+
value: "normal",
|
|
3535
|
+
label: "Normal"
|
|
3536
|
+
},
|
|
3537
|
+
{
|
|
3538
|
+
value: "compact",
|
|
3539
|
+
label: "Compact"
|
|
3540
|
+
}
|
|
3541
|
+
]
|
|
3542
|
+
},
|
|
3543
|
+
mode: {
|
|
3544
|
+
type: "select",
|
|
3545
|
+
label: "Widget Mode",
|
|
3546
|
+
description: "Managed: Adaptive challenge. Non-Interactive: Always visible, minimal friction. Invisible: No visible widget",
|
|
3547
|
+
default: "managed",
|
|
3548
|
+
options: [
|
|
3549
|
+
{
|
|
3550
|
+
value: "managed",
|
|
3551
|
+
label: "Managed (Recommended)"
|
|
3552
|
+
},
|
|
3553
|
+
{
|
|
3554
|
+
value: "non-interactive",
|
|
3555
|
+
label: "Non-Interactive"
|
|
3556
|
+
},
|
|
3557
|
+
{
|
|
3558
|
+
value: "invisible",
|
|
3559
|
+
label: "Invisible"
|
|
3560
|
+
}
|
|
3561
|
+
]
|
|
3562
|
+
},
|
|
3563
|
+
appearance: {
|
|
3564
|
+
type: "select",
|
|
3565
|
+
label: "Appearance",
|
|
3566
|
+
description: "When the Turnstile challenge is executed. Always: Verifies immediately. Execute: Challenge on form submit. Interaction Only: Only after user interaction",
|
|
3567
|
+
default: "always",
|
|
3568
|
+
options: [
|
|
3569
|
+
{
|
|
3570
|
+
value: "always",
|
|
3571
|
+
label: "Always"
|
|
3572
|
+
},
|
|
3573
|
+
{
|
|
3574
|
+
value: "execute",
|
|
3575
|
+
label: "Execute"
|
|
3576
|
+
},
|
|
3577
|
+
{
|
|
3578
|
+
value: "interaction-only",
|
|
3579
|
+
label: "Interaction Only"
|
|
3580
|
+
}
|
|
3581
|
+
]
|
|
3582
|
+
},
|
|
3583
|
+
preClearance: {
|
|
3584
|
+
type: "boolean",
|
|
3585
|
+
label: "Enable Pre-clearance",
|
|
3586
|
+
description: "Issue a clearance cookie that bypasses Cloudflare Firewall Rules (as if the user passed a challenge on your proxied site)",
|
|
3587
|
+
default: false
|
|
3588
|
+
},
|
|
3589
|
+
preClearanceLevel: {
|
|
3590
|
+
type: "select",
|
|
3591
|
+
label: "Pre-clearance Level",
|
|
3592
|
+
description: "Controls which Cloudflare Firewall Rules the clearance cookie bypasses. Only applies if Pre-clearance is enabled",
|
|
3593
|
+
default: "managed",
|
|
3594
|
+
options: [
|
|
3595
|
+
{
|
|
3596
|
+
value: "interactive",
|
|
3597
|
+
label: "Interactive - Bypasses Interactive, Managed & JS Challenge Rules"
|
|
3598
|
+
},
|
|
3599
|
+
{
|
|
3600
|
+
value: "managed",
|
|
3601
|
+
label: "Managed - Bypasses Managed & JS Challenge Rules"
|
|
3602
|
+
},
|
|
3603
|
+
{
|
|
3604
|
+
value: "non-interactive",
|
|
3605
|
+
label: "Non-interactive - Bypasses JS Challenge Rules only"
|
|
3606
|
+
}
|
|
3607
|
+
]
|
|
3608
|
+
},
|
|
3609
|
+
enabled: {
|
|
3610
|
+
type: "boolean",
|
|
3611
|
+
label: "Enable Turnstile",
|
|
3612
|
+
description: "Enable or disable Turnstile verification globally",
|
|
3613
|
+
default: true
|
|
3614
|
+
}
|
|
3615
|
+
},
|
|
3616
|
+
adminMenu: {
|
|
3617
|
+
label: "Turnstile",
|
|
3618
|
+
icon: "shield-check",
|
|
3619
|
+
href: "/admin/plugins/turnstile/settings",
|
|
3620
|
+
parentId: "plugins",
|
|
3621
|
+
order: 100
|
|
3622
|
+
},
|
|
3623
|
+
codeName: "turnstile-plugin",
|
|
3624
|
+
iconEmoji: "\u{1F6E1}\uFE0F",
|
|
3625
|
+
is_core: true,
|
|
3626
|
+
defaultSettings: {
|
|
3627
|
+
siteKey: "",
|
|
3628
|
+
secretKey: "",
|
|
3629
|
+
theme: "auto",
|
|
3630
|
+
size: "normal",
|
|
3631
|
+
mode: "managed",
|
|
3632
|
+
appearance: "always",
|
|
3633
|
+
preClearanceEnabled: false,
|
|
3634
|
+
preClearanceLevel: "managed",
|
|
3635
|
+
enabled: false
|
|
3636
|
+
}
|
|
3637
|
+
};
|
|
3638
|
+
|
|
3639
|
+
// src/plugins/core-plugins/turnstile-plugin/services/turnstile.ts
|
|
3640
|
+
var TurnstileService = class {
|
|
3641
|
+
db;
|
|
3642
|
+
VERIFY_URL = "https://challenges.cloudflare.com/turnstile/v0/siteverify";
|
|
3643
|
+
constructor(db) {
|
|
3644
|
+
this.db = db;
|
|
3645
|
+
}
|
|
3646
|
+
/**
|
|
3647
|
+
* Get Turnstile settings from database
|
|
3648
|
+
*/
|
|
3649
|
+
async getSettings() {
|
|
3650
|
+
try {
|
|
3651
|
+
const plugin = await this.db.prepare(`SELECT settings FROM plugins WHERE id = ? LIMIT 1`).bind(manifest_default.id).first();
|
|
3652
|
+
if (!plugin || !plugin.settings) {
|
|
3653
|
+
return null;
|
|
3654
|
+
}
|
|
3655
|
+
return JSON.parse(plugin.settings);
|
|
3656
|
+
} catch (error) {
|
|
3657
|
+
console.error("Error getting Turnstile settings:", error);
|
|
3658
|
+
return null;
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3661
|
+
/**
|
|
3662
|
+
* Verify a Turnstile token with Cloudflare
|
|
3663
|
+
*/
|
|
3664
|
+
async verifyToken(token, remoteIp) {
|
|
3665
|
+
try {
|
|
3666
|
+
const settings = await this.getSettings();
|
|
3667
|
+
if (!settings) {
|
|
3668
|
+
return { success: false, error: "Turnstile not configured" };
|
|
3669
|
+
}
|
|
3670
|
+
if (!settings.enabled) {
|
|
3671
|
+
return { success: true };
|
|
3672
|
+
}
|
|
3673
|
+
if (!settings.secretKey) {
|
|
3674
|
+
return { success: false, error: "Turnstile secret key not configured" };
|
|
3675
|
+
}
|
|
3676
|
+
const formData = new FormData();
|
|
3677
|
+
formData.append("secret", settings.secretKey);
|
|
3678
|
+
formData.append("response", token);
|
|
3679
|
+
if (remoteIp) {
|
|
3680
|
+
formData.append("remoteip", remoteIp);
|
|
3681
|
+
}
|
|
3682
|
+
const response = await fetch(this.VERIFY_URL, {
|
|
3683
|
+
method: "POST",
|
|
3684
|
+
body: formData
|
|
3685
|
+
});
|
|
3686
|
+
if (!response.ok) {
|
|
3687
|
+
return { success: false, error: "Turnstile verification request failed" };
|
|
3688
|
+
}
|
|
3689
|
+
const result = await response.json();
|
|
3690
|
+
if (!result.success) {
|
|
3691
|
+
const errorCode = result["error-codes"]?.[0] || "unknown-error";
|
|
3692
|
+
return { success: false, error: `Turnstile verification failed: ${errorCode}` };
|
|
3693
|
+
}
|
|
3694
|
+
return { success: true };
|
|
3695
|
+
} catch (error) {
|
|
3696
|
+
console.error("Error verifying Turnstile token:", error);
|
|
3697
|
+
return { success: false, error: "Turnstile verification error" };
|
|
3698
|
+
}
|
|
3699
|
+
}
|
|
3700
|
+
/**
|
|
3701
|
+
* Save Turnstile settings to database
|
|
3702
|
+
*/
|
|
3703
|
+
async saveSettings(settings) {
|
|
3704
|
+
try {
|
|
3705
|
+
await this.db.prepare(`UPDATE plugins SET settings = ?, updated_at = ? WHERE id = ?`).bind(JSON.stringify(settings), Date.now(), manifest_default.id).run();
|
|
3706
|
+
console.log("Turnstile settings saved successfully");
|
|
3707
|
+
} catch (error) {
|
|
3708
|
+
console.error("Error saving Turnstile settings:", error);
|
|
3709
|
+
throw new Error("Failed to save Turnstile settings");
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3712
|
+
/**
|
|
3713
|
+
* Check if Turnstile is enabled
|
|
3714
|
+
*/
|
|
3715
|
+
async isEnabled() {
|
|
3716
|
+
const settings = await this.getSettings();
|
|
3717
|
+
return settings?.enabled === true && !!settings.siteKey && !!settings.secretKey;
|
|
3718
|
+
}
|
|
3719
|
+
};
|
|
3720
|
+
|
|
3087
3721
|
// src/plugins/core-plugins/turnstile-plugin/middleware/verify.ts
|
|
3088
3722
|
async function verifyTurnstile(c, next) {
|
|
3089
3723
|
const db = c.get("db") || c.env?.DB;
|
|
@@ -3091,7 +3725,7 @@ async function verifyTurnstile(c, next) {
|
|
|
3091
3725
|
console.error("Turnstile middleware: Database not available");
|
|
3092
3726
|
return c.json({ error: "Database not available" }, 500);
|
|
3093
3727
|
}
|
|
3094
|
-
const turnstileService = new
|
|
3728
|
+
const turnstileService = new TurnstileService(db);
|
|
3095
3729
|
const isEnabled = await turnstileService.isEnabled();
|
|
3096
3730
|
if (!isEnabled) {
|
|
3097
3731
|
return next();
|
|
@@ -3131,7 +3765,7 @@ function createTurnstileMiddleware(options) {
|
|
|
3131
3765
|
if (!db) {
|
|
3132
3766
|
return options?.onError?.(c, "Database not available") || c.json({ error: "Database not available" }, 500);
|
|
3133
3767
|
}
|
|
3134
|
-
const turnstileService = new
|
|
3768
|
+
const turnstileService = new TurnstileService(db);
|
|
3135
3769
|
const isEnabled = await turnstileService.isEnabled();
|
|
3136
3770
|
if (!isEnabled) {
|
|
3137
3771
|
return next();
|
|
@@ -3159,26 +3793,40 @@ function createTurnstileMiddleware(options) {
|
|
|
3159
3793
|
}
|
|
3160
3794
|
|
|
3161
3795
|
// src/plugins/core-plugins/turnstile-plugin/index.ts
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
version:
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
}).addService("turnstile", chunk635JAMSE_cjs.TurnstileService).addSingleMiddleware("verifyTurnstile", verifyTurnstile, {
|
|
3171
|
-
description: "Verify Cloudflare Turnstile token",
|
|
3172
|
-
global: false
|
|
3173
|
-
}).build();
|
|
3796
|
+
chunkUHRHZXVR_cjs.definePlugin({
|
|
3797
|
+
id: manifest_default.id,
|
|
3798
|
+
version: manifest_default.version,
|
|
3799
|
+
name: manifest_default.name,
|
|
3800
|
+
description: manifest_default.description,
|
|
3801
|
+
sonicjsVersionRange: "^3.0.0",
|
|
3802
|
+
author: { name: manifest_default.author }
|
|
3803
|
+
});
|
|
3174
3804
|
|
|
3175
3805
|
exports.HookSystemImpl = HookSystemImpl;
|
|
3176
3806
|
exports.HookUtils = HookUtils;
|
|
3807
|
+
exports.PluginDependencyCycleError = PluginDependencyCycleError;
|
|
3177
3808
|
exports.PluginManager = PluginManager;
|
|
3809
|
+
exports.PluginRegisterMustBeSyncError = PluginRegisterMustBeSyncError;
|
|
3178
3810
|
exports.PluginRegistryImpl = PluginRegistryImpl;
|
|
3179
3811
|
exports.PluginValidator = PluginValidator;
|
|
3812
|
+
exports.RegisterPluginsError = RegisterPluginsError;
|
|
3180
3813
|
exports.ScopedHookSystem = ScopedHookSystem;
|
|
3814
|
+
exports.TurnstileService = TurnstileService;
|
|
3815
|
+
exports.collectCronSchedules = collectCronSchedules;
|
|
3816
|
+
exports.collectCrons = collectCrons;
|
|
3817
|
+
exports.createPluginWirer = createPluginWirer;
|
|
3818
|
+
exports.createScheduledHandler = createScheduledHandler;
|
|
3181
3819
|
exports.createTurnstileMiddleware = createTurnstileMiddleware;
|
|
3820
|
+
exports.dispatchCronTick = dispatchCronTick;
|
|
3821
|
+
exports.getPluginMenu = getPluginMenu;
|
|
3822
|
+
exports.mountPlugin = mountPlugin;
|
|
3823
|
+
exports.registerPluginRoutes = registerPluginRoutes;
|
|
3824
|
+
exports.registerPlugins = registerPlugins;
|
|
3825
|
+
exports.resetPluginMenu = resetPluginMenu;
|
|
3826
|
+
exports.resolvePluginMenuItems = resolvePluginMenuItems;
|
|
3827
|
+
exports.setPluginMenu = setPluginMenu;
|
|
3828
|
+
exports.topoSort = topoSort;
|
|
3182
3829
|
exports.verifyTurnstile = verifyTurnstile;
|
|
3183
|
-
|
|
3184
|
-
//# sourceMappingURL=chunk-
|
|
3830
|
+
exports.wireRegisteredPlugins = wireRegisteredPlugins;
|
|
3831
|
+
//# sourceMappingURL=chunk-MKKGA3C4.cjs.map
|
|
3832
|
+
//# sourceMappingURL=chunk-MKKGA3C4.cjs.map
|