@objectstack/plugin-webhooks 16.1.0 → 17.0.0-rc.1
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/CHANGELOG.md +626 -0
- package/dist/{chunk-RBCYKJVL.js → chunk-6EPMRZ7I.js} +28 -2
- package/dist/chunk-6EPMRZ7I.js.map +1 -0
- package/dist/{chunk-PTMJ5BLL.cjs → chunk-QUTQSOQC.cjs} +28 -2
- package/dist/chunk-QUTQSOQC.cjs.map +1 -0
- package/dist/index.cjs +250 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +231 -14
- package/dist/index.js.map +1 -1
- package/dist/schema.cjs +2 -2
- package/dist/schema.d.cts +515 -304
- package/dist/schema.d.ts +515 -304
- package/dist/schema.js +1 -1
- package/dist/translations-CBQRUIS5.cjs +383 -0
- package/dist/translations-CBQRUIS5.cjs.map +1 -0
- package/dist/translations-Y3CXWOTM.js +383 -0
- package/dist/translations-Y3CXWOTM.js.map +1 -0
- package/package.json +11 -5
- package/.turbo/turbo-build.log +0 -36
- package/dist/chunk-PTMJ5BLL.cjs.map +0 -1
- package/dist/chunk-RBCYKJVL.js.map +0 -1
- package/dist/translations-EPJYANXJ.js +0 -727
- package/dist/translations-EPJYANXJ.js.map +0 -1
- package/dist/translations-L2JAQDJB.cjs +0 -727
- package/dist/translations-L2JAQDJB.cjs.map +0 -1
- package/scripts/i18n-extract.config.ts +0 -32
- package/src/auto-enqueuer.test.ts +0 -431
- package/src/auto-enqueuer.ts +0 -383
- package/src/index.ts +0 -29
- package/src/schema.ts +0 -21
- package/src/sys-webhook.object.ts +0 -193
- package/src/translations/en.objects.generated.ts +0 -187
- package/src/translations/es-ES.objects.generated.ts +0 -187
- package/src/translations/index.ts +0 -23
- package/src/translations/ja-JP.objects.generated.ts +0 -187
- package/src/translations/zh-CN.objects.generated.ts +0 -187
- package/src/webhook-outbox-plugin.ts +0 -259
- package/tsconfig.json +0 -10
- package/tsup.config.ts +0 -14
|
@@ -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 * ## Two authoring doors, one row\n * Rows land here two ways, distinguished by the `managed_by` provenance column:\n * - **admin** — created/edited directly through this object's CRUD UI.\n * - **package** — declared in code (`defineStack({ webhooks })` /\n * `defineWebhook()`) and materialized on boot by\n * `bootstrapDeclaredWebhooks` (#3461). Re-seeded every boot, but an admin\n * edit stamps `customized: true` and freezes the row (seed-not-clobber,\n * mirrors `sys_sharing_rule` #2909).\n *\n * One row per `name`. This plugin's {@link AutoEnqueuer} loads active rows on\n * boot + on `sys_webhook:changed` events, and turns matching `data.record.*`\n * events into deliveries on the shared `service-messaging` HTTP outbox\n * (ADR-0018 M3 — `sys_http_delivery`, drained by the messaging dispatcher).\n *\n * Ownership (ADR-0029 K2.a): this object is **owned by\n * `@objectstack/plugin-webhooks`** — the plugin that consumes these rows. It\n * used to live in the `@objectstack/platform-objects` monolith and be imported\n * here; the definition now lives with its owner so the plugin ships both data\n * and 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. Declared in code via defineStack({ webhooks }) / defineWebhook() (materialized into rows on boot) or authored directly in the Studio editor; dispatched by the webhook auto-enqueuer onto the shared HTTP outbox.',\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 // ── Provenance (#3461 — record-authoritative seed-not-clobber) ──\n // Mirrors sys_sharing_rule (#2909). Both columns are `readonly`: the\n // engine strips them from non-system payloads (forge/clear-proof), while\n // bootstrapDeclaredWebhooks and the provenance stamp hook write with\n // isSystem. Deliberately NOT a write gate: webhooks are a first-class admin\n // authoring/tuning surface — admins may edit or deactivate a package row;\n // the seeder simply stops overwriting it once `customized` is stamped.\n managed_by: Field.select(\n ['platform', 'package', 'admin'],\n {\n label: 'Managed By',\n required: false,\n readonly: true,\n defaultValue: 'admin',\n description:\n 'Record provenance: platform = framework built-in / package = app/package-declared ' +\n '(boot-seeded from defineStack webhooks) / admin = created in Setup.',\n group: 'System',\n },\n ),\n\n customized: Field.boolean({\n label: 'Customized',\n required: false,\n readonly: true,\n defaultValue: false,\n description:\n 'Set when an admin edits a package-declared webhook; boot seeding will no longer ' +\n 'overwrite the row (a deactivated noisy webhook survives redeploys). Meaningless on admin rows.',\n group: 'System',\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":[]}
|
|
@@ -13,7 +13,7 @@ var SysWebhook = _data.ObjectSchema.create({
|
|
|
13
13
|
// create/edit/delete so admins can at least toggle `active` and edit
|
|
14
14
|
// simple URL/method fields without round-tripping through code.
|
|
15
15
|
userActions: { create: true, edit: true, delete: true, import: false },
|
|
16
|
-
description: "Outbound HTTP webhook subscription.
|
|
16
|
+
description: "Outbound HTTP webhook subscription. Declared in code via defineStack({ webhooks }) / defineWebhook() (materialized into rows on boot) or authored directly in the Studio editor; dispatched by the webhook auto-enqueuer onto the shared HTTP outbox.",
|
|
17
17
|
displayNameField: "name",
|
|
18
18
|
nameField: "name",
|
|
19
19
|
// [ADR-0079] canonical primary-title pointer (mirrors deprecated displayNameField)
|
|
@@ -133,6 +133,32 @@ var SysWebhook = _data.ObjectSchema.create({
|
|
|
133
133
|
description: "Serialised Webhook JSON (see @objectstack/spec/automation/webhook) \u2014 full headers/auth/retry/payload config",
|
|
134
134
|
group: "Definition"
|
|
135
135
|
}),
|
|
136
|
+
// ── Provenance (#3461 — record-authoritative seed-not-clobber) ──
|
|
137
|
+
// Mirrors sys_sharing_rule (#2909). Both columns are `readonly`: the
|
|
138
|
+
// engine strips them from non-system payloads (forge/clear-proof), while
|
|
139
|
+
// bootstrapDeclaredWebhooks and the provenance stamp hook write with
|
|
140
|
+
// isSystem. Deliberately NOT a write gate: webhooks are a first-class admin
|
|
141
|
+
// authoring/tuning surface — admins may edit or deactivate a package row;
|
|
142
|
+
// the seeder simply stops overwriting it once `customized` is stamped.
|
|
143
|
+
managed_by: _data.Field.select(
|
|
144
|
+
["platform", "package", "admin"],
|
|
145
|
+
{
|
|
146
|
+
label: "Managed By",
|
|
147
|
+
required: false,
|
|
148
|
+
readonly: true,
|
|
149
|
+
defaultValue: "admin",
|
|
150
|
+
description: "Record provenance: platform = framework built-in / package = app/package-declared (boot-seeded from defineStack webhooks) / admin = created in Setup.",
|
|
151
|
+
group: "System"
|
|
152
|
+
}
|
|
153
|
+
),
|
|
154
|
+
customized: _data.Field.boolean({
|
|
155
|
+
label: "Customized",
|
|
156
|
+
required: false,
|
|
157
|
+
readonly: true,
|
|
158
|
+
defaultValue: false,
|
|
159
|
+
description: "Set when an admin edits a package-declared webhook; boot seeding will no longer overwrite the row (a deactivated noisy webhook survives redeploys). Meaningless on admin rows.",
|
|
160
|
+
group: "System"
|
|
161
|
+
}),
|
|
136
162
|
created_at: _data.Field.datetime({
|
|
137
163
|
label: "Created At",
|
|
138
164
|
required: true,
|
|
@@ -152,4 +178,4 @@ var SysWebhook = _data.ObjectSchema.create({
|
|
|
152
178
|
|
|
153
179
|
|
|
154
180
|
exports.SysWebhook = SysWebhook;
|
|
155
|
-
//# sourceMappingURL=chunk-
|
|
181
|
+
//# sourceMappingURL=chunk-QUTQSOQC.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/objectstack/objectstack/packages/plugins/plugin-webhooks/dist/chunk-QUTQSOQC.cjs","../src/sys-webhook.object.ts"],"names":[],"mappings":"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","file":"/home/runner/work/objectstack/objectstack/packages/plugins/plugin-webhooks/dist/chunk-QUTQSOQC.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 * ## Two authoring doors, one row\n * Rows land here two ways, distinguished by the `managed_by` provenance column:\n * - **admin** — created/edited directly through this object's CRUD UI.\n * - **package** — declared in code (`defineStack({ webhooks })` /\n * `defineWebhook()`) and materialized on boot by\n * `bootstrapDeclaredWebhooks` (#3461). Re-seeded every boot, but an admin\n * edit stamps `customized: true` and freezes the row (seed-not-clobber,\n * mirrors `sys_sharing_rule` #2909).\n *\n * One row per `name`. This plugin's {@link AutoEnqueuer} loads active rows on\n * boot + on `sys_webhook:changed` events, and turns matching `data.record.*`\n * events into deliveries on the shared `service-messaging` HTTP outbox\n * (ADR-0018 M3 — `sys_http_delivery`, drained by the messaging dispatcher).\n *\n * Ownership (ADR-0029 K2.a): this object is **owned by\n * `@objectstack/plugin-webhooks`** — the plugin that consumes these rows. It\n * used to live in the `@objectstack/platform-objects` monolith and be imported\n * here; the definition now lives with its owner so the plugin ships both data\n * and 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. Declared in code via defineStack({ webhooks }) / defineWebhook() (materialized into rows on boot) or authored directly in the Studio editor; dispatched by the webhook auto-enqueuer onto the shared HTTP outbox.',\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 // ── Provenance (#3461 — record-authoritative seed-not-clobber) ──\n // Mirrors sys_sharing_rule (#2909). Both columns are `readonly`: the\n // engine strips them from non-system payloads (forge/clear-proof), while\n // bootstrapDeclaredWebhooks and the provenance stamp hook write with\n // isSystem. Deliberately NOT a write gate: webhooks are a first-class admin\n // authoring/tuning surface — admins may edit or deactivate a package row;\n // the seeder simply stops overwriting it once `customized` is stamped.\n managed_by: Field.select(\n ['platform', 'package', 'admin'],\n {\n label: 'Managed By',\n required: false,\n readonly: true,\n defaultValue: 'admin',\n description:\n 'Record provenance: platform = framework built-in / package = app/package-declared ' +\n '(boot-seeded from defineStack webhooks) / admin = created in Setup.',\n group: 'System',\n },\n ),\n\n customized: Field.boolean({\n label: 'Customized',\n required: false,\n readonly: true,\n defaultValue: false,\n description:\n 'Set when an admin edits a package-declared webhook; boot seeding will no longer ' +\n 'overwrite the row (a deactivated noisy webhook survives redeploys). Meaningless on admin rows.',\n group: 'System',\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"]}
|
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
|
|
3
|
+
var _chunkQUTQSOQCcjs = require('./chunk-QUTQSOQC.cjs');
|
|
4
4
|
|
|
5
5
|
// src/auto-enqueuer.ts
|
|
6
6
|
var AutoEnqueuer = class {
|
|
@@ -180,12 +180,21 @@ var AutoEnqueuer = class {
|
|
|
180
180
|
headers: sub.headers,
|
|
181
181
|
signingSecret: sub.secret,
|
|
182
182
|
timeoutMs: sub.timeoutMs,
|
|
183
|
+
// [#3946] Envelope keys are written LAST so the event payload
|
|
184
|
+
// cannot rewrite them. Behaviour-neutral for the engine's own
|
|
185
|
+
// publishers — `data.record.*` payloads are
|
|
186
|
+
// `{ recordId, after, changes }`, with record fields nested
|
|
187
|
+
// under `after`, so none of these four keys collide today. It
|
|
188
|
+
// is the shape that was wrong: a publisher that flattened
|
|
189
|
+
// record fields into the payload (the `payload.id` fallback
|
|
190
|
+
// above suggests some do) would have silently rewritten the
|
|
191
|
+
// `object` / `action` / `timestamp` a subscriber receives.
|
|
183
192
|
payload: {
|
|
193
|
+
...payload,
|
|
184
194
|
object: event.object,
|
|
185
195
|
recordId,
|
|
186
196
|
action,
|
|
187
|
-
timestamp: event.timestamp
|
|
188
|
-
...payload
|
|
197
|
+
timestamp: event.timestamp
|
|
189
198
|
}
|
|
190
199
|
}).catch(
|
|
191
200
|
(err) => _optionalChain([this, 'access', _25 => _25.logger, 'access', _26 => _26.warn, 'optionalCall', _27 => _27("[webhook-auto-enqueuer] enqueue failed", {
|
|
@@ -222,6 +231,163 @@ function mapActionToTrigger(action) {
|
|
|
222
231
|
}
|
|
223
232
|
var DISPATCHABLE_WEBHOOK_TRIGGERS = /* @__PURE__ */ new Set(["create", "update", "delete"]);
|
|
224
233
|
|
|
234
|
+
// src/bootstrap-declared-webhooks.ts
|
|
235
|
+
var _automation = require('@objectstack/spec/automation');
|
|
236
|
+
var SYSTEM_CTX = { isSystem: true, positions: [], permissions: [] };
|
|
237
|
+
function uid(prefix) {
|
|
238
|
+
const g = globalThis;
|
|
239
|
+
if (_optionalChain([g, 'access', _35 => _35.crypto, 'optionalAccess', _36 => _36.randomUUID])) return `${prefix}_${g.crypto.randomUUID()}`;
|
|
240
|
+
return `${prefix}_${Math.random().toString(36).slice(2, 10)}`;
|
|
241
|
+
}
|
|
242
|
+
function readDeclared(engine, metadataService, type) {
|
|
243
|
+
try {
|
|
244
|
+
const reg = _optionalChain([engine, 'optionalAccess', _37 => _37._registry]);
|
|
245
|
+
if (_optionalChain([reg, 'optionalAccess', _38 => _38.listItems])) {
|
|
246
|
+
const items = (_nullishCoalesce(reg.listItems(type), () => ( []))).map((i) => _nullishCoalesce(_optionalChain([i, 'optionalAccess', _39 => _39.content]), () => ( i))).filter(Boolean);
|
|
247
|
+
if (items.length > 0) return items;
|
|
248
|
+
}
|
|
249
|
+
} catch (e3) {
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
const listed = _optionalChain([metadataService, 'optionalAccess', _40 => _40.list, 'optionalCall', _41 => _41(type)]);
|
|
253
|
+
const arr = typeof _optionalChain([listed, 'optionalAccess', _42 => _42.then]) === "function" ? [] : _nullishCoalesce(listed, () => ( []));
|
|
254
|
+
return Array.isArray(arr) ? arr.map((i) => _nullishCoalesce(_optionalChain([i, 'optionalAccess', _43 => _43.content]), () => ( i))).filter(Boolean) : [];
|
|
255
|
+
} catch (e4) {
|
|
256
|
+
return [];
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async function bootstrapDeclaredWebhooks(engine, metadataService, logger, subscriptionsObject = "sys_webhook") {
|
|
260
|
+
const declared = readDeclared(engine, metadataService, "webhook");
|
|
261
|
+
if (declared.length === 0) return { seeded: 0, skipped: 0 };
|
|
262
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
263
|
+
let seeded = 0;
|
|
264
|
+
let skipped = 0;
|
|
265
|
+
for (const raw of declared) {
|
|
266
|
+
let wh;
|
|
267
|
+
try {
|
|
268
|
+
wh = _automation.WebhookSchema.parse(raw);
|
|
269
|
+
} catch (err) {
|
|
270
|
+
_optionalChain([logger, 'optionalAccess', _44 => _44.warn, 'optionalCall', _45 => _45("[webhook] declared webhook failed validation \u2014 skipped", {
|
|
271
|
+
name: _optionalChain([raw, 'optionalAccess', _46 => _46.name]),
|
|
272
|
+
error: _nullishCoalesce(_optionalChain([err, 'optionalAccess', _47 => _47.message]), () => ( String(err)))
|
|
273
|
+
})]);
|
|
274
|
+
skipped += 1;
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
try {
|
|
278
|
+
const existing = await engine.find(subscriptionsObject, {
|
|
279
|
+
where: { name: wh.name },
|
|
280
|
+
limit: 1,
|
|
281
|
+
context: SYSTEM_CTX
|
|
282
|
+
});
|
|
283
|
+
const row = Array.isArray(existing) ? existing[0] : void 0;
|
|
284
|
+
if (row) {
|
|
285
|
+
if (row.managed_by === "admin") {
|
|
286
|
+
_optionalChain([logger, 'optionalAccess', _48 => _48.warn, 'optionalCall', _49 => _49("[webhook] declared name collides with an admin-authored row \u2014 seed skipped", {
|
|
287
|
+
name: wh.name
|
|
288
|
+
})]);
|
|
289
|
+
skipped += 1;
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
if (row.customized === true) {
|
|
293
|
+
skipped += 1;
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
const patch = {
|
|
297
|
+
id: row.id,
|
|
298
|
+
...mapWebhookToRow(wh),
|
|
299
|
+
// Adopt pristine/legacy (pre-provenance) rows so future boots
|
|
300
|
+
// recognize them as package-managed.
|
|
301
|
+
managed_by: "package",
|
|
302
|
+
updated_at: now
|
|
303
|
+
};
|
|
304
|
+
await engine.update(subscriptionsObject, patch, { context: SYSTEM_CTX });
|
|
305
|
+
seeded += 1;
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const newRow = {
|
|
309
|
+
id: uid("whk"),
|
|
310
|
+
...mapWebhookToRow(wh),
|
|
311
|
+
managed_by: "package",
|
|
312
|
+
customized: false,
|
|
313
|
+
created_at: now,
|
|
314
|
+
updated_at: now
|
|
315
|
+
};
|
|
316
|
+
await engine.insert(subscriptionsObject, newRow, { context: SYSTEM_CTX });
|
|
317
|
+
seeded += 1;
|
|
318
|
+
} catch (err) {
|
|
319
|
+
_optionalChain([logger, 'optionalAccess', _50 => _50.warn, 'optionalCall', _51 => _51("[webhook] declared webhook seed failed", {
|
|
320
|
+
name: wh.name,
|
|
321
|
+
error: _nullishCoalesce(_optionalChain([err, 'optionalAccess', _52 => _52.message]), () => ( String(err)))
|
|
322
|
+
})]);
|
|
323
|
+
skipped += 1;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
_optionalChain([logger, 'optionalAccess', _53 => _53.info, 'optionalCall', _54 => _54("[webhook] declared webhooks materialized into sys_webhook", {
|
|
327
|
+
seeded,
|
|
328
|
+
skipped,
|
|
329
|
+
total: declared.length
|
|
330
|
+
})]);
|
|
331
|
+
return { seeded, skipped };
|
|
332
|
+
}
|
|
333
|
+
function mapWebhookToRow(wh) {
|
|
334
|
+
return {
|
|
335
|
+
name: wh.name,
|
|
336
|
+
label: _nullishCoalesce(wh.label, () => ( wh.name)),
|
|
337
|
+
object_name: _nullishCoalesce(wh.object, () => ( null)),
|
|
338
|
+
triggers: _nullishCoalesce(wh.triggers, () => ( [])),
|
|
339
|
+
url: wh.url,
|
|
340
|
+
// Store lowercase to match the object's Field.select option values
|
|
341
|
+
// (get/post/…); the enqueuer upper-cases before delivery either way.
|
|
342
|
+
method: String(_nullishCoalesce(wh.method, () => ( "POST"))).toLowerCase(),
|
|
343
|
+
description: _nullishCoalesce(wh.description, () => ( null)),
|
|
344
|
+
active: wh.isActive !== false,
|
|
345
|
+
definition_json: JSON.stringify(wh)
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// src/webhook-provenance.ts
|
|
350
|
+
var WEBHOOK_PROVENANCE_PACKAGE = "plugin-webhooks:provenance";
|
|
351
|
+
var SYSTEM_CTX2 = { isSystem: true, positions: [], permissions: [] };
|
|
352
|
+
function bindWebhookProvenanceStamp(engine, logger) {
|
|
353
|
+
if (typeof _optionalChain([engine, 'optionalAccess', _55 => _55.registerHook]) !== "function") return;
|
|
354
|
+
engine.registerHook(
|
|
355
|
+
"beforeUpdate",
|
|
356
|
+
async (ctx) => {
|
|
357
|
+
if (_optionalChain([ctx, 'optionalAccess', _56 => _56.session, 'optionalAccess', _57 => _57.isSystem])) return;
|
|
358
|
+
const id = _nullishCoalesce(_optionalChain([ctx, 'optionalAccess', _58 => _58.input, 'optionalAccess', _59 => _59.id]), () => ( _optionalChain([ctx, 'optionalAccess', _60 => _60.input, 'optionalAccess', _61 => _61.data, 'optionalAccess', _62 => _62.id])));
|
|
359
|
+
if (!id) return;
|
|
360
|
+
const data = _optionalChain([ctx, 'optionalAccess', _63 => _63.input, 'optionalAccess', _64 => _64.data]);
|
|
361
|
+
if (!data || typeof data !== "object") return;
|
|
362
|
+
try {
|
|
363
|
+
const rows = await engine.find("sys_webhook", {
|
|
364
|
+
where: { id },
|
|
365
|
+
fields: ["id", "managed_by", "customized"],
|
|
366
|
+
limit: 1,
|
|
367
|
+
context: SYSTEM_CTX2
|
|
368
|
+
});
|
|
369
|
+
const row = Array.isArray(rows) ? rows[0] : void 0;
|
|
370
|
+
if (!row) return;
|
|
371
|
+
if ((row.managed_by === "package" || row.managed_by === "platform") && row.customized !== true) {
|
|
372
|
+
data.customized = true;
|
|
373
|
+
}
|
|
374
|
+
} catch (err) {
|
|
375
|
+
_optionalChain([logger, 'optionalAccess', _65 => _65.warn, 'optionalCall', _66 => _66("[webhook] provenance stamp failed (edit proceeds unstamped)", {
|
|
376
|
+
id,
|
|
377
|
+
error: _optionalChain([err, 'optionalAccess', _67 => _67.message])
|
|
378
|
+
})]);
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
{ object: "sys_webhook", packageId: WEBHOOK_PROVENANCE_PACKAGE, priority: 150 }
|
|
382
|
+
);
|
|
383
|
+
_optionalChain([logger, 'optionalAccess', _68 => _68.info, 'optionalCall', _69 => _69("[webhook] provenance stamp hook bound")]);
|
|
384
|
+
}
|
|
385
|
+
function unbindWebhookProvenanceStamp(engine) {
|
|
386
|
+
if (typeof _optionalChain([engine, 'optionalAccess', _70 => _70.unregisterHooksByPackage]) === "function") {
|
|
387
|
+
engine.unregisterHooksByPackage(WEBHOOK_PROVENANCE_PACKAGE);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
225
391
|
// src/webhook-outbox-plugin.ts
|
|
226
392
|
var WebhookOutboxPlugin = class {
|
|
227
393
|
constructor(options = {}) {
|
|
@@ -230,6 +396,16 @@ var WebhookOutboxPlugin = class {
|
|
|
230
396
|
this.version = "2.0.0";
|
|
231
397
|
this.type = "standard";
|
|
232
398
|
this.dependencies = ["com.objectstack.service.messaging"];
|
|
399
|
+
/**
|
|
400
|
+
* `init()` registers this plugin's schema through `manifest` with no
|
|
401
|
+
* fallback. Until #4187 that was safe only TRANSITIVELY — messaging happens
|
|
402
|
+
* to depend on ObjectQL, which provides `manifest` — so the guarantee would
|
|
403
|
+
* have evaporated silently the day messaging stopped depending on the
|
|
404
|
+
* engine, and the failure would have surfaced as an unrelated plugin's
|
|
405
|
+
* init crash. Declaring the requirement directly makes the kernel check it
|
|
406
|
+
* regardless of what messaging depends on.
|
|
407
|
+
*/
|
|
408
|
+
this.requiresServices = ["manifest"];
|
|
233
409
|
}
|
|
234
410
|
async init(ctx) {
|
|
235
411
|
const manifest = ctx.getService("manifest");
|
|
@@ -242,7 +418,7 @@ var WebhookOutboxPlugin = class {
|
|
|
242
418
|
scope: "system",
|
|
243
419
|
name: "Webhook Schemas",
|
|
244
420
|
description: "Registers sys_webhook (configuration). Deliveries use messaging's sys_http_delivery outbox.",
|
|
245
|
-
objects: [
|
|
421
|
+
objects: [_chunkQUTQSOQCcjs.SysWebhook],
|
|
246
422
|
navigationContributions: [
|
|
247
423
|
{
|
|
248
424
|
app: "setup",
|
|
@@ -256,7 +432,7 @@ var WebhookOutboxPlugin = class {
|
|
|
256
432
|
]
|
|
257
433
|
});
|
|
258
434
|
} else {
|
|
259
|
-
_optionalChain([ctx, 'access',
|
|
435
|
+
_optionalChain([ctx, 'access', _71 => _71.logger, 'access', _72 => _72.warn, 'optionalCall', _73 => _73(
|
|
260
436
|
"[webhook-outbox] manifest service unavailable \u2014 sys_webhook will NOT appear in REST or Studio nav. Register MetadataService before WebhookOutboxPlugin."
|
|
261
437
|
)]);
|
|
262
438
|
}
|
|
@@ -265,47 +441,88 @@ var WebhookOutboxPlugin = class {
|
|
|
265
441
|
try {
|
|
266
442
|
const i18n = ctx.getService("i18n");
|
|
267
443
|
if (i18n && typeof i18n.loadTranslations === "function") {
|
|
268
|
-
const { WebhooksTranslations } = await Promise.resolve().then(() => _interopRequireWildcard(require("./translations-
|
|
444
|
+
const { WebhooksTranslations } = await Promise.resolve().then(() => _interopRequireWildcard(require("./translations-CBQRUIS5.cjs")));
|
|
269
445
|
for (const [locale, data] of Object.entries(WebhooksTranslations)) {
|
|
270
446
|
i18n.loadTranslations(locale, data);
|
|
271
447
|
}
|
|
272
448
|
}
|
|
273
|
-
} catch (
|
|
449
|
+
} catch (e5) {
|
|
274
450
|
}
|
|
275
451
|
});
|
|
276
452
|
}
|
|
277
453
|
const autoEnqueueOpt = _nullishCoalesce(this.options.autoEnqueue, () => ( true));
|
|
278
454
|
if (typeof ctx.hook === "function") {
|
|
279
455
|
ctx.hook("kernel:ready", async () => {
|
|
456
|
+
await this.bootDeclaredWebhooks(ctx);
|
|
280
457
|
await this.bootAutoEnqueue(ctx, autoEnqueueOpt);
|
|
281
458
|
this.registerAdminRoutes(ctx);
|
|
282
459
|
});
|
|
283
460
|
}
|
|
284
|
-
_optionalChain([ctx, 'access',
|
|
461
|
+
_optionalChain([ctx, 'access', _74 => _74.logger, 'access', _75 => _75.info, 'optionalCall', _76 => _76("[webhook-outbox] initialised (delivery via shared messaging HTTP outbox)", {
|
|
285
462
|
autoEnqueue: autoEnqueueOpt !== false
|
|
286
463
|
})]);
|
|
287
464
|
}
|
|
288
465
|
async dispose() {
|
|
289
|
-
await _optionalChain([this, 'access',
|
|
466
|
+
await _optionalChain([this, 'access', _77 => _77.autoEnqueuer, 'optionalAccess', _78 => _78.stop, 'call', _79 => _79()]);
|
|
467
|
+
if (this.boundEngine) {
|
|
468
|
+
try {
|
|
469
|
+
unbindWebhookProvenanceStamp(this.boundEngine);
|
|
470
|
+
} catch (e6) {
|
|
471
|
+
}
|
|
472
|
+
this.boundEngine = void 0;
|
|
473
|
+
}
|
|
290
474
|
}
|
|
291
475
|
getMessaging(ctx) {
|
|
292
476
|
const svc = this.tryGetService(ctx, ["messaging"]);
|
|
293
477
|
return svc && typeof svc.enqueueHttp === "function" ? svc : void 0;
|
|
294
478
|
}
|
|
479
|
+
/**
|
|
480
|
+
* [#3461] Bridge the declarative authoring surface to the dispatcher:
|
|
481
|
+
* materialize stack/connector-declared `webhook` metadata into `sys_webhook`
|
|
482
|
+
* rows so the auto-enqueuer (and the Studio UI) can see them.
|
|
483
|
+
*
|
|
484
|
+
* Gated on the DATA ENGINE alone — deliberately independent of the
|
|
485
|
+
* auto-enqueue dispatch prerequisites (realtime + messaging). Materializing
|
|
486
|
+
* rows is a pure write; a deployment that mounts the webhook plugin without
|
|
487
|
+
* realtime must still get its declared webhooks into the table (and the
|
|
488
|
+
* Setup UI), even if nothing dispatches them yet. Runs before
|
|
489
|
+
* {@link bootAutoEnqueue} so the enqueuer's first cache refresh sees the rows.
|
|
490
|
+
*/
|
|
491
|
+
async bootDeclaredWebhooks(ctx) {
|
|
492
|
+
const engine = this.tryGetService(ctx, ["objectql", "data"]);
|
|
493
|
+
if (!engine) {
|
|
494
|
+
_optionalChain([ctx, 'access', _80 => _80.logger, 'access', _81 => _81.warn, 'optionalCall', _82 => _82("[webhook] declared-webhook bootstrap skipped \u2014 no data engine available")]);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
this.boundEngine = engine;
|
|
498
|
+
bindWebhookProvenanceStamp(engine, ctx.logger);
|
|
499
|
+
let metadataService;
|
|
500
|
+
try {
|
|
501
|
+
metadataService = ctx.getService("metadata");
|
|
502
|
+
} catch (e7) {
|
|
503
|
+
}
|
|
504
|
+
try {
|
|
505
|
+
await bootstrapDeclaredWebhooks(engine, metadataService, ctx.logger);
|
|
506
|
+
} catch (err) {
|
|
507
|
+
_optionalChain([ctx, 'access', _83 => _83.logger, 'access', _84 => _84.warn, 'optionalCall', _85 => _85("[webhook] declared-webhook bootstrap failed (dispatcher still serves admin rows)", {
|
|
508
|
+
error: _nullishCoalesce(_optionalChain([err, 'optionalAccess', _86 => _86.message]), () => ( String(err)))
|
|
509
|
+
})]);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
295
512
|
async bootAutoEnqueue(ctx, opt) {
|
|
296
513
|
if (opt === false) return;
|
|
297
514
|
const engine = this.tryGetService(ctx, ["objectql", "data"]);
|
|
298
515
|
const realtime = this.tryGetService(ctx, ["realtime"]);
|
|
299
516
|
const messaging = this.getMessaging(ctx);
|
|
300
517
|
if (!engine || !realtime || !messaging) {
|
|
301
|
-
_optionalChain([ctx, 'access',
|
|
518
|
+
_optionalChain([ctx, 'access', _87 => _87.logger, 'access', _88 => _88.warn, 'optionalCall', _89 => _89(
|
|
302
519
|
"[webhook-auto-enqueuer] disabled \u2014 ObjectQL, Realtime, or Messaging service not available",
|
|
303
520
|
{ hasEngine: !!engine, hasRealtime: !!realtime, hasMessaging: !!messaging }
|
|
304
521
|
)]);
|
|
305
522
|
return;
|
|
306
523
|
}
|
|
307
524
|
if (!messaging.isHttpDeliveryReady()) {
|
|
308
|
-
_optionalChain([ctx, 'access',
|
|
525
|
+
_optionalChain([ctx, 'access', _90 => _90.logger, 'access', _91 => _91.warn, 'optionalCall', _92 => _92(
|
|
309
526
|
"[webhook-auto-enqueuer] messaging HTTP outbox not ready (no data engine / reliableDelivery off) \u2014 webhook deliveries will not be durable"
|
|
310
527
|
)]);
|
|
311
528
|
}
|
|
@@ -318,14 +535,14 @@ var WebhookOutboxPlugin = class {
|
|
|
318
535
|
);
|
|
319
536
|
await this.autoEnqueuer.start();
|
|
320
537
|
ctx.registerService("webhook.autoEnqueuer", this.autoEnqueuer);
|
|
321
|
-
_optionalChain([ctx, 'access',
|
|
538
|
+
_optionalChain([ctx, 'access', _93 => _93.logger, 'access', _94 => _94.info, 'optionalCall', _95 => _95("[webhook-auto-enqueuer] started (enqueues source=webhook onto sys_http_delivery)")]);
|
|
322
539
|
}
|
|
323
540
|
tryGetService(ctx, names) {
|
|
324
541
|
for (const n of names) {
|
|
325
542
|
try {
|
|
326
543
|
const svc = ctx.getService(n);
|
|
327
544
|
if (svc) return svc;
|
|
328
|
-
} catch (
|
|
545
|
+
} catch (e8) {
|
|
329
546
|
}
|
|
330
547
|
}
|
|
331
548
|
return void 0;
|
|
@@ -338,7 +555,7 @@ var WebhookOutboxPlugin = class {
|
|
|
338
555
|
registerAdminRoutes(ctx) {
|
|
339
556
|
const http = this.tryGetService(ctx, ["http-server"]);
|
|
340
557
|
if (!http || typeof http.getRawApp !== "function") {
|
|
341
|
-
_optionalChain([ctx, 'access',
|
|
558
|
+
_optionalChain([ctx, 'access', _96 => _96.logger, 'access', _97 => _97.debug, 'optionalCall', _98 => _98("[webhook-outbox] HTTP server not available; redeliver endpoint not mounted")]);
|
|
342
559
|
return;
|
|
343
560
|
}
|
|
344
561
|
const rawApp = http.getRawApp();
|
|
@@ -348,43 +565,43 @@ var WebhookOutboxPlugin = class {
|
|
|
348
565
|
const userId = await this.resolveSessionUserId(ctx, c);
|
|
349
566
|
if (!userId) {
|
|
350
567
|
return c.json(
|
|
351
|
-
{ success: false, error: "
|
|
568
|
+
{ success: false, error: { code: "UNAUTHENTICATED", message: "Sign in to redeliver webhook deliveries." } },
|
|
352
569
|
401
|
|
353
570
|
);
|
|
354
571
|
}
|
|
355
572
|
let body;
|
|
356
573
|
try {
|
|
357
574
|
body = await c.req.json();
|
|
358
|
-
} catch (
|
|
359
|
-
return c.json({ success: false, error: "
|
|
575
|
+
} catch (e9) {
|
|
576
|
+
return c.json({ success: false, error: { code: "INVALID_REQUEST", message: "Request body must be JSON." } }, 400);
|
|
360
577
|
}
|
|
361
|
-
const deliveryId = typeof _optionalChain([body, 'optionalAccess',
|
|
578
|
+
const deliveryId = typeof _optionalChain([body, 'optionalAccess', _99 => _99.deliveryId]) === "string" ? body.deliveryId.trim() : "";
|
|
362
579
|
if (!deliveryId) {
|
|
363
580
|
return c.json(
|
|
364
|
-
{ success: false, error: "
|
|
581
|
+
{ success: false, error: { code: "MISSING_REQUIRED_FIELD", message: "Body must include `deliveryId: string`." } },
|
|
365
582
|
400
|
|
366
583
|
);
|
|
367
584
|
}
|
|
368
585
|
try {
|
|
369
586
|
const row = await messaging.redeliverHttp(deliveryId);
|
|
370
|
-
_optionalChain([ctx, 'access',
|
|
587
|
+
_optionalChain([ctx, 'access', _100 => _100.logger, 'access', _101 => _101.info, 'optionalCall', _102 => _102("[webhook-outbox] redelivered", { deliveryId, requestedBy: userId })]);
|
|
371
588
|
return c.json({ success: true, data: { id: row.id, status: row.status } });
|
|
372
589
|
} catch (err) {
|
|
373
|
-
const code = _optionalChain([err, 'optionalAccess',
|
|
374
|
-
if (code === "
|
|
375
|
-
return c.json({ success: false, error:
|
|
590
|
+
const code = _optionalChain([err, 'optionalAccess', _103 => _103.code]);
|
|
591
|
+
if (code === "RESOURCE_NOT_FOUND") {
|
|
592
|
+
return c.json({ success: false, error: { code, message: err.message } }, 404);
|
|
376
593
|
}
|
|
377
|
-
if (code === "
|
|
378
|
-
return c.json({ success: false, error:
|
|
594
|
+
if (code === "DELIVERY_NOT_ELIGIBLE") {
|
|
595
|
+
return c.json({ success: false, error: { code, message: err.message } }, 409);
|
|
379
596
|
}
|
|
380
|
-
_optionalChain([ctx, 'access',
|
|
597
|
+
_optionalChain([ctx, 'access', _104 => _104.logger, 'access', _105 => _105.error, 'optionalCall', _106 => _106("[webhook-outbox] redeliver failed", err)]);
|
|
381
598
|
return c.json(
|
|
382
|
-
{ success: false, error: "
|
|
599
|
+
{ success: false, error: { code: "INTERNAL_ERROR", message: _nullishCoalesce(_optionalChain([err, 'optionalAccess', _107 => _107.message]), () => ( String(err))) } },
|
|
383
600
|
500
|
|
384
601
|
);
|
|
385
602
|
}
|
|
386
603
|
});
|
|
387
|
-
_optionalChain([ctx, 'access',
|
|
604
|
+
_optionalChain([ctx, 'access', _108 => _108.logger, 'access', _109 => _109.info, 'optionalCall', _110 => _110("[webhook-outbox] redeliver endpoint mounted at POST /api/v1/webhooks/redeliver")]);
|
|
388
605
|
}
|
|
389
606
|
async resolveSessionUserId(ctx, c) {
|
|
390
607
|
try {
|
|
@@ -394,11 +611,11 @@ var WebhookOutboxPlugin = class {
|
|
|
394
611
|
if (!api && typeof authService.getApi === "function") {
|
|
395
612
|
api = await authService.getApi();
|
|
396
613
|
}
|
|
397
|
-
if (!_optionalChain([api, 'optionalAccess',
|
|
614
|
+
if (!_optionalChain([api, 'optionalAccess', _111 => _111.getSession])) return void 0;
|
|
398
615
|
const session = await api.getSession({ headers: c.req.raw.headers });
|
|
399
|
-
const
|
|
400
|
-
return typeof
|
|
401
|
-
} catch (
|
|
616
|
+
const uid2 = _optionalChain([session, 'optionalAccess', _112 => _112.user, 'optionalAccess', _113 => _113.id]);
|
|
617
|
+
return typeof uid2 === "string" && uid2.length > 0 ? uid2 : void 0;
|
|
618
|
+
} catch (e10) {
|
|
402
619
|
return void 0;
|
|
403
620
|
}
|
|
404
621
|
}
|
|
@@ -407,5 +624,5 @@ var WebhookOutboxPlugin = class {
|
|
|
407
624
|
|
|
408
625
|
|
|
409
626
|
|
|
410
|
-
exports.AutoEnqueuer = AutoEnqueuer; exports.SysWebhook =
|
|
627
|
+
exports.AutoEnqueuer = AutoEnqueuer; exports.SysWebhook = _chunkQUTQSOQCcjs.SysWebhook; exports.WebhookOutboxPlugin = WebhookOutboxPlugin;
|
|
411
628
|
//# sourceMappingURL=index.cjs.map
|