@premium-cms/plugin-webhook-notifier 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -7,7 +7,7 @@
7
7
  /** @type {import("@premium-cms/emdash").PluginDescriptor} */
8
8
  const descriptor = Object.freeze({
9
9
  "id": "webhook-notifier",
10
- "version": "0.2.0",
10
+ "version": "0.3.0",
11
11
  "format": "standard",
12
12
  "entrypoint": "@premium-cms/plugin-webhook-notifier/sandbox",
13
13
  "capabilities": [
@@ -23,10 +23,51 @@ const descriptor = Object.freeze({
23
23
  ]
24
24
  }
25
25
  },
26
+ "settingsSchema": {
27
+ "webhookUrl": {
28
+ "label": "Webhook URL",
29
+ "type": "url",
30
+ "placeholder": "https://example.com/hooks/emdash"
31
+ },
32
+ "secretToken": {
33
+ "label": "Secret token",
34
+ "description": "Sent as the X-Webhook-Secret header so the receiver can verify deliveries.",
35
+ "type": "secret"
36
+ },
37
+ "enabled": {
38
+ "label": "Enable webhooks",
39
+ "type": "boolean",
40
+ "default": true
41
+ },
42
+ "events": {
43
+ "label": "Events to send",
44
+ "type": "select",
45
+ "options": [
46
+ {
47
+ "value": "all",
48
+ "label": "All events"
49
+ },
50
+ {
51
+ "value": "content",
52
+ "label": "Content changes only"
53
+ },
54
+ {
55
+ "value": "media",
56
+ "label": "Media uploads only"
57
+ }
58
+ ],
59
+ "default": "all"
60
+ },
61
+ "includeData": {
62
+ "label": "Include content data",
63
+ "type": "boolean",
64
+ "default": false
65
+ }
66
+ },
26
67
  "adminPages": [
27
68
  {
28
- "path": "/settings",
29
- "label": "Webhook Settings",
69
+ "path": "/status",
70
+ "label": "Webhooks",
30
71
  "icon": "send"
31
72
  }
32
73
  ],
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "webhook-notifier",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "declaredAccess": {
5
5
  "network": {
6
6
  "request": {}
@@ -40,14 +40,54 @@
40
40
  "admin",
41
41
  "status",
42
42
  "settings",
43
- "settings/save",
44
43
  "test"
45
44
  ],
46
45
  "admin": {
46
+ "settingsSchema": {
47
+ "webhookUrl": {
48
+ "label": "Webhook URL",
49
+ "type": "url",
50
+ "placeholder": "https://example.com/hooks/emdash"
51
+ },
52
+ "secretToken": {
53
+ "label": "Secret token",
54
+ "description": "Sent as the X-Webhook-Secret header so the receiver can verify deliveries.",
55
+ "type": "secret"
56
+ },
57
+ "enabled": {
58
+ "label": "Enable webhooks",
59
+ "type": "boolean",
60
+ "default": true
61
+ },
62
+ "events": {
63
+ "label": "Events to send",
64
+ "type": "select",
65
+ "options": [
66
+ {
67
+ "value": "all",
68
+ "label": "All events"
69
+ },
70
+ {
71
+ "value": "content",
72
+ "label": "Content changes only"
73
+ },
74
+ {
75
+ "value": "media",
76
+ "label": "Media uploads only"
77
+ }
78
+ ],
79
+ "default": "all"
80
+ },
81
+ "includeData": {
82
+ "label": "Include content data",
83
+ "type": "boolean",
84
+ "default": false
85
+ }
86
+ },
47
87
  "pages": [
48
88
  {
49
- "path": "/settings",
50
- "label": "Webhook Settings",
89
+ "path": "/status",
90
+ "label": "Webhooks",
51
91
  "icon": "send"
52
92
  }
53
93
  ],
package/dist/plugin.d.mts CHANGED
@@ -60,15 +60,6 @@ declare const _default: {
60
60
  events: string;
61
61
  }>;
62
62
  };
63
- "settings/save": {
64
- handler: (routeCtx: _premium_cms_emdash_plugin0.SandboxedRouteContext, ctx: PluginContext<_premium_cms_plugin_types0.PluginStorageConfig>) => Promise<{
65
- success: boolean;
66
- error?: undefined;
67
- } | {
68
- success: boolean;
69
- error: string;
70
- }>;
71
- };
72
63
  test: {
73
64
  handler: (routeCtx: _premium_cms_emdash_plugin0.SandboxedRouteContext, ctx: PluginContext<_premium_cms_plugin_types0.PluginStorageConfig>) => Promise<{
74
65
  success: boolean;
package/dist/plugin.mjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=/^\[|\]$/g,t=new Set([`localhost`,`metadata.google.internal`,`[::1]`]),n=[{start:127<<24>>>0,end:2147483647},{start:10<<24>>>0,end:184549375},{start:2886729728,end:2887778303},{start:3232235520,end:3232301055},{start:2851995648,end:2852061183},{start:0,end:16777215}];function r(r){let i;try{i=new URL(r)}catch{throw Error(`Invalid webhook URL`)}if(i.protocol!==`http:`&&i.protocol!==`https:`)throw Error(`Webhook URL scheme '${i.protocol}' is not allowed`);let a=i.hostname.replace(e,``);if(t.has(a.toLowerCase()))throw Error(`Webhook URLs targeting internal hosts are not allowed`);let o=a.split(`.`);if(o.length===4){let e=o.map(Number);if(e.every(e=>!isNaN(e)&&e>=0&&e<=255)){let t=(e[0]<<24|e[1]<<16|e[2]<<8|e[3])>>>0;if(n.some(e=>t>=e.start&&t<=e.end))throw Error(`Webhook URLs targeting private IP addresses are not allowed`)}}if(a===`::1`||a.startsWith(`fe80:`)||a.startsWith(`fc`)||a.startsWith(`fd`))throw Error(`Webhook URLs targeting internal addresses are not allowed`)}async function i(e,t,n,i,a,o){r(n);let s,c;for(let r=1;r<=o;r++){try{let l={"Content-Type":`application/json`,"X-EmDash-Event":i.event};a&&(l.Authorization=`Bearer ${a}`);let u=await e(n,{method:`POST`,headers:l,body:JSON.stringify(i)});if(c=u.status,u.ok)return t.info(`Delivered ${i.event} to ${n} (${u.status})`),{success:!0,status:u.status};s=`HTTP ${u.status}: ${u.statusText}`,t.warn(`Attempt ${r}/${o} failed: ${s}`)}catch(e){s=e instanceof Error?e.message:`Unknown error`,t.warn(`Attempt ${r}/${o} failed: ${s}`)}r<o&&await new Promise(e=>setTimeout(e,100*2**(r-1)))}return t.error(`Failed to deliver ${i.event} after ${o} attempts`),{success:!1,status:c,error:s}}function a(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function o(e,t){if(!a(e))return;let n=e[t];return typeof n==`string`?n:void 0}async function s(e){return{url:await e.kv.get(`settings:webhookUrl`),token:await e.kv.get(`settings:secretToken`),enabled:await e.kv.get(`settings:enabled`)}}function c(e){if(!e.http)throw Error(`Webhook notifier requires network:request capability`);return e.http.fetch}var l={hooks:{"content:afterSave":{priority:210,timeout:1e4,dependencies:[`audit-log`],errorPolicy:`continue`,handler:async(e,t)=>{let{url:n,token:r,enabled:a}=await s(t);if(a===!1||!n)return;let o=typeof e.content.id==`string`?e.content.id:String(e.content.id),l={event:e.isNew?`content:create`:`content:update`,timestamp:new Date().toISOString(),collection:e.collection,resourceId:o,resourceType:`content`,metadata:{slug:e.content.slug,status:e.content.status}};await i(c(t),t.log,n,l,r??void 0,3)}},"content:afterDelete":{priority:210,timeout:1e4,dependencies:[`audit-log`],errorPolicy:`continue`,handler:async(e,t)=>{let{url:n,token:r,enabled:a}=await s(t);if(a===!1||!n)return;let o={event:`content:delete`,timestamp:new Date().toISOString(),collection:e.collection,resourceId:e.id,resourceType:`content`};await i(c(t),t.log,n,o,r??void 0,3)}},"media:afterUpload":{priority:210,timeout:1e4,errorPolicy:`continue`,handler:async(e,t)=>{let{url:n,token:r,enabled:a}=await s(t);if(a===!1||!n)return;let o={event:`media:upload`,timestamp:new Date().toISOString(),resourceId:e.media.id,resourceType:`media`};await i(c(t),t.log,n,o,r??void 0,3)}}},routes:{admin:{handler:async(e,t)=>{let n=e.input;return n.type===`page_load`&&n.page===`widget:webhook-status`?u(t):n.type===`page_load`&&n.page===`/settings`?d(t):n.type===`form_submit`&&n.action_id===`save_settings`?f(t,n.values??{}):n.type===`block_action`&&n.action_id===`test_webhook`?p(t):{blocks:[]}}},status:{handler:async(e,t)=>{try{let e=await t.kv.get(`settings:webhookUrl`),n=await t.kv.get(`settings:enabled`),r=t.storage.deliveries,i=await r.count({status:`success`}),a=await r.count({status:`failed`}),o=await r.count({status:`pending`});return{configured:!!e,enabled:n??!0,stats:{successful:i,failed:a,pending:o}}}catch(e){return t.log.error(`Failed to get status`,e),{configured:!1,enabled:!0,stats:{successful:0,failed:0,pending:0}}}}},settings:{handler:async(e,t)=>{try{let e=await t.kv.list(`settings:`),n={};for(let t of e)n[t.key.replace(`settings:`,``)]=t.value;return{webhookUrl:typeof n.webhookUrl==`string`?n.webhookUrl:``,enabled:typeof n.enabled==`boolean`?n.enabled:!0,includeData:typeof n.includeData==`boolean`?n.includeData:!1,events:typeof n.events==`string`?n.events:`all`}}catch(e){return t.log.error(`Failed to get settings`,e),{webhookUrl:``,enabled:!0,includeData:!1,events:`all`}}}},"settings/save":{handler:async(e,t)=>{try{let n=a(e.input)?e.input:{};return typeof n.webhookUrl==`string`&&await t.kv.set(`settings:webhookUrl`,n.webhookUrl),typeof n.enabled==`boolean`&&await t.kv.set(`settings:enabled`,n.enabled),typeof n.includeData==`boolean`&&await t.kv.set(`settings:includeData`,n.includeData),typeof n.events==`string`&&await t.kv.set(`settings:events`,n.events),{success:!0}}catch(e){return t.log.error(`Failed to save settings`,e),{success:!1,error:String(e)}}}},test:{handler:async(e,t)=>{let n=o(e.input,`url`);if(!n)return{success:!1,error:`No webhook URL provided`};let r=await t.kv.get(`settings:secretToken`),a={event:`content:create`,timestamp:new Date().toISOString(),resourceId:`test-`+Date.now(),resourceType:`content`,metadata:{test:!0,message:`Webhook test from EmDash CMS`}},s=await i(c(t),t.log,n,a,r??void 0,1);return{success:s.success,status:s.status,error:s.error,payload:a}}}}};async function u(e){try{let t=await e.kv.get(`settings:webhookUrl`),n=await e.kv.get(`settings:enabled`),r=!!t&&n!==!1,i=0,a=0,o=0;try{let t=e.storage.deliveries;i=await t.count({status:`success`}),a=await t.count({status:`failed`}),o=await t.count({status:`pending`})}catch{}let s=[{type:`fields`,fields:[{label:`Status`,value:r?`Active`:`Not Configured`},{label:`Endpoint`,value:t||`None`}]}];return r?s.push({type:`stats`,stats:[{label:`Delivered`,value:String(i)},{label:`Failed`,value:String(a)},{label:`Pending`,value:String(o)}]}):s.push({type:`context`,text:`Configure a webhook URL in settings to start sending events.`}),{blocks:s}}catch(t){return e.log.error(`Failed to build status widget`,t),{blocks:[{type:`context`,text:`Failed to load webhook status`}]}}}async function d(e){try{let t=await e.kv.get(`settings:webhookUrl`)??``,n=await e.kv.get(`settings:enabled`)??!0,r=await e.kv.get(`settings:includeData`)??!1,i=await e.kv.get(`settings:events`)??`all`,a=JSON.stringify({event:`content:create`,timestamp:new Date().toISOString(),collection:`posts`,resourceId:`abc123`,resourceType:`content`,...r&&{data:{title:`Example Post`,slug:`example-post`}},metadata:{slug:`example-post`,status:`published`}},null,2);return{blocks:[{type:`header`,text:`Webhook Settings`},{type:`context`,text:`Send notifications to external services when content changes.`},{type:`divider`},{type:`form`,block_id:`webhook-settings`,fields:[{type:`text_input`,action_id:`webhookUrl`,label:`Webhook URL`,initial_value:t},{type:`secret_input`,action_id:`secretToken`,label:`Secret Token`},{type:`toggle`,action_id:`enabled`,label:`Enable Webhooks`,initial_value:n},{type:`select`,action_id:`events`,label:`Events to Send`,options:[{label:`All events`,value:`all`},{label:`Content changes only`,value:`content`},{label:`Media uploads only`,value:`media`}],initial_value:i},{type:`toggle`,action_id:`includeData`,label:`Include Content Data`,initial_value:r}],submit:{label:`Save Settings`,action_id:`save_settings`}},{type:`divider`},{type:`section`,text:`**Payload Preview**`},{type:`section`,text:"```json\n"+a+"\n```"},{type:`actions`,elements:[{type:`button`,text:`Test Webhook`,action_id:`test_webhook`,style:`primary`}]}]}}catch(t){return e.log.error(`Failed to build settings page`,t),{blocks:[{type:`context`,text:`Failed to load settings`}]}}}async function f(e,t){try{return typeof t.webhookUrl==`string`&&await e.kv.set(`settings:webhookUrl`,t.webhookUrl),typeof t.secretToken==`string`&&t.secretToken!==``&&await e.kv.set(`settings:secretToken`,t.secretToken),typeof t.enabled==`boolean`&&await e.kv.set(`settings:enabled`,t.enabled),typeof t.events==`string`&&await e.kv.set(`settings:events`,t.events),typeof t.includeData==`boolean`&&await e.kv.set(`settings:includeData`,t.includeData),{...await d(e),toast:{message:`Settings saved`,type:`success`}}}catch(t){return e.log.error(`Failed to save settings`,t),{blocks:[{type:`banner`,style:`error`,text:`Failed to save settings`}],toast:{message:`Failed to save settings`,type:`error`}}}}async function p(e){let t=await e.kv.get(`settings:webhookUrl`);if(!t)return{blocks:[{type:`banner`,style:`warning`,text:`Enter a webhook URL first.`}],toast:{message:`No webhook URL configured`,type:`error`}};let n=await e.kv.get(`settings:secretToken`),r={event:`content:create`,timestamp:new Date().toISOString(),resourceId:`test-`+Date.now(),resourceType:`content`,metadata:{test:!0,message:`Webhook test from EmDash CMS`}};try{let a=await i(c(e),e.log,t,r,n??void 0,1);return a.success?{...await d(e),toast:{message:`Test sent -- HTTP ${a.status}`,type:`success`}}:{...await d(e),toast:{message:`Test failed: ${a.error??`Unknown error`}`,type:`error`}}}catch(t){let n=t instanceof Error?t.message:String(t);return{...await d(e),toast:{message:`Test failed: ${n}`,type:`error`}}}}export{l as default};
1
+ const e=/^\[|\]$/g,t=new Set([`localhost`,`metadata.google.internal`,`[::1]`]),n=[{start:127<<24>>>0,end:2147483647},{start:10<<24>>>0,end:184549375},{start:2886729728,end:2887778303},{start:3232235520,end:3232301055},{start:2851995648,end:2852061183},{start:0,end:16777215}];function r(r){let i;try{i=new URL(r)}catch{throw Error(`Invalid webhook URL`)}if(i.protocol!==`http:`&&i.protocol!==`https:`)throw Error(`Webhook URL scheme '${i.protocol}' is not allowed`);let a=i.hostname.replace(e,``);if(t.has(a.toLowerCase()))throw Error(`Webhook URLs targeting internal hosts are not allowed`);let o=a.split(`.`);if(o.length===4){let e=o.map(Number);if(e.every(e=>!isNaN(e)&&e>=0&&e<=255)){let t=(e[0]<<24|e[1]<<16|e[2]<<8|e[3])>>>0;if(n.some(e=>t>=e.start&&t<=e.end))throw Error(`Webhook URLs targeting private IP addresses are not allowed`)}}if(a===`::1`||a.startsWith(`fe80:`)||a.startsWith(`fc`)||a.startsWith(`fd`))throw Error(`Webhook URLs targeting internal addresses are not allowed`)}async function i(e,t,n,i,a,o){r(n);let s,c;for(let r=1;r<=o;r++){try{let l={"Content-Type":`application/json`,"X-EmDash-Event":i.event};a&&(l.Authorization=`Bearer ${a}`);let u=await e(n,{method:`POST`,headers:l,body:JSON.stringify(i)});if(c=u.status,u.ok)return t.info(`Delivered ${i.event} to ${n} (${u.status})`),{success:!0,status:u.status};s=`HTTP ${u.status}: ${u.statusText}`,t.warn(`Attempt ${r}/${o} failed: ${s}`)}catch(e){s=e instanceof Error?e.message:`Unknown error`,t.warn(`Attempt ${r}/${o} failed: ${s}`)}r<o&&await new Promise(e=>setTimeout(e,100*2**(r-1)))}return t.error(`Failed to deliver ${i.event} after ${o} attempts`),{success:!1,status:c,error:s}}function a(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function o(e,t){if(!a(e))return;let n=e[t];return typeof n==`string`?n:void 0}async function s(e){return{url:await e.kv.get(`settings:webhookUrl`),token:await e.kv.get(`settings:secretToken`),enabled:await e.kv.get(`settings:enabled`)}}function c(e){if(!e.http)throw Error(`Webhook notifier requires network:request capability`);return e.http.fetch}var l={hooks:{"content:afterSave":{priority:210,timeout:1e4,dependencies:[`audit-log`],errorPolicy:`continue`,handler:async(e,t)=>{let{url:n,token:r,enabled:a}=await s(t);if(a===!1||!n)return;let o=typeof e.content.id==`string`?e.content.id:String(e.content.id),l={event:e.isNew?`content:create`:`content:update`,timestamp:new Date().toISOString(),collection:e.collection,resourceId:o,resourceType:`content`,metadata:{slug:e.content.slug,status:e.content.status}};await i(c(t),t.log,n,l,r??void 0,3)}},"content:afterDelete":{priority:210,timeout:1e4,dependencies:[`audit-log`],errorPolicy:`continue`,handler:async(e,t)=>{let{url:n,token:r,enabled:a}=await s(t);if(a===!1||!n)return;let o={event:`content:delete`,timestamp:new Date().toISOString(),collection:e.collection,resourceId:e.id,resourceType:`content`};await i(c(t),t.log,n,o,r??void 0,3)}},"media:afterUpload":{priority:210,timeout:1e4,errorPolicy:`continue`,handler:async(e,t)=>{let{url:n,token:r,enabled:a}=await s(t);if(a===!1||!n)return;let o={event:`media:upload`,timestamp:new Date().toISOString(),resourceId:e.media.id,resourceType:`media`};await i(c(t),t.log,n,o,r??void 0,3)}}},routes:{admin:{handler:async(e,t)=>{let n=e.input;return n.type===`page_load`&&n.page===`widget:webhook-status`?u(t):n.type===`page_load`&&n.page===`/status`?d(t):n.type===`block_action`&&n.action_id===`test_webhook`?f(t):{blocks:[]}}},status:{handler:async(e,t)=>{try{let e=await t.kv.get(`settings:webhookUrl`),n=await t.kv.get(`settings:enabled`),r=t.storage.deliveries,i=await r.count({status:`success`}),a=await r.count({status:`failed`}),o=await r.count({status:`pending`});return{configured:!!e,enabled:n??!0,stats:{successful:i,failed:a,pending:o}}}catch(e){return t.log.error(`Failed to get status`,e),{configured:!1,enabled:!0,stats:{successful:0,failed:0,pending:0}}}}},settings:{handler:async(e,t)=>{try{let e=await t.kv.list(`settings:`),n={};for(let t of e)n[t.key.replace(`settings:`,``)]=t.value;return{webhookUrl:typeof n.webhookUrl==`string`?n.webhookUrl:``,enabled:typeof n.enabled==`boolean`?n.enabled:!0,includeData:typeof n.includeData==`boolean`?n.includeData:!1,events:typeof n.events==`string`?n.events:`all`}}catch(e){return t.log.error(`Failed to get settings`,e),{webhookUrl:``,enabled:!0,includeData:!1,events:`all`}}}},test:{handler:async(e,t)=>{let n=o(e.input,`url`);if(!n)return{success:!1,error:`No webhook URL provided`};let r=await t.kv.get(`settings:secretToken`),a={event:`content:create`,timestamp:new Date().toISOString(),resourceId:`test-`+Date.now(),resourceType:`content`,metadata:{test:!0,message:`Webhook test from EmDash CMS`}},s=await i(c(t),t.log,n,a,r??void 0,1);return{success:s.success,status:s.status,error:s.error,payload:a}}}}};async function u(e){try{let t=await e.kv.get(`settings:webhookUrl`),n=await e.kv.get(`settings:enabled`),r=!!t&&n!==!1,i=0,a=0,o=0;try{let t=e.storage.deliveries;i=await t.count({status:`success`}),a=await t.count({status:`failed`}),o=await t.count({status:`pending`})}catch{}let s=[{type:`fields`,fields:[{label:`Status`,value:r?`Active`:`Not Configured`},{label:`Endpoint`,value:t||`None`}]}];return r?s.push({type:`stats`,stats:[{label:`Delivered`,value:String(i)},{label:`Failed`,value:String(a)},{label:`Pending`,value:String(o)}]}):s.push({type:`context`,text:`Configure a webhook URL in settings to start sending events.`}),{blocks:s}}catch(t){return e.log.error(`Failed to build status widget`,t),{blocks:[{type:`context`,text:`Failed to load webhook status`}]}}}async function d(e){try{let t=await e.kv.get(`settings:webhookUrl`)??``,n=await e.kv.get(`settings:enabled`)??!0,r=await e.kv.get(`settings:includeData`)??!1,i=await e.kv.get(`settings:events`)??`all`,a=JSON.stringify({event:`content:create`,timestamp:new Date().toISOString(),collection:`posts`,resourceId:`abc123`,resourceType:`content`,...r&&{data:{title:`Example Post`,slug:`example-post`}},metadata:{slug:`example-post`,status:`published`}},null,2);return{blocks:[{type:`header`,text:`Webhooks`},{type:`context`,text:`Send notifications to external services when content changes.`},{type:`fields`,fields:[{label:`Status`,value:n?`Enabled`:`Disabled`},{label:`Endpoint`,value:t||`Not configured`},{label:`Events`,value:i},{label:`Content data`,value:r?`Included`:`Not included`}]},{type:`context`,text:`The endpoint, secret and event filter are set under Plugins → Webhook Notifier → Settings.`},{type:`divider`},{type:`section`,text:`**Payload Preview**`},{type:`section`,text:"```json\n"+a+"\n```"},{type:`actions`,elements:[{type:`button`,text:`Test Webhook`,action_id:`test_webhook`,style:`primary`}]}]}}catch(t){return e.log.error(`Failed to build status page`,t),{blocks:[{type:`context`,text:`Failed to load webhook status`}]}}}async function f(e){let t=await e.kv.get(`settings:webhookUrl`);if(!t)return{blocks:[{type:`banner`,style:`warning`,text:`Enter a webhook URL first.`}],toast:{message:`No webhook URL configured`,type:`error`}};let n=await e.kv.get(`settings:secretToken`),r={event:`content:create`,timestamp:new Date().toISOString(),resourceId:`test-`+Date.now(),resourceType:`content`,metadata:{test:!0,message:`Webhook test from EmDash CMS`}};try{let a=await i(c(e),e.log,t,r,n??void 0,1);return a.success?{...await d(e),toast:{message:`Test sent -- HTTP ${a.status}`,type:`success`}}:{...await d(e),toast:{message:`Test failed: ${a.error??`Unknown error`}`,type:`error`}}}catch(t){let n=t instanceof Error?t.message:String(t);return{...await d(e),toast:{message:`Test failed: ${n}`,type:`error`}}}}export{l as default};
2
2
  //# sourceMappingURL=plugin.mjs.map
@@ -20,7 +20,27 @@
20
20
  },
21
21
 
22
22
  "admin": {
23
- "pages": [{ "path": "/settings", "label": "Webhook Settings", "icon": "send" }],
23
+ "settingsSchema": {
24
+ "webhookUrl": { "type": "url", "label": "Webhook URL", "placeholder": "https://example.com/hooks/emdash" },
25
+ "secretToken": {
26
+ "type": "secret",
27
+ "label": "Secret token",
28
+ "description": "Sent as the X-Webhook-Secret header so the receiver can verify deliveries."
29
+ },
30
+ "enabled": { "type": "boolean", "label": "Enable webhooks", "default": true },
31
+ "events": {
32
+ "type": "select",
33
+ "label": "Events to send",
34
+ "options": [
35
+ { "value": "all", "label": "All events" },
36
+ { "value": "content", "label": "Content changes only" },
37
+ { "value": "media", "label": "Media uploads only" }
38
+ ],
39
+ "default": "all"
40
+ },
41
+ "includeData": { "type": "boolean", "label": "Include content data", "default": false }
42
+ },
43
+ "pages": [{ "path": "/status", "label": "Webhooks", "icon": "send" }],
24
44
  "widgets": [{ "id": "status", "title": "Webhooks", "size": "third" }],
25
45
  },
26
46
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@premium-cms/plugin-webhook-notifier",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Webhook notification plugin for EmDash CMS - posts to external URLs on content changes",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -31,7 +31,7 @@
31
31
  "devDependencies": {
32
32
  "tsdown": "0.20.3",
33
33
  "typescript": "^6.0.3",
34
- "@premium-cms/plugin-cli": "0.8.1"
34
+ "@premium-cms/plugin-cli": "0.8.5"
35
35
  },
36
36
  "repository": {
37
37
  "type": "git",