@marinoscar/platform-web 0.1.0-next.18 → 0.1.0-next.20

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 (256) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +5 -3
  3. package/dist/ai/headless/errors.d.ts +7 -0
  4. package/dist/ai/headless/errors.d.ts.map +1 -1
  5. package/dist/ai/headless/errors.js +2 -0
  6. package/dist/ai/headless/errors.js.map +1 -1
  7. package/dist/ai/headless/types.d.ts +30 -5
  8. package/dist/ai/headless/types.d.ts.map +1 -1
  9. package/dist/ai/headless/types.js +22 -10
  10. package/dist/ai/headless/types.js.map +1 -1
  11. package/dist/ai/headless/use-ai-usage.d.ts +5 -2
  12. package/dist/ai/headless/use-ai-usage.d.ts.map +1 -1
  13. package/dist/ai/headless/use-ai-usage.js +15 -5
  14. package/dist/ai/headless/use-ai-usage.js.map +1 -1
  15. package/dist/ai/ui/AiUsagePage.d.ts.map +1 -1
  16. package/dist/ai/ui/AiUsagePage.js +7 -5
  17. package/dist/ai/ui/AiUsagePage.js.map +1 -1
  18. package/dist/ai/ui/shared/AiErrorAlert.d.ts.map +1 -1
  19. package/dist/ai/ui/shared/AiErrorAlert.js +5 -1
  20. package/dist/ai/ui/shared/AiErrorAlert.js.map +1 -1
  21. package/dist/ai/ui/usage/aiUsageFormat.d.ts +9 -6
  22. package/dist/ai/ui/usage/aiUsageFormat.d.ts.map +1 -1
  23. package/dist/ai/ui/usage/aiUsageFormat.js +28 -12
  24. package/dist/ai/ui/usage/aiUsageFormat.js.map +1 -1
  25. package/dist/ai/ui/user/MyAiUsageSection.d.ts.map +1 -1
  26. package/dist/ai/ui/user/MyAiUsageSection.js +5 -2
  27. package/dist/ai/ui/user/MyAiUsageSection.js.map +1 -1
  28. package/dist/ai/ui/user/aiErrorText.d.ts +4 -1
  29. package/dist/ai/ui/user/aiErrorText.d.ts.map +1 -1
  30. package/dist/ai/ui/user/aiErrorText.js +10 -2
  31. package/dist/ai/ui/user/aiErrorText.js.map +1 -1
  32. package/dist/alerts/headless/client.d.ts +134 -0
  33. package/dist/alerts/headless/client.d.ts.map +1 -0
  34. package/dist/alerts/headless/client.js +105 -0
  35. package/dist/alerts/headless/client.js.map +1 -0
  36. package/dist/alerts/headless/format.d.ts +95 -0
  37. package/dist/alerts/headless/format.d.ts.map +1 -0
  38. package/dist/alerts/headless/format.js +164 -0
  39. package/dist/alerts/headless/format.js.map +1 -0
  40. package/dist/alerts/headless/hooks.d.ts +245 -0
  41. package/dist/alerts/headless/hooks.d.ts.map +1 -0
  42. package/dist/alerts/headless/hooks.js +315 -0
  43. package/dist/alerts/headless/hooks.js.map +1 -0
  44. package/dist/alerts/headless/index.d.ts +9 -0
  45. package/dist/alerts/headless/index.d.ts.map +1 -0
  46. package/dist/alerts/headless/index.js +9 -0
  47. package/dist/alerts/headless/index.js.map +1 -0
  48. package/dist/alerts/headless/rule-draft.d.ts +175 -0
  49. package/dist/alerts/headless/rule-draft.d.ts.map +1 -0
  50. package/dist/alerts/headless/rule-draft.js +261 -0
  51. package/dist/alerts/headless/rule-draft.js.map +1 -0
  52. package/dist/alerts/ui/AlertIncidentDrawer.d.ts +30 -0
  53. package/dist/alerts/ui/AlertIncidentDrawer.d.ts.map +1 -0
  54. package/dist/alerts/ui/AlertIncidentDrawer.js +33 -0
  55. package/dist/alerts/ui/AlertIncidentDrawer.js.map +1 -0
  56. package/dist/alerts/ui/AlertRuleDialog.d.ts +47 -0
  57. package/dist/alerts/ui/AlertRuleDialog.d.ts.map +1 -0
  58. package/dist/alerts/ui/AlertRuleDialog.js +124 -0
  59. package/dist/alerts/ui/AlertRuleDialog.js.map +1 -0
  60. package/dist/alerts/ui/AlertRuleTestResult.d.ts +23 -0
  61. package/dist/alerts/ui/AlertRuleTestResult.d.ts.map +1 -0
  62. package/dist/alerts/ui/AlertRuleTestResult.js +30 -0
  63. package/dist/alerts/ui/AlertRuleTestResult.js.map +1 -0
  64. package/dist/alerts/ui/AlertsPage.d.ts +41 -0
  65. package/dist/alerts/ui/AlertsPage.d.ts.map +1 -0
  66. package/dist/alerts/ui/AlertsPage.js +238 -0
  67. package/dist/alerts/ui/AlertsPage.js.map +1 -0
  68. package/dist/alerts/ui/FiringAlertsBanner.d.ts +28 -0
  69. package/dist/alerts/ui/FiringAlertsBanner.d.ts.map +1 -0
  70. package/dist/alerts/ui/FiringAlertsBanner.js +45 -0
  71. package/dist/alerts/ui/FiringAlertsBanner.js.map +1 -0
  72. package/dist/alerts/ui/copy.d.ts +15 -0
  73. package/dist/alerts/ui/copy.d.ts.map +1 -0
  74. package/dist/alerts/ui/copy.js +14 -0
  75. package/dist/alerts/ui/copy.js.map +1 -0
  76. package/dist/alerts/ui/index.d.ts +14 -0
  77. package/dist/alerts/ui/index.d.ts.map +1 -0
  78. package/dist/alerts/ui/index.js +12 -0
  79. package/dist/alerts/ui/index.js.map +1 -0
  80. package/dist/alerts/ui/parts.d.ts +26 -0
  81. package/dist/alerts/ui/parts.d.ts.map +1 -0
  82. package/dist/alerts/ui/parts.js +27 -0
  83. package/dist/alerts/ui/parts.js.map +1 -0
  84. package/dist/alerts/ui/settings.d.ts +27 -0
  85. package/dist/alerts/ui/settings.d.ts.map +1 -0
  86. package/dist/alerts/ui/settings.js +37 -0
  87. package/dist/alerts/ui/settings.js.map +1 -0
  88. package/dist/core/http/client.d.ts.map +1 -1
  89. package/dist/core/http/client.js +7 -0
  90. package/dist/core/http/client.js.map +1 -1
  91. package/dist/core/http/sse.d.ts.map +1 -1
  92. package/dist/core/http/sse.js +3 -1
  93. package/dist/core/http/sse.js.map +1 -1
  94. package/dist/core/index.d.ts +1 -0
  95. package/dist/core/index.d.ts.map +1 -1
  96. package/dist/core/index.js +1 -0
  97. package/dist/core/index.js.map +1 -1
  98. package/dist/core/time-zone/format.d.ts +6 -2
  99. package/dist/core/time-zone/format.d.ts.map +1 -1
  100. package/dist/core/time-zone/format.js +27 -25
  101. package/dist/core/time-zone/format.js.map +1 -1
  102. package/dist/core/time-zone/request.d.ts +17 -0
  103. package/dist/core/time-zone/request.d.ts.map +1 -0
  104. package/dist/core/time-zone/request.js +26 -0
  105. package/dist/core/time-zone/request.js.map +1 -0
  106. package/dist/datatable/headless/export/exportModel.d.ts +7 -1
  107. package/dist/datatable/headless/export/exportModel.d.ts.map +1 -1
  108. package/dist/datatable/headless/export/exportModel.js +10 -2
  109. package/dist/datatable/headless/export/exportModel.js.map +1 -1
  110. package/dist/datatable/headless/filter/dateRange.d.ts +40 -0
  111. package/dist/datatable/headless/filter/dateRange.d.ts.map +1 -0
  112. package/dist/datatable/headless/filter/dateRange.js +53 -0
  113. package/dist/datatable/headless/filter/dateRange.js.map +1 -0
  114. package/dist/datatable/headless/filter/filterTypes.d.ts.map +1 -1
  115. package/dist/datatable/headless/filter/filterTypes.js +24 -4
  116. package/dist/datatable/headless/filter/filterTypes.js.map +1 -1
  117. package/dist/datatable/headless/index.d.ts +2 -0
  118. package/dist/datatable/headless/index.d.ts.map +1 -1
  119. package/dist/datatable/headless/index.js +1 -0
  120. package/dist/datatable/headless/index.js.map +1 -1
  121. package/dist/db-backup/internal/time-zones.d.ts +3 -0
  122. package/dist/db-backup/internal/time-zones.d.ts.map +1 -0
  123. package/dist/db-backup/internal/time-zones.js +24 -0
  124. package/dist/db-backup/internal/time-zones.js.map +1 -0
  125. package/dist/db-backup/ui/DbBackupConfigPanel.d.ts +11 -6
  126. package/dist/db-backup/ui/DbBackupConfigPanel.d.ts.map +1 -1
  127. package/dist/db-backup/ui/DbBackupConfigPanel.js +18 -11
  128. package/dist/db-backup/ui/DbBackupConfigPanel.js.map +1 -1
  129. package/dist/identity/ui/tokens/CreatePatDialog.d.ts +17 -0
  130. package/dist/identity/ui/tokens/CreatePatDialog.d.ts.map +1 -1
  131. package/dist/identity/ui/tokens/CreatePatDialog.js +34 -11
  132. package/dist/identity/ui/tokens/CreatePatDialog.js.map +1 -1
  133. package/dist/nodes/headless/api.d.ts +3 -1
  134. package/dist/nodes/headless/api.d.ts.map +1 -1
  135. package/dist/nodes/headless/api.js +22 -0
  136. package/dist/nodes/headless/api.js.map +1 -1
  137. package/dist/nodes/headless/index.d.ts +7 -2
  138. package/dist/nodes/headless/index.d.ts.map +1 -1
  139. package/dist/nodes/headless/index.js +4 -1
  140. package/dist/nodes/headless/index.js.map +1 -1
  141. package/dist/nodes/headless/node-events.d.ts +43 -0
  142. package/dist/nodes/headless/node-events.d.ts.map +1 -0
  143. package/dist/nodes/headless/node-events.js +150 -0
  144. package/dist/nodes/headless/node-events.js.map +1 -0
  145. package/dist/nodes/headless/power.d.ts +43 -0
  146. package/dist/nodes/headless/power.d.ts.map +1 -0
  147. package/dist/nodes/headless/power.js +74 -0
  148. package/dist/nodes/headless/power.js.map +1 -0
  149. package/dist/nodes/headless/types.d.ts +40 -3
  150. package/dist/nodes/headless/types.d.ts.map +1 -1
  151. package/dist/nodes/headless/types.js +1 -1
  152. package/dist/nodes/headless/types.js.map +1 -1
  153. package/dist/nodes/headless/use-node-events.d.ts +59 -0
  154. package/dist/nodes/headless/use-node-events.d.ts.map +1 -0
  155. package/dist/nodes/headless/use-node-events.js +159 -0
  156. package/dist/nodes/headless/use-node-events.js.map +1 -0
  157. package/dist/nodes/ui/NodeEventsTimeline.d.ts +39 -0
  158. package/dist/nodes/ui/NodeEventsTimeline.d.ts.map +1 -0
  159. package/dist/nodes/ui/NodeEventsTimeline.js +63 -0
  160. package/dist/nodes/ui/NodeEventsTimeline.js.map +1 -0
  161. package/dist/nodes/ui/NodePowerBadge.d.ts +27 -0
  162. package/dist/nodes/ui/NodePowerBadge.d.ts.map +1 -0
  163. package/dist/nodes/ui/NodePowerBadge.js +48 -0
  164. package/dist/nodes/ui/NodePowerBadge.js.map +1 -0
  165. package/dist/nodes/ui/NodeVitalsDialog.d.ts +11 -1
  166. package/dist/nodes/ui/NodeVitalsDialog.d.ts.map +1 -1
  167. package/dist/nodes/ui/NodeVitalsDialog.js +14 -5
  168. package/dist/nodes/ui/NodeVitalsDialog.js.map +1 -1
  169. package/dist/nodes/ui/WorkersPage.d.ts.map +1 -1
  170. package/dist/nodes/ui/WorkersPage.js +2 -1
  171. package/dist/nodes/ui/WorkersPage.js.map +1 -1
  172. package/dist/nodes/ui/workerVitals.d.ts +17 -1
  173. package/dist/nodes/ui/workerVitals.d.ts.map +1 -1
  174. package/dist/nodes/ui/workerVitals.js +43 -0
  175. package/dist/nodes/ui/workerVitals.js.map +1 -1
  176. package/dist/nodes/ui/workersTable.d.ts.map +1 -1
  177. package/dist/nodes/ui/workersTable.js +2 -1
  178. package/dist/nodes/ui/workersTable.js.map +1 -1
  179. package/dist/settings/ui/ProfileSettings.d.ts +1 -1
  180. package/dist/settings/ui/ProfileSettings.d.ts.map +1 -1
  181. package/dist/settings/ui/UserSettingsSection.d.ts +1 -1
  182. package/dist/settings/ui/UserSettingsSection.d.ts.map +1 -1
  183. package/dist/sharing/internal/format.d.ts +10 -1
  184. package/dist/sharing/internal/format.d.ts.map +1 -1
  185. package/dist/sharing/internal/format.js +10 -1
  186. package/dist/sharing/internal/format.js.map +1 -1
  187. package/dist/telemetry/headless/hooks/useTelemetryDashboard.d.ts +1 -1
  188. package/dist/telemetry/ui/components/dashboard/metrics/MetricSections.d.ts +11 -0
  189. package/dist/telemetry/ui/components/dashboard/metrics/MetricSections.d.ts.map +1 -1
  190. package/dist/telemetry/ui/components/dashboard/metrics/MetricSections.js +17 -2
  191. package/dist/telemetry/ui/components/dashboard/metrics/MetricSections.js.map +1 -1
  192. package/dist/webhooks/headless/client.d.ts +101 -0
  193. package/dist/webhooks/headless/client.d.ts.map +1 -0
  194. package/dist/webhooks/headless/client.js +105 -0
  195. package/dist/webhooks/headless/client.js.map +1 -0
  196. package/dist/webhooks/headless/event-selection.d.ts +119 -0
  197. package/dist/webhooks/headless/event-selection.d.ts.map +1 -0
  198. package/dist/webhooks/headless/event-selection.js +225 -0
  199. package/dist/webhooks/headless/event-selection.js.map +1 -0
  200. package/dist/webhooks/headless/format.d.ts +84 -0
  201. package/dist/webhooks/headless/format.d.ts.map +1 -0
  202. package/dist/webhooks/headless/format.js +142 -0
  203. package/dist/webhooks/headless/format.js.map +1 -0
  204. package/dist/webhooks/headless/hooks.d.ts +199 -0
  205. package/dist/webhooks/headless/hooks.d.ts.map +1 -0
  206. package/dist/webhooks/headless/hooks.js +249 -0
  207. package/dist/webhooks/headless/hooks.js.map +1 -0
  208. package/dist/webhooks/headless/index.d.ts +9 -0
  209. package/dist/webhooks/headless/index.d.ts.map +1 -0
  210. package/dist/webhooks/headless/index.js +9 -0
  211. package/dist/webhooks/headless/index.js.map +1 -0
  212. package/dist/webhooks/ui/WebhookDeliveryDrawer.d.ts +32 -0
  213. package/dist/webhooks/ui/WebhookDeliveryDrawer.d.ts.map +1 -0
  214. package/dist/webhooks/ui/WebhookDeliveryDrawer.js +64 -0
  215. package/dist/webhooks/ui/WebhookDeliveryDrawer.js.map +1 -0
  216. package/dist/webhooks/ui/WebhookEndpointDetail.d.ts +21 -0
  217. package/dist/webhooks/ui/WebhookEndpointDetail.d.ts.map +1 -0
  218. package/dist/webhooks/ui/WebhookEndpointDetail.js +96 -0
  219. package/dist/webhooks/ui/WebhookEndpointDetail.js.map +1 -0
  220. package/dist/webhooks/ui/WebhookEndpointDialog.d.ts +39 -0
  221. package/dist/webhooks/ui/WebhookEndpointDialog.d.ts.map +1 -0
  222. package/dist/webhooks/ui/WebhookEndpointDialog.js +79 -0
  223. package/dist/webhooks/ui/WebhookEndpointDialog.js.map +1 -0
  224. package/dist/webhooks/ui/WebhookEventPicker.d.ts +30 -0
  225. package/dist/webhooks/ui/WebhookEventPicker.d.ts.map +1 -0
  226. package/dist/webhooks/ui/WebhookEventPicker.js +33 -0
  227. package/dist/webhooks/ui/WebhookEventPicker.js.map +1 -0
  228. package/dist/webhooks/ui/WebhookSecretDialog.d.ts +27 -0
  229. package/dist/webhooks/ui/WebhookSecretDialog.d.ts.map +1 -0
  230. package/dist/webhooks/ui/WebhookSecretDialog.js +52 -0
  231. package/dist/webhooks/ui/WebhookSecretDialog.js.map +1 -0
  232. package/dist/webhooks/ui/WebhookSignatureHelp.d.ts +18 -0
  233. package/dist/webhooks/ui/WebhookSignatureHelp.d.ts.map +1 -0
  234. package/dist/webhooks/ui/WebhookSignatureHelp.js +40 -0
  235. package/dist/webhooks/ui/WebhookSignatureHelp.js.map +1 -0
  236. package/dist/webhooks/ui/WebhooksPage.d.ts +47 -0
  237. package/dist/webhooks/ui/WebhooksPage.d.ts.map +1 -0
  238. package/dist/webhooks/ui/WebhooksPage.js +172 -0
  239. package/dist/webhooks/ui/WebhooksPage.js.map +1 -0
  240. package/dist/webhooks/ui/copy.d.ts +24 -0
  241. package/dist/webhooks/ui/copy.d.ts.map +1 -0
  242. package/dist/webhooks/ui/copy.js +34 -0
  243. package/dist/webhooks/ui/copy.js.map +1 -0
  244. package/dist/webhooks/ui/index.d.ts +15 -0
  245. package/dist/webhooks/ui/index.d.ts.map +1 -0
  246. package/dist/webhooks/ui/index.js +12 -0
  247. package/dist/webhooks/ui/index.js.map +1 -0
  248. package/dist/webhooks/ui/parts.d.ts +25 -0
  249. package/dist/webhooks/ui/parts.d.ts.map +1 -0
  250. package/dist/webhooks/ui/parts.js +28 -0
  251. package/dist/webhooks/ui/parts.js.map +1 -0
  252. package/dist/webhooks/ui/settings.d.ts +58 -0
  253. package/dist/webhooks/ui/settings.d.ts.map +1 -0
  254. package/dist/webhooks/ui/settings.js +79 -0
  255. package/dist/webhooks/ui/settings.js.map +1 -0
  256. package/package.json +18 -2
