@objectstack/plugin-webhooks 7.5.0 → 7.7.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.
Files changed (52) hide show
  1. package/.turbo/turbo-build.log +20 -32
  2. package/CHANGELOG.md +60 -0
  3. package/dist/chunk-HWFTXTTI.js +138 -0
  4. package/dist/chunk-HWFTXTTI.js.map +1 -0
  5. package/dist/chunk-KPKLAXNA.cjs +138 -0
  6. package/dist/chunk-KPKLAXNA.cjs.map +1 -0
  7. package/dist/index.cjs +62 -616
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +41 -325
  10. package/dist/index.d.ts +41 -325
  11. package/dist/index.js +52 -606
  12. package/dist/index.js.map +1 -1
  13. package/dist/schema.cjs +2 -6
  14. package/dist/schema.cjs.map +1 -1
  15. package/dist/schema.d.cts +5 -4764
  16. package/dist/schema.d.ts +5 -4764
  17. package/dist/schema.js +3 -7
  18. package/package.json +4 -11
  19. package/src/auto-enqueuer.test.ts +83 -116
  20. package/src/auto-enqueuer.ts +38 -27
  21. package/src/index.ts +13 -40
  22. package/src/schema.ts +11 -16
  23. package/src/webhook-outbox-plugin.ts +80 -296
  24. package/tsup.config.ts +1 -1
  25. package/dist/chunk-7HS5DLU2.js +0 -319
  26. package/dist/chunk-7HS5DLU2.js.map +0 -1
  27. package/dist/chunk-HF7CCDPB.cjs +0 -256
  28. package/dist/chunk-HF7CCDPB.cjs.map +0 -1
  29. package/dist/chunk-KNGLLSSP.js +0 -256
  30. package/dist/chunk-KNGLLSSP.js.map +0 -1
  31. package/dist/chunk-TDSI7UHY.cjs +0 -319
  32. package/dist/chunk-TDSI7UHY.cjs.map +0 -1
  33. package/dist/outbox-CIn7LSyB.d.cts +0 -155
  34. package/dist/outbox-CIn7LSyB.d.ts +0 -155
  35. package/dist/sql-outbox.cjs +0 -8
  36. package/dist/sql-outbox.cjs.map +0 -1
  37. package/dist/sql-outbox.d.cts +0 -55
  38. package/dist/sql-outbox.d.ts +0 -55
  39. package/dist/sql-outbox.js +0 -8
  40. package/dist/sql-outbox.js.map +0 -1
  41. package/src/dispatcher.test.ts +0 -324
  42. package/src/dispatcher.ts +0 -218
  43. package/src/http-sender.ts +0 -187
  44. package/src/memory-outbox.test.ts +0 -86
  45. package/src/memory-outbox.ts +0 -155
  46. package/src/outbox.ts +0 -175
  47. package/src/partition.ts +0 -19
  48. package/src/retention.test.ts +0 -116
  49. package/src/retention.ts +0 -144
  50. package/src/sql-outbox.test.ts +0 -490
  51. package/src/sql-outbox.ts +0 -343
  52. package/src/sys-webhook-delivery.object.ts +0 -224
@@ -1,8 +1,8 @@
1
1
 
2
- > @objectstack/plugin-webhooks@7.5.0 build /home/runner/work/framework/framework/packages/plugins/plugin-webhooks
2
+ > @objectstack/plugin-webhooks@7.7.0 build /home/runner/work/framework/framework/packages/plugins/plugin-webhooks
3
3
  > tsup
4
4
 
5
- CLI Building entry: src/index.ts, src/schema.ts, src/sql-outbox.ts
5
+ CLI Building entry: src/index.ts, src/schema.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v8.5.1
8
8
  CLI Using tsup config: /home/runner/work/framework/framework/packages/plugins/plugin-webhooks/tsup.config.ts
@@ -10,39 +10,27 @@
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
12
  CJS Build start
