@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,28 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Props of {@link FiringAlertsBanner}.
|
|
4
|
+
*
|
|
5
|
+
* @stability experimental
|
|
6
|
+
*/
|
|
7
|
+
export interface FiringAlertsBannerProps {
|
|
8
|
+
/** Where "View incidents" goes; default the Alerts page's Incidents tab. */
|
|
9
|
+
to?: string;
|
|
10
|
+
/** The poll interval in milliseconds; default 30 000. */
|
|
11
|
+
intervalMs?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The number of firing alerts by severity, with a link to the incidents.
|
|
15
|
+
*
|
|
16
|
+
* @param props - see {@link FiringAlertsBannerProps}.
|
|
17
|
+
* @returns the banner, or `null` when nothing is firing.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <TelemetryDashboardPage slots={{ BeforeContent: () => <FiringAlertsBanner /> }} />
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @extensionPoint component
|
|
25
|
+
* @stability experimental
|
|
26
|
+
*/
|
|
27
|
+
export declare function FiringAlertsBanner({ to, intervalMs }?: FiringAlertsBannerProps): ReactElement | null;
|
|
28
|
+
//# sourceMappingURL=FiringAlertsBanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FiringAlertsBanner.d.ts","sourceRoot":"","sources":["../../../src/alerts/ui/FiringAlertsBanner.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAU1C;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,4EAA4E;IAC5E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAQD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAA6C,EAAE,UAAU,EAAE,GAAE,uBAA4B,GAAG,YAAY,GAAG,IAAI,CAgCnJ"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// The firing-alerts banner (issue #1047): how many alerts are firing now, by
|
|
3
|
+
// severity, linking to the Alerts page's incidents. Built for the telemetry
|
|
4
|
+
// dashboard's `BeforeContent` slot (the app passes it; telemetry does not
|
|
5
|
+
// depend on alerts), and usable on any page. Draws nothing while nothing is
|
|
6
|
+
// firing, before the first answer, or for a viewer without `alerts:read`.
|
|
7
|
+
import { Alert, AlertTitle, Button, Stack } from '@mui/material';
|
|
8
|
+
import { Link as RouterLink } from 'react-router-dom';
|
|
9
|
+
import { ALERT_PERMISSIONS, ALERT_SEVERITIES } from '@marinoscar/platform-contract/alerts';
|
|
10
|
+
import { usePlatformViewer } from '../../core/index.js';
|
|
11
|
+
import { ALERT_SEVERITY_LABELS, alertFiringTotal, alertTopSeverity, useAlertSummary } from '../headless/index.js';
|
|
12
|
+
import { ALERTS_PAGE_COPY } from './copy.js';
|
|
13
|
+
import { SeverityChip } from './parts.js';
|
|
14
|
+
const ALERT_SEVERITY_FOR = {
|
|
15
|
+
critical: 'error',
|
|
16
|
+
warning: 'warning',
|
|
17
|
+
info: 'info',
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* The number of firing alerts by severity, with a link to the incidents.
|
|
21
|
+
*
|
|
22
|
+
* @param props - see {@link FiringAlertsBannerProps}.
|
|
23
|
+
* @returns the banner, or `null` when nothing is firing.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* <TelemetryDashboardPage slots={{ BeforeContent: () => <FiringAlertsBanner /> }} />
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @extensionPoint component
|
|
31
|
+
* @stability experimental
|
|
32
|
+
*/
|
|
33
|
+
export function FiringAlertsBanner({ to = `${ALERTS_PAGE_COPY.path}?tab=incidents`, intervalMs } = {}) {
|
|
34
|
+
const viewer = usePlatformViewer();
|
|
35
|
+
const allowed = viewer.hasPermission(ALERT_PERMISSIONS.READ);
|
|
36
|
+
const { summary } = useAlertSummary({ enabled: allowed, ...(intervalMs === undefined ? {} : { intervalMs }) });
|
|
37
|
+
const total = alertFiringTotal(summary);
|
|
38
|
+
const top = alertTopSeverity(summary);
|
|
39
|
+
if (!allowed || !summary || total === 0 || !top)
|
|
40
|
+
return null;
|
|
41
|
+
return (_jsxs(Alert, { severity: ALERT_SEVERITY_FOR[top] ?? 'warning', sx: { mb: 2 }, "data-testid": "firing-alerts-banner", action: _jsx(Button, { component: RouterLink, to: to, color: "inherit", size: "small", sx: { minHeight: 44 }, children: "View incidents" }), children: [_jsx(AlertTitle, { children: total === 1 ? '1 alert is firing' : `${total} alerts are firing` }), _jsx(Stack, { direction: "row", spacing: 1, useFlexGap: true, sx: { flexWrap: 'wrap' }, children: ALERT_SEVERITIES.filter((severity) => summary.firing[severity] > 0)
|
|
42
|
+
.reverse()
|
|
43
|
+
.map((severity) => (_jsx(SeverityChip, { severity: severity, label: `${summary.firing[severity]} ${ALERT_SEVERITY_LABELS[severity].toLowerCase()}` }, severity))) })] }));
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=FiringAlertsBanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FiringAlertsBanner.js","sourceRoot":"","sources":["../../../src/alerts/ui/FiringAlertsBanner.tsx"],"names":[],"mappings":";AAAA,6EAA6E;AAC7E,4EAA4E;AAC5E,0EAA0E;AAC1E,4EAA4E;AAC5E,0EAA0E;AAE1E,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAE3F,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAClH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAc1C,MAAM,kBAAkB,GAA2D;IACjF,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;CACb,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAAC,EAAE,EAAE,GAAG,GAAG,gBAAgB,CAAC,IAAI,gBAAgB,EAAE,UAAU,KAA8B,EAAE;IAC5H,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC7D,MAAM,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/G,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAC7D,OAAO,CACL,MAAC,KAAK,IACJ,QAAQ,EAAE,kBAAkB,CAAC,GAAG,CAAC,IAAI,SAAS,EAC9C,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,iBACD,sBAAsB,EAClC,MAAM,EACJ,KAAC,MAAM,IAAC,SAAS,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAC,SAAS,EAAC,IAAI,EAAC,OAAO,EAAC,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,+BAEhF,aAGX,KAAC,UAAU,cAAE,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,GAAG,KAAK,oBAAoB,GAAc,EAC3F,KAAC,KAAK,IAAC,SAAS,EAAC,KAAK,EAAC,OAAO,EAAE,CAAC,EAAE,UAAU,QAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,YACnE,gBAAgB,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;qBACjE,OAAO,EAAE;qBACT,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CACjB,KAAC,YAAY,IAEX,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,qBAAqB,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,EAAE,IAFhF,QAAQ,CAGb,CACH,CAAC,GACE,IACF,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The title, description and route of the Alerts page: the registry card's
|
|
3
|
+
* text and the page's heading.
|
|
4
|
+
*
|
|
5
|
+
* @stability experimental
|
|
6
|
+
*/
|
|
7
|
+
export declare const ALERTS_PAGE_COPY: Readonly<{
|
|
8
|
+
/** The card title and the page heading. */
|
|
9
|
+
readonly title: string;
|
|
10
|
+
/** The card text and the page lead. */
|
|
11
|
+
readonly description: string;
|
|
12
|
+
/** The route of the page. */
|
|
13
|
+
readonly path: string;
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=copy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../../../src/alerts/ui/copy.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC;IACtC,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAKC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// The alerts UI's copy (issue #1047), in one place so a fork rewords it once.
|
|
2
|
+
// The card text and the page heading are the same words.
|
|
3
|
+
/**
|
|
4
|
+
* The title, description and route of the Alerts page: the registry card's
|
|
5
|
+
* text and the page's heading.
|
|
6
|
+
*
|
|
7
|
+
* @stability experimental
|
|
8
|
+
*/
|
|
9
|
+
export const ALERTS_PAGE_COPY = Object.freeze({
|
|
10
|
+
title: 'Alerts',
|
|
11
|
+
description: 'Get told when something needs attention: metric thresholds, worker node events, offline nodes and the dashboard verdict, with the incidents they raised.',
|
|
12
|
+
path: '/admin/settings/alerts',
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=copy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy.js","sourceRoot":"","sources":["../../../src/alerts/ui/copy.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,yDAAyD;AAEzD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAOxB,MAAM,CAAC,MAAM,CAAC;IACjB,KAAK,EAAE,QAAQ;IACf,WAAW,EACT,0JAA0J;IAC5J,IAAI,EAAE,wBAAwB;CAC/B,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { ALERTS_PAGE_COPY } from './copy.js';
|
|
2
|
+
export { alertsAdminCards } from './settings.js';
|
|
3
|
+
export type { AlertsAdminCard } from './settings.js';
|
|
4
|
+
export { AlertIncidentDrawer } from './AlertIncidentDrawer.js';
|
|
5
|
+
export type { AlertIncidentDrawerProps } from './AlertIncidentDrawer.js';
|
|
6
|
+
export { AlertRuleDialog } from './AlertRuleDialog.js';
|
|
7
|
+
export type { AlertRuleDialogProps } from './AlertRuleDialog.js';
|
|
8
|
+
export { AlertRuleTestResult } from './AlertRuleTestResult.js';
|
|
9
|
+
export type { AlertRuleTestResultProps } from './AlertRuleTestResult.js';
|
|
10
|
+
export { AlertsPage } from './AlertsPage.js';
|
|
11
|
+
export type { AlertsPageProps, AlertsPageSlots } from './AlertsPage.js';
|
|
12
|
+
export { FiringAlertsBanner } from './FiringAlertsBanner.js';
|
|
13
|
+
export type { FiringAlertsBannerProps } from './FiringAlertsBanner.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/alerts/ui/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// `@marinoscar/platform-web/alerts/ui`: the Alerts page (Rules and Incidents
|
|
2
|
+
// tabs), the rule editor, the dry-run result, the incident drawer, the firing
|
|
3
|
+
// banner for the telemetry dashboard and the admin card as data, built on
|
|
4
|
+
// `/alerts/headless` (issue #1047). Documented in ../README.md.
|
|
5
|
+
export { ALERTS_PAGE_COPY } from './copy.js';
|
|
6
|
+
export { alertsAdminCards } from './settings.js';
|
|
7
|
+
export { AlertIncidentDrawer } from './AlertIncidentDrawer.js';
|
|
8
|
+
export { AlertRuleDialog } from './AlertRuleDialog.js';
|
|
9
|
+
export { AlertRuleTestResult } from './AlertRuleTestResult.js';
|
|
10
|
+
export { AlertsPage } from './AlertsPage.js';
|
|
11
|
+
export { FiringAlertsBanner } from './FiringAlertsBanner.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/alerts/ui/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,8EAA8E;AAC9E,0EAA0E;AAC1E,gEAAgE;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import type { AlertIncidentState, AlertSeverity } from '@marinoscar/platform-contract/alerts';
|
|
3
|
+
/** A severity as a labelled chip (the words carry the meaning, not the colour). */
|
|
4
|
+
export declare function SeverityChip({ severity, label }: {
|
|
5
|
+
severity: AlertSeverity;
|
|
6
|
+
label?: string;
|
|
7
|
+
}): ReactElement;
|
|
8
|
+
/** An incident state as a labelled chip. */
|
|
9
|
+
export declare function StateChip({ state }: {
|
|
10
|
+
state: AlertIncidentState;
|
|
11
|
+
}): ReactElement;
|
|
12
|
+
/** A timestamp in the display zone, or a dash. */
|
|
13
|
+
export declare function when(iso: string | null | undefined): string;
|
|
14
|
+
export interface ConfirmDialogProps {
|
|
15
|
+
open: boolean;
|
|
16
|
+
title: string;
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
confirmLabel: string;
|
|
19
|
+
destructive?: boolean;
|
|
20
|
+
busy?: boolean;
|
|
21
|
+
onConfirm: () => void;
|
|
22
|
+
onClose: () => void;
|
|
23
|
+
}
|
|
24
|
+
/** A yes/no dialog whose text says what will happen. */
|
|
25
|
+
export declare function ConfirmDialog({ open, title, children, confirmLabel, destructive, busy, onConfirm, onClose }: ConfirmDialogProps): ReactElement;
|
|
26
|
+
//# sourceMappingURL=parts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parts.d.ts","sourceRoot":"","sources":["../../../src/alerts/ui/parts.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAErD,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAe9F,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAE3G;AAED,4CAA4C;AAC5C,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,kBAAkB,CAAA;CAAE,GAAG,YAAY,CAGhF;AAED,kDAAkD;AAClD,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAE3D;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,kBAAkB,GAAG,YAAY,CAiB9I"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Small building blocks of the alerts UI (issue #1047): the severity and state
|
|
3
|
+
// chips, the confirm dialog and the date text. Internal to the slice.
|
|
4
|
+
import { Button, Chip, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@mui/material';
|
|
5
|
+
import { formatDateTime } from '../../core/index.js';
|
|
6
|
+
import { ALERT_SEVERITY_LABELS, ALERT_SEVERITY_TONES, ALERT_STATE_LABELS, ALERT_STATE_TONES, } from '../headless/index.js';
|
|
7
|
+
function chipColor(tone) {
|
|
8
|
+
return tone;
|
|
9
|
+
}
|
|
10
|
+
/** A severity as a labelled chip (the words carry the meaning, not the colour). */
|
|
11
|
+
export function SeverityChip({ severity, label }) {
|
|
12
|
+
return _jsx(Chip, { size: "small", label: label ?? ALERT_SEVERITY_LABELS[severity], color: chipColor(ALERT_SEVERITY_TONES[severity]) });
|
|
13
|
+
}
|
|
14
|
+
/** An incident state as a labelled chip. */
|
|
15
|
+
export function StateChip({ state }) {
|
|
16
|
+
const tone = ALERT_STATE_TONES[state];
|
|
17
|
+
return _jsx(Chip, { size: "small", label: ALERT_STATE_LABELS[state], color: chipColor(tone), variant: state === 'resolved' ? 'outlined' : 'filled' });
|
|
18
|
+
}
|
|
19
|
+
/** A timestamp in the display zone, or a dash. */
|
|
20
|
+
export function when(iso) {
|
|
21
|
+
return iso ? formatDateTime(iso) : '—';
|
|
22
|
+
}
|
|
23
|
+
/** A yes/no dialog whose text says what will happen. */
|
|
24
|
+
export function ConfirmDialog({ open, title, children, confirmLabel, destructive, busy, onConfirm, onClose }) {
|
|
25
|
+
return (_jsxs(Dialog, { open: open, onClose: onClose, maxWidth: "xs", fullWidth: true, "aria-labelledby": "alerts-confirm-title", children: [_jsx(DialogTitle, { id: "alerts-confirm-title", children: title }), _jsx(DialogContent, { children: _jsx(DialogContentText, { component: "div", children: children }) }), _jsxs(DialogActions, { children: [_jsx(Button, { onClick: onClose, sx: { minHeight: 44 }, children: "Cancel" }), _jsx(Button, { variant: "contained", color: destructive ? 'error' : 'primary', onClick: onConfirm, disabled: busy, sx: { minHeight: 44 }, children: confirmLabel })] })] }));
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=parts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parts.js","sourceRoot":"","sources":["../../../src/alerts/ui/parts.tsx"],"names":[],"mappings":";AAAA,+EAA+E;AAC/E,sEAAsE;AAEtE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAKnH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,GAElB,MAAM,sBAAsB,CAAC;AAE9B,SAAS,SAAS,CAAC,IAAe;IAChC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAA+C;IAC3F,OAAO,KAAC,IAAI,IAAC,IAAI,EAAC,OAAO,EAAC,KAAK,EAAE,KAAK,IAAI,qBAAqB,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,GAAI,CAAC;AAClI,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,SAAS,CAAC,EAAE,KAAK,EAAiC;IAChE,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO,KAAC,IAAI,IAAC,IAAI,EAAC,OAAO,EAAC,KAAK,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,GAAI,CAAC;AAChJ,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,IAAI,CAAC,GAA8B;IACjD,OAAO,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACzC,CAAC;AAaD,wDAAwD;AACxD,MAAM,UAAU,aAAa,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAsB;IAC9H,OAAO,CACL,MAAC,MAAM,IAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAC,IAAI,EAAC,SAAS,2BAAiB,sBAAsB,aAClG,KAAC,WAAW,IAAC,EAAE,EAAC,sBAAsB,YAAE,KAAK,GAAe,EAC5D,KAAC,aAAa,cACZ,KAAC,iBAAiB,IAAC,SAAS,EAAC,KAAK,YAAE,QAAQ,GAAqB,GACnD,EAChB,MAAC,aAAa,eACZ,KAAC,MAAM,IAAC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,uBAEtC,EACT,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,EAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,YAC5H,YAAY,GACN,IACK,IACT,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { PlatformSettingsPage } from '../../core/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* One alerts registry card: the `PlatformSettingsPage` card shape plus its
|
|
4
|
+
* icon, structurally a `SettingsCardDef` of the reference app.
|
|
5
|
+
*
|
|
6
|
+
* @stability experimental
|
|
7
|
+
*/
|
|
8
|
+
export type AlertsAdminCard = PlatformSettingsPage<never>['card'] & {
|
|
9
|
+
/** The card and rail icon (an MUI SvgIcon). */
|
|
10
|
+
Icon: PlatformSettingsPage['Icon'];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* The Observability card of the alerts slice: `Alerts`
|
|
14
|
+
* (`/admin/settings/alerts`, `alerts:read`, no `feature`). Route it to
|
|
15
|
+
* `<AlertsPage />`.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* // apps/web/src/config/adminSections.tsx, the Observability section
|
|
20
|
+
* cards: [...telemetryAdminCards, doctorCard, ...alertsAdminCards],
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @extensionPoint component
|
|
24
|
+
* @stability experimental
|
|
25
|
+
*/
|
|
26
|
+
export declare const alertsAdminCards: readonly AlertsAdminCard[];
|
|
27
|
+
//# sourceMappingURL=settings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/alerts/ui/settings.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGhE;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG;IAClE,+CAA+C;IAC/C,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,CAAC;CACpC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,eAAe,EAQrD,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// The alerts slice's admin registry card (issue #1047). DATA, not a new
|
|
2
|
+
// registry: the app declares every card in its own `ADMIN_SECTIONS` and
|
|
3
|
+
// spreads this one where it belongs (the Observability section). No page
|
|
4
|
+
// component is referenced here, so importing the card never pulls the page
|
|
5
|
+
// into the app's main chunk.
|
|
6
|
+
//
|
|
7
|
+
// `alerts:read` is the exact string every read route of the packaged
|
|
8
|
+
// `/api/admin/alerts` controller enforces (`ALERT_PERMISSIONS.READ` of
|
|
9
|
+
// `@marinoscar/platform-contract/alerts`); writes (`alerts:write`) are gated
|
|
10
|
+
// inside the page. NO `feature`: node rules work with telemetry switched off.
|
|
11
|
+
import NotificationImportantOutlinedIcon from '@mui/icons-material/NotificationImportantOutlined';
|
|
12
|
+
import { ALERT_PERMISSIONS } from '@marinoscar/platform-contract/alerts';
|
|
13
|
+
import { ALERTS_PAGE_COPY } from './copy.js';
|
|
14
|
+
/**
|
|
15
|
+
* The Observability card of the alerts slice: `Alerts`
|
|
16
|
+
* (`/admin/settings/alerts`, `alerts:read`, no `feature`). Route it to
|
|
17
|
+
* `<AlertsPage />`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* // apps/web/src/config/adminSections.tsx, the Observability section
|
|
22
|
+
* cards: [...telemetryAdminCards, doctorCard, ...alertsAdminCards],
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @extensionPoint component
|
|
26
|
+
* @stability experimental
|
|
27
|
+
*/
|
|
28
|
+
export const alertsAdminCards = Object.freeze([
|
|
29
|
+
{
|
|
30
|
+
title: ALERTS_PAGE_COPY.title,
|
|
31
|
+
description: ALERTS_PAGE_COPY.description,
|
|
32
|
+
path: ALERTS_PAGE_COPY.path,
|
|
33
|
+
Icon: NotificationImportantOutlinedIcon,
|
|
34
|
+
permission: ALERT_PERMISSIONS.READ,
|
|
35
|
+
},
|
|
36
|
+
]);
|
|
37
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/alerts/ui/settings.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,wEAAwE;AACxE,yEAAyE;AACzE,2EAA2E;AAC3E,6BAA6B;AAC7B,EAAE;AACF,qEAAqE;AACrE,uEAAuE;AACvE,6EAA6E;AAC7E,8EAA8E;AAE9E,OAAO,iCAAiC,MAAM,mDAAmD,CAAC;AAClG,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAGzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAa7C;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA+B,MAAM,CAAC,MAAM,CAAC;IACxE;QACE,KAAK,EAAE,gBAAgB,CAAC,KAAK;QAC7B,WAAW,EAAE,gBAAgB,CAAC,WAAW;QACzC,IAAI,EAAE,gBAAgB,CAAC,IAAI;QAC3B,IAAI,EAAE,iCAAiC;QACvC,UAAU,EAAE,iBAAiB,CAAC,IAAI;KACnC;CACF,CAAC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PlatformApiClient } from '../../core/index.js';
|
|
2
|
-
import type { CreateNodeCredentialInput, NodeCredential, NodeCredentialCreated, WorkerNode } from './types.js';
|
|
2
|
+
import type { CreateNodeCredentialInput, NodeCredential, NodeCredentialCreated, NodeEventsQuery, WorkerNode, WorkerNodeEventList } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Every call the worker-node page and hooks make. `createNodesApi` builds one
|
|
5
5
|
* over the app's transport; a test or an app with its own client implements it.
|
|
@@ -20,6 +20,8 @@ export interface NodesApi {
|
|
|
20
20
|
createNodeCredential(input: CreateNodeCredentialInput): Promise<NodeCredentialCreated>;
|
|
21
21
|
/** `DELETE /admin/nodes/credentials/:id`: effective on the node's next request; one-way. */
|
|
22
22
|
revokeNodeCredential(id: string): Promise<void>;
|
|
23
|
+
/** `GET /admin/nodes/:id/events`: a page of the node's events, newest first (`nodes:read`). */
|
|
24
|
+
listNodeEvents(nodeId: string, query?: NodeEventsQuery): Promise<WorkerNodeEventList>;
|
|
23
25
|
}
|
|
24
26
|
/**
|
|
25
27
|
* The worker-node client over the app's transport.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/nodes/headless/api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/nodes/headless/api.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EACV,yBAAyB,EACzB,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,8EAA8E;IAC9E,cAAc,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACxC,6DAA6D;IAC7D,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/C,yGAAyG;IACzG,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,6FAA6F;IAC7F,kBAAkB,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAChD,kFAAkF;IAClF,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACvF,4FAA4F;IAC5F,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,+FAA+F;IAC/F,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACvF;AAgBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,QAAQ,CAmBlE"}
|
|
@@ -16,7 +16,28 @@
|
|
|
16
16
|
//
|
|
17
17
|
// `GET /admin/nodes` returns the whole fleet as a bare array, not a page: a
|
|
18
18
|
// fleet is tens of machines, and the page tallies its health verdicts.
|
|
19
|
+
//
|
|
20
|
+
// A node's events (#1045) ARE paged (`GET /admin/nodes/:id/events`): a laptop node
|
|
21
|
+
// on battery reports a change every few minutes, and a timeline only ever
|
|
22
|
+
// needs the newest screenful.
|
|
19
23
|
// =============================================================================
|
|
24
|
+
/**
|
|
25
|
+
* `GET /admin/nodes/:id/events`'s query string: only the members that are set, in a
|
|
26
|
+
* fixed order (page, pageSize, type, severity), so a request is byte-stable.
|
|
27
|
+
*/
|
|
28
|
+
function nodeEventsQueryString(query) {
|
|
29
|
+
const params = new URLSearchParams();
|
|
30
|
+
if (query.page !== undefined)
|
|
31
|
+
params.set('page', String(query.page));
|
|
32
|
+
if (query.pageSize !== undefined)
|
|
33
|
+
params.set('pageSize', String(query.pageSize));
|
|
34
|
+
if (query.type)
|
|
35
|
+
params.set('type', query.type);
|
|
36
|
+
if (query.severity)
|
|
37
|
+
params.set('severity', query.severity);
|
|
38
|
+
const text = params.toString();
|
|
39
|
+
return text ? `?${text}` : '';
|
|
40
|
+
}
|
|
20
41
|
/**
|
|
21
42
|
* The worker-node client over the app's transport.
|
|
22
43
|
*
|
|
@@ -48,6 +69,7 @@ export function createNodesApi(client) {
|
|
|
48
69
|
revokeNodeCredential: async (id) => {
|
|
49
70
|
await client.delete(`/admin/nodes/credentials/${id}`);
|
|
50
71
|
},
|
|
72
|
+
listNodeEvents: (nodeId, query = {}) => client.get(`/admin/nodes/${encodeURIComponent(nodeId)}/events${nodeEventsQueryString(query)}`),
|
|
51
73
|
};
|
|
52
74
|
}
|
|
53
75
|
//# sourceMappingURL=api.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/nodes/headless/api.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,4CAA4C;AAC5C,gFAAgF;AAChF,EAAE;AACF,gFAAgF;AAChF,2EAA2E;AAC3E,8EAA8E;AAC9E,wDAAwD;AACxD,EAAE;AACF,+EAA+E;AAC/E,4EAA4E;AAC5E,4EAA4E;AAC5E,iEAAiE;AACjE,6EAA6E;AAC7E,SAAS;AACT,EAAE;AACF,4EAA4E;AAC5E,uEAAuE;AACvE,gFAAgF;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/nodes/headless/api.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,4CAA4C;AAC5C,gFAAgF;AAChF,EAAE;AACF,gFAAgF;AAChF,2EAA2E;AAC3E,8EAA8E;AAC9E,wDAAwD;AACxD,EAAE;AACF,+EAA+E;AAC/E,4EAA4E;AAC5E,4EAA4E;AAC5E,iEAAiE;AACjE,6EAA6E;AAC7E,SAAS;AACT,EAAE;AACF,4EAA4E;AAC5E,uEAAuE;AACvE,EAAE;AACF,mFAAmF;AACnF,0EAA0E;AAC1E,8BAA8B;AAC9B,gFAAgF;AAoChF;;;GAGG;AACH,SAAS,qBAAqB,CAAC,KAAsB;IACnD,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACrE,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;QAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjF,IAAI,KAAK,CAAC,IAAI;QAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,KAAK,CAAC,QAAQ;QAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC3D,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC/B,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAChC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAAC,MAAyB;IACtD,OAAO;QACL,cAAc,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAe,cAAc,CAAC;QAC9D,aAAa,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAa,gBAAgB,EAAE,EAAE,CAAC;QACnE,gBAAgB,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;YAC7B,MAAM,MAAM,CAAC,MAAM,CAAO,gBAAgB,EAAE,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,kBAAkB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAmB,0BAA0B,CAAC;QAClF,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAE;YAC9B,MAAM,IAAI,GAA8B,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YAC7D,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS;gBAAE,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;YAChF,OAAO,MAAM,CAAC,IAAI,CAAwB,mBAAmB,EAAE,IAAI,CAAC,CAAC;QACvE,CAAC;QACD,oBAAoB,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;YACjC,MAAM,MAAM,CAAC,MAAM,CAAO,4BAA4B,EAAE,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,cAAc,EAAE,CAAC,MAAM,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,CACrC,MAAM,CAAC,GAAG,CAAsB,gBAAgB,kBAAkB,CAAC,MAAM,CAAC,UAAU,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;KACtH,CAAC;AACJ,CAAC"}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export { createNodesApi } from './api.js';
|
|
2
2
|
export type { NodesApi } from './api.js';
|
|
3
|
-
export { MAX_NODE_CREDENTIAL_DAYS, MAX_NODE_CREDENTIAL_NAME_LENGTH, NODE_HEALTHS, NODE_STATUSES, nodeCredentialStatus, } from './types.js';
|
|
4
|
-
export type { CreateNodeCredentialInput, NodeCredential, NodeCredentialCreated, NodeCredentialStatus, NodeHealth, NodeJobCounts, NodeOwner, NodeStatus, NodeVitals, NodeVitalsCounters, WorkerNode, } from './types.js';
|
|
3
|
+
export { MAX_NODE_CREDENTIAL_DAYS, MAX_NODE_CREDENTIAL_NAME_LENGTH, NODE_EVENT_TYPES, NODE_HEALTHS, NODE_STATUSES, nodeCredentialStatus, } from './types.js';
|
|
4
|
+
export type { CreateNodeCredentialInput, NodeCredential, NodeCredentialCreated, NodeCredentialStatus, NodeEventSeverity, NodeEventsQuery, NodeHealth, NodeHostVitals, NodeJobCounts, NodeOwner, NodePower, NodeStatus, NodeVitals, NodeVitalsCounters, WorkerNode, WorkerNodeEvent, WorkerNodeEventList, } from './types.js';
|
|
5
|
+
export { MAX_NODE_EVENT_SUMMARY_ATTRS, humanizeNodeEventType, nodeEventLabel, nodeEventSummary } from './node-events.js';
|
|
6
|
+
export { NODE_BATTERY_CRITICAL_PERCENT, NODE_BATTERY_WARNING_PERCENT, describeNodePower } from './power.js';
|
|
7
|
+
export type { NodePowerDescription } from './power.js';
|
|
8
|
+
export { useNodeEvents } from './use-node-events.js';
|
|
9
|
+
export type { UseNodeEventsResult } from './use-node-events.js';
|
|
5
10
|
export { formatDateTime, formatDuration, shortId } from './format.js';
|
|
6
11
|
export { formatNodeVital, nodeVitalFor, nodeVitalRows, registerNodeVital, registeredNodeVitals } from './node-vitals.js';
|
|
7
12
|
export type { NodeVitalDef, NodeVitalRow, NodeVitalUnit } from './node-vitals.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/nodes/headless/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,YAAY,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,YAAY,EACZ,aAAa,EACb,oBAAoB,GACrB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,yBAAyB,EACzB,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,SAAS,EACT,UAAU,EACV,UAAU,EACV,kBAAkB,EAClB,UAAU,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/nodes/headless/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,YAAY,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,oBAAoB,GACrB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,yBAAyB,EACzB,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,cAAc,EACd,aAAa,EACb,SAAS,EACT,SAAS,EACT,UAAU,EACV,UAAU,EACV,kBAAkB,EAClB,UAAU,EACV,eAAe,EACf,mBAAmB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzH,OAAO,EAAE,6BAA6B,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC5G,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACzH,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7G,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC3F,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACzE,YAAY,EACV,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,wBAAwB,EACxB,mBAAmB,EACnB,gBAAgB,EAChB,6BAA6B,EAC7B,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EACL,6BAA6B,EAC7B,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,cAAc,GACf,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC"}
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
// the data hooks, the visible-tab poll, the adapters and the formatting
|
|
5
5
|
// helpers. Documented in ../README.md. Explicit named exports only.
|
|
6
6
|
export { createNodesApi } from './api.js';
|
|
7
|
-
export { MAX_NODE_CREDENTIAL_DAYS, MAX_NODE_CREDENTIAL_NAME_LENGTH, NODE_HEALTHS, NODE_STATUSES, nodeCredentialStatus, } from './types.js';
|
|
7
|
+
export { MAX_NODE_CREDENTIAL_DAYS, MAX_NODE_CREDENTIAL_NAME_LENGTH, NODE_EVENT_TYPES, NODE_HEALTHS, NODE_STATUSES, nodeCredentialStatus, } from './types.js';
|
|
8
|
+
export { MAX_NODE_EVENT_SUMMARY_ATTRS, humanizeNodeEventType, nodeEventLabel, nodeEventSummary } from './node-events.js';
|
|
9
|
+
export { NODE_BATTERY_CRITICAL_PERCENT, NODE_BATTERY_WARNING_PERCENT, describeNodePower } from './power.js';
|
|
10
|
+
export { useNodeEvents } from './use-node-events.js';
|
|
8
11
|
export { formatDateTime, formatDuration, shortId } from './format.js';
|
|
9
12
|
export { formatNodeVital, nodeVitalFor, nodeVitalRows, registerNodeVital, registeredNodeVitals } from './node-vitals.js';
|
|
10
13
|
export { MAX_CAPABILITY_TEXT_LENGTH, MAX_LISTED_CAPABILITIES, nodeCapabilityItems } from './capabilities.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/nodes/headless/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,4EAA4E;AAC5E,wFAAwF;AACxF,wEAAwE;AACxE,oEAAoE;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,YAAY,EACZ,aAAa,EACb,oBAAoB,GACrB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/nodes/headless/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,4EAA4E;AAC5E,wFAAwF;AACxF,wEAAwE;AACxE,oEAAoE;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAoBpB,OAAO,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzH,OAAO,EAAE,6BAA6B,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE5G,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAEzH,OAAO,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7G,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAc3F,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EACL,6BAA6B,EAC7B,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,cAAc,GACf,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { WorkerNodeEvent } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Most attributes a summary of an unknown event prints.
|
|
4
|
+
*
|
|
5
|
+
* @stability experimental
|
|
6
|
+
*/
|
|
7
|
+
export declare const MAX_NODE_EVENT_SUMMARY_ATTRS = 4;
|
|
8
|
+
/**
|
|
9
|
+
* A dotted event type as words: the last segment is the event, the ones before
|
|
10
|
+
* it its area (`transcode.queue_full` to "Transcode: queue full").
|
|
11
|
+
*
|
|
12
|
+
* @param type - the event's dotted type.
|
|
13
|
+
* @returns the humanized text; the input itself when it has no segments.
|
|
14
|
+
*
|
|
15
|
+
* @stability experimental
|
|
16
|
+
*/
|
|
17
|
+
export declare function humanizeNodeEventType(type: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* How an event type reads: the platform's label for a `NODE_EVENT_TYPES` name,
|
|
20
|
+
* else {@link humanizeNodeEventType}.
|
|
21
|
+
*
|
|
22
|
+
* @param type - the event's dotted type.
|
|
23
|
+
* @returns the label.
|
|
24
|
+
*
|
|
25
|
+
* @stability experimental
|
|
26
|
+
*/
|
|
27
|
+
export declare function nodeEventLabel(type: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* One line that says what an event's attributes mean, or `null` when it has
|
|
30
|
+
* none worth printing.
|
|
31
|
+
*
|
|
32
|
+
* Known types read as a sentence fragment ("AC → Battery (64%)", "12% (threshold
|
|
33
|
+
* 20%)", "Asleep for 2h 03m", "4.5% free (1.2 GB)"); an unknown type, or a known
|
|
34
|
+
* one missing the attributes its fragment needs, reads as `key: value` pairs, at
|
|
35
|
+
* most {@link MAX_NODE_EVENT_SUMMARY_ATTRS} of them, sorted by key.
|
|
36
|
+
*
|
|
37
|
+
* @param event - the event (its `type` and `attrs`).
|
|
38
|
+
* @returns the summary, or `null`.
|
|
39
|
+
*
|
|
40
|
+
* @stability experimental
|
|
41
|
+
*/
|
|
42
|
+
export declare function nodeEventSummary(event: Pick<WorkerNodeEvent, 'type' | 'attrs'>): string | null;
|
|
43
|
+
//# sourceMappingURL=node-events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-events.d.ts","sourceRoot":"","sources":["../../../src/nodes/headless/node-events.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAYlD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAU9C;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAyBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CA4C9F"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Node events: how the Worker Nodes page words one (issue #1045)
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// A node reports what it observed about itself on its heartbeat (a power
|
|
6
|
+
// change, a low battery, a wake from sleep, a low disk); the API stores each one
|
|
7
|
+
// and serves them at `GET /api/admin/nodes/:id/events`. These helpers turn one into
|
|
8
|
+
// text: a label for its type and a one-line summary of its attributes.
|
|
9
|
+
//
|
|
10
|
+
// The type is an OPEN dotted string: an app's node may report its own. A known
|
|
11
|
+
// type (`NODE_EVENT_TYPES`) reads by its label; an unknown one is still shown,
|
|
12
|
+
// humanized from its dotted name (`transcode.queue_full` -> "Transcode: queue
|
|
13
|
+
// full"), never hidden. Attributes are self-reported scalars; they are printed
|
|
14
|
+
// as plain text, bounded, and never turned into a verdict.
|
|
15
|
+
//
|
|
16
|
+
// Pure functions, no markup, so they live in the headless entry.
|
|
17
|
+
// =============================================================================
|
|
18
|
+
import { NODE_EVENT_TYPES } from '@marinoscar/platform-contract/nodes';
|
|
19
|
+
import { formatBytes } from '../internal/format-bytes.js';
|
|
20
|
+
import { formatDuration } from './format.js';
|
|
21
|
+
/** The platform's own event types, as an operator reads them. */
|
|
22
|
+
const NODE_EVENT_LABELS = Object.freeze({
|
|
23
|
+
[NODE_EVENT_TYPES.POWER_SOURCE_CHANGED]: 'Power source changed',
|
|
24
|
+
[NODE_EVENT_TYPES.BATTERY_LOW]: 'Battery low',
|
|
25
|
+
[NODE_EVENT_TYPES.BATTERY_CRITICAL]: 'Battery critical',
|
|
26
|
+
[NODE_EVENT_TYPES.BATTERY_RECOVERED]: 'Battery recovered',
|
|
27
|
+
[NODE_EVENT_TYPES.SLEEP_RESUMED]: 'Resumed from sleep',
|
|
28
|
+
[NODE_EVENT_TYPES.DISK_LOW]: 'Disk space low',
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* Most attributes a summary of an unknown event prints.
|
|
32
|
+
*
|
|
33
|
+
* @stability experimental
|
|
34
|
+
*/
|
|
35
|
+
export const MAX_NODE_EVENT_SUMMARY_ATTRS = 4;
|
|
36
|
+
/** Longest attribute value a summary prints before an ellipsis. */
|
|
37
|
+
const MAX_ATTR_TEXT = 64;
|
|
38
|
+
function sentenceCase(text) {
|
|
39
|
+
const spaced = text.replace(/_/g, ' ').trim();
|
|
40
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A dotted event type as words: the last segment is the event, the ones before
|
|
44
|
+
* it its area (`transcode.queue_full` to "Transcode: queue full").
|
|
45
|
+
*
|
|
46
|
+
* @param type - the event's dotted type.
|
|
47
|
+
* @returns the humanized text; the input itself when it has no segments.
|
|
48
|
+
*
|
|
49
|
+
* @stability experimental
|
|
50
|
+
*/
|
|
51
|
+
export function humanizeNodeEventType(type) {
|
|
52
|
+
const segments = type.split('.').filter((segment) => segment !== '');
|
|
53
|
+
if (segments.length === 0)
|
|
54
|
+
return type;
|
|
55
|
+
if (segments.length === 1)
|
|
56
|
+
return sentenceCase(segments[0]);
|
|
57
|
+
const last = segments[segments.length - 1];
|
|
58
|
+
const area = segments.slice(0, -1).map(sentenceCase).join(' ');
|
|
59
|
+
return `${area}: ${last.replace(/_/g, ' ')}`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* How an event type reads: the platform's label for a `NODE_EVENT_TYPES` name,
|
|
63
|
+
* else {@link humanizeNodeEventType}.
|
|
64
|
+
*
|
|
65
|
+
* @param type - the event's dotted type.
|
|
66
|
+
* @returns the label.
|
|
67
|
+
*
|
|
68
|
+
* @stability experimental
|
|
69
|
+
*/
|
|
70
|
+
export function nodeEventLabel(type) {
|
|
71
|
+
return NODE_EVENT_LABELS[type] ?? humanizeNodeEventType(type);
|
|
72
|
+
}
|
|
73
|
+
function attrNumber(attrs, key) {
|
|
74
|
+
const value = attrs[key];
|
|
75
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
76
|
+
}
|
|
77
|
+
function percent(value) {
|
|
78
|
+
return `${Math.round(value * 10) / 10}%`;
|
|
79
|
+
}
|
|
80
|
+
const POWER_SOURCE_WORDS = Object.freeze({ ac: 'AC', battery: 'Battery', unknown: 'Unknown' });
|
|
81
|
+
function powerSourceWord(value) {
|
|
82
|
+
if (typeof value !== 'string' || value === '')
|
|
83
|
+
return '?';
|
|
84
|
+
return POWER_SOURCE_WORDS[value] ?? value;
|
|
85
|
+
}
|
|
86
|
+
function plainAttr(value) {
|
|
87
|
+
const text = typeof value === 'number' ? value.toLocaleString(undefined, { maximumFractionDigits: 2 }) : String(value);
|
|
88
|
+
return text.length > MAX_ATTR_TEXT ? `${text.slice(0, MAX_ATTR_TEXT - 1)}…` : text;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* One line that says what an event's attributes mean, or `null` when it has
|
|
92
|
+
* none worth printing.
|
|
93
|
+
*
|
|
94
|
+
* Known types read as a sentence fragment ("AC → Battery (64%)", "12% (threshold
|
|
95
|
+
* 20%)", "Asleep for 2h 03m", "4.5% free (1.2 GB)"); an unknown type, or a known
|
|
96
|
+
* one missing the attributes its fragment needs, reads as `key: value` pairs, at
|
|
97
|
+
* most {@link MAX_NODE_EVENT_SUMMARY_ATTRS} of them, sorted by key.
|
|
98
|
+
*
|
|
99
|
+
* @param event - the event (its `type` and `attrs`).
|
|
100
|
+
* @returns the summary, or `null`.
|
|
101
|
+
*
|
|
102
|
+
* @stability experimental
|
|
103
|
+
*/
|
|
104
|
+
export function nodeEventSummary(event) {
|
|
105
|
+
const attrs = event.attrs && typeof event.attrs === 'object' ? event.attrs : {};
|
|
106
|
+
const battery = attrNumber(attrs, 'batteryPercent');
|
|
107
|
+
const threshold = attrNumber(attrs, 'threshold');
|
|
108
|
+
switch (event.type) {
|
|
109
|
+
case NODE_EVENT_TYPES.POWER_SOURCE_CHANGED:
|
|
110
|
+
if (attrs.from !== undefined || attrs.to !== undefined) {
|
|
111
|
+
const change = `${powerSourceWord(attrs.from)} → ${powerSourceWord(attrs.to)}`;
|
|
112
|
+
return battery !== undefined ? `${change} (${percent(battery)})` : change;
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
case NODE_EVENT_TYPES.BATTERY_LOW:
|
|
116
|
+
case NODE_EVENT_TYPES.BATTERY_CRITICAL:
|
|
117
|
+
case NODE_EVENT_TYPES.BATTERY_RECOVERED:
|
|
118
|
+
if (battery !== undefined) {
|
|
119
|
+
return threshold !== undefined ? `${percent(battery)} (threshold ${percent(threshold)})` : percent(battery);
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
case NODE_EVENT_TYPES.SLEEP_RESUMED: {
|
|
123
|
+
const gap = attrNumber(attrs, 'gapSeconds');
|
|
124
|
+
if (gap !== undefined)
|
|
125
|
+
return `Asleep for ${formatDuration(gap * 1000)}`;
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
case NODE_EVENT_TYPES.DISK_LOW: {
|
|
129
|
+
const freePercent = attrNumber(attrs, 'freePercent');
|
|
130
|
+
const freeBytes = attrNumber(attrs, 'freeBytes');
|
|
131
|
+
if (freePercent !== undefined) {
|
|
132
|
+
return freeBytes !== undefined ? `${percent(freePercent)} free (${formatBytes(freeBytes)})` : `${percent(freePercent)} free`;
|
|
133
|
+
}
|
|
134
|
+
if (freeBytes !== undefined)
|
|
135
|
+
return `${formatBytes(freeBytes)} free`;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
default:
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
const entries = Object.entries(attrs)
|
|
142
|
+
.filter(([, value]) => typeof value === 'string' || typeof value === 'boolean' || (typeof value === 'number' && Number.isFinite(value)))
|
|
143
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
|
144
|
+
if (entries.length === 0)
|
|
145
|
+
return null;
|
|
146
|
+
const shown = entries.slice(0, MAX_NODE_EVENT_SUMMARY_ATTRS).map(([key, value]) => `${key}: ${plainAttr(value)}`);
|
|
147
|
+
const rest = entries.length - shown.length;
|
|
148
|
+
return rest > 0 ? `${shown.join(', ')} (+${rest} more)` : shown.join(', ');
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=node-events.js.map
|