@objectstack/plugin-webhooks 15.1.0 → 16.0.0-rc.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @objectstack/plugin-webhooks@15.1.0 build /home/runner/work/framework/framework/packages/plugins/plugin-webhooks
2
+ > @objectstack/plugin-webhooks@16.0.0-rc.0 build /home/runner/work/framework/framework/packages/plugins/plugin-webhooks
3
3
  > tsup
4
4
 
5
5
  CLI Building entry: src/index.ts, src/schema.ts
@@ -10,27 +10,27 @@
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
12
  CJS Build start
13
- ESM dist/index.js 13.47 KB
13
+ ESM dist/index.js 13.97 KB
14
14
  ESM dist/schema.js 111.00 B
15
- ESM dist/chunk-YQG6SUP3.js 5.67 KB
16
- ESM dist/translations-AV47AVPV.js 19.41 KB
17
- ESM dist/index.js.map 34.03 KB
15
+ ESM dist/chunk-RBCYKJVL.js 5.61 KB
16
+ ESM dist/translations-EPJYANXJ.js 19.34 KB
17
+ ESM dist/index.js.map 35.28 KB
18
18
  ESM dist/schema.js.map 71.00 B
19
- ESM dist/chunk-YQG6SUP3.js.map 10.28 KB
20
- ESM dist/translations-AV47AVPV.js.map 30.54 KB
21
- ESM ⚡️ Build success in 987ms
22
- CJS dist/index.cjs 17.15 KB
19
+ ESM dist/chunk-RBCYKJVL.js.map 10.21 KB
20
+ ESM dist/translations-EPJYANXJ.js.map 30.50 KB
21
+ ESM ⚡️ Build success in 741ms
22
+ CJS dist/index.cjs 17.76 KB
23
23
  CJS dist/schema.cjs 220.00 B
24
- CJS dist/chunk-I63ISOGO.cjs 5.81 KB
25
- CJS dist/translations-OAKKANSP.cjs 19.50 KB
26
- CJS dist/index.cjs.map 31.50 KB
24
+ CJS dist/chunk-PTMJ5BLL.cjs 5.76 KB
25
+ CJS dist/translations-L2JAQDJB.cjs 19.43 KB
26
+ CJS dist/index.cjs.map 32.52 KB
27
27
  CJS dist/schema.cjs.map 278.00 B
28
- CJS dist/chunk-I63ISOGO.cjs.map 12.15 KB
29
- CJS dist/translations-OAKKANSP.cjs.map 34.65 KB
30
- CJS ⚡️ Build success in 1012ms
28
+ CJS dist/chunk-PTMJ5BLL.cjs.map 12.08 KB
29
+ CJS dist/translations-L2JAQDJB.cjs.map 34.61 KB
30
+ CJS ⚡️ Build success in 752ms
31
31
  DTS Build start
32
- DTS ⚡️ Build success in 18921ms
33
- DTS dist/index.d.ts 6.97 KB
34
- DTS dist/schema.d.ts 138.01 KB
35
- DTS dist/index.d.cts 6.97 KB
36
- DTS dist/schema.d.cts 138.01 KB
32
+ DTS ⚡️ Build success in 24563ms
33
+ DTS dist/index.d.ts 6.96 KB
34
+ DTS dist/schema.d.ts 107.18 KB
35
+ DTS dist/index.d.cts 6.96 KB
36
+ DTS dist/schema.d.cts 107.18 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,64 @@
1
1
  # @objectstack/plugin-webhooks
2
2
 