@@ -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":"AAoBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,yBAAyB,EAAE,cAAc,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE/G;;;;;;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;CACjD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,QAAQ,CAiBlE"}
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;AA2BhF;;;;;;;;;;;;;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;KACF,CAAC;AACJ,CAAC"}
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,GACX,MAAM,YAAY,CAAC;AACpB,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"}
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;AAcpB,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"}
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-events.js","sourceRoot":"","sources":["../../../src/nodes/headless/node-events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { NodePower } from './types.js';
2
+ /**
3
+ * At or under this battery charge the badge reads in the warning colour.
4
+ *
5
+ * @stability experimental
6
+ */
7
+ export declare const NODE_BATTERY_WARNING_PERCENT = 20;
8
+ /**
9
+ * At or under this battery charge the badge reads in the error colour.
10
+ *
11
+ * @stability experimental
12
+ */
13
+ export declare const NODE_BATTERY_CRITICAL_PERCENT = 10;
14
+ /**
15
+ * A node's power state, ready to draw.
16
+ *
17
+ * @stability experimental
18
+ */
19
+ export interface NodePowerDescription {
20
+ /** Where power comes from (`unknown` is never described). */
21
+ source: 'ac' | 'battery';
22
+ /** Battery charge, rounded to a whole percent, or `null` when not reported. */
23
+ percent: number | null;
24
+ /** Whether the battery is charging, or `null` when not reported. */
25
+ charging: boolean | null;
26
+ /** `warning` at or under 20%, `error` at or under 10%, on battery only. */
27
+ level: 'normal' | 'warning' | 'error';
28
+ /** The short visible text: `42%`, `AC`. */
29
+ text: string;
30
+ /** The full sentence, the accessible label: "On battery, 42%, discharging". */
31
+ label: string;
32
+ }
33
+ /**
34
+ * The badge's words and level for a node's reported power, or `null` when
35
+ * there is nothing to draw (no report, or source `unknown`).
36
+ *
37
+ * @param power - `lastVitals.power`, if any.
38
+ * @returns the description, or `null`.
39
+ *
40
+ * @stability experimental
41
+ */
42
+ export declare function describeNodePower(power: NodePower | null | undefined): NodePowerDescription | null;
43
+ //# sourceMappingURL=power.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"power.d.ts","sourceRoot":"","sources":["../../../src/nodes/headless/power.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAE/C;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,6DAA6D;IAC7D,MAAM,EAAE,IAAI,GAAG,SAAS,CAAC;IACzB,+EAA+E;IAC/E,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,oEAAoE;IACpE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,2EAA2E;IAC3E,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;IACtC,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,oBAAoB,GAAG,IAAI,CAkClG"}
@@ -0,0 +1,74 @@
1
+ // =============================================================================
2
+ // A node's power state, as the Worker Nodes page words it (issue #1045)
3
+ // =============================================================================
4
+ //
5
+ // A node on a laptop reports `vitals.power` (source, battery charge, charging);
6
+ // the fleet table shows a badge for it. This module is the badge's words and
7
+ // level, without markup: the UI draws the icon and the colour from the level,
8
+ // and the SAME sentence is its accessible label, so nothing rests on colour.
9
+ //
10
+ // Display only: a node on battery is not "unhealthy", and nothing here turns
11
+ // the reading into a health verdict (health is the API's, from the heartbeat).
12
+ // An `unknown` or absent source draws nothing: a desktop that cannot tell is not
13
+ // worth a badge on every row.
14
+ // =============================================================================
15
+ /**
16
+ * At or under this battery charge the badge reads in the warning colour.
17
+ *
18
+ * @stability experimental
19
+ */
20
+ export const NODE_BATTERY_WARNING_PERCENT = 20;
21
+ /**
22
+ * At or under this battery charge the badge reads in the error colour.
23
+ *
24
+ * @stability experimental
25
+ */
26
+ export const NODE_BATTERY_CRITICAL_PERCENT = 10;
27
+ /**
28
+ * The badge's words and level for a node's reported power, or `null` when
29
+ * there is nothing to draw (no report, or source `unknown`).
30
+ *
31
+ * @param power - `lastVitals.power`, if any.
32
+ * @returns the description, or `null`.
33
+ *
34
+ * @stability experimental
35
+ */
36
+ export function describeNodePower(power) {
37
+ if (!power || typeof power !== 'object')
38
+ return null;
39
+ const percent = typeof power.batteryPercent === 'number' && Number.isFinite(power.batteryPercent)
40
+ ? Math.round(Math.min(100, Math.max(0, power.batteryPercent)))
41
+ : null;
42
+ const charging = typeof power.charging === 'boolean' ? power.charging : null;
43
+ if (power.source === 'ac') {
44
+ const parts = ['On AC power'];
45
+ if (percent !== null)
46
+ parts.push(`battery ${percent}%`);
47
+ if (charging === true)
48
+ parts.push('charging');
49
+ return { source: 'ac', percent, charging, level: 'normal', text: 'AC', label: parts.join(', ') };
50
+ }
51
+ if (power.source !== 'battery')
52
+ return null;
53
+ const level = percent !== null && percent <= NODE_BATTERY_CRITICAL_PERCENT
54
+ ? 'error'
55
+ : percent !== null && percent <= NODE_BATTERY_WARNING_PERCENT
56
+ ? 'warning'
57
+ : 'normal';
58
+ const parts = ['On battery'];
59
+ if (percent !== null)
60
+ parts.push(`${percent}%`);
61
+ if (charging !== null)
62
+ parts.push(charging ? 'charging' : 'discharging');
63
+ if (power.lowPowerMode === true)
64
+ parts.push('low power mode');
65
+ return {
66
+ source: 'battery',
67
+ percent,
68
+ charging,
69
+ level,
70
+ text: percent !== null ? `${percent}%` : 'Battery',
71
+ label: parts.join(', '),
72
+ };
73
+ }
74
+ //# sourceMappingURL=power.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"power.js","sourceRoot":"","sources":["../../../src/nodes/headless/power.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,wEAAwE;AACxE,gFAAgF;AAChF,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,8EAA8E;AAC9E,6EAA6E;AAC7E,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAC/E,iFAAiF;AACjF,8BAA8B;AAC9B,gFAAgF;AAIhF;;;;GAIG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAE/C;;;;GAIG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAsBhD;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAmC;IACnE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACrD,MAAM,OAAO,GACX,OAAO,KAAK,CAAC,cAAc,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC;QAC/E,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;QAC9D,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IAE7E,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,CAAC,aAAa,CAAC,CAAC;QAC9B,IAAI,OAAO,KAAK,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,GAAG,CAAC,CAAC;QACxD,IAAI,QAAQ,KAAK,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9C,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACnG,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAE5C,MAAM,KAAK,GACT,OAAO,KAAK,IAAI,IAAI,OAAO,IAAI,6BAA6B;QAC1D,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,OAAO,KAAK,IAAI,IAAI,OAAO,IAAI,4BAA4B;YAC3D,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,QAAQ,CAAC;IACjB,MAAM,KAAK,GAAG,CAAC,YAAY,CAAC,CAAC;IAC7B,IAAI,OAAO,KAAK,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC;IAChD,IAAI,QAAQ,KAAK,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;IACzE,IAAI,KAAK,CAAC,YAAY,KAAK,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC9D,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,OAAO;QACP,QAAQ;QACR,KAAK;QACL,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,SAAS;QAClD,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;KACxB,CAAC;AACJ,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import type { z } from 'zod';
2
- import type { AdminNode, AdminNodeCredential, NodeCredentialCreated, NodeHealth, NodeJobCounts, NodeOwner, NodeStatus, NodeVitals, NodeVitalsCounters, createNodeCredentialSchema } from '@marinoscar/platform-contract/nodes';
3
- export { MAX_NODE_CREDENTIAL_DAYS, MAX_NODE_CREDENTIAL_NAME_LENGTH, NODE_HEALTHS, NODE_STATUSES, } from '@marinoscar/platform-contract/nodes';
4
- export type { NodeCredentialCreated, NodeHealth, NodeJobCounts, NodeOwner, NodeStatus, NodeVitals, NodeVitalsCounters, };
2
+ import type { AdminNode, AdminNodeCredential, AdminNodeEvent, AdminNodeEventList, NodeCredentialCreated, NodeHealth, NodeHostVitals, NodeJobCounts, NodeOwner, NodePower, NodeStatus, NodeVitals, NodeVitalsCounters, createNodeCredentialSchema } from '@marinoscar/platform-contract/nodes';
3
+ export { MAX_NODE_CREDENTIAL_DAYS, MAX_NODE_CREDENTIAL_NAME_LENGTH, NODE_EVENT_TYPES, NODE_HEALTHS, NODE_STATUSES, } from '@marinoscar/platform-contract/nodes';
4
+ export type { NodeCredentialCreated, NodeHealth, NodeHostVitals, NodeJobCounts, NodeOwner, NodePower, NodeStatus, NodeVitals, NodeVitalsCounters, };
5
5
  /**
6
6
  * One node as `GET /api/admin/nodes` returns it (`AdminNodeDto`,
7
7
  * `adminNodeSchema`).
@@ -9,6 +9,43 @@ export type { NodeCredentialCreated, NodeHealth, NodeJobCounts, NodeOwner, NodeS
9
9
  * @stability experimental
10
10
  */
