@marinoscar/platform-web 0.1.0-next.19 → 0.1.0-next.21
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 +21 -0
- package/README.md +5 -3
- package/dist/alerts/headless/client.d.ts +134 -0
- package/dist/alerts/headless/client.d.ts.map +1 -0
- package/dist/alerts/headless/client.js +105 -0
- package/dist/alerts/headless/client.js.map +1 -0
- package/dist/alerts/headless/format.d.ts +95 -0
- package/dist/alerts/headless/format.d.ts.map +1 -0
- package/dist/alerts/headless/format.js +164 -0
- package/dist/alerts/headless/format.js.map +1 -0
- package/dist/alerts/headless/hooks.d.ts +245 -0
- package/dist/alerts/headless/hooks.d.ts.map +1 -0
- package/dist/alerts/headless/hooks.js +315 -0
- package/dist/alerts/headless/hooks.js.map +1 -0
- package/dist/alerts/headless/index.d.ts +9 -0
- package/dist/alerts/headless/index.d.ts.map +1 -0
- package/dist/alerts/headless/index.js +9 -0
- package/dist/alerts/headless/index.js.map +1 -0
- package/dist/alerts/headless/rule-draft.d.ts +175 -0
- package/dist/alerts/headless/rule-draft.d.ts.map +1 -0
- package/dist/alerts/headless/rule-draft.js +261 -0
- package/dist/alerts/headless/rule-draft.js.map +1 -0
- package/dist/alerts/ui/AlertIncidentDrawer.d.ts +30 -0
- package/dist/alerts/ui/AlertIncidentDrawer.d.ts.map +1 -0
- package/dist/alerts/ui/AlertIncidentDrawer.js +33 -0
- package/dist/alerts/ui/AlertIncidentDrawer.js.map +1 -0
- package/dist/alerts/ui/AlertRuleDialog.d.ts +47 -0
- package/dist/alerts/ui/AlertRuleDialog.d.ts.map +1 -0
- package/dist/alerts/ui/AlertRuleDialog.js +124 -0
- package/dist/alerts/ui/AlertRuleDialog.js.map +1 -0
- package/dist/alerts/ui/AlertRuleTestResult.d.ts +23 -0
- package/dist/alerts/ui/AlertRuleTestResult.d.ts.map +1 -0
- package/dist/alerts/ui/AlertRuleTestResult.js +30 -0
- package/dist/alerts/ui/AlertRuleTestResult.js.map +1 -0
- package/dist/alerts/ui/AlertsPage.d.ts +41 -0
- package/dist/alerts/ui/AlertsPage.d.ts.map +1 -0
- package/dist/alerts/ui/AlertsPage.js +238 -0
- package/dist/alerts/ui/AlertsPage.js.map +1 -0
- package/dist/alerts/ui/FiringAlertsBanner.d.ts +28 -0
- package/dist/alerts/ui/FiringAlertsBanner.d.ts.map +1 -0
- package/dist/alerts/ui/FiringAlertsBanner.js +45 -0
- package/dist/alerts/ui/FiringAlertsBanner.js.map +1 -0
- package/dist/alerts/ui/copy.d.ts +15 -0
- package/dist/alerts/ui/copy.d.ts.map +1 -0
- package/dist/alerts/ui/copy.js +14 -0
- package/dist/alerts/ui/copy.js.map +1 -0
- package/dist/alerts/ui/index.d.ts +14 -0
- package/dist/alerts/ui/index.d.ts.map +1 -0
- package/dist/alerts/ui/index.js +12 -0
- package/dist/alerts/ui/index.js.map +1 -0
- package/dist/alerts/ui/parts.d.ts +26 -0
- package/dist/alerts/ui/parts.d.ts.map +1 -0
- package/dist/alerts/ui/parts.js +27 -0
- package/dist/alerts/ui/parts.js.map +1 -0
- package/dist/alerts/ui/settings.d.ts +27 -0
- package/dist/alerts/ui/settings.d.ts.map +1 -0
- package/dist/alerts/ui/settings.js +37 -0
- package/dist/alerts/ui/settings.js.map +1 -0
- package/dist/nodes/headless/api.d.ts +3 -1
- package/dist/nodes/headless/api.d.ts.map +1 -1
- package/dist/nodes/headless/api.js +22 -0
- package/dist/nodes/headless/api.js.map +1 -1
- package/dist/nodes/headless/index.d.ts +7 -2
- package/dist/nodes/headless/index.d.ts.map +1 -1
- package/dist/nodes/headless/index.js +4 -1
- package/dist/nodes/headless/index.js.map +1 -1
- package/dist/nodes/headless/node-events.d.ts +43 -0
- package/dist/nodes/headless/node-events.d.ts.map +1 -0
- package/dist/nodes/headless/node-events.js +150 -0
- package/dist/nodes/headless/node-events.js.map +1 -0
- package/dist/nodes/headless/power.d.ts +43 -0
- package/dist/nodes/headless/power.d.ts.map +1 -0
- package/dist/nodes/headless/power.js +74 -0
- package/dist/nodes/headless/power.js.map +1 -0
- package/dist/nodes/headless/types.d.ts +40 -3
- package/dist/nodes/headless/types.d.ts.map +1 -1
- package/dist/nodes/headless/types.js +1 -1
- package/dist/nodes/headless/types.js.map +1 -1
- package/dist/nodes/headless/use-node-events.d.ts +59 -0
- package/dist/nodes/headless/use-node-events.d.ts.map +1 -0
- package/dist/nodes/headless/use-node-events.js +159 -0
- package/dist/nodes/headless/use-node-events.js.map +1 -0
- package/dist/nodes/ui/NodeEventsTimeline.d.ts +39 -0
- package/dist/nodes/ui/NodeEventsTimeline.d.ts.map +1 -0
- package/dist/nodes/ui/NodeEventsTimeline.js +63 -0
- package/dist/nodes/ui/NodeEventsTimeline.js.map +1 -0
- package/dist/nodes/ui/NodePowerBadge.d.ts +27 -0
- package/dist/nodes/ui/NodePowerBadge.d.ts.map +1 -0
- package/dist/nodes/ui/NodePowerBadge.js +48 -0
- package/dist/nodes/ui/NodePowerBadge.js.map +1 -0
- package/dist/nodes/ui/NodeVitalsDialog.d.ts +11 -1
- package/dist/nodes/ui/NodeVitalsDialog.d.ts.map +1 -1
- package/dist/nodes/ui/NodeVitalsDialog.js +14 -5
- package/dist/nodes/ui/NodeVitalsDialog.js.map +1 -1
- package/dist/nodes/ui/WorkersPage.d.ts.map +1 -1
- package/dist/nodes/ui/WorkersPage.js +2 -1
- package/dist/nodes/ui/WorkersPage.js.map +1 -1
- package/dist/nodes/ui/workerVitals.d.ts +17 -1
- package/dist/nodes/ui/workerVitals.d.ts.map +1 -1
- package/dist/nodes/ui/workerVitals.js +43 -0
- package/dist/nodes/ui/workerVitals.js.map +1 -1
- package/dist/nodes/ui/workersTable.d.ts.map +1 -1
- package/dist/nodes/ui/workersTable.js +2 -1
- package/dist/nodes/ui/workersTable.js.map +1 -1
- package/dist/telemetry/headless/hooks/useTelemetryDashboard.d.ts +1 -1
- package/dist/telemetry/ui/components/dashboard/metrics/MetricSections.d.ts +11 -0
- package/dist/telemetry/ui/components/dashboard/metrics/MetricSections.d.ts.map +1 -1
- package/dist/telemetry/ui/components/dashboard/metrics/MetricSections.js +17 -2
- package/dist/telemetry/ui/components/dashboard/metrics/MetricSections.js.map +1 -1
- package/dist/webhooks/headless/client.d.ts +101 -0
- package/dist/webhooks/headless/client.d.ts.map +1 -0
- package/dist/webhooks/headless/client.js +105 -0
- package/dist/webhooks/headless/client.js.map +1 -0
- package/dist/webhooks/headless/event-selection.d.ts +119 -0
- package/dist/webhooks/headless/event-selection.d.ts.map +1 -0
- package/dist/webhooks/headless/event-selection.js +225 -0
- package/dist/webhooks/headless/event-selection.js.map +1 -0
- package/dist/webhooks/headless/format.d.ts +84 -0
- package/dist/webhooks/headless/format.d.ts.map +1 -0
- package/dist/webhooks/headless/format.js +142 -0
- package/dist/webhooks/headless/format.js.map +1 -0
- package/dist/webhooks/headless/hooks.d.ts +199 -0
- package/dist/webhooks/headless/hooks.d.ts.map +1 -0
- package/dist/webhooks/headless/hooks.js +249 -0
- package/dist/webhooks/headless/hooks.js.map +1 -0
- package/dist/webhooks/headless/index.d.ts +9 -0
- package/dist/webhooks/headless/index.d.ts.map +1 -0
- package/dist/webhooks/headless/index.js +9 -0
- package/dist/webhooks/headless/index.js.map +1 -0
- package/dist/webhooks/ui/WebhookDeliveryDrawer.d.ts +32 -0
- package/dist/webhooks/ui/WebhookDeliveryDrawer.d.ts.map +1 -0
- package/dist/webhooks/ui/WebhookDeliveryDrawer.js +64 -0
- package/dist/webhooks/ui/WebhookDeliveryDrawer.js.map +1 -0
- package/dist/webhooks/ui/WebhookEndpointDetail.d.ts +21 -0
- package/dist/webhooks/ui/WebhookEndpointDetail.d.ts.map +1 -0
- package/dist/webhooks/ui/WebhookEndpointDetail.js +96 -0
- package/dist/webhooks/ui/WebhookEndpointDetail.js.map +1 -0
- package/dist/webhooks/ui/WebhookEndpointDialog.d.ts +39 -0
- package/dist/webhooks/ui/WebhookEndpointDialog.d.ts.map +1 -0
- package/dist/webhooks/ui/WebhookEndpointDialog.js +79 -0
- package/dist/webhooks/ui/WebhookEndpointDialog.js.map +1 -0
- package/dist/webhooks/ui/WebhookEventPicker.d.ts +30 -0
- package/dist/webhooks/ui/WebhookEventPicker.d.ts.map +1 -0
- package/dist/webhooks/ui/WebhookEventPicker.js +33 -0
- package/dist/webhooks/ui/WebhookEventPicker.js.map +1 -0
- package/dist/webhooks/ui/WebhookSecretDialog.d.ts +27 -0
- package/dist/webhooks/ui/WebhookSecretDialog.d.ts.map +1 -0
- package/dist/webhooks/ui/WebhookSecretDialog.js +52 -0
- package/dist/webhooks/ui/WebhookSecretDialog.js.map +1 -0
- package/dist/webhooks/ui/WebhookSignatureHelp.d.ts +18 -0
- package/dist/webhooks/ui/WebhookSignatureHelp.d.ts.map +1 -0
- package/dist/webhooks/ui/WebhookSignatureHelp.js +40 -0
- package/dist/webhooks/ui/WebhookSignatureHelp.js.map +1 -0
- package/dist/webhooks/ui/WebhooksPage.d.ts +47 -0
- package/dist/webhooks/ui/WebhooksPage.d.ts.map +1 -0
- package/dist/webhooks/ui/WebhooksPage.js +172 -0
- package/dist/webhooks/ui/WebhooksPage.js.map +1 -0
- package/dist/webhooks/ui/copy.d.ts +24 -0
- package/dist/webhooks/ui/copy.d.ts.map +1 -0
- package/dist/webhooks/ui/copy.js +34 -0
- package/dist/webhooks/ui/copy.js.map +1 -0
- package/dist/webhooks/ui/index.d.ts +15 -0
- package/dist/webhooks/ui/index.d.ts.map +1 -0
- package/dist/webhooks/ui/index.js +12 -0
- package/dist/webhooks/ui/index.js.map +1 -0
- package/dist/webhooks/ui/parts.d.ts +25 -0
- package/dist/webhooks/ui/parts.d.ts.map +1 -0
- package/dist/webhooks/ui/parts.js +28 -0
- package/dist/webhooks/ui/parts.js.map +1 -0
- package/dist/webhooks/ui/settings.d.ts +58 -0
- package/dist/webhooks/ui/settings.d.ts.map +1 -0
- package/dist/webhooks/ui/settings.js +79 -0
- package/dist/webhooks/ui/settings.js.map +1 -0
- package/package.json +18 -2
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { WebhookDeliveryStatus, WebhookEndpoint } from '@marinoscar/platform-contract/webhooks';
|
|
2
|
+
/**
|
|
3
|
+
* The tone of a status chip, mapped by the UI onto its theme palette.
|
|
4
|
+
*
|
|
5
|
+
* @stability experimental
|
|
6
|
+
*/
|
|
7
|
+
export type WebhookStatusTone = 'success' | 'warning' | 'error' | 'info' | 'default';
|
|
8
|
+
/**
|
|
9
|
+
* The words for each `disabledReason` the platform sets when it switches an
|
|
10
|
+
* endpoint off. A reason not listed here is shown as "Disabled".
|
|
11
|
+
*
|
|
12
|
+
* @stability experimental
|
|
13
|
+
*/
|
|
14
|
+
export declare const WEBHOOK_DISABLED_REASON_LABELS: Readonly<Record<string, string>>;
|
|
15
|
+
/**
|
|
16
|
+
* An endpoint's status as the UI shows it.
|
|
17
|
+
*
|
|
18
|
+
* @stability experimental
|
|
19
|
+
*/
|
|
20
|
+
export interface WebhookEndpointStatus {
|
|
21
|
+
/** The chip text. */
|
|
22
|
+
label: string;
|
|
23
|
+
/** The chip tone. */
|
|
24
|
+
tone: WebhookStatusTone;
|
|
25
|
+
/** A sentence on what to do, when the platform disabled the endpoint. */
|
|
26
|
+
hint: string | null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* An endpoint's status in words: Active, Disabled (by its owner) or the reason
|
|
30
|
+
* the platform switched it off.
|
|
31
|
+
*
|
|
32
|
+
* @param endpoint - the endpoint's `enabled` and `disabledReason`.
|
|
33
|
+
* @returns the label, tone and hint.
|
|
34
|
+
*
|
|
35
|
+
* @stability experimental
|
|
36
|
+
*/
|
|
37
|
+
export declare function webhookEndpointStatus(endpoint: Pick<WebhookEndpoint, 'enabled' | 'disabledReason'>): WebhookEndpointStatus;
|
|
38
|
+
/**
|
|
39
|
+
* A delivery's status in words: Queued, Delivering, Delivered, Retrying
|
|
40
|
+
* (`failed`: an attempt failed and another is scheduled) and Failed (`dead`).
|
|
41
|
+
*
|
|
42
|
+
* @param status - the delivery status.
|
|
43
|
+
* @returns the label.
|
|
44
|
+
*
|
|
45
|
+
* @stability experimental
|
|
46
|
+
*/
|
|
47
|
+
export declare function webhookDeliveryStatusLabel(status: WebhookDeliveryStatus): string;
|
|
48
|
+
/**
|
|
49
|
+
* The chip tone of a delivery status.
|
|
50
|
+
*
|
|
51
|
+
* @param status - the delivery status.
|
|
52
|
+
* @returns the tone.
|
|
53
|
+
*
|
|
54
|
+
* @stability experimental
|
|
55
|
+
*/
|
|
56
|
+
export declare function webhookDeliveryStatusTone(status: WebhookDeliveryStatus): WebhookStatusTone;
|
|
57
|
+
/**
|
|
58
|
+
* The host of an endpoint URL (what a list shows; never the path or query).
|
|
59
|
+
*
|
|
60
|
+
* @param url - the endpoint URL.
|
|
61
|
+
* @returns the host with its port, or the input when it does not parse.
|
|
62
|
+
*
|
|
63
|
+
* @stability experimental
|
|
64
|
+
*/
|
|
65
|
+
export declare function webhookUrlHost(url: string): string;
|
|
66
|
+
/**
|
|
67
|
+
* Whether a URL uses `https:` (the UI warns otherwise; the API decides).
|
|
68
|
+
*
|
|
69
|
+
* @param url - the typed URL.
|
|
70
|
+
* @returns `true` for an https URL.
|
|
71
|
+
*
|
|
72
|
+
* @stability experimental
|
|
73
|
+
*/
|
|
74
|
+
export declare function isHttpsWebhookUrl(url: string): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* A duration in milliseconds as short text (`240 ms`, `1.2 s`).
|
|
77
|
+
*
|
|
78
|
+
* @param ms - the duration, or `null`.
|
|
79
|
+
* @returns the text, or an empty string for `null`.
|
|
80
|
+
*
|
|
81
|
+
* @stability experimental
|
|
82
|
+
*/
|
|
83
|
+
export declare function formatWebhookDuration(ms: number | null): string;
|
|
84
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/webhooks/headless/format.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAErG;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAErF;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAI1E,CAAC;AAEH;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,IAAI,EAAE,iBAAiB,CAAC;IACxB,yEAAyE;IACzE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,gBAAgB,CAAC,GAAG,qBAAqB,CAwB1H;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAahF;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,qBAAqB,GAAG,iBAAiB,CAa1F;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAMtD;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAI/D"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Webhook presentation helpers (issue #1046): status in words, never a colour alone
|
|
3
|
+
// =============================================================================
|
|
4
|
+
/**
|
|
5
|
+
* The words for each `disabledReason` the platform sets when it switches an
|
|
6
|
+
* endpoint off. A reason not listed here is shown as "Disabled".
|
|
7
|
+
*
|
|
8
|
+
* @stability experimental
|
|
9
|
+
*/
|
|
10
|
+
export const WEBHOOK_DISABLED_REASON_LABELS = Object.freeze({
|
|
11
|
+
circuit_open: 'Paused after repeated failures',
|
|
12
|
+
owner_lost_access: 'Owner lost access',
|
|
13
|
+
gone: 'Endpoint gone',
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* An endpoint's status in words: Active, Disabled (by its owner) or the reason
|
|
17
|
+
* the platform switched it off.
|
|
18
|
+
*
|
|
19
|
+
* @param endpoint - the endpoint's `enabled` and `disabledReason`.
|
|
20
|
+
* @returns the label, tone and hint.
|
|
21
|
+
*
|
|
22
|
+
* @stability experimental
|
|
23
|
+
*/
|
|
24
|
+
export function webhookEndpointStatus(endpoint) {
|
|
25
|
+
if (endpoint.enabled)
|
|
26
|
+
return { label: 'Active', tone: 'success', hint: null };
|
|
27
|
+
switch (endpoint.disabledReason) {
|
|
28
|
+
case 'circuit_open':
|
|
29
|
+
return {
|
|
30
|
+
label: WEBHOOK_DISABLED_REASON_LABELS.circuit_open,
|
|
31
|
+
tone: 'warning',
|
|
32
|
+
hint: 'Deliveries kept failing, so they were paused. Fix the receiver, then enable the endpoint again.',
|
|
33
|
+
};
|
|
34
|
+
case 'owner_lost_access':
|
|
35
|
+
return {
|
|
36
|
+
label: WEBHOOK_DISABLED_REASON_LABELS.owner_lost_access,
|
|
37
|
+
tone: 'warning',
|
|
38
|
+
hint: 'The owner no longer holds the permission these events need. Enable it again once access is restored.',
|
|
39
|
+
};
|
|
40
|
+
case 'gone':
|
|
41
|
+
return {
|
|
42
|
+
label: WEBHOOK_DISABLED_REASON_LABELS.gone,
|
|
43
|
+
tone: 'error',
|
|
44
|
+
hint: 'The receiver answered 410 Gone. Point the endpoint at a new URL, then enable it again.',
|
|
45
|
+
};
|
|
46
|
+
default:
|
|
47
|
+
return { label: 'Disabled', tone: 'default', hint: null };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* A delivery's status in words: Queued, Delivering, Delivered, Retrying
|
|
52
|
+
* (`failed`: an attempt failed and another is scheduled) and Failed (`dead`).
|
|
53
|
+
*
|
|
54
|
+
* @param status - the delivery status.
|
|
55
|
+
* @returns the label.
|
|
56
|
+
*
|
|
57
|
+
* @stability experimental
|
|
58
|
+
*/
|
|
59
|
+
export function webhookDeliveryStatusLabel(status) {
|
|
60
|
+
switch (status) {
|
|
61
|
+
case 'pending':
|
|
62
|
+
return 'Queued';
|
|
63
|
+
case 'delivering':
|
|
64
|
+
return 'Delivering';
|
|
65
|
+
case 'succeeded':
|
|
66
|
+
return 'Delivered';
|
|
67
|
+
case 'failed':
|
|
68
|
+
return 'Retrying';
|
|
69
|
+
case 'dead':
|
|
70
|
+
return 'Failed';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The chip tone of a delivery status.
|
|
75
|
+
*
|
|
76
|
+
* @param status - the delivery status.
|
|
77
|
+
* @returns the tone.
|
|
78
|
+
*
|
|
79
|
+
* @stability experimental
|
|
80
|
+
*/
|
|
81
|
+
export function webhookDeliveryStatusTone(status) {
|
|
82
|
+
switch (status) {
|
|
83
|
+
case 'succeeded':
|
|
84
|
+
return 'success';
|
|
85
|
+
case 'failed':
|
|
86
|
+
return 'warning';
|
|
87
|
+
case 'dead':
|
|
88
|
+
return 'error';
|
|
89
|
+
case 'delivering':
|
|
90
|
+
return 'info';
|
|
91
|
+
case 'pending':
|
|
92
|
+
return 'default';
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The host of an endpoint URL (what a list shows; never the path or query).
|
|
97
|
+
*
|
|
98
|
+
* @param url - the endpoint URL.
|
|
99
|
+
* @returns the host with its port, or the input when it does not parse.
|
|
100
|
+
*
|
|
101
|
+
* @stability experimental
|
|
102
|
+
*/
|
|
103
|
+
export function webhookUrlHost(url) {
|
|
104
|
+
try {
|
|
105
|
+
return new URL(url).host;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return url;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Whether a URL uses `https:` (the UI warns otherwise; the API decides).
|
|
113
|
+
*
|
|
114
|
+
* @param url - the typed URL.
|
|
115
|
+
* @returns `true` for an https URL.
|
|
116
|
+
*
|
|
117
|
+
* @stability experimental
|
|
118
|
+
*/
|
|
119
|
+
export function isHttpsWebhookUrl(url) {
|
|
120
|
+
try {
|
|
121
|
+
return new URL(url).protocol === 'https:';
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* A duration in milliseconds as short text (`240 ms`, `1.2 s`).
|
|
129
|
+
*
|
|
130
|
+
* @param ms - the duration, or `null`.
|
|
131
|
+
* @returns the text, or an empty string for `null`.
|
|
132
|
+
*
|
|
133
|
+
* @stability experimental
|
|
134
|
+
*/
|
|
135
|
+
export function formatWebhookDuration(ms) {
|
|
136
|
+
if (ms === null)
|
|
137
|
+
return '';
|
|
138
|
+
if (ms < 1000)
|
|
139
|
+
return `${ms} ms`;
|
|
140
|
+
return `${(ms / 1000).toFixed(ms < 10_000 ? 1 : 0)} s`;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/webhooks/headless/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import type { CreateWebhookEndpointInput, RotateWebhookSecretResponse, UpdateWebhookEndpoint, WebhookDelivery, WebhookDeliveryDetail, WebhookEndpoint, WebhookEndpointCreated, WebhookEventCatalogEntry, WebhookScope, WebhookTestResponse } from '@marinoscar/platform-contract/webhooks';
|
|
2
|
+
import { type WebhookDeliveriesQuery, type WebhooksApi } from './client.js';
|
|
3
|
+
import { type WebhookEventGroup } from './event-selection.js';
|
|
4
|
+
/**
|
|
5
|
+
* A webhook API failure in words: the stable error code's sentence, else the
|
|
6
|
+
* API's message, else `fallback`.
|
|
7
|
+
*
|
|
8
|
+
* @param error - what the call rejected with.
|
|
9
|
+
* @param fallback - the sentence when nothing better is known.
|
|
10
|
+
* @returns the message.
|
|
11
|
+
*
|
|
12
|
+
* @stability experimental
|
|
13
|
+
*/
|
|
14
|
+
export declare function webhookErrorMessage(error: unknown, fallback: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* The webhooks client of one scope over the host's transport, memoised.
|
|
17
|
+
*
|
|
18
|
+
* @param scope - `user`, `org` or `system`.
|
|
19
|
+
* @returns the client.
|
|
20
|
+
*
|
|
21
|
+
* @stability experimental
|
|
22
|
+
*/
|
|
23
|
+
export declare function useWebhooksApi(scope: WebhookScope): WebhooksApi;
|
|
24
|
+
/**
|
|
25
|
+
* What {@link useWebhookEndpoints} returns.
|
|
26
|
+
*
|
|
27
|
+
* @stability experimental
|
|
28
|
+
*/
|
|
29
|
+
export interface WebhookEndpointsState {
|
|
30
|
+
/** The endpoints, in the API's order. */
|
|
31
|
+
endpoints: WebhookEndpoint[];
|
|
32
|
+
/** Whether a load is in flight. */
|
|
33
|
+
isLoading: boolean;
|
|
34
|
+
/** A load failure, in words. */
|
|
35
|
+
error: string | null;
|
|
36
|
+
/** Reloads now. */
|
|
37
|
+
refresh: () => Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The endpoints the caller may see at a scope (`GET <base>`).
|
|
41
|
+
*
|
|
42
|
+
* @param scope - `user`, `org` or `system`.
|
|
43
|
+
* @returns the endpoints and the load state.
|
|
44
|
+
*
|
|
45
|
+
* @extensionPoint hook
|
|
46
|
+
* @stability experimental
|
|
47
|
+
*/
|
|
48
|
+
export declare function useWebhookEndpoints(scope: WebhookScope): WebhookEndpointsState;
|
|
49
|
+
/**
|
|
50
|
+
* What {@link useWebhookEndpoint} returns.
|
|
51
|
+
*
|
|
52
|
+
* @stability experimental
|
|
53
|
+
*/
|
|
54
|
+
export interface WebhookEndpointState {
|
|
55
|
+
/** The endpoint, once loaded. */
|
|
56
|
+
endpoint: WebhookEndpoint | null;
|
|
57
|
+
/** Whether a load is in flight. */
|
|
58
|
+
isLoading: boolean;
|
|
59
|
+
/** A load failure, in words. */
|
|
60
|
+
error: string | null;
|
|
61
|
+
/** Reloads now. */
|
|
62
|
+
refresh: () => Promise<void>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* One endpoint (`GET <base>/:id`).
|
|
66
|
+
*
|
|
67
|
+
* @param scope - `user`, `org` or `system`.
|
|
68
|
+
* @param id - the endpoint id, or `null` for none.
|
|
69
|
+
* @returns the endpoint and the load state.
|
|
70
|
+
*
|
|
71
|
+
* @extensionPoint hook
|
|
72
|
+
* @stability experimental
|
|
73
|
+
*/
|
|
74
|
+
export declare function useWebhookEndpoint(scope: WebhookScope, id: string | null): WebhookEndpointState;
|
|
75
|
+
/**
|
|
76
|
+
* What {@link useWebhookDeliveries} returns.
|
|
77
|
+
*
|
|
78
|
+
* @stability experimental
|
|
79
|
+
*/
|
|
80
|
+
export interface WebhookDeliveriesState {
|
|
81
|
+
/** The page of deliveries, newest first. */
|
|
82
|
+
deliveries: WebhookDelivery[];
|
|
83
|
+
/** Deliveries matching the filters, across every page. */
|
|
84
|
+
total: number;
|
|
85
|
+
/** Pages at the requested page size. */
|
|
86
|
+
totalPages: number;
|
|
87
|
+
/** Whether a load is in flight. */
|
|
88
|
+
isLoading: boolean;
|
|
89
|
+
/** A load failure, in words. */
|
|
90
|
+
error: string | null;
|
|
91
|
+
/** Reloads the current page now. */
|
|
92
|
+
refresh: () => Promise<void>;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* One page of an endpoint's deliveries
|
|
96
|
+
* (`GET <base>/:id/deliveries?page&pageSize&status&eventKey`), reloaded when
|
|
97
|
+
* the endpoint, the page or a filter changes.
|
|
98
|
+
*
|
|
99
|
+
* @param scope - `user`, `org` or `system`.
|
|
100
|
+
* @param endpointId - the endpoint, or `null` for none.
|
|
101
|
+
* @param query - the one-based page, page size and filters.
|
|
102
|
+
* @returns the page and the load state.
|
|
103
|
+
*
|
|
104
|
+
* @extensionPoint hook
|
|
105
|
+
* @stability experimental
|
|
106
|
+
*/
|
|
107
|
+
export declare function useWebhookDeliveries(scope: WebhookScope, endpointId: string | null, query?: WebhookDeliveriesQuery): WebhookDeliveriesState;
|
|
108
|
+
/**
|
|
109
|
+
* What {@link useWebhookDelivery} returns.
|
|
110
|
+
*
|
|
111
|
+
* @stability experimental
|
|
112
|
+
*/
|
|
113
|
+
export interface WebhookDeliveryState {
|
|
114
|
+
/** The delivery with its payload and request headers, once loaded. */
|
|
115
|
+
delivery: WebhookDeliveryDetail | null;
|
|
116
|
+
/** Whether a load is in flight. */
|
|
117
|
+
isLoading: boolean;
|
|
118
|
+
/** A load failure, in words. */
|
|
119
|
+
error: string | null;
|
|
120
|
+
/** Reloads now. */
|
|
121
|
+
refresh: () => Promise<void>;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* One delivery with its body and headers (`GET <base>/deliveries/:id`).
|
|
125
|
+
*
|
|
126
|
+
* @param scope - `user`, `org` or `system`.
|
|
127
|
+
* @param deliveryId - the delivery, or `null` for none.
|
|
128
|
+
* @returns the delivery and the load state.
|
|
129
|
+
*
|
|
130
|
+
* @extensionPoint hook
|
|
131
|
+
* @stability experimental
|
|
132
|
+
*/
|
|
133
|
+
export declare function useWebhookDelivery(scope: WebhookScope, deliveryId: string | null): WebhookDeliveryState;
|
|
134
|
+
/**
|
|
135
|
+
* What {@link useWebhookEventCatalog} returns.
|
|
136
|
+
*
|
|
137
|
+
* @stability experimental
|
|
138
|
+
*/
|
|
139
|
+
export interface WebhookEventCatalogState {
|
|
140
|
+
/** The events the caller may subscribe to, in catalog order. */
|
|
141
|
+
entries: WebhookEventCatalogEntry[];
|
|
142
|
+
/** The same, grouped for the picker. */
|
|
143
|
+
groups: WebhookEventGroup[];
|
|
144
|
+
/** Whether the load is in flight. */
|
|
145
|
+
isLoading: boolean;
|
|
146
|
+
/** A load failure, in words. */
|
|
147
|
+
error: string | null;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The event catalog of a scope (`GET <base>/events`), already filtered by the
|
|
151
|
+
* API to what the caller may subscribe to.
|
|
152
|
+
*
|
|
153
|
+
* @param scope - `user`, `org` or `system`.
|
|
154
|
+
* @param options - `enabled: false` skips the request (a read-only viewer never opens the picker).
|
|
155
|
+
* @returns the catalog and the load state.
|
|
156
|
+
*
|
|
157
|
+
* @extensionPoint hook
|
|
158
|
+
* @stability experimental
|
|
159
|
+
*/
|
|
160
|
+
export declare function useWebhookEventCatalog(scope: WebhookScope, options?: {
|
|
161
|
+
enabled?: boolean;
|
|
162
|
+
}): WebhookEventCatalogState;
|
|
163
|
+
/**
|
|
164
|
+
* What {@link useWebhookMutations} returns. Each action resolves with the
|
|
165
|
+
* API's answer, or `null` when it refused (see `error`).
|
|
166
|
+
*
|
|
167
|
+
* @stability experimental
|
|
168
|
+
*/
|
|
169
|
+
export interface WebhookMutations {
|
|
170
|
+
/** `POST <base>`: the endpoint and its secret, shown once. */
|
|
171
|
+
create: (input: CreateWebhookEndpointInput) => Promise<WebhookEndpointCreated | null>;
|
|
172
|
+
/** `PATCH <base>/:id`. */
|
|
173
|
+
update: (id: string, patch: UpdateWebhookEndpoint) => Promise<WebhookEndpoint | null>;
|
|
174
|
+
/** `DELETE <base>/:id`; resolves `true` on success. */
|
|
175
|
+
remove: (id: string) => Promise<boolean>;
|
|
176
|
+
/** `POST <base>/:id/rotate-secret`: the new secret, shown once. */
|
|
177
|
+
rotateSecret: (id: string) => Promise<RotateWebhookSecretResponse | null>;
|
|
178
|
+
/** `POST <base>/:id/test`: the queued ping delivery. */
|
|
179
|
+
sendTest: (id: string) => Promise<WebhookTestResponse | null>;
|
|
180
|
+
/** `POST <base>/deliveries/:id/redeliver`; resolves `true` on success. */
|
|
181
|
+
redeliver: (deliveryId: string) => Promise<boolean>;
|
|
182
|
+
/** Whether a write is in flight. */
|
|
183
|
+
pending: boolean;
|
|
184
|
+
/** The last refusal, in words. */
|
|
185
|
+
error: string | null;
|
|
186
|
+
/** Clears `error`. */
|
|
187
|
+
reset: () => void;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The webhook writes of one scope, with one shared pending flag and error.
|
|
191
|
+
*
|
|
192
|
+
* @param scope - `user`, `org` or `system`.
|
|
193
|
+
* @returns the actions and their state.
|
|
194
|
+
*
|
|
195
|
+
* @extensionPoint hook
|
|
196
|
+
* @stability experimental
|
|
197
|
+
*/
|
|
198
|
+
export declare function useWebhookMutations(scope: WebhookScope): WebhookMutations;
|
|
199
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/webhooks/headless/hooks.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,0BAA0B,EAC1B,2BAA2B,EAC3B,qBAAqB,EACrB,eAAe,EACf,qBAAqB,EACrB,eAAe,EACf,sBAAsB,EACtB,wBAAwB,EACxB,YAAY,EACZ,mBAAmB,EACpB,MAAM,wCAAwC,CAAC;AAGhD,OAAO,EAAqB,KAAK,sBAAsB,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/F,OAAO,EAA4B,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAaxF;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM5E;AAqDD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,WAAW,CAG/D;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,yCAAyC;IACzC,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,gCAAgC;IAChC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,mBAAmB;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,qBAAqB,CAK9E;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,iCAAiC;IACjC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,gCAAgC;IAChC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,mBAAmB;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,oBAAoB,CAK/F;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,4CAA4C;IAC5C,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,gCAAgC;IAChC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,oCAAoC;IACpC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,YAAY,EACnB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,KAAK,GAAE,sBAA2B,GACjC,sBAAsB,CAyBxB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,sEAAsE;IACtE,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACvC,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,gCAAgC;IAChC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,mBAAmB;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,oBAAoB,CAKvG;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,gEAAgE;IAChE,OAAO,EAAE,wBAAwB,EAAE,CAAC;IACpC,wCAAwC;IACxC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,gCAAgC;IAChC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,wBAAwB,CAQzH;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,MAAM,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IACtF,0BAA0B;IAC1B,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB,KAAK,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IACtF,uDAAuD;IACvD,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,mEAAmE;IACnE,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,CAAC;IAC1E,wDAAwD;IACxD,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IAC9D,0EAA0E;IAC1E,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,oCAAoC;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,kCAAkC;IAClC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,sBAAsB;IACtB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,gBAAgB,CAwCzE"}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// The webhooks hooks (issue #1046): reads with a load state, and the writes
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// Every hook takes the scope and talks to that scope's routes only. A failure
|
|
6
|
+
// becomes a sentence in `error` (the API's message, or a stable code mapped to
|
|
7
|
+
// words); a write resolves with `null` instead of throwing.
|
|
8
|
+
// =============================================================================
|
|
9
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
10
|
+
import { WEBHOOK_ERROR_CODES } from '@marinoscar/platform-contract/webhooks';
|
|
11
|
+
import { isPlatformApiError, usePlatformApi } from '../../core/index.js';
|
|
12
|
+
import { createWebhooksApi } from './client.js';
|
|
13
|
+
import { groupWebhookEventCatalog } from './event-selection.js';
|
|
14
|
+
const CODE_MESSAGES = {
|
|
15
|
+
[WEBHOOK_ERROR_CODES.WEBHOOK_NOT_FOUND]: 'That webhook endpoint no longer exists.',
|
|
16
|
+
[WEBHOOK_ERROR_CODES.WEBHOOK_DELIVERY_NOT_FOUND]: 'That delivery no longer exists.',
|
|
17
|
+
[WEBHOOK_ERROR_CODES.WEBHOOK_URL_INVALID]: 'Enter a valid https:// URL.',
|
|
18
|
+
[WEBHOOK_ERROR_CODES.WEBHOOK_URL_FORBIDDEN]: 'That URL points at a private or internal address, which webhooks may not call.',
|
|
19
|
+
[WEBHOOK_ERROR_CODES.WEBHOOK_EVENT_UNKNOWN]: 'One of the selected events does not exist.',
|
|
20
|
+
[WEBHOOK_ERROR_CODES.WEBHOOK_EVENT_NOT_PERMITTED]: 'One of the selected events is not available to you.',
|
|
21
|
+
[WEBHOOK_ERROR_CODES.WEBHOOK_LIMIT_REACHED]: 'The maximum number of webhook endpoints has been reached.',
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* A webhook API failure in words: the stable error code's sentence, else the
|
|
25
|
+
* API's message, else `fallback`.
|
|
26
|
+
*
|
|
27
|
+
* @param error - what the call rejected with.
|
|
28
|
+
* @param fallback - the sentence when nothing better is known.
|
|
29
|
+
* @returns the message.
|
|
30
|
+
*
|
|
31
|
+
* @stability experimental
|
|
32
|
+
*/
|
|
33
|
+
export function webhookErrorMessage(error, fallback) {
|
|
34
|
+
if (isPlatformApiError(error)) {
|
|
35
|
+
if (typeof error.code === 'string' && CODE_MESSAGES[error.code])
|
|
36
|
+
return CODE_MESSAGES[error.code];
|
|
37
|
+
if (typeof error.message === 'string' && error.message !== '')
|
|
38
|
+
return error.message;
|
|
39
|
+
}
|
|
40
|
+
return fallback;
|
|
41
|
+
}
|
|
42
|
+
function useMounted() {
|
|
43
|
+
const mounted = useRef(true);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
mounted.current = true;
|
|
46
|
+
return () => {
|
|
47
|
+
mounted.current = false;
|
|
48
|
+
};
|
|
49
|
+
}, []);
|
|
50
|
+
return useCallback(() => mounted.current, []);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Runs `load` now and on `refresh`, keeping only the newest answer.
|
|
54
|
+
*/
|
|
55
|
+
function useLoad(load, fallback) {
|
|
56
|
+
const mounted = useMounted();
|
|
57
|
+
const [data, setData] = useState(null);
|
|
58
|
+
const [isLoading, setIsLoading] = useState(load !== null);
|
|
59
|
+
const [error, setError] = useState(null);
|
|
60
|
+
const seq = useRef(0);
|
|
61
|
+
const refresh = useCallback(async () => {
|
|
62
|
+
if (!load)
|
|
63
|
+
return;
|
|
64
|
+
const ticket = ++seq.current;
|
|
65
|
+
setIsLoading(true);
|
|
66
|
+
try {
|
|
67
|
+
const next = await load();
|
|
68
|
+
if (!mounted() || ticket !== seq.current)
|
|
69
|
+
return;
|
|
70
|
+
setData(next);
|
|
71
|
+
setError(null);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
if (mounted() && ticket === seq.current)
|
|
75
|
+
setError(webhookErrorMessage(err, fallback));
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
if (mounted() && ticket === seq.current)
|
|
79
|
+
setIsLoading(false);
|
|
80
|
+
}
|
|
81
|
+
}, [load, fallback, mounted]);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (!load) {
|
|
84
|
+
seq.current += 1;
|
|
85
|
+
setData(null);
|
|
86
|
+
setIsLoading(false);
|
|
87
|
+
setError(null);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
void refresh();
|
|
91
|
+
}, [load, refresh]);
|
|
92
|
+
return { data, isLoading, error, refresh };
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The webhooks client of one scope over the host's transport, memoised.
|
|
96
|
+
*
|
|
97
|
+
* @param scope - `user`, `org` or `system`.
|
|
98
|
+
* @returns the client.
|
|
99
|
+
*
|
|
100
|
+
* @stability experimental
|
|
101
|
+
*/
|
|
102
|
+
export function useWebhooksApi(scope) {
|
|
103
|
+
const api = usePlatformApi();
|
|
104
|
+
return useMemo(() => createWebhooksApi(api, scope), [api, scope]);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The endpoints the caller may see at a scope (`GET <base>`).
|
|
108
|
+
*
|
|
109
|
+
* @param scope - `user`, `org` or `system`.
|
|
110
|
+
* @returns the endpoints and the load state.
|
|
111
|
+
*
|
|
112
|
+
* @extensionPoint hook
|
|
113
|
+
* @stability experimental
|
|
114
|
+
*/
|
|
115
|
+
export function useWebhookEndpoints(scope) {
|
|
116
|
+
const client = useWebhooksApi(scope);
|
|
117
|
+
const load = useCallback(() => client.list(), [client]);
|
|
118
|
+
const { data, isLoading, error, refresh } = useLoad(load, 'Could not load the webhook endpoints.');
|
|
119
|
+
return { endpoints: data?.items ?? [], isLoading, error, refresh };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* One endpoint (`GET <base>/:id`).
|
|
123
|
+
*
|
|
124
|
+
* @param scope - `user`, `org` or `system`.
|
|
125
|
+
* @param id - the endpoint id, or `null` for none.
|
|
126
|
+
* @returns the endpoint and the load state.
|
|
127
|
+
*
|
|
128
|
+
* @extensionPoint hook
|
|
129
|
+
* @stability experimental
|
|
130
|
+
*/
|
|
131
|
+
export function useWebhookEndpoint(scope, id) {
|
|
132
|
+
const client = useWebhooksApi(scope);
|
|
133
|
+
const load = useMemo(() => (id ? () => client.get(id) : null), [client, id]);
|
|
134
|
+
const { data, isLoading, error, refresh } = useLoad(load, 'Could not load the webhook endpoint.');
|
|
135
|
+
return { endpoint: data, isLoading, error, refresh };
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* One page of an endpoint's deliveries
|
|
139
|
+
* (`GET <base>/:id/deliveries?page&pageSize&status&eventKey`), reloaded when
|
|
140
|
+
* the endpoint, the page or a filter changes.
|
|
141
|
+
*
|
|
142
|
+
* @param scope - `user`, `org` or `system`.
|
|
143
|
+
* @param endpointId - the endpoint, or `null` for none.
|
|
144
|
+
* @param query - the one-based page, page size and filters.
|
|
145
|
+
* @returns the page and the load state.
|
|
146
|
+
*
|
|
147
|
+
* @extensionPoint hook
|
|
148
|
+
* @stability experimental
|
|
149
|
+
*/
|
|
150
|
+
export function useWebhookDeliveries(scope, endpointId, query = {}) {
|
|
151
|
+
const client = useWebhooksApi(scope);
|
|
152
|
+
const { page, pageSize, status, eventKey } = query;
|
|
153
|
+
const load = useMemo(() => endpointId
|
|
154
|
+
? () => client.listDeliveries(endpointId, {
|
|
155
|
+
...(page === undefined ? {} : { page }),
|
|
156
|
+
...(pageSize === undefined ? {} : { pageSize }),
|
|
157
|
+
...(status ? { status } : {}),
|
|
158
|
+
...(eventKey ? { eventKey } : {}),
|
|
159
|
+
})
|
|
160
|
+
: null, [client, endpointId, page, pageSize, status, eventKey]);
|
|
161
|
+
const { data, isLoading, error, refresh } = useLoad(load, 'Could not load the deliveries.');
|
|
162
|
+
return {
|
|
163
|
+
deliveries: data?.items ?? [],
|
|
164
|
+
total: data?.total ?? 0,
|
|
165
|
+
totalPages: data?.totalPages ?? 0,
|
|
166
|
+
isLoading,
|
|
167
|
+
error,
|
|
168
|
+
refresh,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* One delivery with its body and headers (`GET <base>/deliveries/:id`).
|
|
173
|
+
*
|
|
174
|
+
* @param scope - `user`, `org` or `system`.
|
|
175
|
+
* @param deliveryId - the delivery, or `null` for none.
|
|
176
|
+
* @returns the delivery and the load state.
|
|
177
|
+
*
|
|
178
|
+
* @extensionPoint hook
|
|
179
|
+
* @stability experimental
|
|
180
|
+
*/
|
|
181
|
+
export function useWebhookDelivery(scope, deliveryId) {
|
|
182
|
+
const client = useWebhooksApi(scope);
|
|
183
|
+
const load = useMemo(() => (deliveryId ? () => client.getDelivery(deliveryId) : null), [client, deliveryId]);
|
|
184
|
+
const { data, isLoading, error, refresh } = useLoad(load, 'Could not load the delivery.');
|
|
185
|
+
return { delivery: data, isLoading, error, refresh };
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* The event catalog of a scope (`GET <base>/events`), already filtered by the
|
|
189
|
+
* API to what the caller may subscribe to.
|
|
190
|
+
*
|
|
191
|
+
* @param scope - `user`, `org` or `system`.
|
|
192
|
+
* @param options - `enabled: false` skips the request (a read-only viewer never opens the picker).
|
|
193
|
+
* @returns the catalog and the load state.
|
|
194
|
+
*
|
|
195
|
+
* @extensionPoint hook
|
|
196
|
+
* @stability experimental
|
|
197
|
+
*/
|
|
198
|
+
export function useWebhookEventCatalog(scope, options = {}) {
|
|
199
|
+
const enabled = options.enabled ?? true;
|
|
200
|
+
const client = useWebhooksApi(scope);
|
|
201
|
+
const load = useMemo(() => (enabled ? () => client.eventCatalog() : null), [client, enabled]);
|
|
202
|
+
const { data, isLoading, error } = useLoad(load, 'Could not load the available events.');
|
|
203
|
+
const entries = useMemo(() => data?.items ?? [], [data]);
|
|
204
|
+
const groups = useMemo(() => groupWebhookEventCatalog(entries), [entries]);
|
|
205
|
+
return { entries, groups, isLoading, error };
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* The webhook writes of one scope, with one shared pending flag and error.
|
|
209
|
+
*
|
|
210
|
+
* @param scope - `user`, `org` or `system`.
|
|
211
|
+
* @returns the actions and their state.
|
|
212
|
+
*
|
|
213
|
+
* @extensionPoint hook
|
|
214
|
+
* @stability experimental
|
|
215
|
+
*/
|
|
216
|
+
export function useWebhookMutations(scope) {
|
|
217
|
+
const client = useWebhooksApi(scope);
|
|
218
|
+
const mounted = useMounted();
|
|
219
|
+
const [pendingCount, setPendingCount] = useState(0);
|
|
220
|
+
const [error, setError] = useState(null);
|
|
221
|
+
const run = useCallback(async (call, fallback) => {
|
|
222
|
+
setPendingCount((count) => count + 1);
|
|
223
|
+
setError(null);
|
|
224
|
+
try {
|
|
225
|
+
return await call();
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
if (mounted())
|
|
229
|
+
setError(webhookErrorMessage(err, fallback));
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
finally {
|
|
233
|
+
if (mounted())
|
|
234
|
+
setPendingCount((count) => count - 1);
|
|
235
|
+
}
|
|
236
|
+
}, [mounted]);
|
|
237
|
+
return {
|
|
238
|
+
create: useCallback((input) => run(() => client.create(input), 'The endpoint could not be created.'), [client, run]),
|
|
239
|
+
update: useCallback((id, patch) => run(() => client.update(id, patch), 'The endpoint could not be saved.'), [client, run]),
|
|
240
|
+
remove: useCallback(async (id) => (await run(async () => (await client.remove(id), true), 'The endpoint could not be deleted.')) === true, [client, run]),
|
|
241
|
+
rotateSecret: useCallback((id) => run(() => client.rotateSecret(id), 'The secret could not be rotated.'), [client, run]),
|
|
242
|
+
sendTest: useCallback((id) => run(() => client.sendTest(id), 'The test event could not be sent.'), [client, run]),
|
|
243
|
+
redeliver: useCallback(async (deliveryId) => (await run(async () => (await client.redeliver(deliveryId), true), 'The delivery could not be queued again.')) === true, [client, run]),
|
|
244
|
+
pending: pendingCount > 0,
|
|
245
|
+
error,
|
|
246
|
+
reset: useCallback(() => setError(null), []),
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=hooks.js.map
|