3
+ ## 16.0.0-rc.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 4b6fde8: Trim the dead `undelete` and `api` webhook triggers (#3196). `WebhookTriggerType` declared five triggers but only three ever fired:
8
+
9
+ - `undelete` had no event source — the engine has no soft-delete/restore capability (`delete` is a hard delete; no `deleted_at` convention, no restore operation, and `data.record.undeleted` is never emitted). The `undeleted` case in the auto-enqueuer's action mapper was dead code awaiting a producer that doesn't exist.
10
+ - `api` ("manually triggered") had no fire path — the only webhook HTTP surface re-queues already-failed deliveries; nothing originates a manual fire.
11
+
12
+ Both are removed from the enum (contract-first, matching #3184/#3195): authoring a webhook on a removed trigger now fails loudly at `os validate` / registration instead of registering a webhook that silently never fires. No shipped webhook metadata used either. The auto-enqueuer now also warns when a persisted `sys_webhook` row carries a trigger it can't map to an emitted record event (a drift-guard, so a dead trigger can't silently no-op again). Reintroduce `undelete` only alongside a real restore subsystem, and `api` only alongside a real manual-fire endpoint. Updated the `sys_webhook` trigger options, field help (all locales), docs, and reference; added rejection tests.
13
+
14
+ - Updated dependencies [f972574]
15
+ - Updated dependencies [22013aa]
16
+ - Updated dependencies [3ad3dd5]
17
+ - Updated dependencies [3a18b60]
18
+ - Updated dependencies [a8aa34c]
19
+ - Updated dependencies [e057f42]
20
+ - Updated dependencies [a3823b2]
21
+ - Updated dependencies [43a3efb]
22
+ - Updated dependencies [524696a]
23
+ - Updated dependencies [5e3301d]
24
+ - Updated dependencies [dd9f223]
25
+ - Updated dependencies [46e876c]
26
+ - Updated dependencies [5f05de2]
27
+ - Updated dependencies [021ba4c]
28
+ - Updated dependencies [158aa14]
29
+ - Updated dependencies [d2723e2]
30
+ - Updated dependencies [fefcd54]
31
+ - Updated dependencies [beaf2de]
32
+ - Updated dependencies [369eb6e]
33
+ - Updated dependencies [b659111]
34
+ - Updated dependencies [5754a23]
35
+ - Updated dependencies [6c270a6]
36
+ - Updated dependencies [290e2f0]
37
+ - Updated dependencies [668dd17]
38
+ - Updated dependencies [8abf133]
39
+ - Updated dependencies [e0859b1]
40
+ - Updated dependencies [04ecd4e]
41
+ - Updated dependencies [4d5a892]
42
+ - Updated dependencies [16cebeb]
43
+ - Updated dependencies [86d30af]
44
+ - Updated dependencies [8923843]
45
+ - Updated dependencies [a2795f6]
46
+ - Updated dependencies [f16b492]
47
+ - Updated dependencies [4b6fde8]
48
+ - Updated dependencies [2018df9]
49
+ - Updated dependencies [fc5a3a2]
50
+ - @objectstack/spec@16.0.0-rc.0
51
+ - @objectstack/service-messaging@16.0.0-rc.0
52
+ - @objectstack/core@16.0.0-rc.0
53
+
54
+ ## 15.1.1
55
+
56
+ ### Patch Changes
57
+
58
+ - @objectstack/spec@15.1.1
59
+ - @objectstack/core@15.1.1
60
+ - @objectstack/service-messaging@15.1.1
61
+
3
62
  ## 15.1.0
4
63
 
5
64
  ### Patch Changes
@@ -82,11 +82,11 @@ var SysWebhook = _data.ObjectSchema.create({
82
82
  // Object picker (same widget as sys_sharing_rule) instead of a free-text
83
83
  // machine name. Falls back to a text input when the widget is unavailable.
84
84
  widget: "object-ref",
85
- description: "Short object name whose events fire this webhook (blank = manual / API-triggered)",
85
+ description: "Short object name whose record events (create/update/delete) fire this webhook",
86
86
  group: "Definition"
87
87
  }),
88
88
  triggers: _data.Field.select(
89
- ["create", "update", "delete", "undelete", "api"],
89
+ ["create", "update", "delete"],
90
90
  {
91
91
  label: "Triggers",
92
92
  required: false,
@@ -94,7 +94,7 @@ var SysWebhook = _data.ObjectSchema.create({
94
94
  // an array; the auto-enqueuer parser also tolerates the legacy
95
95
  // comma-separated / JSON-string forms so existing rows keep working.
96
96
  multiple: true,
97
- description: "Record events that fire this webhook (empty = manual / API-triggered)",
97
+ description: "Record events that fire this webhook",
98
98
  group: "Definition"
99
99
  }
100
100
  ),
@@ -152,4 +152,4 @@ var SysWebhook = _data.ObjectSchema.create({
152
152
 
153
153
 
154
154
  exports.SysWebhook = SysWebhook;
155
- //# sourceMappingURL=chunk-I63ISOGO.cjs.map
155
+ //# sourceMappingURL=chunk-PTMJ5BLL.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/framework/framework/packages/plugins/plugin-webhooks/dist/chunk-PTMJ5BLL.cjs","../src/sys-webhook.object.ts"],"names":[],"mappings":"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","file":"/home/runner/work/framework/framework/packages/plugins/plugin-webhooks/dist/chunk-PTMJ5BLL.cjs","sourcesContent":[null,"// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * sys_webhook — Outbound HTTP integration configuration (runtime).\n *\n * Persists a single {@link Webhook} envelope per row so administrators\n * can author, enable/disable, and edit webhook subscriptions from the\n * Studio UI without code changes. The canonical Zod schema for the\n * `definition_json` envelope lives at `@objectstack/spec/automation/webhook`.\n *\n * One row per `name`. The automation runtime\n * (`@objectstack/service-automation`, built-in `http_request` node) loads\n * active rows on boot + on `sys_webhook:changed` events, registers\n * `afterInsert` / `afterUpdate` / `afterDelete` listeners for the\n * targeted object, and dispatches outbound HTTP calls when matching\n * record events fire.\n *\n * Ownership (ADR-0029 K2.a): this object is **owned by\n * `@objectstack/plugin-webhooks`** — the plugin that consumes these rows —\n * alongside its sibling `sys_webhook_delivery`. It used to live in the\n * `@objectstack/platform-objects` monolith and be imported here; the\n * definition now lives with its owner so the plugin ships both data and\n * behavior as one unit.\n *\n * Platform-wide on purpose: every project (standalone, single-tenant,\n * cloud) can integrate with external systems (Slack, Stripe, internal\n * services) the same way.\n *\n * @namespace sys\n */\nexport const SysWebhook = ObjectSchema.create({\n name: 'sys_webhook',\n label: 'Webhook',\n pluralLabel: 'Webhooks',\n icon: 'webhook',\n isSystem: true,\n managedBy: 'config',\n // Authoring a webhook from the UI requires a structured form for the\n // headers / auth / retry / payload blocks — the generic JSON textarea\n // is acceptable as a v1 until a dedicated builder lands. Re-enable\n // create/edit/delete so admins can at least toggle `active` and edit\n // simple URL/method fields without round-tripping through code.\n userActions: { create: true, edit: true, delete: true, import: false },\n description: 'Outbound HTTP webhook subscription. Authored via defineWebhook() in code or the Studio editor; executed by the HTTP connector plugin.',\n displayNameField: 'name',\n nameField: 'name', // [ADR-0079] canonical primary-title pointer (mirrors deprecated displayNameField)\n titleFormat: '{label}',\n highlightFields: ['name', 'object_name', 'url', 'active', 'updated_at'],\n\n listViews: {\n active: {\n type: 'grid',\n name: 'active',\n label: 'Active',\n data: { provider: 'object', object: 'sys_webhook' },\n columns: ['label', 'object_name', 'url', 'method', 'active', 'updated_at'],\n filter: [{ field: 'active', operator: 'equals', value: true }],\n sort: [{ field: 'label', order: 'asc' }],\n pagination: { pageSize: 50 },\n },\n inactive: {\n type: 'grid',\n name: 'inactive',\n label: 'Inactive',\n data: { provider: 'object', object: 'sys_webhook' },\n columns: ['label', 'object_name', 'url', 'method', 'active', 'updated_at'],\n filter: [{ field: 'active', operator: 'equals', value: false }],\n sort: [{ field: 'label', order: 'asc' }],\n pagination: { pageSize: 50 },\n },\n by_object: {\n type: 'grid',\n name: 'by_object',\n label: 'By Object',\n data: { provider: 'object', object: 'sys_webhook' },\n columns: ['object_name', 'label', 'url', 'active', 'updated_at'],\n sort: [{ field: 'object_name', order: 'asc' }, { field: 'label', order: 'asc' }],\n grouping: { fields: [{ field: 'object_name', order: 'asc', collapsed: false }] },\n pagination: { pageSize: 100 },\n },\n all_webhooks: {\n type: 'grid',\n name: 'all_webhooks',\n label: 'All',\n data: { provider: 'object', object: 'sys_webhook' },\n columns: ['label', 'object_name', 'url', 'method', 'active', 'updated_at'],\n sort: [{ field: 'label', order: 'asc' }],\n pagination: { pageSize: 50 },\n },\n },\n\n fields: {\n id: Field.text({ label: 'Webhook ID', required: true, readonly: true, group: 'System' }),\n\n name: Field.text({\n label: 'Name',\n required: true,\n maxLength: 100,\n description: 'Unique snake_case name — referenced in logs and audit',\n group: 'Definition',\n }),\n\n label: Field.text({\n label: 'Display Label',\n required: false,\n maxLength: 200,\n group: 'Definition',\n }),\n\n object_name: Field.text({\n label: 'Object',\n required: false,\n maxLength: 100,\n // Object picker (same widget as sys_sharing_rule) instead of a free-text\n // machine name. Falls back to a text input when the widget is unavailable.\n widget: 'object-ref',\n description: 'Short object name whose record events (create/update/delete) fire this webhook',\n group: 'Definition',\n }),\n\n triggers: Field.select(\n ['create', 'update', 'delete'],\n {\n label: 'Triggers',\n required: false,\n // Multi-select instead of a hand-typed comma-separated string. Stored as\n // an array; the auto-enqueuer parser also tolerates the legacy\n // comma-separated / JSON-string forms so existing rows keep working.\n multiple: true,\n description: 'Record events that fire this webhook',\n group: 'Definition',\n },\n ),\n\n url: Field.text({\n label: 'Target URL',\n required: true,\n maxLength: 2048,\n description: 'External endpoint that receives the POST',\n group: 'Definition',\n }),\n\n method: Field.select(\n ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],\n {\n label: 'HTTP Method',\n required: true,\n // Select instead of free text. Option values are lowercased by the\n // Field.select helper (get/post/…); the auto-enqueuer upper-cases the\n // resolved method before delivery, so existing 'POST' rows and the\n // lowercase option values both normalise correctly.\n defaultValue: 'post',\n description: 'HTTP method used for the callback request',\n group: 'Definition',\n },\n ),\n\n description: Field.textarea({ label: 'Description', required: false, group: 'Definition' }),\n\n active: Field.boolean({\n label: 'Active',\n required: true,\n defaultValue: true,\n description: 'Inactive webhooks are skipped by the dispatcher',\n group: 'Definition',\n }),\n\n definition_json: Field.textarea({\n label: 'Definition',\n required: true,\n description: 'Serialised Webhook JSON (see @objectstack/spec/automation/webhook) — full headers/auth/retry/payload config',\n group: 'Definition',\n }),\n\n created_at: Field.datetime({\n label: 'Created At',\n required: true,\n defaultValue: 'NOW()',\n readonly: true,\n group: 'System',\n }),\n\n updated_at: Field.datetime({ label: 'Updated At', required: false, group: 'System' }),\n },\n\n indexes: [\n { fields: ['name'], unique: true },\n { fields: ['object_name'] },\n { fields: ['active', 'object_name'] },\n ],\n});\n"]}
@@ -82,11 +82,11 @@ var SysWebhook = ObjectSchema.create({
82
82
  // Object picker (same widget as sys_sharing_rule) instead of a free-text
83
83
  // machine name. Falls back to a text input when the widget is unavailable.
84
84
  widget: "object-ref",
85
- description: "Short object name whose events fire this webhook (blank = manual / API-triggered)",
85
+ description: "Short object name whose record events (create/update/delete) fire this webhook",
86
86
  group: "Definition"
87
87
  }),
88
88
  triggers: Field.select(
89
- ["create", "update", "delete", "undelete", "api"],
89
+ ["create", "update", "delete"],
90
90
  {
91
91
  label: "Triggers",
92
92
  required: false,
@@ -94,7 +94,7 @@ var SysWebhook = ObjectSchema.create({
94
94
  // an array; the auto-enqueuer parser also tolerates the legacy
95
95
  // comma-separated / JSON-string forms so existing rows keep working.
96
96
  multiple: true,
97
- description: "Record events that fire this webhook (empty = manual / API-triggered)",
97
+ description: "Record events that fire this webhook",
98
98
  group: "Definition"
99
99
  }
100
100
  ),
@@ -152,4 +152,4 @@ var SysWebhook = ObjectSchema.create({
152
152
  export {
153
153
  SysWebhook
154
154
  };
155
- //# sourceMappingURL=chunk-YQG6SUP3.js.map
155
+ //# sourceMappingURL=chunk-RBCYKJVL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sys-webhook.object.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectSchema, Field } from '@objectstack/spec/data';\n\n/**\n * sys_webhook — Outbound HTTP integration configuration (runtime).\n *\n * Persists a single {@link Webhook} envelope per row so administrators\n * can author, enable/disable, and edit webhook subscriptions from the\n * Studio UI without code changes. The canonical Zod schema for the\n * `definition_json` envelope lives at `@objectstack/spec/automation/webhook`.\n *\n * One row per `name`. The automation runtime\n * (`@objectstack/service-automation`, built-in `http_request` node) loads\n * active rows on boot + on `sys_webhook:changed` events, registers\n * `afterInsert` / `afterUpdate` / `afterDelete` listeners for the\n * targeted object, and dispatches outbound HTTP calls when matching\n * record events fire.\n *\n * Ownership (ADR-0029 K2.a): this object is **owned by\n * `@objectstack/plugin-webhooks`** — the plugin that consumes these rows —\n * alongside its sibling `sys_webhook_delivery`. It used to live in the\n * `@objectstack/platform-objects` monolith and be imported here; the\n * definition now lives with its owner so the plugin ships both data and\n * behavior as one unit.\n *\n * Platform-wide on purpose: every project (standalone, single-tenant,\n * cloud) can integrate with external systems (Slack, Stripe, internal\n * services) the same way.\n *\n * @namespace sys\n */\nexport const SysWebhook = ObjectSchema.create({\n name: 'sys_webhook',\n label: 'Webhook',\n pluralLabel: 'Webhooks',\n icon: 'webhook',\n isSystem: true,\n managedBy: 'config',\n // Authoring a webhook from the UI requires a structured form for the\n // headers / auth / retry / payload blocks — the generic JSON textarea\n // is acceptable as a v1 until a dedicated builder lands. Re-enable\n // create/edit/delete so admins can at least toggle `active` and edit\n // simple URL/method fields without round-tripping through code.\n userActions: { create: true, edit: true, delete: true, import: false },\n description: 'Outbound HTTP webhook subscription. Authored via defineWebhook() in code or the Studio editor; executed by the HTTP connector plugin.',\n displayNameField: 'name',\n nameField: 'name', // [ADR-0079] canonical primary-title pointer (mirrors deprecated displayNameField)\n titleFormat: '{label}',\n highlightFields: ['name', 'object_name', 'url', 'active', 'updated_at'],\n\n listViews: {\n active: {\n type: 'grid',\n name: 'active',\n label: 'Active',\n data: { provider: 'object', object: 'sys_webhook' },\n columns: ['label', 'object_name', 'url', 'method', 'active', 'updated_at'],\n filter: [{ field: 'active', operator: 'equals', value: true }],\n sort: [{ field: 'label', order: 'asc' }],\n pagination: { pageSize: 50 },\n },\n inactive: {\n type: 'grid',\n name: 'inactive',\n label: 'Inactive',\n data: { provider: 'object', object: 'sys_webhook' },\n columns: ['label', 'object_name', 'url', 'method', 'active', 'updated_at'],\n filter: [{ field: 'active', operator: 'equals', value: false }],\n sort: [{ field: 'label', order: 'asc' }],\n pagination: { pageSize: 50 },\n },\n by_object: {\n type: 'grid',\n name: 'by_object',\n label: 'By Object',\n data: { provider: 'object', object: 'sys_webhook' },\n columns: ['object_name', 'label', 'url', 'active', 'updated_at'],\n sort: [{ field: 'object_name', order: 'asc' }, { field: 'label', order: 'asc' }],\n grouping: { fields: [{ field: 'object_name', order: 'asc', collapsed: false }] },\n pagination: { pageSize: 100 },\n },\n all_webhooks: {\n type: 'grid',\n name: 'all_webhooks',\n label: 'All',\n data: { provider: 'object', object: 'sys_webhook' },\n columns: ['label', 'object_name', 'url', 'method', 'active', 'updated_at'],\n sort: [{ field: 'label', order: 'asc' }],\n pagination: { pageSize: 50 },\n },\n },\n\n fields: {\n id: Field.text({ label: 'Webhook ID', required: true, readonly: true, group: 'System' }),\n\n name: Field.text({\n label: 'Name',\n required: true,\n maxLength: 100,\n description: 'Unique snake_case name — referenced in logs and audit',\n group: 'Definition',\n }),\n\n label: Field.text({\n label: 'Display Label',\n required: false,\n maxLength: 200,\n group: 'Definition',\n }),\n\n object_name: Field.text({\n label: 'Object',\n required: false,\n maxLength: 100,\n // Object picker (same widget as sys_sharing_rule) instead of a free-text\n // machine name. Falls back to a text input when the widget is unavailable.\n widget: 'object-ref',\n description: 'Short object name whose record events (create/update/delete) fire this webhook',\n group: 'Definition',\n }),\n\n triggers: Field.select(\n ['create', 'update', 'delete'],\n {\n label: 'Triggers',\n required: false,\n // Multi-select instead of a hand-typed comma-separated string. Stored as\n // an array; the auto-enqueuer parser also tolerates the legacy\n // comma-separated / JSON-string forms so existing rows keep working.\n multiple: true,\n description: 'Record events that fire this webhook',\n group: 'Definition',\n },\n ),\n\n url: Field.text({\n label: 'Target URL',\n required: true,\n maxLength: 2048,\n description: 'External endpoint that receives the POST',\n group: 'Definition',\n }),\n\n method: Field.select(\n ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],\n {\n label: 'HTTP Method',\n required: true,\n // Select instead of free text. Option values are lowercased by the\n // Field.select helper (get/post/…); the auto-enqueuer upper-cases the\n // resolved method before delivery, so existing 'POST' rows and the\n // lowercase option values both normalise correctly.\n defaultValue: 'post',\n description: 'HTTP method used for the callback request',\n group: 'Definition',\n },\n ),\n\n description: Field.textarea({ label: 'Description', required: false, group: 'Definition' }),\n\n active: Field.boolean({\n label: 'Active',\n required: true,\n defaultValue: true,\n description: 'Inactive webhooks are skipped by the dispatcher',\n group: 'Definition',\n }),\n\n definition_json: Field.textarea({\n label: 'Definition',\n required: true,\n description: 'Serialised Webhook JSON (see @objectstack/spec/automation/webhook) — full headers/auth/retry/payload config',\n group: 'Definition',\n }),\n\n created_at: Field.datetime({\n label: 'Created At',\n required: true,\n defaultValue: 'NOW()',\n readonly: true,\n group: 'System',\n }),\n\n updated_at: Field.datetime({ label: 'Updated At', required: false, group: 'System' }),\n },\n\n indexes: [\n { fields: ['name'], unique: true },\n { fields: ['object_name'] },\n { fields: ['active', 'object_name'] },\n ],\n});\n"],"mappings":"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","names":[]}
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
- var _chunkI63ISOGOcjs = require('./chunk-I63ISOGO.cjs');
3
+ var _chunkPTMJ5BLLcjs = require('./chunk-PTMJ5BLL.cjs');
4
4
 
5
5
  // src/auto-enqueuer.ts
6
6
  var AutoEnqueuer = class {
@@ -108,8 +108,16 @@ var AutoEnqueuer = class {
108
108
  triggerList = s.split(",");
109
109
  }
110
110
  }
111
+ const normalized = triggerList.map((t) => t.trim().toLowerCase()).filter(Boolean);
112
+ const unknown = normalized.filter((t) => !DISPATCHABLE_WEBHOOK_TRIGGERS.has(t));
113
+ if (unknown.length > 0) {
114
+ _optionalChain([this, 'access', _15 => _15.logger, 'access', _16 => _16.warn, 'optionalCall', _17 => _17(
115
+ `[webhook-auto-enqueuer] webhook '${_nullishCoalesce(row.name, () => ( row.id))}' declares trigger(s) the engine never emits: ${unknown.join(", ")} \u2014 ignored. Dispatchable triggers: create, update, delete.`,
116
+ { id: row.id, unknown }
117
+ )]);
118
+ }
111
119
  const triggers = new Set(
112
- triggerList.map((t) => t.trim().toLowerCase()).filter(Boolean)
120
+ normalized.filter((t) => DISPATCHABLE_WEBHOOK_TRIGGERS.has(t))
113
121
  );
114
122
  if (triggers.size === 0) {
115
123
  return null;
@@ -146,7 +154,7 @@ var AutoEnqueuer = class {
146
154
  * webhook persistence.
147
155
  */
148
156
  handleEvent(event) {
149
- if (!_optionalChain([event, 'access', _15 => _15.type, 'optionalAccess', _16 => _16.startsWith, 'call', _17 => _17("data.record.")])) return;
157
+ if (!_optionalChain([event, 'access', _18 => _18.type, 'optionalAccess', _19 => _19.startsWith, 'call', _20 => _20("data.record.")])) return;
150
158
  if (!event.object) return;
151
159
  if (event.object === this.subscriptionsObject) return;
152
160
  const action = event.type.slice("data.record.".length);
@@ -158,7 +166,7 @@ var AutoEnqueuer = class {
158
166
  ];
159
167
  if (subs.length === 0) return;
160
168
  const payload = _nullishCoalesce(event.payload, () => ( {}));
161
- const recordId = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(payload.recordId, () => ( payload.id)), () => ( _optionalChain([payload, 'access', _18 => _18.after, 'optionalAccess', _19 => _19.id]))), () => ( _optionalChain([payload, 'access', _20 => _20.before, 'optionalAccess', _21 => _21.id]))), () => ( "unknown"));
169
+ const recordId = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(payload.recordId, () => ( payload.id)), () => ( _optionalChain([payload, 'access', _21 => _21.after, 'optionalAccess', _22 => _22.id]))), () => ( _optionalChain([payload, 'access', _23 => _23.before, 'optionalAccess', _24 => _24.id]))), () => ( "unknown"));
162
170
  const eventId = `${event.object}:${recordId}:${action}:${event.timestamp}`;
163
171
  for (const sub of subs) {
164
172
  if (!sub.triggers.has(trigger)) continue;
@@ -180,19 +188,19 @@ var AutoEnqueuer = class {
180
188
  ...payload
181
189
  }
182
190
  }).catch(
183
- (err) => _optionalChain([this, 'access', _22 => _22.logger, 'access', _23 => _23.warn, 'optionalCall', _24 => _24("[webhook-auto-enqueuer] enqueue failed", {
191
+ (err) => _optionalChain([this, 'access', _25 => _25.logger, 'access', _26 => _26.warn, 'optionalCall', _27 => _27("[webhook-auto-enqueuer] enqueue failed", {
184
192
  webhook: sub.name,
185
193
  eventId,
186
- err: _nullishCoalesce(_optionalChain([err, 'optionalAccess', _25 => _25.message]), () => ( err))
194
+ err: _nullishCoalesce(_optionalChain([err, 'optionalAccess', _28 => _28.message]), () => ( err))
187
195
  })])
188
196
  );
189
197
  }
190
198
  }
191
199
  handleSelfHealEvent(event) {
192
200
  if (event.object !== this.subscriptionsObject) return;
193
- if (!_optionalChain([event, 'access', _26 => _26.type, 'optionalAccess', _27 => _27.startsWith, 'call', _28 => _28("data.record.")])) return;
201
+ if (!_optionalChain([event, 'access', _29 => _29.type, 'optionalAccess', _30 => _30.startsWith, 'call', _31 => _31("data.record.")])) return;
194
202
  this.refresh().catch(
195
- (err) => _optionalChain([this, 'access', _29 => _29.logger, 'access', _30 => _30.warn, 'optionalCall', _31 => _31("[webhook-auto-enqueuer] self-heal refresh failed", err)])
203
+ (err) => _optionalChain([this, 'access', _32 => _32.logger, 'access', _33 => _33.warn, 'optionalCall', _34 => _34("[webhook-auto-enqueuer] self-heal refresh failed", err)])
196
204
  );
197
205
  }
198
206
  /** Test / admin accessor. */
@@ -208,12 +216,11 @@ function mapActionToTrigger(action) {
208
216
  return "update";
209
217
  case "deleted":
210
218
  return "delete";
211
- case "undeleted":
212
- return "undelete";
213
219
  default:
214
220
  return null;
215
221
  }
216
222
  }
223
+ var DISPATCHABLE_WEBHOOK_TRIGGERS = /* @__PURE__ */ new Set(["create", "update", "delete"]);
217
224
 
218
225
  // src/webhook-outbox-plugin.ts
219
226
  var WebhookOutboxPlugin = class {
@@ -235,7 +242,7 @@ var WebhookOutboxPlugin = class {
235
242
  scope: "system",
236
243
  name: "Webhook Schemas",
237
244
  description: "Registers sys_webhook (configuration). Deliveries use messaging's sys_http_delivery outbox.",
238
- objects: [_chunkI63ISOGOcjs.SysWebhook],
245
+ objects: [_chunkPTMJ5BLLcjs.SysWebhook],
239
246
  navigationContributions: [
240
247
  {
241
248
  app: "setup",
@@ -249,7 +256,7 @@ var WebhookOutboxPlugin = class {
249
256
  ]
250
257
  });
251
258
  } else {
252
- _optionalChain([ctx, 'access', _32 => _32.logger, 'access', _33 => _33.warn, 'optionalCall', _34 => _34(
259
+ _optionalChain([ctx, 'access', _35 => _35.logger, 'access', _36 => _36.warn, 'optionalCall', _37 => _37(
253
260
  "[webhook-outbox] manifest service unavailable \u2014 sys_webhook will NOT appear in REST or Studio nav. Register MetadataService before WebhookOutboxPlugin."
254
261
  )]);
255
262
  }
@@ -258,7 +265,7 @@ var WebhookOutboxPlugin = class {
258
265
  try {
259
266
  const i18n = ctx.getService("i18n");
260
267
  if (i18n && typeof i18n.loadTranslations === "function") {
261
- const { WebhooksTranslations } = await Promise.resolve().then(() => _interopRequireWildcard(require("./translations-OAKKANSP.cjs")));
268
+ const { WebhooksTranslations } = await Promise.resolve().then(() => _interopRequireWildcard(require("./translations-L2JAQDJB.cjs")));
262
269
  for (const [locale, data] of Object.entries(WebhooksTranslations)) {
263
270
  i18n.loadTranslations(locale, data);
264
271
  }
@@ -274,12 +281,12 @@ var WebhookOutboxPlugin = class {
274
281
  this.registerAdminRoutes(ctx);
275
282
  });
276
283
  }
277
- _optionalChain([ctx, 'access', _35 => _35.logger, 'access', _36 => _36.info, 'optionalCall', _37 => _37("[webhook-outbox] initialised (delivery via shared messaging HTTP outbox)", {
284
+ _optionalChain([ctx, 'access', _38 => _38.logger, 'access', _39 => _39.info, 'optionalCall', _40 => _40("[webhook-outbox] initialised (delivery via shared messaging HTTP outbox)", {
278
285
  autoEnqueue: autoEnqueueOpt !== false
279
286
  })]);
280
287
  }
281
288
  async dispose() {
282
- await _optionalChain([this, 'access', _38 => _38.autoEnqueuer, 'optionalAccess', _39 => _39.stop, 'call', _40 => _40()]);
289
+ await _optionalChain([this, 'access', _41 => _41.autoEnqueuer, 'optionalAccess', _42 => _42.stop, 'call', _43 => _43()]);
283
290
  }
284
291
  getMessaging(ctx) {
285
292
  const svc = this.tryGetService(ctx, ["messaging"]);
@@ -291,14 +298,14 @@ var WebhookOutboxPlugin = class {
291
298
  const realtime = this.tryGetService(ctx, ["realtime"]);
292
299
  const messaging = this.getMessaging(ctx);
293
300
  if (!engine || !realtime || !messaging) {
294
- _optionalChain([ctx, 'access', _41 => _41.logger, 'access', _42 => _42.warn, 'optionalCall', _43 => _43(
301
+ _optionalChain([ctx, 'access', _44 => _44.logger, 'access', _45 => _45.warn, 'optionalCall', _46 => _46(
295
302
  "[webhook-auto-enqueuer] disabled \u2014 ObjectQL, Realtime, or Messaging service not available",
296
303
  { hasEngine: !!engine, hasRealtime: !!realtime, hasMessaging: !!messaging }
297
304
  )]);
298
305
  return;
299
306
  }
300
307
  if (!messaging.isHttpDeliveryReady()) {
301
- _optionalChain([ctx, 'access', _44 => _44.logger, 'access', _45 => _45.warn, 'optionalCall', _46 => _46(
308
+ _optionalChain([ctx, 'access', _47 => _47.logger, 'access', _48 => _48.warn, 'optionalCall', _49 => _49(
302
309
  "[webhook-auto-enqueuer] messaging HTTP outbox not ready (no data engine / reliableDelivery off) \u2014 webhook deliveries will not be durable"
303
310
  )]);
304
311
  }
@@ -311,7 +318,7 @@ var WebhookOutboxPlugin = class {
311
318
  );
312
319
  await this.autoEnqueuer.start();
313
320
  ctx.registerService("webhook.autoEnqueuer", this.autoEnqueuer);
314
- _optionalChain([ctx, 'access', _47 => _47.logger, 'access', _48 => _48.info, 'optionalCall', _49 => _49("[webhook-auto-enqueuer] started (enqueues source=webhook onto sys_http_delivery)")]);
321
+ _optionalChain([ctx, 'access', _50 => _50.logger, 'access', _51 => _51.info, 'optionalCall', _52 => _52("[webhook-auto-enqueuer] started (enqueues source=webhook onto sys_http_delivery)")]);
315
322
  }
316
323
  tryGetService(ctx, names) {
317
324
  for (const n of names) {
@@ -331,7 +338,7 @@ var WebhookOutboxPlugin = class {
331
338
  registerAdminRoutes(ctx) {
332
339
  const http = this.tryGetService(ctx, ["http-server"]);
333
340
  if (!http || typeof http.getRawApp !== "function") {
334
- _optionalChain([ctx, 'access', _50 => _50.logger, 'access', _51 => _51.debug, 'optionalCall', _52 => _52("[webhook-outbox] HTTP server not available; redeliver endpoint not mounted")]);
341
+ _optionalChain([ctx, 'access', _53 => _53.logger, 'access', _54 => _54.debug, 'optionalCall', _55 => _55("[webhook-outbox] HTTP server not available; redeliver endpoint not mounted")]);
335
342
  return;
336
343
  }
337
344
  const rawApp = http.getRawApp();
@@ -351,7 +358,7 @@ var WebhookOutboxPlugin = class {
351
358
  } catch (e5) {
352
359
  return c.json({ success: false, error: "invalid_body", message: "Request body must be JSON." }, 400);
353
360
  }
354
- const deliveryId = typeof _optionalChain([body, 'optionalAccess', _53 => _53.deliveryId]) === "string" ? body.deliveryId.trim() : "";
361
+ const deliveryId = typeof _optionalChain([body, 'optionalAccess', _56 => _56.deliveryId]) === "string" ? body.deliveryId.trim() : "";
355
362
  if (!deliveryId) {
356
363
  return c.json(
357
364
  { success: false, error: "missing_delivery_id", message: "Body must include `deliveryId: string`." },
@@ -360,24 +367,24 @@ var WebhookOutboxPlugin = class {
360
367
  }
361
368
  try {
362
369
  const row = await messaging.redeliverHttp(deliveryId);
363
- _optionalChain([ctx, 'access', _54 => _54.logger, 'access', _55 => _55.info, 'optionalCall', _56 => _56("[webhook-outbox] redelivered", { deliveryId, requestedBy: userId })]);
370
+ _optionalChain([ctx, 'access', _57 => _57.logger, 'access', _58 => _58.info, 'optionalCall', _59 => _59("[webhook-outbox] redelivered", { deliveryId, requestedBy: userId })]);
364
371
  return c.json({ success: true, data: { id: row.id, status: row.status } });
365
372
  } catch (err) {
366
- const code = _optionalChain([err, 'optionalAccess', _57 => _57.code]);
373
+ const code = _optionalChain([err, 'optionalAccess', _60 => _60.code]);
367
374
  if (code === "not_found") {
368
375
  return c.json({ success: false, error: "not_found", message: err.message }, 404);
369
376
  }
370
377
  if (code === "not_eligible") {
371
378
  return c.json({ success: false, error: "not_eligible", message: err.message }, 409);
372
379
  }
373
- _optionalChain([ctx, 'access', _58 => _58.logger, 'access', _59 => _59.error, 'optionalCall', _60 => _60("[webhook-outbox] redeliver failed", err)]);
380
+ _optionalChain([ctx, 'access', _61 => _61.logger, 'access', _62 => _62.error, 'optionalCall', _63 => _63("[webhook-outbox] redeliver failed", err)]);
374
381
  return c.json(
375
- { success: false, error: "internal_error", message: _nullishCoalesce(_optionalChain([err, 'optionalAccess', _61 => _61.message]), () => ( String(err))) },
382
+ { success: false, error: "internal_error", message: _nullishCoalesce(_optionalChain([err, 'optionalAccess', _64 => _64.message]), () => ( String(err))) },
376
383
  500
377
384
  );
378
385
  }
379
386
  });
380
- _optionalChain([ctx, 'access', _62 => _62.logger, 'access', _63 => _63.info, 'optionalCall', _64 => _64("[webhook-outbox] redeliver endpoint mounted at POST /api/v1/webhooks/redeliver")]);
387
+ _optionalChain([ctx, 'access', _65 => _65.logger, 'access', _66 => _66.info, 'optionalCall', _67 => _67("[webhook-outbox] redeliver endpoint mounted at POST /api/v1/webhooks/redeliver")]);
381
388
  }
382
389
  async resolveSessionUserId(ctx, c) {
383
390
  try {
@@ -387,9 +394,9 @@ var WebhookOutboxPlugin = class {
387
394
  if (!api && typeof authService.getApi === "function") {
388
395
  api = await authService.getApi();
389
396
  }
390
- if (!_optionalChain([api, 'optionalAccess', _65 => _65.getSession])) return void 0;
397
+ if (!_optionalChain([api, 'optionalAccess', _68 => _68.getSession])) return void 0;
391
398
  const session = await api.getSession({ headers: c.req.raw.headers });
392
- const uid = _optionalChain([session, 'optionalAccess', _66 => _66.user, 'optionalAccess', _67 => _67.id]);
399
+ const uid = _optionalChain([session, 'optionalAccess', _69 => _69.user, 'optionalAccess', _70 => _70.id]);
393
400
  return typeof uid === "string" && uid.length > 0 ? uid : void 0;
394
401
  } catch (e6) {
395
402
  return void 0;
@@ -400,5 +407,5 @@ var WebhookOutboxPlugin = class {
400
407
 
401
408
 
402
409
 
403
- exports.AutoEnqueuer = AutoEnqueuer; exports.SysWebhook = _chunkI63ISOGOcjs.SysWebhook; exports.WebhookOutboxPlugin = WebhookOutboxPlugin;
410
+ exports.AutoEnqueuer = AutoEnqueuer; exports.SysWebhook = _chunkPTMJ5BLLcjs.SysWebhook; exports.WebhookOutboxPlugin = WebhookOutboxPlugin;
404
411
  //# sourceMappingURL=index.cjs.map