11
11
  export type WorkerNode = AdminNode;
12
+ /**
13
+ * One stored node event as `GET /api/admin/nodes/:id/events` returns it
14
+ * (`adminNodeEventSchema`, #1045): a power change, a low battery, a wake from
15
+ * sleep, a low disk. `type` is an OPEN dotted string (`NODE_EVENT_TYPES` names
16
+ * the platform's own); `occurredAt` is the node's clock, `receivedAt` the server's.
17
+ *
18
+ * @stability experimental
19
+ */
20
+ export type WorkerNodeEvent = AdminNodeEvent;
21
+ /**
22
+ * A page of node events (`adminNodeEventListSchema`), newest first.
23
+ *
24
+ * @stability experimental
25
+ */
26
+ export type WorkerNodeEventList = AdminNodeEventList;
27
+ /**
28
+ * How loud a node event is: `info`, `warning` or `critical`.
29
+ *
30
+ * @stability experimental
31
+ */
32
+ export type NodeEventSeverity = AdminNodeEvent['severity'];
33
+ /**
34
+ * The query `GET /api/admin/nodes/:id/events` takes. Every member optional; an absent
35
+ * one is left out of the query string (the API's defaults apply).
36
+ *
37
+ * @stability experimental
38
+ */
39
+ export interface NodeEventsQuery {
40
+ /** 1-based page. */
41
+ page?: number;
42
+ /** Events per page. */
43
+ pageSize?: number;
44
+ /** Only events of this exact type (`power.battery_low`). */
45
+ type?: string;
46
+ /** Only events of this severity. */
47
+ severity?: NodeEventSeverity;
48
+ }
12
49
  /**
13
50
  * One credential as `GET /api/admin/nodes/credentials` returns it
14
51
  * (`AdminNodeCredentialDto`, `adminNodeCredentialSchema`). No `token`, no hash;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/nodes/headless/types.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EACV,SAAS,EACT,mBAAmB,EACnB,qBAAqB,EACrB,UAAU,EACV,aAAa,EACb,SAAS,EACT,UAAU,EACV,UAAU,EACV,kBAAkB,EAClB,0BAA0B,EAC3B,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,YAAY,EACZ,aAAa,GACd,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,qBAAqB,EACrB,UAAU,EACV,aAAa,EACb,SAAS,EACT,UAAU,EACV,UAAU,EACV,kBAAkB,GACnB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,CAAC;AAEnC;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,mBAAmB,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAEnF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpE;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,WAAW,CAAC,EAC3D,GAAG,GAAE,IAAiB,GACrB,oBAAoB,CAStB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/nodes/headless/types.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EACV,SAAS,EACT,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,UAAU,EACV,cAAc,EACd,aAAa,EACb,SAAS,EACT,SAAS,EACT,UAAU,EACV,UAAU,EACV,kBAAkB,EAClB,0BAA0B,EAC3B,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,gBAAgB,EAChB,YAAY,EACZ,aAAa,GACd,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,qBAAqB,EACrB,UAAU,EACV,cAAc,EACd,aAAa,EACb,SAAS,EACT,SAAS,EACT,UAAU,EACV,UAAU,EACV,kBAAkB,GACnB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,CAAC;AAEnC;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC;AAE7C;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;AAErD;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,oBAAoB;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,mBAAmB,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAEnF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpE;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,WAAW,CAAC,EAC3D,GAAG,GAAE,IAAiB,GACrB,oBAAoB,CAStB"}
@@ -19,7 +19,7 @@
19
19
  // heartbeat against the `nodes.staleHeartbeatSeconds` system setting, which
20
20
  // the browser does not read), so nothing in this slice recomputes it.
21
21
  // =============================================================================
22
- export { MAX_NODE_CREDENTIAL_DAYS, MAX_NODE_CREDENTIAL_NAME_LENGTH, NODE_HEALTHS, NODE_STATUSES, } from '@marinoscar/platform-contract/nodes';
22
+ export { MAX_NODE_CREDENTIAL_DAYS, MAX_NODE_CREDENTIAL_NAME_LENGTH, NODE_EVENT_TYPES, NODE_HEALTHS, NODE_STATUSES, } from '@marinoscar/platform-contract/nodes';
23
23
  /**
24
24
  * Whether a credential can still authenticate a node right now.
25
25
  *
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/nodes/headless/types.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,sEAAsE;AACtE,gFAAgF;AAChF,EAAE;AACF,wFAAwF;AACxF,gFAAgF;AAChF,8EAA8E;AAC9E,+EAA+E;AAC/E,eAAe;AACf,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,6EAA6E;AAC7E,qEAAqE;AACrE,2EAA2E;AAC3E,mCAAmC;AACnC,EAAE;AACF,8EAA8E;AAC9E,4EAA4E;AAC5E,sEAAsE;AACtE,gFAAgF;AAgBhF,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,YAAY,EACZ,aAAa,GACd,MAAM,qCAAqC,CAAC;AA2C7C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAClC,UAA2D,EAC3D,MAAY,IAAI,IAAI,EAAE;IAEtB,IAAI,UAAU,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,0EAA0E;IAC1E,yEAAyE;IACzE,gDAAgD;IAChD,IAAI,UAAU,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;QACtF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/nodes/headless/types.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,sEAAsE;AACtE,gFAAgF;AAChF,EAAE;AACF,wFAAwF;AACxF,gFAAgF;AAChF,8EAA8E;AAC9E,+EAA+E;AAC/E,eAAe;AACf,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,6EAA6E;AAC7E,qEAAqE;AACrE,2EAA2E;AAC3E,mCAAmC;AACnC,EAAE;AACF,8EAA8E;AAC9E,4EAA4E;AAC5E,sEAAsE;AACtE,gFAAgF;AAoBhF,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,gBAAgB,EAChB,YAAY,EACZ,aAAa,GACd,MAAM,qCAAqC,CAAC;AAsF7C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAClC,UAA2D,EAC3D,MAAY,IAAI,IAAI,EAAE;IAEtB,IAAI,UAAU,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,0EAA0E;IAC1E,yEAAyE;IACzE,gDAAgD;IAChD,IAAI,UAAU,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;QACtF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * One node's recent events (issue #1045): `GET /api/admin/nodes/:id/events`, newest
3
+ * first, with "load more".
4
+ *
5
+ * The same contract as the fleet hooks (`use-worker-nodes.ts`): every function
6
+ * resolves rather than throws, and a failure is a STRING the caller renders.
7
+ *
8
+ * The first page is asked for when the node or the filters change; `loadMore`
9
+ * appends the next page; `refresh` re-reads from the first page WITHOUT raising
10
+ * the loading flag (the list stays on screen). An event that arrives between a
11
+ * first page and a "load more" shifts the pages by one, so an appended page is
12
+ * de-duplicated by id rather than trusted to start where the last one ended.
13
+ *
14
+ * The query is read member by member (`page`, `pageSize`, `type`, `severity`),
15
+ * so an inline object literal does not re-fetch on every render.
16
+ */
17
+ import type { NodesApi } from './api.js';
18
+ import type { NodeEventsQuery, WorkerNodeEvent } from './types.js';
19
+ /**
20
+ * What {@link useNodeEvents} returns.
21
+ *
22
+ * @stability experimental
23
+ */
24
+ export interface UseNodeEventsResult {
25
+ /** The events read so far, newest first; emptied on an error or with no node. */
26
+ events: WorkerNodeEvent[];
27
+ /** How many events the node has in total (for the filters), `0` before an answer. */
28
+ total: number;
29
+ /** Whether a further page exists. */
30
+ hasMore: boolean;
31
+ /** The first page is in flight. */
32
+ isLoading: boolean;
33
+ /** A `loadMore` page is in flight. */
34
+ isLoadingMore: boolean;
35
+ /** The last failure as a sentence, or `null`. */
36
+ error: string | null;
37
+ /** Re-read from the first page without raising the loading flag. */
38
+ refresh: () => Promise<void>;
39
+ /** Append the next page. A no-op while one is in flight or when there is none. */
40
+ loadMore: () => Promise<void>;
41
+ }
42
+ /**
43
+ * `GET /api/admin/nodes/:id/events`: a node's events, newest first, page by page.
44
+ *
45
+ * @param nodeId - the node id, or `null` to ask for nothing.
46
+ * @param query - the first page, its size and the filters (every member optional).
47
+ * @param api - a client to use instead of the adapters' or the host's.
48
+ * @returns the events and their state.
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * const { events, hasMore, loadMore } = useNodeEvents(node.id, { pageSize: 20, severity: 'critical' });
53
+ * ```
54
+ *
55
+ * @extensionPoint hook
56
+ * @stability experimental
57
+ */
58
+ export declare function useNodeEvents(nodeId: string | null, query?: NodeEventsQuery, api?: NodesApi): UseNodeEventsResult;
59
+ //# sourceMappingURL=use-node-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-node-events.d.ts","sourceRoot":"","sources":["../../../src/nodes/headless/use-node-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAuB,MAAM,YAAY,CAAC;AAExF;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,aAAa,EAAE,OAAO,CAAC;IACvB,iDAAiD;IACjD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,oEAAoE;IACpE,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,kFAAkF;IAClF,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AA2BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,GAAE,eAAoB,EAAE,GAAG,CAAC,EAAE,QAAQ,GAAG,mBAAmB,CAqGrH"}