@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.
Files changed (174) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +5 -3
  3. package/dist/alerts/headless/client.d.ts +134 -0
  4. package/dist/alerts/headless/client.d.ts.map +1 -0
  5. package/dist/alerts/headless/client.js +105 -0
  6. package/dist/alerts/headless/client.js.map +1 -0
  7. package/dist/alerts/headless/format.d.ts +95 -0
  8. package/dist/alerts/headless/format.d.ts.map +1 -0
  9. package/dist/alerts/headless/format.js +164 -0
  10. package/dist/alerts/headless/format.js.map +1 -0
  11. package/dist/alerts/headless/hooks.d.ts +245 -0
  12. package/dist/alerts/headless/hooks.d.ts.map +1 -0
  13. package/dist/alerts/headless/hooks.js +315 -0
  14. package/dist/alerts/headless/hooks.js.map +1 -0
  15. package/dist/alerts/headless/index.d.ts +9 -0
  16. package/dist/alerts/headless/index.d.ts.map +1 -0
  17. package/dist/alerts/headless/index.js +9 -0
  18. package/dist/alerts/headless/index.js.map +1 -0
  19. package/dist/alerts/headless/rule-draft.d.ts +175 -0
  20. package/dist/alerts/headless/rule-draft.d.ts.map +1 -0
  21. package/dist/alerts/headless/rule-draft.js +261 -0
  22. package/dist/alerts/headless/rule-draft.js.map +1 -0
  23. package/dist/alerts/ui/AlertIncidentDrawer.d.ts +30 -0
  24. package/dist/alerts/ui/AlertIncidentDrawer.d.ts.map +1 -0
  25. package/dist/alerts/ui/AlertIncidentDrawer.js +33 -0
  26. package/dist/alerts/ui/AlertIncidentDrawer.js.map +1 -0
  27. package/dist/alerts/ui/AlertRuleDialog.d.ts +47 -0
  28. package/dist/alerts/ui/AlertRuleDialog.d.ts.map +1 -0
  29. package/dist/alerts/ui/AlertRuleDialog.js +124 -0
  30. package/dist/alerts/ui/AlertRuleDialog.js.map +1 -0
  31. package/dist/alerts/ui/AlertRuleTestResult.d.ts +23 -0
  32. package/dist/alerts/ui/AlertRuleTestResult.d.ts.map +1 -0
  33. package/dist/alerts/ui/AlertRuleTestResult.js +30 -0
  34. package/dist/alerts/ui/AlertRuleTestResult.js.map +1 -0
  35. package/dist/alerts/ui/AlertsPage.d.ts +41 -0
  36. package/dist/alerts/ui/AlertsPage.d.ts.map +1 -0
  37. package/dist/alerts/ui/AlertsPage.js +238 -0
  38. package/dist/alerts/ui/AlertsPage.js.map +1 -0
  39. package/dist/alerts/ui/FiringAlertsBanner.d.ts +28 -0
  40. package/dist/alerts/ui/FiringAlertsBanner.d.ts.map +1 -0
  41. package/dist/alerts/ui/FiringAlertsBanner.js +45 -0
  42. package/dist/alerts/ui/FiringAlertsBanner.js.map +1 -0
  43. package/dist/alerts/ui/copy.d.ts +15 -0
  44. package/dist/alerts/ui/copy.d.ts.map +1 -0
  45. package/dist/alerts/ui/copy.js +14 -0
  46. package/dist/alerts/ui/copy.js.map +1 -0
  47. package/dist/alerts/ui/index.d.ts +14 -0
  48. package/dist/alerts/ui/index.d.ts.map +1 -0
  49. package/dist/alerts/ui/index.js +12 -0
  50. package/dist/alerts/ui/index.js.map +1 -0
  51. package/dist/alerts/ui/parts.d.ts +26 -0
  52. package/dist/alerts/ui/parts.d.ts.map +1 -0
  53. package/dist/alerts/ui/parts.js +27 -0
  54. package/dist/alerts/ui/parts.js.map +1 -0
  55. package/dist/alerts/ui/settings.d.ts +27 -0
  56. package/dist/alerts/ui/settings.d.ts.map +1 -0
  57. package/dist/alerts/ui/settings.js +37 -0
  58. package/dist/alerts/ui/settings.js.map +1 -0
  59. package/dist/nodes/headless/api.d.ts +3 -1
  60. package/dist/nodes/headless/api.d.ts.map +1 -1
  61. package/dist/nodes/headless/api.js +22 -0
  62. package/dist/nodes/headless/api.js.map +1 -1
  63. package/dist/nodes/headless/index.d.ts +7 -2
  64. package/dist/nodes/headless/index.d.ts.map +1 -1
  65. package/dist/nodes/headless/index.js +4 -1
  66. package/dist/nodes/headless/index.js.map +1 -1
  67. package/dist/nodes/headless/node-events.d.ts +43 -0
  68. package/dist/nodes/headless/node-events.d.ts.map +1 -0
  69. package/dist/nodes/headless/node-events.js +150 -0
  70. package/dist/nodes/headless/node-events.js.map +1 -0
  71. package/dist/nodes/headless/power.d.ts +43 -0
  72. package/dist/nodes/headless/power.d.ts.map +1 -0
  73. package/dist/nodes/headless/power.js +74 -0
  74. package/dist/nodes/headless/power.js.map +1 -0
  75. package/dist/nodes/headless/types.d.ts +40 -3
  76. package/dist/nodes/headless/types.d.ts.map +1 -1
  77. package/dist/nodes/headless/types.js +1 -1
  78. package/dist/nodes/headless/types.js.map +1 -1
  79. package/dist/nodes/headless/use-node-events.d.ts +59 -0
  80. package/dist/nodes/headless/use-node-events.d.ts.map +1 -0
  81. package/dist/nodes/headless/use-node-events.js +159 -0
  82. package/dist/nodes/headless/use-node-events.js.map +1 -0
  83. package/dist/nodes/ui/NodeEventsTimeline.d.ts +39 -0
  84. package/dist/nodes/ui/NodeEventsTimeline.d.ts.map +1 -0
  85. package/dist/nodes/ui/NodeEventsTimeline.js +63 -0
  86. package/dist/nodes/ui/NodeEventsTimeline.js.map +1 -0
  87. package/dist/nodes/ui/NodePowerBadge.d.ts +27 -0
  88. package/dist/nodes/ui/NodePowerBadge.d.ts.map +1 -0
  89. package/dist/nodes/ui/NodePowerBadge.js +48 -0
  90. package/dist/nodes/ui/NodePowerBadge.js.map +1 -0
  91. package/dist/nodes/ui/NodeVitalsDialog.d.ts +11 -1
  92. package/dist/nodes/ui/NodeVitalsDialog.d.ts.map +1 -1
  93. package/dist/nodes/ui/NodeVitalsDialog.js +14 -5
  94. package/dist/nodes/ui/NodeVitalsDialog.js.map +1 -1
  95. package/dist/nodes/ui/WorkersPage.d.ts.map +1 -1
  96. package/dist/nodes/ui/WorkersPage.js +2 -1
  97. package/dist/nodes/ui/WorkersPage.js.map +1 -1
  98. package/dist/nodes/ui/workerVitals.d.ts +17 -1
  99. package/dist/nodes/ui/workerVitals.d.ts.map +1 -1
  100. package/dist/nodes/ui/workerVitals.js +43 -0
  101. package/dist/nodes/ui/workerVitals.js.map +1 -1
  102. package/dist/nodes/ui/workersTable.d.ts.map +1 -1
  103. package/dist/nodes/ui/workersTable.js +2 -1
  104. package/dist/nodes/ui/workersTable.js.map +1 -1
  105. package/dist/telemetry/headless/hooks/useTelemetryDashboard.d.ts +1 -1
  106. package/dist/telemetry/ui/components/dashboard/metrics/MetricSections.d.ts +11 -0
  107. package/dist/telemetry/ui/components/dashboard/metrics/MetricSections.d.ts.map +1 -1
  108. package/dist/telemetry/ui/components/dashboard/metrics/MetricSections.js +17 -2
  109. package/dist/telemetry/ui/components/dashboard/metrics/MetricSections.js.map +1 -1
  110. package/dist/webhooks/headless/client.d.ts +101 -0
  111. package/dist/webhooks/headless/client.d.ts.map +1 -0
  112. package/dist/webhooks/headless/client.js +105 -0
  113. package/dist/webhooks/headless/client.js.map +1 -0
  114. package/dist/webhooks/headless/event-selection.d.ts +119 -0
  115. package/dist/webhooks/headless/event-selection.d.ts.map +1 -0
  116. package/dist/webhooks/headless/event-selection.js +225 -0
  117. package/dist/webhooks/headless/event-selection.js.map +1 -0
  118. package/dist/webhooks/headless/format.d.ts +84 -0
  119. package/dist/webhooks/headless/format.d.ts.map +1 -0
  120. package/dist/webhooks/headless/format.js +142 -0
  121. package/dist/webhooks/headless/format.js.map +1 -0
  122. package/dist/webhooks/headless/hooks.d.ts +199 -0
  123. package/dist/webhooks/headless/hooks.d.ts.map +1 -0
  124. package/dist/webhooks/headless/hooks.js +249 -0
  125. package/dist/webhooks/headless/hooks.js.map +1 -0
  126. package/dist/webhooks/headless/index.d.ts +9 -0
  127. package/dist/webhooks/headless/index.d.ts.map +1 -0
  128. package/dist/webhooks/headless/index.js +9 -0
  129. package/dist/webhooks/headless/index.js.map +1 -0
  130. package/dist/webhooks/ui/WebhookDeliveryDrawer.d.ts +32 -0
  131. package/dist/webhooks/ui/WebhookDeliveryDrawer.d.ts.map +1 -0
  132. package/dist/webhooks/ui/WebhookDeliveryDrawer.js +64 -0
  133. package/dist/webhooks/ui/WebhookDeliveryDrawer.js.map +1 -0
  134. package/dist/webhooks/ui/WebhookEndpointDetail.d.ts +21 -0
  135. package/dist/webhooks/ui/WebhookEndpointDetail.d.ts.map +1 -0
  136. package/dist/webhooks/ui/WebhookEndpointDetail.js +96 -0
  137. package/dist/webhooks/ui/WebhookEndpointDetail.js.map +1 -0
  138. package/dist/webhooks/ui/WebhookEndpointDialog.d.ts +39 -0
  139. package/dist/webhooks/ui/WebhookEndpointDialog.d.ts.map +1 -0
  140. package/dist/webhooks/ui/WebhookEndpointDialog.js +79 -0
  141. package/dist/webhooks/ui/WebhookEndpointDialog.js.map +1 -0
  142. package/dist/webhooks/ui/WebhookEventPicker.d.ts +30 -0
  143. package/dist/webhooks/ui/WebhookEventPicker.d.ts.map +1 -0
  144. package/dist/webhooks/ui/WebhookEventPicker.js +33 -0
  145. package/dist/webhooks/ui/WebhookEventPicker.js.map +1 -0
  146. package/dist/webhooks/ui/WebhookSecretDialog.d.ts +27 -0
  147. package/dist/webhooks/ui/WebhookSecretDialog.d.ts.map +1 -0
  148. package/dist/webhooks/ui/WebhookSecretDialog.js +52 -0
  149. package/dist/webhooks/ui/WebhookSecretDialog.js.map +1 -0
  150. package/dist/webhooks/ui/WebhookSignatureHelp.d.ts +18 -0
  151. package/dist/webhooks/ui/WebhookSignatureHelp.d.ts.map +1 -0
  152. package/dist/webhooks/ui/WebhookSignatureHelp.js +40 -0
  153. package/dist/webhooks/ui/WebhookSignatureHelp.js.map +1 -0
  154. package/dist/webhooks/ui/WebhooksPage.d.ts +47 -0
  155. package/dist/webhooks/ui/WebhooksPage.d.ts.map +1 -0
  156. package/dist/webhooks/ui/WebhooksPage.js +172 -0
  157. package/dist/webhooks/ui/WebhooksPage.js.map +1 -0
  158. package/dist/webhooks/ui/copy.d.ts +24 -0
  159. package/dist/webhooks/ui/copy.d.ts.map +1 -0
  160. package/dist/webhooks/ui/copy.js +34 -0
  161. package/dist/webhooks/ui/copy.js.map +1 -0
  162. package/dist/webhooks/ui/index.d.ts +15 -0
  163. package/dist/webhooks/ui/index.d.ts.map +1 -0
  164. package/dist/webhooks/ui/index.js +12 -0
  165. package/dist/webhooks/ui/index.js.map +1 -0
  166. package/dist/webhooks/ui/parts.d.ts +25 -0
  167. package/dist/webhooks/ui/parts.d.ts.map +1 -0
  168. package/dist/webhooks/ui/parts.js +28 -0
  169. package/dist/webhooks/ui/parts.js.map +1 -0
  170. package/dist/webhooks/ui/settings.d.ts +58 -0
  171. package/dist/webhooks/ui/settings.d.ts.map +1 -0
  172. package/dist/webhooks/ui/settings.js +79 -0
  173. package/dist/webhooks/ui/settings.js.map +1 -0
  174. package/package.json +18 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @marinoscar/platform-web