13
- ESM dist/index.js 29.28 KB
14
- ESM dist/schema.js 203.00 B
15
- ESM dist/sql-outbox.js 157.00 B
16
- ESM dist/chunk-KNGLLSSP.js 6.92 KB
17
- ESM dist/chunk-7HS5DLU2.js 11.84 KB
13
+ ESM dist/index.js 12.73 KB
14
+ ESM dist/schema.js 111.00 B
15
+ ESM dist/chunk-HWFTXTTI.js 4.71 KB
18
16
  ESM dist/translations-AV47AVPV.js 19.41 KB
19
- ESM dist/index.js.map 75.63 KB
17
+ ESM dist/index.js.map 32.44 KB
20
18
  ESM dist/schema.js.map 71.00 B
21
- ESM dist/sql-outbox.js.map 71.00 B
22
- ESM dist/chunk-KNGLLSSP.js.map 24.11 KB
23
- ESM dist/chunk-7HS5DLU2.js.map 23.16 KB
19
+ ESM dist/chunk-HWFTXTTI.js.map 9.15 KB
24
20
  ESM dist/translations-AV47AVPV.js.map 30.54 KB
25
- ESM ⚡️ Build success in 1209ms
26
- CJS dist/index.cjs 35.43 KB
27
- CJS dist/schema.cjs 362.00 B
28
- CJS dist/sql-outbox.cjs 269.00 B
29
- CJS dist/chunk-HF7CCDPB.cjs 8.30 KB
30
- CJS dist/chunk-TDSI7UHY.cjs 12.07 KB
21
+ ESM ⚡️ Build success in 1199ms
22
+ CJS dist/index.cjs 16.40 KB
23
+ CJS dist/schema.cjs 220.00 B
24
+ CJS dist/chunk-KPKLAXNA.cjs 4.86 KB
31
25
  CJS dist/translations-OAKKANSP.cjs 19.50 KB
32
- CJS dist/schema.cjs.map 298.00 B
33
- CJS dist/sql-outbox.cjs.map 299.00 B
34
- CJS dist/index.cjs.map 68.17 KB
35
- CJS dist/chunk-HF7CCDPB.cjs.map 27.71 KB
36
- CJS dist/chunk-TDSI7UHY.cjs.map 27.46 KB
26
+ CJS dist/index.cjs.map 30.14 KB
27
+ CJS dist/schema.cjs.map 278.00 B
28
+ CJS dist/chunk-KPKLAXNA.cjs.map 10.96 KB
37
29
  CJS dist/translations-OAKKANSP.cjs.map 34.65 KB
38
- CJS ⚡️ Build success in 1240ms
30
+ CJS ⚡️ Build success in 1224ms
39
31
  DTS Build start
40
- DTS ⚡️ Build success in 24544ms
41
- DTS dist/index.d.ts 17.49 KB
42
- DTS dist/schema.d.ts 339.13 KB
43
- DTS dist/sql-outbox.d.ts 2.44 KB
44
- DTS dist/outbox-CIn7LSyB.d.ts 5.82 KB
45
- DTS dist/index.d.cts 17.49 KB
46
- DTS dist/schema.d.cts 339.13 KB
47
- DTS dist/sql-outbox.d.cts 2.45 KB
48
- DTS dist/outbox-CIn7LSyB.d.cts 5.82 KB
32
+ DTS ⚡️ Build success in 22646ms
33
+ DTS dist/index.d.ts 6.97 KB
34
+ DTS dist/schema.d.ts 127.81 KB
35
+ DTS dist/index.d.cts 6.97 KB
36
+ DTS dist/schema.d.cts 127.81 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,65 @@
1
1
  # @objectstack/plugin-webhooks
2
2
 
3
+ ## 7.7.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [b391955]
8
+ - Updated dependencies [f06b64e]
9
+ - Updated dependencies [023bf93]
10
+ - @objectstack/spec@7.7.0
11
+ - @objectstack/core@7.7.0
12
+ - @objectstack/service-messaging@7.7.0
13
+
14
+ ## 7.6.0
15
+
16
+ ### Minor Changes
17
+
18
+ - 11905fa: ADR-0018 M3 (Phase 5): `plugin-webhooks` now delivers through the shared
19
+ `service-messaging` HTTP outbox instead of its own.
20
+
21
+ The webhook delivery substrate — durable outbox, cluster-coordinated dispatcher,
22
+ retry/backoff/dead-letter, retention — is removed from `plugin-webhooks` and
23
+ replaced by the generic `sys_http_delivery` outbox + `HttpDispatcher` in
24
+ `@objectstack/service-messaging`. Webhooks keep only their domain concerns: the
25
+ `sys_webhook` config object, the `AutoEnqueuer` (now enqueues `source: 'webhook'`
26
+ rows via `messaging.enqueueHttp`), and the redeliver admin endpoint (now backed
27
+ by `messaging.redeliverHttp`).
28
+
29
+ **`@objectstack/service-messaging`:** `MessagingService` gains `redeliverHttp(id)`
30
+ and `listHttp(filter)` over the HTTP outbox.
31
+
32
+ **`@objectstack/plugin-webhooks` — BREAKING:**
33
+
34
+ - Now **requires** `MessagingServicePlugin` (declared as a plugin dependency).
35
+ - Removed exports: `WebhookDispatcher`, `MemoryWebhookOutbox`, `SqlWebhookOutbox`
36
+ (and the `./sql` subpath), `DeliveryRetentionSweeper`, `hashPartition`,
37
+ `sendOnce` / `classifyAttempt` / `nextRetryDelayMs`, and the `IWebhookOutbox` /
38
+ `WebhookDelivery` / `EnqueueInput` / `AckResult` / `RedeliverError` types.
39
+ - Removed the `sys_webhook_delivery` object — webhook deliveries are now rows in
40
+ `sys_http_delivery` (`source = 'webhook'`). The Setup nav points there.
41
+ - `AutoEnqueuer`'s constructor takes an `HttpEnqueueFn` instead of an
42
+ `IWebhookOutbox`.
43
+ - `WebhookOutboxPluginOptions` reduced to `{ autoEnqueue }` (dispatcher / outbox /
44
+ retention / nodeId options removed — those now live on `MessagingServicePlugin`).
45
+
46
+ ### Patch Changes
47
+
48
+ - Updated dependencies [955d4c8]
49
+ - Updated dependencies [11905fa]
50
+ - Updated dependencies [c4a4cbd]
51
+ - Updated dependencies [b046ec2]
52
+ - Updated dependencies [2170ad9]
53
+ - Updated dependencies [02d6359]
54
+ - Updated dependencies [7648242]
55
+ - Updated dependencies [8fa1e7f]
56
+ - Updated dependencies [55866f5]
57
+ - Updated dependencies [8e539cc]
58
+ - Updated dependencies [60f9c45]
59
+ - @objectstack/service-messaging@7.6.0
60
+ - @objectstack/spec@7.6.0
61
+ - @objectstack/core@7.6.0
62
+
3
63
  ## 7.5.0
4
64
 
5
65
  ### Patch Changes