2
2
 
3
+ ## 0.1.0-next.21
4
+
5
+ ### Patch Changes
6
+
7
+ - @marinoscar/platform-contract@0.1.0-next.21
8
+
9
+ ## 0.1.0-next.20
10
+
11
+ ### Minor Changes
12
+
13
+ - 64fc8fc: Add the alerts web slice (#1047): `@marinoscar/platform-web/alerts/headless` (`createAlertsApi`, `useAlertRules`, `useAlertRule`, `useAlertKinds`, `useAlertIncidents`, `useAlertIncident`, `useAlertSummary` polled every 30 seconds, `useAlertMetricCatalog`, `useAlertMutations`, the rule editor's draft model and alerts in words) and `@marinoscar/platform-web/alerts/ui` (`AlertsPage` with Rules and Incidents tabs, `AlertRuleDialog` with a form per built-in kind and a dry-run Test, `AlertRuleTestResult`, `AlertIncidentDrawer`, `FiringAlertsBanner` for the telemetry dashboard's `BeforeContent` slot, and the `alertsAdminCards` Observability card, `alerts:read`). Starter rules show "Built-in" and cannot be deleted from the UI.
14
+ - c9b5944: Worker Nodes page: a power badge per node (AC or battery with percent and charging state), a "Host machine" section in the vitals dialog (host CPU, memory, load, OS, power) and a paginated node events timeline backed by `useNodeEvents` / `NodesApi.listNodeEvents`. The telemetry metric table now renders 0/1 status gauges. Apps with their own `NodesApi` implementation must add `listNodeEvents`.
15
+ - 5016783: Add the `webhooks` slice (issue #1046): `@marinoscar/platform-web/webhooks/headless` (`createWebhooksApi` for the `user`, `org` and `system` scopes, the endpoint, delivery and event catalog hooks, `useWebhookMutations`, the event picker's wildcard model and status helpers) and `@marinoscar/platform-web/webhooks/ui` (`WebhooksPage` with its create and edit dialog, grouped event picker, one-time secret dialog, deliveries table, delivery drawer with Redeliver and the "Verifying signatures" panel, plus the settings cards as data `webhooksUserSettingsSections` and `webhooksAdminSections`).
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies [7b5796f]
20
+ - Updated dependencies [6949b6b]
21
+ - Updated dependencies [f3b9700]
22
+ - @marinoscar/platform-contract@0.1.0-next.20
23
+
3
24
  ## 0.1.0-next.19
4
25
 
5
26
  ### Minor Changes
package/README.md CHANGED
@@ -31,6 +31,8 @@ Status: pre-release (the current channel and how to install it: the [release run
31
31
  - `@marinoscar/platform-web/host/headless` and `@marinoscar/platform-web/host/ui`: the About page, the admin Maintenance page and the public maintenance screen, with the maintenance recogniser and block store, `createHostApi` and the `useAbout`, `useMaintenance` and `useMaintenanceBlock` hooks (#891). [README](src/host/README.md).
32
32
  - `@marinoscar/platform-web/datatable/headless`, `@marinoscar/platform-web/datatable/ui` and `@marinoscar/platform-web/datatable/testing`: the responsive `DataTable` (desktop grid, tablet expander, phone cards) with its filters, view bar, CSV export and bulk actions, the layout-preference port `DataTablePreferencesPort`, and the jsdom layout stubs and conformance suite (#897). [README](src/datatable/README.md).
33
33
  - `@marinoscar/platform-web/timezone/headless` and `@marinoscar/platform-web/timezone/ui`: the display time zone (the user's `profile.timezone`, else the device's) with its store, `useDisplayTimeZone` and `UserTimeZoneSync`, the formatters that render in it (`formatDateTime`, `formatDate`, `formatTime`, `zonedDateKey`), the zone catalog, and the world-map picker (`TimeZoneMap`, `TimeZonePickerDialog`, `TimeZoneField`). [README](src/timezone/README.md).
34
+ - `@marinoscar/platform-web/webhooks/headless` and `@marinoscar/platform-web/webhooks/ui`: outbound webhooks for the `user`, `org` and `system` scopes: `createWebhooksApi`, the endpoint, delivery and event catalog hooks, the event picker's wildcard model, and `WebhooksPage` with its create and edit dialog, one-time secret dialog, deliveries table and delivery drawer, plus the settings cards as data (`webhooksUserSettingsSections`, `webhooksAdminSections`) (#1046). [README](src/webhooks/README.md).
35
+ - `@marinoscar/platform-web/alerts/headless` and `@marinoscar/platform-web/alerts/ui`: alert rules and incidents: `createAlertsApi`, the rule, kind, incident, summary and metric-catalog hooks, the rule editor's draft model, and `AlertsPage` (Rules and Incidents tabs) with the rule editor, the dry-run result and the incident drawer, `FiringAlertsBanner` for the telemetry dashboard, plus the admin card as data (`alertsAdminCards`) (#1047). [README](src/alerts/README.md).
34
36
 
35
37
  ## Install and peer dependencies
36
38
 
@@ -54,10 +56,10 @@ Optional peers, installed for the slices that need them:
54
56
 
55
57
  | Package | Range | Needed by |
56
58
  |---|---|---|
57
- | `@mui/icons-material` | `^9.1.0` | every slice with a `/ui` entry (`doctor`, `identity`, `settings`, `sharing`, `onboarding`, `email`, `nodes`, `jobs`, `storage`, `notifications`, `exports`, `ai`, `db-backup`, `android-app`, `user-data`, `shell`, `host`, `datatable`, `telemetry`, `timezone`) |
58
- | `react-router-dom` | `^7.17.0` | the same slices, except `exports`, `datatable` and `timezone` |
59
+ | `@mui/icons-material` | `^9.1.0` | every slice with a `/ui` entry (`doctor`, `identity`, `settings`, `sharing`, `onboarding`, `email`, `nodes`, `jobs`, `storage`, `notifications`, `exports`, `ai`, `db-backup`, `android-app`, `user-data`, `shell`, `host`, `datatable`, `telemetry`, `timezone`, `webhooks`, `alerts`) |
60
+ | `react-router-dom` | `^7.17.0` | the same slices, except `exports`, `datatable`, `timezone` and `webhooks` |
59
61
  | `zod` | `^4.4.3` | `nodes`, `jobs` (and the app's own use of `@marinoscar/platform-contract`) |
60
- | `@mui/x-data-grid` | `^9.10.1` | `datatable/ui` and, since the AI lists use it, `ai/ui`; `telemetry/ui` |
62
+ | `@mui/x-data-grid` | `^9.10.1` | `datatable/ui` and, since the AI lists use it, `ai/ui`; `telemetry/ui`; `webhooks/ui`; `alerts/ui` |
61
63
  | `@mui/x-charts` | `^9.14.0` | `telemetry/ui` (#704) |
62
64
  | `@uiw/react-codemirror` | `^4.25.12` | `telemetry/ui` |
63
65
  | `@codemirror/lang-sql` | `^6.10.0` | `telemetry/ui` |
@@ -0,0 +1,134 @@
1
+ import type { AlertIncident, AlertIncidentState, AlertKind, AlertRule, AlertRuleTestResponse, AlertSeverity, AlertSummary, CreateAlertRule, UpdateAlertRule } from '@marinoscar/platform-contract/alerts';
2
+ import type { TelemetrySchema } from '@marinoscar/platform-contract/telemetry';
3
+ import type { PlatformApiClient } from '../../core/index.js';
4
+ /**
5
+ * The route base of the alerts slice, relative to the API root (`/api`).
6
+ *
7
+ * @stability experimental
8
+ */
9
+ export declare const ALERTS_BASE_PATH = "/admin/alerts";
10
+ /**
11
+ * The telemetry route the metric picker reads (relative to `/api`).
12
+ *
13
+ * @stability experimental
14
+ */
15
+ export declare const ALERTS_METRIC_CATALOG_PATH = "/admin/telemetry/schema";
16
+ /**
17
+ * The filters of a rule list request.
18
+ *
19
+ * @stability experimental
20
+ */
21
+ export interface AlertRulesQuery {
22
+ /** Only rules of this kind. */
23
+ kind?: string;
24
+ /** Only rules of this severity. */
25
+ severity?: AlertSeverity;
26
+ /** Only enabled (`true`) or disabled (`false`) rules. */
27
+ enabled?: boolean;
28
+ }
29
+ /**
30
+ * The filters and page of an incident list request. `page` is one-based, as
31
+ * on the wire.
32
+ *
33
+ * @stability experimental
34
+ */
35
+ export interface AlertIncidentsQuery {
36
+ /** Only incidents in this state. */
37
+ state?: AlertIncidentState;
38
+ /** Only incidents of this severity. */
39
+ severity?: AlertSeverity;
40
+ /** Only incidents of this rule. */
41
+ ruleId?: string;
42
+ /** One-based page; default 1. */
43
+ page?: number;
44
+ /** Rows per page; default the API's (20). */
45
+ pageSize?: number;
46
+ }
47
+ /**
48
+ * One page of incidents as `GET /admin/alerts/incidents` returns it.
49
+ *
50
+ * @stability experimental
51
+ */
52
+ export interface AlertIncidentPage {
53
+ /** The incidents of the page. */
54
+ items: AlertIncident[];
55
+ /** Incidents matching the filters, across every page. */
56
+ total: number;
57
+ /** The one-based page. */
58
+ page: number;
59
+ /** Rows per page. */
60
+ pageSize: number;
61
+ /** Pages at this page size. */
62
+ totalPages: number;
63
+ }
64
+ /**
65
+ * One metric the rule editor can pick: a telemetry store table and its
66
+ * attribute columns (the `groupBy` and filter candidates).
67
+ *
68
+ * @stability experimental
69
+ */
70
+ export interface AlertMetricCatalogEntry {
71
+ /** The table name, accepted as `metric` by `metric_threshold` (`app_jobs_settled`). */
72
+ name: string;
73
+ /** The columns other than the value and the timestamp. */
74
+ attributes: string[];
75
+ }
76
+ /**
77
+ * The alerts API calls.
78
+ *
79
+ * @stability experimental
80
+ */
81
+ export interface AlertsApi {
82
+ /** `GET /admin/alerts/rules`. */
83
+ listRules(query?: AlertRulesQuery): Promise<AlertRule[]>;
84
+ /** `GET /admin/alerts/rules/:id`. */
85
+ getRule(id: string): Promise<AlertRule>;
86
+ /** `POST /admin/alerts/rules`. */
87
+ createRule(input: CreateAlertRule): Promise<AlertRule>;
88
+ /** `PATCH /admin/alerts/rules/:id` (the kind cannot change). */
89
+ updateRule(id: string, patch: UpdateAlertRule): Promise<AlertRule>;
90
+ /** `DELETE /admin/alerts/rules/:id` (a starter rule answers 409). */
91
+ deleteRule(id: string): Promise<void>;
92
+ /** `POST /admin/alerts/rules/:id/test`: a dry run, nothing stored or sent. */
93
+ testRule(id: string): Promise<AlertRuleTestResponse>;
94
+ /** `GET /admin/alerts/kinds`. */
95
+ listKinds(): Promise<AlertKind[]>;
96
+ /** `GET /admin/alerts/incidents?state&severity&ruleId&page&pageSize`. */
97
+ listIncidents(query?: AlertIncidentsQuery): Promise<AlertIncidentPage>;
98
+ /** `GET /admin/alerts/incidents/:id`. */
99
+ getIncident(id: string): Promise<AlertIncident>;
100
+ /** `POST /admin/alerts/incidents/:id/acknowledge`. */
101
+ acknowledge(id: string): Promise<AlertIncident>;
102
+ /** `GET /admin/alerts/summary`: firing counts by severity. */
103
+ summary(): Promise<AlertSummary>;
104
+ /** `GET /admin/telemetry/schema`, reduced to the metric tables and their attributes. */
105
+ metricCatalog(): Promise<AlertMetricCatalogEntry[]>;
106
+ }
107
+ /**
108
+ * The store's table list as the metric picker's entries: the metric tables
109
+ * (not the trace and log tables), each with its attribute columns, sorted by
110
+ * name.
111
+ *
112
+ * @param schema - what `GET /admin/telemetry/schema` returned.
113
+ * @returns the entries.
114
+ *
115
+ * @stability experimental
116
+ */
117
+ export declare function metricCatalogFromSchema(schema: Pick<TelemetrySchema, 'tables'>): AlertMetricCatalogEntry[];
118
+ /**
119
+ * The alerts client over the app's transport.
120
+ *
121
+ * @param api - the app's transport (`usePlatformApi()`).
122
+ * @returns the client.
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * const alerts = createAlertsApi(usePlatformApi());
127
+ * const { firing } = await alerts.summary();
128
+ * ```
129
+ *
130
+ * @extensionPoint hook
131
+ * @stability experimental
132
+ */
133
+ export declare function createAlertsApi(api: PlatformApiClient): AlertsApi;
134
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/alerts/headless/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ // =============================================================================
2
+ // The alerts client (issue #1047): the `/api/admin/alerts` routes
3
+ // =============================================================================
4
+ //
5
+ // Every route is a SYSTEM route: reads need `alerts:read`, writes (create,
6
+ // edit, delete, test, acknowledge) need `alerts:write` (`ALERT_PERMISSIONS` of
7
+ // `@marinoscar/platform-contract/alerts`). The transport (`PlatformApiClient`)
8
+ // prefixes `/api` and unwraps the `{ data }` envelope. The API decides who may
9
+ // do what; the client only builds paths.
10
+ //
11
+ // One route here is not the alerts slice's: the metric picker of the rule
12
+ // editor reads the telemetry store's table list (`GET /admin/telemetry/schema`,
13
+ // `telemetry:query`), the same list the telemetry explorer's schema panel
14
+ // reads. It is read through the contract's wire type only, so the alerts web
15
+ // slice does not depend on the telemetry web slice.
16
+ // =============================================================================
17
+ /**
18
+ * The route base of the alerts slice, relative to the API root (`/api`).
19
+ *
20
+ * @stability experimental
21
+ */
22
+ export const ALERTS_BASE_PATH = '/admin/alerts';
23
+ /**
24
+ * The telemetry route the metric picker reads (relative to `/api`).
25
+ *
26
+ * @stability experimental
27
+ */
28
+ export const ALERTS_METRIC_CATALOG_PATH = '/admin/telemetry/schema';
29
+ /** Columns of a metric table that are never a `groupBy` or filter candidate. */
30
+ const NON_ATTRIBUTE_COLUMNS = new Set(['greptime_value', 'greptime_timestamp', 'val', 'ts', 'timestamp']);
31
+ /** Tables of the store that are traces or logs, not metrics. */
32
+ function isMetricTable(name) {
33
+ return !name.startsWith('opentelemetry_') && !name.startsWith('information_schema');
34
+ }
35
+ /**
36
+ * The store's table list as the metric picker's entries: the metric tables
37
+ * (not the trace and log tables), each with its attribute columns, sorted by
38
+ * name.
39
+ *
40
+ * @param schema - what `GET /admin/telemetry/schema` returned.
41
+ * @returns the entries.
42
+ *
43
+ * @stability experimental
44
+ */
45
+ export function metricCatalogFromSchema(schema) {
46
+ return schema.tables
47
+ .filter((table) => isMetricTable(table.name))
48
+ .map((table) => ({
49
+ name: table.name,
50
+ attributes: table.columns.map((column) => column.name).filter((name) => !NON_ATTRIBUTE_COLUMNS.has(name)),
51
+ }))
52
+ .sort((a, b) => a.name.localeCompare(b.name));
53
+ }
54
+ function queryString(params) {
55
+ const search = new URLSearchParams();
56
+ for (const [key, value] of Object.entries(params)) {
57
+ if (value === undefined || value === '')
58
+ continue;
59
+ search.set(key, String(value));
60
+ }
61
+ const text = search.toString();
62
+ return text === '' ? '' : `?${text}`;
63
+ }
64
+ /**
65
+ * The alerts client over the app's transport.
66
+ *
67
+ * @param api - the app's transport (`usePlatformApi()`).
68
+ * @returns the client.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * const alerts = createAlertsApi(usePlatformApi());
73
+ * const { firing } = await alerts.summary();
74
+ * ```
75
+ *
76
+ * @extensionPoint hook
77
+ * @stability experimental
78
+ */
79
+ export function createAlertsApi(api) {
80
+ const rule = (id) => `${ALERTS_BASE_PATH}/rules/${encodeURIComponent(id)}`;
81
+ const incident = (id) => `${ALERTS_BASE_PATH}/incidents/${encodeURIComponent(id)}`;
82
+ return {
83
+ listRules: (query = {}) => api.get(`${ALERTS_BASE_PATH}/rules${queryString({ kind: query.kind, severity: query.severity, enabled: query.enabled })}`),
84
+ getRule: (id) => api.get(rule(id)),
85
+ createRule: (input) => api.post(`${ALERTS_BASE_PATH}/rules`, input),
86
+ updateRule: (id, patch) => api.patch(rule(id), patch),
87
+ deleteRule: async (id) => {
88
+ await api.delete(rule(id));
89
+ },
90
+ testRule: (id) => api.post(`${rule(id)}/test`),
91
+ listKinds: () => api.get(`${ALERTS_BASE_PATH}/kinds`),
92
+ listIncidents: (query = {}) => api.get(`${ALERTS_BASE_PATH}/incidents${queryString({
93
+ state: query.state,
94
+ severity: query.severity,
95
+ ruleId: query.ruleId,
96
+ page: query.page,
97
+ pageSize: query.pageSize,
98
+ })}`),
99
+ getIncident: (id) => api.get(incident(id)),
100
+ acknowledge: (id) => api.post(`${incident(id)}/acknowledge`),
101
+ summary: () => api.get(`${ALERTS_BASE_PATH}/summary`),
102
+ metricCatalog: async () => metricCatalogFromSchema(await api.get(ALERTS_METRIC_CATALOG_PATH)),
103
+ };
104
+ }
105
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/alerts/headless/client.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,kEAAkE;AAClE,gFAAgF;AAChF,EAAE;AACF,2EAA2E;AAC3E,+EAA+E;AAC/E,+EAA+E;AAC/E,+EAA+E;AAC/E,yCAAyC;AACzC,EAAE;AACF,0EAA0E;AAC1E,gFAAgF;AAChF,0EAA0E;AAC1E,6EAA6E;AAC7E,oDAAoD;AACpD,gFAAgF;AAiBhF;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,eAAe,CAAC;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,yBAAyB,CAAC;AAkGpE,gFAAgF;AAChF,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,gBAAgB,EAAE,oBAAoB,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;AAE1G,gEAAgE;AAChE,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;AACtF,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAuC;IAC7E,OAAO,MAAM,CAAC,MAAM;SACjB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SAC5C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACf,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;KAC1G,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,WAAW,CAAC,MAA6D;IAChF,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;YAAE,SAAS;QAClD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC/B,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;AACvC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAAC,GAAsB;IACpD,MAAM,IAAI,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,GAAG,gBAAgB,UAAU,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC;IACnF,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,GAAG,gBAAgB,cAAc,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC;IAC3F,OAAO;QACL,SAAS,EAAE,CAAC,KAAK,GAAG,EAAE,EAAE,EAAE,CACxB,GAAG,CAAC,GAAG,CACL,GAAG,gBAAgB,SAAS,WAAW,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,CAClH;QACH,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAY,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7C,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAY,GAAG,gBAAgB,QAAQ,EAAE,KAAK,CAAC;QAC9E,UAAU,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAY,IAAI,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC;QAChE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;YACvB,MAAM,GAAG,CAAC,MAAM,CAAU,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACtC,CAAC;QACD,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAwB,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;QACrE,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAc,GAAG,gBAAgB,QAAQ,CAAC;QAClE,aAAa,EAAE,CAAC,KAAK,GAAG,EAAE,EAAE,EAAE,CAC5B,GAAG,CAAC,GAAG,CACL,GAAG,gBAAgB,aAAa,WAAW,CAAC;YAC1C,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzB,CAAC,EAAE,CACL;QACH,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAgB,QAAQ,CAAC,EAAE,CAAC,CAAC;QACzD,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAgB,GAAG,QAAQ,CAAC,EAAE,CAAC,cAAc,CAAC;QAC3E,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAe,GAAG,gBAAgB,UAAU,CAAC;QACnE,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC,uBAAuB,CAAC,MAAM,GAAG,CAAC,GAAG,CAAkB,0BAA0B,CAAC,CAAC;KAC/G,CAAC;AACJ,CAAC"}
@@ -0,0 +1,95 @@
1
+ import type { AlertAggregation, AlertComparator, AlertIncidentState, AlertSeverity, AlertSummary } from '@marinoscar/platform-contract/alerts';
2
+ /**
3
+ * A status tone, mapped to an MUI colour by the UI. The words carry the
4
+ * meaning; the tone only reinforces it.
5
+ *
6
+ * @stability experimental
7
+ */
8
+ export type AlertTone = 'error' | 'warning' | 'info' | 'success' | 'default';
9
+ /**
10
+ * Each severity in words.
11
+ *
12
+ * @stability experimental
13
+ */
14
+ export declare const ALERT_SEVERITY_LABELS: Readonly<Record<AlertSeverity, string>>;
15
+ /**
16
+ * The tone of each severity.
17
+ *
18
+ * @stability experimental
19
+ */
20
+ export declare const ALERT_SEVERITY_TONES: Readonly<Record<AlertSeverity, AlertTone>>;
21
+ /**
22
+ * Each incident state in words.
23
+ *
24
+ * @stability experimental
25
+ */
26
+ export declare const ALERT_STATE_LABELS: Readonly<Record<AlertIncidentState, string>>;
27
+ /**
28
+ * The tone of each incident state.
29
+ *
30
+ * @stability experimental
31
+ */
32
+ export declare const ALERT_STATE_TONES: Readonly<Record<AlertIncidentState, AlertTone>>;
33
+ /**
34
+ * Each comparator in words and as a symbol.
35
+ *
36
+ * @stability experimental
37
+ */
38
+ export declare const ALERT_COMPARATOR_LABELS: Readonly<Record<AlertComparator, string>>;
39
+ /**
40
+ * Each aggregation in words.
41
+ *
42
+ * @stability experimental
43
+ */
44
+ export declare const ALERT_AGGREGATION_LABELS: Readonly<Record<AlertAggregation, string>>;
45
+ /**
46
+ * A kind id in words: the label `GET /kinds` gave, else the built-in label,
47
+ * else the id itself.
48
+ *
49
+ * @param kind - the kind id.
50
+ * @param kinds - the registered kinds, when loaded.
51
+ * @returns the label.
52
+ *
53
+ * @stability experimental
54
+ */
55
+ export declare function alertKindLabel(kind: string, kinds?: ReadonlyArray<{
56
+ id: string;
57
+ label: string;
58
+ }>): string;
59
+ /**
60
+ * The firing count of a summary, in total.
61
+ *
62
+ * @param summary - `GET /admin/alerts/summary`.
63
+ * @returns critical + warning + info.
64
+ *
65
+ * @stability experimental
66
+ */
67
+ export declare function alertFiringTotal(summary: Pick<AlertSummary, 'firing'> | null | undefined): number;
68
+ /**
69
+ * The most serious severity that has a firing incident, or `null`.
70
+ *
71
+ * @param summary - `GET /admin/alerts/summary`.
72
+ * @returns the severity.
73
+ *
74
+ * @stability experimental
75
+ */
76
+ export declare function alertTopSeverity(summary: Pick<AlertSummary, 'firing'> | null | undefined): AlertSeverity | null;
77
+ /**
78
+ * An incident's labels as `key=value` text, in key order; `''` for none.
79
+ *
80
+ * @param labels - the labels.
81
+ * @returns the text.
82
+ *
83
+ * @stability experimental
84
+ */
85
+ export declare function formatAlertLabels(labels: Readonly<Record<string, string>>): string;
86
+ /**
87
+ * A duration in seconds as short words (`90` is `1 min 30 s`, `3600` is `1 h`).
88
+ *
89
+ * @param seconds - whole seconds.
90
+ * @returns the text.
91
+ *
92
+ * @stability experimental
93
+ */
94
+ export declare function formatAlertSeconds(seconds: number): string;
95
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/alerts/headless/format.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,YAAY,EACb,MAAM,sCAAsC,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;AAE7E;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAIxE,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,SAAS,CAAC,CAI1E,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAI1E,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAI5E,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAO5E,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAO9E,CAAC;AAUH;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,aAAa,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAM,GAAG,MAAM,CAE7G;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAGjG;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,aAAa,GAAG,IAAI,CAM/G;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAKlF;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAY1D"}
@@ -0,0 +1,164 @@
1
+ // =============================================================================
2
+ // Alerts in words (issue #1047): labels for severities, states, comparators,
3
+ // aggregations and kinds, and the summary's totals. Pure; no React.
4
+ // =============================================================================
5
+ import { ALERT_KIND_IDS } from '@marinoscar/platform-contract/alerts';
6
+ /**
7
+ * Each severity in words.
8
+ *
9
+ * @stability experimental
10
+ */
11
+ export const ALERT_SEVERITY_LABELS = Object.freeze({
12
+ critical: 'Critical',
13
+ warning: 'Warning',
14
+ info: 'Info',
15
+ });
16
+ /**
17
+ * The tone of each severity.
18
+ *
19
+ * @stability experimental
20
+ */
21
+ export const ALERT_SEVERITY_TONES = Object.freeze({
22
+ critical: 'error',
23
+ warning: 'warning',
24
+ info: 'info',
25
+ });
26
+ /**
27
+ * Each incident state in words.
28
+ *
29
+ * @stability experimental
30
+ */
31
+ export const ALERT_STATE_LABELS = Object.freeze({
32
+ pending: 'Pending',
33
+ firing: 'Firing',
34
+ resolved: 'Resolved',
35
+ });
36
+ /**
37
+ * The tone of each incident state.
38
+ *
39
+ * @stability experimental
40
+ */
41
+ export const ALERT_STATE_TONES = Object.freeze({
42
+ pending: 'warning',
43
+ firing: 'error',
44
+ resolved: 'success',
45
+ });
46
+ /**
47
+ * Each comparator in words and as a symbol.
48
+ *
49
+ * @stability experimental
50
+ */
51
+ export const ALERT_COMPARATOR_LABELS = Object.freeze({
52
+ gt: 'greater than (>)',
53
+ gte: 'at least (≥)',
54
+ lt: 'less than (<)',
55
+ lte: 'at most (≤)',
56
+ eq: 'equal to (=)',
57
+ neq: 'not equal to (≠)',
58
+ });
59
+ /**
60
+ * Each aggregation in words.
61
+ *
62
+ * @stability experimental
63
+ */
64
+ export const ALERT_AGGREGATION_LABELS = Object.freeze({
65
+ avg: 'Average',
66
+ max: 'Maximum',
67
+ min: 'Minimum',
68
+ sum: 'Sum',
69
+ last: 'Last value',
70
+ rate: 'Rate per minute',
71
+ });
72
+ const BUILTIN_KIND_LABELS = Object.freeze({
73
+ [ALERT_KIND_IDS.METRIC_THRESHOLD]: 'Metric threshold',
74
+ [ALERT_KIND_IDS.NODE_EVENT]: 'Node event',
75
+ [ALERT_KIND_IDS.VERDICT]: 'Dashboard verdict',
76
+ [ALERT_KIND_IDS.NODE_OFFLINE]: 'Node offline',
77
+ [ALERT_KIND_IDS.TELEMETRY_UNAVAILABLE]: 'Telemetry unavailable',
78
+ });
79
+ /**
80
+ * A kind id in words: the label `GET /kinds` gave, else the built-in label,
81
+ * else the id itself.
82
+ *
83
+ * @param kind - the kind id.
84
+ * @param kinds - the registered kinds, when loaded.
85
+ * @returns the label.
86
+ *
87
+ * @stability experimental
88
+ */
89
+ export function alertKindLabel(kind, kinds = []) {
90
+ return kinds.find((entry) => entry.id === kind)?.label ?? BUILTIN_KIND_LABELS[kind] ?? kind;
91
+ }
92
+ /**
93
+ * The firing count of a summary, in total.
94
+ *
95
+ * @param summary - `GET /admin/alerts/summary`.
96
+ * @returns critical + warning + info.
97
+ *
98
+ * @stability experimental
99
+ */
100
+ export function alertFiringTotal(summary) {
101
+ if (!summary)
102
+ return 0;
103
+ return summary.firing.critical + summary.firing.warning + summary.firing.info;
104
+ }
105
+ /**
106
+ * The most serious severity that has a firing incident, or `null`.
107
+ *
108
+ * @param summary - `GET /admin/alerts/summary`.
109
+ * @returns the severity.
110
+ *
111
+ * @stability experimental
112
+ */
113
+ export function alertTopSeverity(summary) {
114
+ if (!summary)
115
+ return null;
116
+ if (summary.firing.critical > 0)
117
+ return 'critical';
118
+ if (summary.firing.warning > 0)
119
+ return 'warning';
120
+ if (summary.firing.info > 0)
121
+ return 'info';
122
+ return null;
123
+ }
124
+ /**
125
+ * An incident's labels as `key=value` text, in key order; `''` for none.
126
+ *
127
+ * @param labels - the labels.
128
+ * @returns the text.
129
+ *
130
+ * @stability experimental
131
+ */
132
+ export function formatAlertLabels(labels) {
133
+ return Object.keys(labels)
134
+ .sort()
135
+ .map((key) => `${key}=${labels[key]}`)
136
+ .join(', ');
137
+ }
138
+ /**
139
+ * A duration in seconds as short words (`90` is `1 min 30 s`, `3600` is `1 h`).
140
+ *
141
+ * @param seconds - whole seconds.
142
+ * @returns the text.
143
+ *
144
+ * @stability experimental
145
+ */
146
+ export function formatAlertSeconds(seconds) {
147
+ if (seconds <= 0)
148
+ return '0 s';
149
+ const parts = [];
150
+ const days = Math.floor(seconds / 86_400);
151
+ const hours = Math.floor((seconds % 86_400) / 3600);
152
+ const minutes = Math.floor((seconds % 3600) / 60);
153
+ const rest = seconds % 60;
154
+ if (days)
155
+ parts.push(`${days} d`);
156
+ if (hours)
157
+ parts.push(`${hours} h`);
158
+ if (minutes)
159
+ parts.push(`${minutes} min`);
160
+ if (rest)
161
+ parts.push(`${rest} s`);
162
+ return parts.join(' ');
163
+ }
164
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/alerts/headless/format.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,6EAA6E;AAC7E,oEAAoE;AACpE,gFAAgF;AAEhF,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAiBtE;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAA4C,MAAM,CAAC,MAAM,CAAC;IAC1F,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;CACb,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAA+C,MAAM,CAAC,MAAM,CAAC;IAC5F,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;CACb,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAiD,MAAM,CAAC,MAAM,CAAC;IAC5F,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;CACrB,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAoD,MAAM,CAAC,MAAM,CAAC;IAC9F,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,OAAO;IACf,QAAQ,EAAE,SAAS;CACpB,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAA8C,MAAM,CAAC,MAAM,CAAC;IAC9F,EAAE,EAAE,kBAAkB;IACtB,GAAG,EAAE,cAAc;IACnB,EAAE,EAAE,eAAe;IACnB,GAAG,EAAE,aAAa;IAClB,EAAE,EAAE,cAAc;IAClB,GAAG,EAAE,kBAAkB;CACxB,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAA+C,MAAM,CAAC,MAAM,CAAC;IAChG,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,iBAAiB;CACxB,CAAC,CAAC;AAEH,MAAM,mBAAmB,GAAqC,MAAM,CAAC,MAAM,CAAC;IAC1E,CAAC,cAAc,CAAC,gBAAgB,CAAC,EAAE,kBAAkB;IACrD,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,YAAY;IACzC,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,mBAAmB;IAC7C,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,cAAc;IAC7C,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAE,uBAAuB;CAChE,CAAC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,QAAsD,EAAE;IACnG,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AAC9F,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAwD;IACvF,IAAI,CAAC,OAAO;QAAE,OAAO,CAAC,CAAC;IACvB,OAAO,OAAO,CAAC,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;AAChF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAwD;IACvF,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC;QAAE,OAAO,UAAU,CAAC;IACnD,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IACjD,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC;IAC3C,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAwC;IACxE,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;SACvB,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;SACrC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,IAAI,OAAO,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,OAAO,GAAG,EAAE,CAAC;IAC1B,IAAI,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;IAClC,IAAI,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;IACpC,IAAI,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,MAAM,CAAC,CAAC;IAC1C,IAAI,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;IAClC,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC"}