@@ -0,0 +1,138 @@
1
+ // src/sys-webhook.object.ts
2
+ import { ObjectSchema, Field } from "@objectstack/spec/data";
3
+ var SysWebhook = ObjectSchema.create({
4
+ name: "sys_webhook",
5
+ label: "Webhook",
6
+ pluralLabel: "Webhooks",
7
+ icon: "webhook",
8
+ isSystem: true,
9
+ managedBy: "config",
10
+ // Authoring a webhook from the UI requires a structured form for the
11
+ // headers / auth / retry / payload blocks — the generic JSON textarea
12
+ // is acceptable as a v1 until a dedicated builder lands. Re-enable
13
+ // create/edit/delete so admins can at least toggle `active` and edit
14
+ // simple URL/method fields without round-tripping through code.
15
+ userActions: { create: true, edit: true, delete: true, import: false },
16
+ description: "Outbound HTTP webhook subscription. Authored via defineWebhook() in code or the Studio editor; executed by the HTTP connector plugin.",
17
+ displayNameField: "name",
18
+ titleFormat: "{label}",
19
+ compactLayout: ["name", "object_name", "url", "active", "updated_at"],
20
+ listViews: {
21
+ active: {
22
+ type: "grid",
23
+ name: "active",
24
+ label: "Active",
25
+ data: { provider: "object", object: "sys_webhook" },
26
+ columns: ["label", "object_name", "url", "method", "active", "updated_at"],
27
+ filter: [{ field: "active", operator: "equals", value: true }],
28
+ sort: [{ field: "label", order: "asc" }],
29
+ pagination: { pageSize: 50 }
30
+ },
31
+ inactive: {
32
+ type: "grid",
33
+ name: "inactive",
34
+ label: "Inactive",
35
+ data: { provider: "object", object: "sys_webhook" },
36
+ columns: ["label", "object_name", "url", "method", "active", "updated_at"],
37
+ filter: [{ field: "active", operator: "equals", value: false }],
38
+ sort: [{ field: "label", order: "asc" }],
39
+ pagination: { pageSize: 50 }
40
+ },
41
+ by_object: {
42
+ type: "grid",
43
+ name: "by_object",
44
+ label: "By Object",
45
+ data: { provider: "object", object: "sys_webhook" },
46
+ columns: ["object_name", "label", "url", "active", "updated_at"],
47
+ sort: [{ field: "object_name", order: "asc" }, { field: "label", order: "asc" }],
48
+ grouping: { fields: [{ field: "object_name", order: "asc", collapsed: false }] },
49
+ pagination: { pageSize: 100 }
50
+ },
51
+ all_webhooks: {
52
+ type: "grid",
53
+ name: "all_webhooks",
54
+ label: "All",
55
+ data: { provider: "object", object: "sys_webhook" },
56
+ columns: ["label", "object_name", "url", "method", "active", "updated_at"],
57
+ sort: [{ field: "label", order: "asc" }],
58
+ pagination: { pageSize: 50 }
59
+ }
60
+ },
61
+ fields: {
62
+ id: Field.text({ label: "Webhook ID", required: true, readonly: true, group: "System" }),
63
+ name: Field.text({
64
+ label: "Name",
65
+ required: true,
66
+ maxLength: 100,
67
+ description: "Unique snake_case name \u2014 referenced in logs and audit",
68
+ group: "Definition"
69
+ }),
70
+ label: Field.text({
71
+ label: "Display Label",
72
+ required: false,
73
+ maxLength: 200,
74
+ group: "Definition"
75
+ }),
76
+ object_name: Field.text({
77
+ label: "Object",
78
+ required: false,
79
+ maxLength: 100,
80
+ description: "Short object name whose events fire this webhook (blank = manual / API-triggered)",
81
+ group: "Definition"
82
+ }),
83
+ triggers: Field.text({
84
+ label: "Triggers",
85
+ required: false,
86
+ maxLength: 200,
87
+ description: "Comma-separated event list: create,update,delete,undelete,api",
88
+ group: "Definition"
89
+ }),
90
+ url: Field.text({
91
+ label: "Target URL",
92
+ required: true,
93
+ maxLength: 2048,
94
+ description: "External endpoint that receives the POST",
95
+ group: "Definition"
96
+ }),
97
+ method: Field.text({
98
+ label: "HTTP Method",
99
+ required: true,
100
+ defaultValue: "POST",
101
+ maxLength: 10,
102
+ description: "GET / POST / PUT / PATCH / DELETE",
103
+ group: "Definition"
104
+ }),
105
+ description: Field.textarea({ label: "Description", required: false, group: "Definition" }),
106
+ active: Field.boolean({
107
+ label: "Active",
108
+ required: true,
109
+ defaultValue: true,
110
+ description: "Inactive webhooks are skipped by the dispatcher",
111
+ group: "Definition"
112
+ }),
113
+ definition_json: Field.textarea({
114
+ label: "Definition",
115
+ required: true,
116
+ description: "Serialised Webhook JSON (see @objectstack/spec/automation/webhook) \u2014 full headers/auth/retry/payload config",
117
+ group: "Definition"
118
+ }),
119
+ created_at: Field.datetime({
120
+ label: "Created At",
121
+ required: true,
122
+ defaultValue: "NOW()",
123
+ readonly: true,
124
+ group: "System"
125
+ }),
126
+ updated_at: Field.datetime({ label: "Updated At", required: false, group: "System" })
127
+ },
128
+ indexes: [
129
+ { fields: ["name"], unique: true },
130
+ { fields: ["object_name"] },
131
+ { fields: ["active", "object_name"] }
132
+ ]
133
+ });
134
+
135
+ export {
136
+ SysWebhook
137
+ };
138
+ //# sourceMappingURL=chunk-HWFTXTTI.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 titleFormat: '{label}',\n compactLayout: ['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 description: 'Short object name whose events fire this webhook (blank = manual / API-triggered)',\n group: 'Definition',\n }),\n\n triggers: Field.text({\n label: 'Triggers',\n required: false,\n maxLength: 200,\n description: 'Comma-separated event list: create,update,delete,undelete,api',\n group: 'Definition',\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.text({\n label: 'HTTP Method',\n required: true,\n defaultValue: 'POST',\n maxLength: 10,\n description: 'GET / POST / PUT / PATCH / DELETE',\n group: 'Definition',\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":[]}
@@ -0,0 +1,138 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/sys-webhook.object.ts
2
+ var _data = require('@objectstack/spec/data');
3
+ var SysWebhook = _data.ObjectSchema.create({
4
+ name: "sys_webhook",
5
+ label: "Webhook",
6
+ pluralLabel: "Webhooks",
7
+ icon: "webhook",
8
+ isSystem: true,
9
+ managedBy: "config",
10
+ // Authoring a webhook from the UI requires a structured form for the
11
+ // headers / auth / retry / payload blocks — the generic JSON textarea
12
+ // is acceptable as a v1 until a dedicated builder lands. Re-enable
13
+ // create/edit/delete so admins can at least toggle `active` and edit
14
+ // simple URL/method fields without round-tripping through code.
15
+ userActions: { create: true, edit: true, delete: true, import: false },
16
+ description: "Outbound HTTP webhook subscription. Authored via defineWebhook() in code or the Studio editor; executed by the HTTP connector plugin.",
17
+ displayNameField: "name",
18
+ titleFormat: "{label}",
19
+ compactLayout: ["name", "object_name", "url", "active", "updated_at"],
20
+ listViews: {
21
+ active: {
22
+ type: "grid",
23
+ name: "active",
24
+ label: "Active",
25
+ data: { provider: "object", object: "sys_webhook" },
26
+ columns: ["label", "object_name", "url", "method", "active", "updated_at"],
27
+ filter: [{ field: "active", operator: "equals", value: true }],
28
+ sort: [{ field: "label", order: "asc" }],
29
+ pagination: { pageSize: 50 }
30
+ },
31
+ inactive: {
32
+ type: "grid",
33
+ name: "inactive",
34
+ label: "Inactive",
35
+ data: { provider: "object", object: "sys_webhook" },
36
+ columns: ["label", "object_name", "url", "method", "active", "updated_at"],
37
+ filter: [{ field: "active", operator: "equals", value: false }],
38
+ sort: [{ field: "label", order: "asc" }],
39
+ pagination: { pageSize: 50 }
40
+ },
41
+ by_object: {
42
+ type: "grid",
43
+ name: "by_object",
44
+ label: "By Object",
45
+ data: { provider: "object", object: "sys_webhook" },
46
+ columns: ["object_name", "label", "url", "active", "updated_at"],
47
+ sort: [{ field: "object_name", order: "asc" }, { field: "label", order: "asc" }],
48
+ grouping: { fields: [{ field: "object_name", order: "asc", collapsed: false }] },
49
+ pagination: { pageSize: 100 }
50
+ },
51
+ all_webhooks: {
52
+ type: "grid",
53
+ name: "all_webhooks",
54
+ label: "All",
55
+ data: { provider: "object", object: "sys_webhook" },
56
+ columns: ["label", "object_name", "url", "method", "active", "updated_at"],
57
+ sort: [{ field: "label", order: "asc" }],
58
+ pagination: { pageSize: 50 }
59
+ }
60
+ },
61
+ fields: {
62
+ id: _data.Field.text({ label: "Webhook ID", required: true, readonly: true, group: "System" }),
63
+ name: _data.Field.text({
64
+ label: "Name",
65
+ required: true,
66
+ maxLength: 100,
67
+ description: "Unique snake_case name \u2014 referenced in logs and audit",
68
+ group: "Definition"
69
+ }),
70
+ label: _data.Field.text({
71
+ label: "Display Label",
72
+ required: false,
73
+ maxLength: 200,
74
+ group: "Definition"
75
+ }),
76
+ object_name: _data.Field.text({
77
+ label: "Object",
78
+ required: false,
79
+ maxLength: 100,
80
+ description: "Short object name whose events fire this webhook (blank = manual / API-triggered)",
81
+ group: "Definition"
82
+ }),
83
+ triggers: _data.Field.text({
84
+ label: "Triggers",
85
+ required: false,
86
+ maxLength: 200,
87
+ description: "Comma-separated event list: create,update,delete,undelete,api",
88
+ group: "Definition"
89
+ }),
90
+ url: _data.Field.text({
91
+ label: "Target URL",
92
+ required: true,
93
+ maxLength: 2048,
94
+ description: "External endpoint that receives the POST",
95
+ group: "Definition"
96
+ }),
97
+ method: _data.Field.text({
98
+ label: "HTTP Method",
99
+ required: true,
100
+ defaultValue: "POST",
101
+ maxLength: 10,
102
+ description: "GET / POST / PUT / PATCH / DELETE",
103
+ group: "Definition"
104
+ }),
105
+ description: _data.Field.textarea({ label: "Description", required: false, group: "Definition" }),
106
+ active: _data.Field.boolean({
107
+ label: "Active",
108
+ required: true,
109
+ defaultValue: true,
110
+ description: "Inactive webhooks are skipped by the dispatcher",
111
+ group: "Definition"
112
+ }),
113
+ definition_json: _data.Field.textarea({
114
+ label: "Definition",
115
+ required: true,
116
+ description: "Serialised Webhook JSON (see @objectstack/spec/automation/webhook) \u2014 full headers/auth/retry/payload config",
117
+ group: "Definition"
118
+ }),
119
+ created_at: _data.Field.datetime({
120
+ label: "Created At",
121
+ required: true,
122
+ defaultValue: "NOW()",
123
+ readonly: true,
124
+ group: "System"
125
+ }),
126
+ updated_at: _data.Field.datetime({ label: "Updated At", required: false, group: "System" })
127
+ },
128
+ indexes: [
129
+ { fields: ["name"], unique: true },
130
+ { fields: ["object_name"] },
131
+ { fields: ["active", "object_name"] }
132
+ ]
133
+ });
134
+
135
+
136
+
137
+ exports.SysWebhook = SysWebhook;
138
+ //# sourceMappingURL=chunk-KPKLAXNA.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/framework/framework/packages/plugins/plugin-webhooks/dist/chunk-KPKLAXNA.cjs","../src/sys-webhook.object.ts"],"names":[],"mappings":"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","file":"/home/runner/work/framework/framework/packages/plugins/plugin-webhooks/dist/chunk-KPKLAXNA.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 titleFormat: '{label}',\n compactLayout: ['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 description: 'Short object name whose events fire this webhook (blank = manual / API-triggered)',\n group: 'Definition',\n }),\n\n triggers: Field.text({\n label: 'Triggers',\n required: false,\n maxLength: 200,\n description: 'Comma-separated event list: create,update,delete,undelete,api',\n group: 'Definition',\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.text({\n label: 'HTTP Method',\n required: true,\n defaultValue: 'POST',\n maxLength: 10,\n description: 'GET / POST / PUT / PATCH / DELETE',\n group: 'Definition',\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"]}