@kingsleyweb/bun-ui 0.0.0-stage → 3.0.0-rc.2

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 (240) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -2
  3. package/app/docs/App.tsx +72 -0
  4. package/app/docs/api/client.ts +303 -0
  5. package/app/docs/api/contract.ts +24 -0
  6. package/app/docs/api/docs.ts +38 -0
  7. package/app/docs/api/errors.ts +144 -0
  8. package/app/docs/boot.tsx +58 -0
  9. package/app/docs/components/Badge.tsx +65 -0
  10. package/app/docs/components/Button.tsx +37 -0
  11. package/app/docs/components/Card.tsx +41 -0
  12. package/app/docs/components/ConfirmDialog.tsx +173 -0
  13. package/app/docs/components/CopyButton.tsx +68 -0
  14. package/app/docs/components/Dialog.tsx +230 -0
  15. package/app/docs/components/EmptyState.tsx +34 -0
  16. package/app/docs/components/ErrorView.tsx +70 -0
  17. package/app/docs/components/Field.tsx +93 -0
  18. package/app/docs/components/JsonEditor.tsx +151 -0
  19. package/app/docs/components/JsonView.tsx +338 -0
  20. package/app/docs/components/KeyValue.tsx +63 -0
  21. package/app/docs/components/ProblemBanner.tsx +116 -0
  22. package/app/docs/components/ScreenErrorBoundary.tsx +141 -0
  23. package/app/docs/components/Spinner.tsx +33 -0
  24. package/app/docs/components/Table.tsx +33 -0
  25. package/app/docs/components/Tabs.tsx +226 -0
  26. package/app/docs/components/classNames.ts +4 -0
  27. package/app/docs/components/components.css +691 -0
  28. package/app/docs/components/copy.ts +89 -0
  29. package/app/docs/components/fieldContext.ts +29 -0
  30. package/app/docs/components/inputValues.ts +142 -0
  31. package/app/docs/components/inputs.tsx +387 -0
  32. package/app/docs/components/jsonParse.ts +338 -0
  33. package/app/docs/components/listKeys.ts +30 -0
  34. package/app/docs/config.ts +86 -0
  35. package/app/docs/context.ts +33 -0
  36. package/app/docs/embed.ts +74 -0
  37. package/app/docs/env.d.ts +2 -0
  38. package/app/docs/format.ts +9 -0
  39. package/app/docs/hooks/useUrlTab.ts +16 -0
  40. package/app/docs/main.tsx +11 -0
  41. package/app/docs/queryClient.ts +54 -0
  42. package/app/docs/router.tsx +194 -0
  43. package/app/docs/routing.ts +194 -0
  44. package/app/docs/screens/docs/document.ts +27 -0
  45. package/app/docs/screens/docs/http/OperationView.tsx +407 -0
  46. package/app/docs/screens/docs/http/Sidebar.tsx +190 -0
  47. package/app/docs/screens/docs/http/TryItPanel.tsx +603 -0
  48. package/app/docs/screens/docs/http/http.css +405 -0
  49. package/app/docs/screens/docs/http/index.tsx +395 -0
  50. package/app/docs/screens/docs/http/model.ts +604 -0
  51. package/app/docs/screens/docs/http/tryIt.ts +455 -0
  52. package/app/docs/screens/docs/permissions.ts +6 -0
  53. package/app/docs/screens/docs/schema/Prose.tsx +43 -0
  54. package/app/docs/screens/docs/schema/SchemaTree.tsx +319 -0
  55. package/app/docs/screens/docs/schema/index.ts +30 -0
  56. package/app/docs/screens/docs/schema/resolve.ts +466 -0
  57. package/app/docs/screens/docs/schema/schema.css +137 -0
  58. package/app/docs/screens/docs/schema/skeleton.ts +92 -0
  59. package/app/docs/screens/docs/viewer.tsx +154 -0
  60. package/app/docs/screens/docs/ws/InlineText.tsx +25 -0
  61. package/app/docs/screens/docs/ws/PayloadSchema.tsx +39 -0
  62. package/app/docs/screens/docs/ws/format.ts +82 -0
  63. package/app/docs/screens/docs/ws/index.tsx +286 -0
  64. package/app/docs/screens/docs/ws/items.tsx +786 -0
  65. package/app/docs/screens/docs/ws/model.ts +1178 -0
  66. package/app/docs/screens/docs/ws/panels.tsx +440 -0
  67. package/app/docs/screens/docs/ws/ws.css +231 -0
  68. package/app/docs/shortcuts.ts +94 -0
  69. package/app/docs/styles/base.css +847 -0
  70. package/app/docs/styles/tokens.css +143 -0
  71. package/app/docs/theme.ts +56 -0
  72. package/app/kit/unauthorized.ts +222 -0
  73. package/dist/docs/assets/main-0rchxtv5.js +18 -0
  74. package/dist/docs/assets/main-0rchxtv5.js.map +99 -0
  75. package/dist/docs/assets/main-cqgyvs86.css +1 -0
  76. package/dist/docs/manifest.json +26 -0
  77. package/dist/jobs/assets/AddFlowDialog-h6xkgx9b.js +6 -0
  78. package/dist/jobs/assets/AddFlowDialog-h6xkgx9b.js.map +11 -0
  79. package/dist/jobs/assets/AddFlowDialog-n7gtc84v.css +1 -0
  80. package/dist/jobs/assets/added-cbwsxv3e.js +4 -0
  81. package/dist/jobs/assets/added-cbwsxv3e.js.map +11 -0
  82. package/dist/jobs/assets/bodies-yyw5hmrp.js +6 -0
  83. package/dist/jobs/assets/bodies-yyw5hmrp.js.map +10 -0
  84. package/dist/jobs/assets/channel-tgkvqm8y.js +4 -0
  85. package/dist/jobs/assets/channel-tgkvqm8y.js.map +10 -0
  86. package/dist/jobs/assets/channelChecks-s4yz4yhw.js +4 -0
  87. package/dist/jobs/assets/channelChecks-s4yz4yhw.js.map +10 -0
  88. package/dist/jobs/assets/index-02427smp.css +1 -0
  89. package/dist/jobs/assets/index-09z2cjft.js +4 -0
  90. package/dist/jobs/assets/index-09z2cjft.js.map +16 -0
  91. package/dist/jobs/assets/index-18bn0gvy.css +1 -0
  92. package/dist/jobs/assets/index-47pxmyxn.js +4 -0
  93. package/dist/jobs/assets/index-47pxmyxn.js.map +10 -0
  94. package/dist/jobs/assets/index-4e55z986.js +4 -0
  95. package/dist/jobs/assets/index-4e55z986.js.map +11 -0
  96. package/dist/jobs/assets/index-5c933424.js +4 -0
  97. package/dist/jobs/assets/index-5c933424.js.map +18 -0
  98. package/dist/jobs/assets/index-5kbyqspm.css +1 -0
  99. package/dist/jobs/assets/index-5ng37hk6.css +1 -0
  100. package/dist/jobs/assets/index-5w8w7fvc.css +1 -0
  101. package/dist/jobs/assets/index-71qs5qyx.css +1 -0
  102. package/dist/jobs/assets/index-btpg4r8b.css +1 -0
  103. package/dist/jobs/assets/index-d5r5n0mm.js +4 -0
  104. package/dist/jobs/assets/index-d5r5n0mm.js.map +23 -0
  105. package/dist/jobs/assets/index-e0yy2skq.css +1 -0
  106. package/dist/jobs/assets/index-hs60b25v.js +10 -0
  107. package/dist/jobs/assets/index-hs60b25v.js.map +62 -0
  108. package/dist/jobs/assets/index-k2smrr70.js +4 -0
  109. package/dist/jobs/assets/index-k2smrr70.js.map +9 -0
  110. package/dist/jobs/assets/index-q24jw3w9.js +4 -0
  111. package/dist/jobs/assets/index-q24jw3w9.js.map +32 -0
  112. package/dist/jobs/assets/index-qfb80xen.css +1 -0
  113. package/dist/jobs/assets/index-rtynx6wj.js +4 -0
  114. package/dist/jobs/assets/index-rtynx6wj.js.map +10 -0
  115. package/dist/jobs/assets/live-6k7s6358.js +4 -0
  116. package/dist/jobs/assets/live-6k7s6358.js.map +10 -0
  117. package/dist/jobs/assets/main-0jmeh6mq.js +6 -0
  118. package/dist/jobs/assets/main-0jmeh6mq.js.map +12 -0
  119. package/dist/jobs/assets/main-3yj6bv90.js +5 -0
  120. package/dist/jobs/assets/main-3yj6bv90.js.map +10 -0
  121. package/dist/jobs/assets/main-4g69fn3x.js +5 -0
  122. package/dist/jobs/assets/main-4g69fn3x.js.map +10 -0
  123. package/dist/jobs/assets/main-4gte3eqq.js +5 -0
  124. package/dist/jobs/assets/main-4gte3eqq.js.map +10 -0
  125. package/dist/jobs/assets/main-4j1fcevh.js +5 -0
  126. package/dist/jobs/assets/main-4j1fcevh.js.map +10 -0
  127. package/dist/jobs/assets/main-54qwkz28.css +1 -0
  128. package/dist/jobs/assets/main-5grjvsy7.js +5 -0
  129. package/dist/jobs/assets/main-5grjvsy7.js.map +11 -0
  130. package/dist/jobs/assets/main-5zbx60gq.js +5 -0
  131. package/dist/jobs/assets/main-5zbx60gq.js.map +11 -0
  132. package/dist/jobs/assets/main-9prgjhg4.js +5 -0
  133. package/dist/jobs/assets/main-9prgjhg4.js.map +10 -0
  134. package/dist/jobs/assets/main-a250ffk7.js +17 -0
  135. package/dist/jobs/assets/main-a250ffk7.js.map +115 -0
  136. package/dist/jobs/assets/main-d6ge7w08.js +5 -0
  137. package/dist/jobs/assets/main-d6ge7w08.js.map +10 -0
  138. package/dist/jobs/assets/main-gngzht43.js +5 -0
  139. package/dist/jobs/assets/main-gngzht43.js.map +10 -0
  140. package/dist/jobs/assets/main-hg0hrg8j.js +5 -0
  141. package/dist/jobs/assets/main-hg0hrg8j.js.map +10 -0
  142. package/dist/jobs/assets/main-hm1ng3yg.js +5 -0
  143. package/dist/jobs/assets/main-hm1ng3yg.js.map +12 -0
  144. package/dist/jobs/assets/main-jkvd92z9.js +5 -0
  145. package/dist/jobs/assets/main-jkvd92z9.js.map +10 -0
  146. package/dist/jobs/assets/main-jv5xqd13.js +5 -0
  147. package/dist/jobs/assets/main-jv5xqd13.js.map +21 -0
  148. package/dist/jobs/assets/main-jxre7w93.js +5 -0
  149. package/dist/jobs/assets/main-jxre7w93.js.map +23 -0
  150. package/dist/jobs/assets/main-kwmqkjfx.js +5 -0
  151. package/dist/jobs/assets/main-kwmqkjfx.js.map +11 -0
  152. package/dist/jobs/assets/main-n9cf6bxm.js +5 -0
  153. package/dist/jobs/assets/main-n9cf6bxm.js.map +11 -0
  154. package/dist/jobs/assets/main-pegp0ygb.js +5 -0
  155. package/dist/jobs/assets/main-pegp0ygb.js.map +10 -0
  156. package/dist/jobs/assets/main-qr573853.js +5 -0
  157. package/dist/jobs/assets/main-qr573853.js.map +12 -0
  158. package/dist/jobs/assets/main-rq97rdr4.js +4 -0
  159. package/dist/jobs/assets/main-rq97rdr4.js.map +22 -0
  160. package/dist/jobs/assets/main-szjdmydc.js +5 -0
  161. package/dist/jobs/assets/main-szjdmydc.js.map +13 -0
  162. package/dist/jobs/assets/main-tnbhrm9n.js +7 -0
  163. package/dist/jobs/assets/main-tnbhrm9n.js.map +11 -0
  164. package/dist/jobs/assets/main-ts19j4n0.js +5 -0
  165. package/dist/jobs/assets/main-ts19j4n0.js.map +25 -0
  166. package/dist/jobs/assets/main-w93x1dzs.js +5 -0
  167. package/dist/jobs/assets/main-w93x1dzs.js.map +10 -0
  168. package/dist/jobs/assets/sections-0ksdxs8m.css +1 -0
  169. package/dist/jobs/assets/sections-0y7w4fb4.js +4 -0
  170. package/dist/jobs/assets/sections-0y7w4fb4.js.map +10 -0
  171. package/dist/jobs/assets/sse-mn0t0fh7.js +5 -0
  172. package/dist/jobs/assets/sse-mn0t0fh7.js.map +11 -0
  173. package/dist/jobs/assets/sseChecks-t7tcm7ra.js +4 -0
  174. package/dist/jobs/assets/sseChecks-t7tcm7ra.js.map +10 -0
  175. package/dist/jobs/assets/validation-ysjfy072.js +4 -0
  176. package/dist/jobs/assets/validation-ysjfy072.js.map +9 -0
  177. package/dist/jobs/manifest.json +511 -0
  178. package/dts/docs/assets.d.ts +144 -0
  179. package/dts/docs/assets.d.ts.map +1 -0
  180. package/dts/docs/browser/config.d.ts +61 -0
  181. package/dts/docs/browser/config.d.ts.map +1 -0
  182. package/dts/docs/browser/index.d.ts +12 -0
  183. package/dts/docs/browser/index.d.ts.map +1 -0
  184. package/dts/docs/docsUi.d.ts +42 -0
  185. package/dts/docs/docsUi.d.ts.map +1 -0
  186. package/dts/docs/hosted.d.ts +22 -0
  187. package/dts/docs/hosted.d.ts.map +1 -0
  188. package/dts/docs/index.d.ts +18 -0
  189. package/dts/docs/index.d.ts.map +1 -0
  190. package/dts/docs/shell.d.ts +57 -0
  191. package/dts/docs/shell.d.ts.map +1 -0
  192. package/dts/docs/types.d.ts +137 -0
  193. package/dts/docs/types.d.ts.map +1 -0
  194. package/dts/index.d.ts +21 -0
  195. package/dts/index.d.ts.map +1 -0
  196. package/dts/jobs/assets.d.ts +157 -0
  197. package/dts/jobs/assets.d.ts.map +1 -0
  198. package/dts/jobs/browser/config.d.ts +67 -0
  199. package/dts/jobs/browser/config.d.ts.map +1 -0
  200. package/dts/jobs/browser/index.d.ts +10 -0
  201. package/dts/jobs/browser/index.d.ts.map +1 -0
  202. package/dts/jobs/browser/unauthorized.d.ts +9 -0
  203. package/dts/jobs/browser/unauthorized.d.ts.map +1 -0
  204. package/dts/jobs/index.d.ts +24 -0
  205. package/dts/jobs/index.d.ts.map +1 -0
  206. package/dts/jobs/jobsUi.d.ts +63 -0
  207. package/dts/jobs/jobsUi.d.ts.map +1 -0
  208. package/dts/jobs/shell.d.ts +77 -0
  209. package/dts/jobs/shell.d.ts.map +1 -0
  210. package/dts/jobs/types.d.ts +146 -0
  211. package/dts/jobs/types.d.ts.map +1 -0
  212. package/dts/kit/browser/shared.d.ts +10 -0
  213. package/dts/kit/browser/shared.d.ts.map +1 -0
  214. package/dts/kit/browser/unauthorized.d.ts +74 -0
  215. package/dts/kit/browser/unauthorized.d.ts.map +1 -0
  216. package/dts/kit/unauthorized.d.ts +47 -0
  217. package/dts/kit/unauthorized.d.ts.map +1 -0
  218. package/guides/docs.md +170 -0
  219. package/guides/jobs.md +1120 -0
  220. package/lib/docs/assets.ts +427 -0
  221. package/lib/docs/browser/config.ts +66 -0
  222. package/lib/docs/browser/index.ts +24 -0
  223. package/lib/docs/docsUi.ts +623 -0
  224. package/lib/docs/hosted.ts +31 -0
  225. package/lib/docs/index.ts +37 -0
  226. package/lib/docs/shell.ts +156 -0
  227. package/lib/docs/types.ts +149 -0
  228. package/lib/index.ts +27 -0
  229. package/lib/jobs/assets.ts +448 -0
  230. package/lib/jobs/browser/config.ts +65 -0
  231. package/lib/jobs/browser/index.ts +9 -0
  232. package/lib/jobs/browser/unauthorized.ts +11 -0
  233. package/lib/jobs/index.ts +41 -0
  234. package/lib/jobs/jobsUi.ts +709 -0
  235. package/lib/jobs/shell.ts +205 -0
  236. package/lib/jobs/types.ts +162 -0
  237. package/lib/kit/browser/shared.ts +11 -0
  238. package/lib/kit/browser/unauthorized.ts +114 -0
  239. package/lib/kit/unauthorized.ts +222 -0
  240. package/package.json +198 -4
@@ -0,0 +1 @@
1
+ .events-screen{display:flex;gap:var(--space-4);flex-direction:column}.events-picker{display:flex;align-items:flex-end;gap:var(--space-2)var(--space-3);flex-wrap:wrap}.events-picker .field{min-width:12rem;margin:0}.events-types{margin-top:var(--space-3)}.events-types summary{cursor:pointer;overflow-wrap:anywhere}.events-types fieldset{margin:var(--space-2)0 0;border:0;padding:0}.events-type-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(9rem,1fr));gap:var(--space-1)var(--space-3);margin-bottom:var(--space-2)}.events-types-ignored{margin:var(--space-3)0 0;padding:var(--space-2)var(--space-3);background:var(--warning-bg);color:var(--warning-text);font-size:var(--text-sm);overflow-wrap:anywhere;border-radius:6px}.events-channel{margin:var(--space-3)0 0;font-size:var(--text-sm);overflow-wrap:anywhere}.events-rejected{margin-top:var(--space-3);padding:var(--space-2)var(--space-3);background:var(--warning-bg);color:var(--warning-text);border-radius:6px}.events-rejected p{overflow-wrap:anywhere;margin:0}.events-actions{display:flex;align-items:center;gap:var(--space-2);font-size:var(--text-sm);flex-wrap:wrap}.events-held{font-variant-numeric:tabular-nums}.events-table td{vertical-align:top}.events-time{font-variant-numeric:tabular-nums;white-space:nowrap}.events-kind{white-space:nowrap}.events-target,.events-id{overflow-wrap:anywhere}.events-payload{min-width:12rem}.events-gap td{font-style:italic}.events-summary{margin:0 0 var(--space-1)}.schema-tree{font-size:var(--text-sm);overflow-x:auto}.schema-list{list-style:none;margin:0;padding:0}.schema-list .schema-list{margin-left:var(--space-3);padding-left:var(--space-3);border-left:1px solid var(--border)}.schema-node{padding:var(--space-1)0}.schema-row{display:flex;align-items:baseline;gap:var(--space-1)var(--space-2);flex-wrap:wrap}.schema-toggle,.schema-toggle-spacer{text-align:center;flex:none;width:1.25rem}.schema-toggle{color:var(--text-muted);cursor:pointer;font:inherit;background:0 0;border:0;padding:0}.schema-toggle:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-radius:var(--radius-sm)}.schema-ref-link:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-radius:var(--radius-sm)}.schema-name{font-family:var(--font-mono);overflow-wrap:anywhere;font-weight:600}.schema-required{color:var(--danger-text);font-size:var(--text-xs);text-transform:uppercase;letter-spacing:.03em}.schema-type{font-family:var(--font-mono);color:var(--accent);overflow-wrap:anywhere}.schema-ref{font-family:var(--font-mono);font-size:var(--text-sm)}.schema-ref-link{color:var(--accent);text-decoration:underline;cursor:pointer;background:0 0;border:0;padding:0}.schema-note-inline{font-size:var(--text-xs);color:var(--text-muted);font-style:italic}.schema-unresolved{color:var(--danger-text)}.schema-fact{padding:0 var(--space-1);border-radius:var(--radius-sm);background:var(--surface-2);font-size:var(--text-xs);overflow-wrap:anywhere}.schema-fact-label{color:var(--text-muted)}.schema-description,.schema-closed,.schema-open{margin:0 0 0 calc(1.25rem + var(--space-2));color:var(--text-muted)}.schema-description p{margin:var(--space-1)0 0;overflow-wrap:anywhere}.schema-closed,.schema-open{font-size:var(--text-xs)}.schema-closed{color:var(--warning-text)}.schema-composition{padding-top:var(--space-1);color:var(--text-muted);font-size:var(--text-xs);text-transform:uppercase;letter-spacing:.03em;font-weight:600}.http-docs-title{display:flex;justify-content:space-between;align-items:baseline;gap:var(--space-2)var(--space-4);flex-wrap:wrap}.http-docs-layout{display:grid;grid-template-columns:minmax(14rem,20rem)minmax(0,1fr);gap:var(--space-4);align-items:start}@media (max-width:800px){.http-docs-layout{grid-template-columns:minmax(0,1fr)}}.http-muted{color:var(--text-muted)}.http-sidebar{position:sticky;top:var(--space-3);display:flex;gap:var(--space-2);overflow-y:auto;flex-direction:column;max-height:calc(100vh - 6rem)}@media (max-width:800px){.http-sidebar{position:static;max-height:22rem}}.http-sidebar-count{font-size:var(--text-xs);margin:0}.http-tag{margin-bottom:var(--space-3)}.http-section{margin-bottom:var(--space-4)}.http-section-name{margin:0 0 var(--space-2);font-size:var(--text-md);color:var(--text)}.http-section .http-tag{padding-left:var(--space-2);border-left:1px solid var(--border)}.http-overview-tag+.http-overview-tag{margin-top:var(--space-3)}.http-overview-tag-name,.http-tag-name{margin:0 0 var(--space-1);font-size:var(--text-sm);text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted)}.http-tag-ops,.http-overview-ops,.http-params,.http-responses,.http-components{list-style:none;margin:0;padding:0}.http-op-link{display:flex;gap:var(--space-2);padding:var(--space-1)var(--space-2);border-radius:var(--radius-sm);color:var(--text);text-decoration:none;align-items:flex-start}.http-op-link:hover{background:var(--surface-2)}.http-op-link:focus-visible{background:var(--surface-2)}.http-op-link:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.http-op-link[aria-current=page]{background:var(--info-bg);color:var(--info-text)}.http-method{font-family:var(--font-mono);flex:none;justify-content:center;min-width:3.5rem}.http-op-text{display:flex;flex-direction:column;min-width:0}.http-op-path{font-family:var(--font-mono);font-size:var(--text-sm);overflow-wrap:anywhere}.http-op-summary{font-size:var(--text-xs);color:var(--text-muted)}.http-docs-main{display:flex;gap:var(--space-4);flex-direction:column;min-width:0}.http-info-line,.http-operation-line,.http-markers,.http-param-head,.http-response-head,.http-tryit-status,.http-tryit-actions{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}.http-servers{display:grid;gap:var(--space-2);margin:var(--space-3)0}.http-servers dt{font-size:var(--text-sm);color:var(--text-muted)}.http-servers dd{display:flex;gap:var(--space-2);overflow-wrap:anywhere;align-items:center;margin:0}.http-overview{display:flex;gap:var(--space-3);flex-direction:column}.http-overview-ops li{padding:var(--space-1)0;overflow-wrap:anywhere}.http-components{display:flex;gap:var(--space-2)var(--space-3);flex-wrap:wrap}.http-operation{display:flex;gap:var(--space-3);flex-direction:column}.http-operation-path{font-size:var(--text-md);overflow-wrap:anywhere}.http-operation-title{margin:var(--space-2)0 0;font-size:var(--text-lg)}.http-operation-id{display:flex;align-items:center;gap:var(--space-2);margin:var(--space-1)0 0;font-size:var(--text-sm);flex-wrap:wrap}.http-requires code{margin-right:var(--space-1)}.http-csrf,.http-tryit-disabled{padding:var(--space-2)var(--space-3);border-radius:var(--radius-sm);background:var(--info-bg);color:var(--info-text)}.http-csrf p{margin:0}.http-csrf p+p{margin-top:var(--space-1)}.http-tryit-disabled{margin:0 0 var(--space-3);background:var(--warning-bg);color:var(--warning-text)}.http-description p{margin:0 0 var(--space-2);overflow-wrap:anywhere}.http-section h3,.http-tryit h3{margin:0 0 var(--space-2);font-size:var(--text-md)}.http-param,.http-response{padding:var(--space-2)0;border-top:1px solid var(--border)}.http-param-name{font-weight:600}.http-param-description p,.http-param-style{margin:var(--space-1)0;font-size:var(--text-sm)}.http-media{margin-top:var(--space-2)}.http-media-type{display:inline-block;margin-bottom:var(--space-1);font-size:var(--text-xs);color:var(--text-muted)}.http-codes{display:flex;gap:var(--space-1);list-style:none;margin:var(--space-1)0 0;flex-wrap:wrap;padding:0}.http-codes code{padding:0 var(--space-1);border-radius:var(--radius-sm);background:var(--surface-2);font-size:var(--text-xs)}.http-tryit{padding:var(--space-3);border:1px solid var(--border);border-radius:var(--radius);background:var(--surface)}.http-tryit-form{display:flex;gap:var(--space-2);flex-direction:column}.http-tryit-checks{display:flex;gap:var(--space-1)var(--space-3);flex-wrap:wrap}.http-snippets{margin-top:var(--space-3)}.http-snippet{position:relative}.http-snippet .copy-button,.http-snippet>button{position:absolute;top:var(--space-2);right:var(--space-2)}.http-snippet pre{padding:var(--space-3);border-radius:var(--radius-sm);background:var(--surface-2);font-family:var(--font-mono);font-size:var(--text-xs);overflow-x:auto;white-space:pre;margin:0}.http-tryit-result{display:flex;gap:var(--space-2);margin-top:var(--space-3);padding-top:var(--space-3);border-top:1px solid var(--border);flex-direction:column}.http-tryit-result p{font-size:var(--text-sm);margin:0}.http-tryit-timing{font-size:var(--text-sm);color:var(--text-muted)}.http-tryit-headers summary{cursor:pointer;font-size:var(--text-sm)}.http-tryit-headers dl{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:var(--space-1)var(--space-3);margin:var(--space-2)0 0;font-size:var(--text-xs)}.http-tryit-headers dl>div{display:contents}.http-tryit-headers dd{overflow-wrap:anywhere;margin:0}.http-tryit-text{padding:var(--space-2);border-radius:var(--radius-sm);background:var(--surface-2);font-family:var(--font-mono);font-size:var(--text-xs);overflow-x:auto;white-space:pre-wrap;margin:0}.ws-docs{display:flex;gap:var(--space-4);flex-direction:column}.ws-header .screen-title{display:flex;align-items:center;gap:var(--space-2);overflow-wrap:anywhere;flex-wrap:wrap}.ws-kicker{margin:0}.ws-description summary{cursor:pointer}.ws-description p{overflow-wrap:anywhere;max-width:72ch}.ws-overview{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,22rem),1fr));gap:var(--space-4)}.ws-layout{display:grid;grid-template-columns:minmax(14rem,18rem)minmax(0,1fr);gap:var(--space-4);align-items:start}@media (max-width:800px){.ws-layout{grid-template-columns:minmax(0,1fr)}}.ws-sidebar{position:sticky;top:var(--space-4);max-height:calc(100vh - 2*var(--space-4));overflow-y:auto;padding:var(--space-3);border:1px solid var(--border);border-radius:var(--radius);background:var(--surface)}@media (max-width:800px){.ws-sidebar{position:static;max-height:22rem}}.ws-group+.ws-group{margin-top:var(--space-3)}.ws-group-title{margin:0 0 var(--space-1);font-size:var(--text-xs);letter-spacing:.04em;text-transform:uppercase;color:var(--text-muted);font-weight:600}.ws-group ul{list-style:none;margin:0;padding:0}.ws-nav-link{display:flex;padding:var(--space-1)var(--space-2);border-radius:var(--radius-sm);color:var(--text);text-decoration:none;flex-direction:column}.ws-nav-link:hover{background:var(--surface-2)}.ws-nav-link[data-selected=true]{background:var(--info-bg);color:var(--info-text)}.ws-nav-label{font-family:var(--font-mono);font-size:var(--text-sm);overflow-wrap:anywhere}.ws-nav-hint{font-size:var(--text-xs);color:var(--text-muted);overflow-wrap:anywhere}.ws-main,.ws-pane{display:flex;gap:var(--space-4);flex-direction:column;min-width:0}.ws-links{display:flex;gap:var(--space-1)var(--space-3);list-style:none;flex-wrap:wrap;margin:0;padding:0}.ws-permissions{display:flex;gap:var(--space-2);flex-wrap:wrap}.ws-permission{display:inline-flex;align-items:center;gap:var(--space-1);flex-wrap:wrap}.ws-note{display:block;padding:var(--space-2)var(--space-3);border-radius:var(--radius-sm);background:var(--warning-bg);color:var(--warning-text);overflow-wrap:anywhere}.ws-requirements{margin:0 0 var(--space-3);padding-left:var(--space-5)}.ws-table td{vertical-align:top;overflow-wrap:anywhere}.ws-value{white-space:nowrap;font-variant-numeric:tabular-nums}.ws-highlight{border-color:var(--accent);box-shadow:inset 3px 0 0 var(--accent)}.ws-schema{overflow-x:auto}.ws-example+.ws-example{margin-top:var(--space-3)}.ws-try{display:flex;align-items:flex-start;gap:var(--space-2);flex-direction:column}.ws-try p{margin:0}.ws-try-fields{display:flex;gap:var(--space-2)var(--space-3);flex-wrap:wrap}.ws-try-fields .field{min-width:12rem;margin:0}.ws-try-channel{overflow-wrap:anywhere}.ws-disabled{opacity:.55;cursor:not-allowed}.ws-example-head{display:flex;justify-content:space-between;align-items:center;gap:var(--space-2)}.ws-example-event{margin-block:var(--space-2);padding:var(--space-2)var(--space-3);border:1px solid var(--accent);border-radius:var(--radius,6px)}.ws-try-reason{padding-left:var(--space-4);margin:0}.runner-actions{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}.runner-actions-hint{font-size:var(--text-sm);color:var(--text-muted);flex-basis:100%;margin:0}.runner-form{display:grid;gap:var(--space-3)}.runner-form-row{display:flex;gap:var(--space-3);flex-wrap:wrap}.runner-form-row>.field{flex:10rem;min-width:0}.runner-note{padding:var(--space-2)var(--space-3);border-radius:var(--radius-sm);background:var(--surface-2);font-size:var(--text-sm);margin:0}.runner-note-pending{background:var(--warning-bg);color:var(--warning-text)}.schedule-modes{display:flex;gap:var(--space-2)var(--space-4);padding:var(--space-2)var(--space-3);border:1px solid var(--border);border-radius:var(--radius);flex-wrap:wrap;margin:0}.schedule-modes>legend{padding:0 var(--space-1);font-weight:600;font-size:var(--text-sm)}.schedule-mode{display:inline-flex;align-items:center;gap:var(--space-1);cursor:pointer}.run-id{display:inline-flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}.run-id code{overflow-wrap:anywhere}.runner-note-refused{background:var(--danger-bg);color:var(--danger-text)}.config-source{display:flex;align-items:center;gap:var(--space-2);margin:calc(var(--space-2)*-1)0 0;font-size:var(--text-sm);color:var(--text-muted);flex-wrap:wrap}.log-lines{margin:0 0 var(--space-3);padding:var(--space-2)0;overflow:auto;list-style:none;background:var(--surface-2);border-radius:var(--radius-sm);font-family:var(--font-mono);font-size:var(--text-xs);max-height:480px}.log-line{display:flex;gap:var(--space-3);padding:0 var(--space-3)}.log-number{text-align:right;color:var(--text-muted);user-select:none;flex:none;min-width:4ch}.log-text{white-space:pre-wrap;overflow-wrap:anywhere}.run-log-line{align-items:baseline;gap:var(--space-2)}.run-log-time,.run-log-stream{color:var(--text-muted);user-select:none;flex:none}.run-log-stream{text-transform:uppercase;font-size:calc(var(--text-xs)*.9);letter-spacing:.04em;min-width:6ch}.run-log-line-stderr .run-log-stream,.run-log-line-stderr .log-text{color:var(--danger-text)}.run-log-level,.run-log-cut{flex:none;align-self:center}.run-log-notes{display:grid;gap:var(--space-2);margin:0 0 var(--space-3)}.run-log-notes p{font-size:var(--text-xs);margin:0}.run-log-filter{display:inline-flex;align-items:center;gap:var(--space-2);font-size:var(--text-sm)}.run-log-toggle,.run-log-section{margin-top:var(--space-3)}.runner-link{overflow-wrap:anywhere;font-weight:600}.runner-id{margin-left:var(--space-2);font-size:var(--text-sm);overflow-wrap:anywhere}.runners-where{white-space:nowrap;width:7rem}.runners-status{white-space:nowrap;width:16rem}.runners-count{margin:var(--space-2)0 0;font-size:var(--text-sm)}.runner-screen{display:flex;gap:var(--space-4);flex-direction:column}.runner-header{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--space-3);flex-wrap:wrap}.runner-heading{display:flex;align-items:baseline;gap:var(--space-2)var(--space-3);flex-wrap:wrap;min-width:0}.runner-title{overflow-wrap:anywhere}.runner-badges{display:inline-flex;gap:var(--space-1);flex-wrap:wrap}.runner-last-error{color:var(--danger-text);overflow-wrap:anywhere}.run-list{display:flex;gap:var(--space-3);list-style:none;flex-direction:column;margin:0;padding:0}.run-list>li+li{padding-top:var(--space-3);border-top:1px solid var(--border)}.run-record{display:flex;gap:var(--space-3);flex-direction:column;min-width:0}.run-id-line{display:inline-flex;align-items:center;gap:var(--space-2);overflow-wrap:anywhere;flex-wrap:wrap}.run-id{font-size:var(--text-sm);overflow-wrap:anywhere}.run-toggle{display:inline-flex;border-radius:var(--radius-sm);color:inherit;cursor:pointer;background:0 0;border:1px solid #0000;justify-content:center;align-items:center;min-width:1.75rem;min-height:1.75rem;padding:0}.run-toggle:hover{border-color:var(--border)}.run-toggle:focus-visible{outline:2px solid var(--focus);outline-offset:1px}.run-details-row>td{background:var(--surface-2)}.history-table .numeric{text-align:right;font-variant-numeric:tabular-nums}.history-actions{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap}.history-limit{display:flex;align-items:center;gap:var(--space-2);font-size:var(--text-sm)}.history-open-log-note{display:flex;align-items:center;gap:var(--space-2);margin:var(--space-3)0 0;font-size:var(--text-xs);flex-wrap:wrap}.run-logs-cell{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}.range-picker{display:flex;align-items:flex-end;gap:var(--space-3);flex-wrap:wrap}.range-picker>.field{min-width:0}.range-scope{margin-top:var(--space-2)}.range-caption{font-size:var(--text-sm);color:var(--text-muted);margin:0}.range-not-retained{padding:var(--space-3);border:1px solid var(--border);border-radius:var(--radius);color:var(--text-muted)}.range-not-retained-title{margin:0 0 var(--space-1);color:var(--text);font-weight:600}.range-not-retained-detail{font-size:var(--text-sm);margin:0}.breadcrumb{font-size:var(--text-sm);color:var(--text-muted)}.queue-header{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--space-3);flex-wrap:wrap}.queue-heading{display:flex;align-items:baseline;gap:var(--space-2)var(--space-3);flex-wrap:wrap;min-width:0}.queue-heading .screen-title{overflow-wrap:anywhere}.queue-total{font-variant-numeric:tabular-nums;color:var(--text-muted)}.queue-updated{font-size:var(--text-sm)}.queue-toolbar,.queue-actions{display:flex;gap:var(--space-2);flex-wrap:wrap}.jobs-section{display:flex;gap:var(--space-3);flex-direction:column;min-width:0}.jobs-filters{display:flex;align-items:flex-end;gap:var(--space-2)var(--space-3);flex-wrap:wrap}.jobs-filter{display:flex;gap:var(--space-1);font-size:var(--text-sm);flex-direction:column;min-width:0}.jobs-total{align-self:center}.bulk-bar{display:flex;align-items:center;gap:var(--space-2)var(--space-3);padding:var(--space-2)var(--space-3);border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);flex-wrap:wrap}.bulk-count{font-size:var(--text-sm);font-variant-numeric:tabular-nums}.select-cell{text-align:center;width:2rem}.job-id{display:flex;align-items:center;gap:var(--space-2);font-family:var(--font-mono);max-width:22rem;font-weight:400}.job-id a{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.job-processed-by-col{white-space:nowrap;width:12rem}.job-processed-by-text{display:inline-block;overflow:hidden;text-overflow:ellipsis;vertical-align:bottom;white-space:nowrap;max-width:12rem}.job-failure{color:var(--text-muted);overflow-wrap:anywhere;max-width:24rem}tr[aria-selected=true]{background:var(--info-bg)}.queue-panels{min-width:0}.field-row{display:flex;gap:var(--space-3);flex-wrap:wrap}.field-row>.field{flex:10rem;min-width:0}.limits-editor{display:flex;gap:var(--space-3);flex-direction:column}.limits-names{display:flex;gap:var(--space-3);border:1px solid var(--border);border-radius:var(--radius);padding:var(--space-3);flex-direction:column}.limits-name{border-top:1px solid var(--border);padding-top:var(--space-3)}.form-actions{display:flex;gap:var(--space-2);flex-wrap:wrap}.limits-summary{display:grid;grid-template-columns:max-content 1fr;gap:var(--space-1)var(--space-3);margin:0}.limits-summary>div{display:contents}.limits-summary dd{margin:0}.throughput-controls{display:flex;align-items:center;gap:var(--space-2);margin-bottom:var(--space-3)}.throughput-chart{margin:0}.throughput-legend{display:flex;gap:var(--space-3);font-size:var(--text-sm);margin-bottom:var(--space-2);flex-wrap:wrap}.swatch{display:inline-block;vertical-align:middle;border-radius:2px;width:10px;height:10px}.swatch-completed,.bar-completed{background:var(--state-completed);fill:var(--state-completed)}.swatch-failed,.bar-failed{background:var(--state-failed);fill:var(--state-failed)}.throughput-svg{display:block;width:100%;height:160px}.throughput-baseline{stroke:var(--border);stroke-width:1;vector-effect:non-scaling-stroke}.throughput-hit{fill:transparent}.throughput-hit:hover{fill:var(--surface-2)}.throughput-axis{display:flex;font-size:var(--text-xs);color:var(--text-muted);justify-content:space-between}.repeatable-data{max-width:24rem}.repeatable-actions{display:flex;gap:var(--space-2);flex-wrap:wrap}.demand-panel{display:grid;gap:var(--space-3)}.demand-urls{display:grid;gap:var(--space-2)}.demand-urls p{margin:0}.demand-url{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap;min-width:0}.demand-url-label{min-width:6rem;font-weight:600}.demand-url code{overflow-wrap:anywhere}.summon-panel{display:grid;gap:var(--space-3)}.summon-heading{margin:0 0 var(--space-2);font-size:1rem}.summon-actions{display:flex;gap:var(--space-2);flex-wrap:wrap}.summoning-unit{display:block;font-size:var(--text-sm);font-weight:400}.summon-budget{display:inline-grid;gap:var(--space-1)}.summon-budget-window{display:flex;align-items:center;gap:var(--space-2);font-variant-numeric:tabular-nums;flex-wrap:wrap}.summon-budget-window.is-exhausted{color:var(--warning-text);font-weight:600}.summon-budget-meter{flex:none;width:80px;height:8px}.summon-group{display:grid;gap:var(--space-2);padding:var(--space-3);border:1px solid var(--border);border-radius:var(--radius);background:var(--surface)}.summon-subheading{font-size:var(--text-sm);margin:0;font-weight:600}.summon-group-circuit.is-open{color:var(--warning-text)}.summon-group tr.is-current,.summon-groups tr.is-current{background:var(--surface-2);box-shadow:inset 3px 0 0 var(--accent)}.summon-groups{display:grid;gap:var(--space-2);margin-top:var(--space-5)}.summon-groups-title{font-size:var(--text-lg);margin:0}.summon-group-list{list-style:none;margin:0;padding:0}.summon-group-count{font-variant-numeric:tabular-nums;color:var(--text-muted)}.summon-coverage{display:flex;gap:var(--space-1)var(--space-2);list-style:none;flex-wrap:wrap;margin:0;padding:0}.summon-last-missing{display:block;color:var(--danger-text)}.summon-group-note{display:block;font-size:var(--text-sm);margin:0}.summon-policy-tag{font-size:var(--text-xs);font-style:italic}.summon-policy-names{display:inline-flex;gap:var(--space-1);flex-wrap:wrap}.summon-policy-names code{padding:0 var(--space-1);border:1px solid var(--border);border-radius:var(--radius-sm);overflow-wrap:anywhere}.worker-actions{display:flex;align-items:center;gap:var(--space-1);flex-wrap:wrap}.worker-actions-hint{display:inline-block;font-size:var(--text-sm);max-width:24rem}.worker-config-form{display:grid;gap:var(--space-3)}.worker-config-row{display:flex;align-items:flex-end;gap:var(--space-2);flex-wrap:wrap}.worker-config-row>.field{flex:12rem;min-width:0}.worker-config-note{padding:var(--space-2)var(--space-3);border-radius:var(--radius-sm);background:var(--surface-2);font-size:var(--text-sm);margin:0}.worker-config-instances{padding-left:var(--space-4);font-size:var(--text-sm);color:var(--text-muted);margin:0}.worker-server+.worker-server{margin-top:var(--space-4)}.worker-server-title{margin:0 0 var(--space-2);font-size:var(--text-sm);font-weight:600}.worker-service-note{margin:0 0 var(--space-3);font-size:var(--text-sm)}.workers-sweep-note{margin:0 0 var(--space-3);padding:var(--space-2)var(--space-3);border-left:3px solid var(--warning-text);border-radius:var(--radius-sm);background:var(--warning-bg);color:var(--warning-text);font-size:var(--text-sm)}.worker-filters{display:flex;align-items:flex-end;gap:var(--space-2)var(--space-3);flex-flow:wrap}.worker-filters .field{min-width:10rem;margin:0}.worker-key{margin-top:var(--space-1);font-size:var(--text-sm);font-weight:400}.worker-header{display:flex;gap:var(--space-2);flex-direction:column}.worker-header .screen-title{overflow-wrap:anywhere}.worker-config-summary{margin:0 0 var(--space-3)}.worker-analytics-title{margin:0 0 var(--space-2);font-size:var(--text-sm);font-weight:600}.worker-analytics>*+*{margin-top:var(--space-4)}.worker-target-note{margin:0 0 var(--space-3)}.worker-target-file{overflow-wrap:anywhere}.providers-list{display:grid;gap:var(--space-3)}.provider-test,.provider-schema{display:grid;gap:var(--space-2);margin-top:var(--space-3);justify-items:start}.provider-test-result p{margin:0}.provider-test-fail{color:var(--danger)}.provider-checks{margin:var(--space-1)0 0;padding-left:var(--space-3)}.analytics-section .analytics-headline{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--space-4);margin-bottom:var(--space-4);flex-wrap:wrap}.analytics-section .analytics-charts{display:flex;gap:var(--space-2);flex-direction:column;min-width:0}.analytics-section .analytics-note{font-size:var(--text-sm);color:var(--text-muted);max-width:34rem;margin:0}.overview-jobs-chart{margin-top:var(--space-3)}.job-defaults{display:flex;gap:var(--space-3);flex-direction:column}.job-defaults p{margin:0}.job-defaults-heading{font-size:var(--text-md);margin:0}.job-defaults-form{display:flex;gap:var(--space-3);flex-direction:column}.job-defaults-row{display:flex;align-items:flex-start;gap:var(--space-2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-3);flex-direction:column;margin:0}.job-defaults-row>.field,.job-defaults-row>.field-row{align-self:stretch}.job-defaults-row legend{font-weight:600}.job-defaults-values,.job-defaults-note,.job-defaults-uses-code{font-size:var(--text-sm);margin:0}.job-defaults-reset{display:flex;align-items:center;gap:var(--space-2)var(--space-3);margin-top:var(--space-3);flex-wrap:wrap}.job-defaults-reset-note{font-size:var(--text-sm);color:var(--text-muted);flex:16rem;margin:0}.job-defaults-conflict,.job-defaults-warning{border-radius:var(--radius-sm);padding:var(--space-2)var(--space-3);background:var(--warning-bg);color:var(--warning-text)}.job-defaults-conflict{display:flex;align-items:flex-start;gap:var(--space-2);margin-bottom:var(--space-3);flex-direction:column}.job-defaults-conflict p{margin:0}.job-defaults-apply-states{display:flex;gap:var(--space-1);border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-3);flex-direction:column}.job-defaults-apply-keys{padding-left:var(--space-4);margin:0}.job-defaults-preview h3{margin:var(--space-2)0;font-size:var(--text-md)}[data-testid=apply-progress] progress{width:100%}.breadcrumb ol{display:flex;gap:var(--space-1);margin:0 0 var(--space-3);list-style:none;font-size:var(--text-sm);color:var(--text-muted);flex-wrap:wrap;padding:0}.breadcrumb li+li:before{content:"/";margin-right:var(--space-1);color:var(--text-muted)}.breadcrumb [aria-current=page]{color:var(--text)}.job-header{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--space-3);margin-bottom:var(--space-4);flex-wrap:wrap}.job-heading{min-width:0}.job-title{display:flex;align-items:center;gap:var(--space-2);margin-bottom:var(--space-1);flex-wrap:wrap}.job-name{overflow-wrap:anywhere}.job-id-line{display:flex;align-items:center;gap:var(--space-2);font-size:var(--text-sm);flex-wrap:wrap;margin:0}.job-id{font-family:var(--font-mono);overflow-wrap:anywhere;word-break:break-all}.job-actions{display:flex;gap:var(--space-2);flex-wrap:wrap}.job-screen .card{margin-bottom:var(--space-4)}.job-error{display:grid;gap:var(--space-2)}.job-error-line{overflow-wrap:anywhere;margin:0}.job-error-name{color:var(--danger-text)}.job-error-code{margin-left:var(--space-2);font-size:var(--text-xs);color:var(--text-muted)}.job-error-stack{padding:var(--space-2)var(--space-3);overflow-x:auto;background:var(--surface-2);border-radius:var(--radius-sm);font-family:var(--font-mono);font-size:var(--text-xs);white-space:pre;max-height:320px;margin:0}.job-error-causes{display:grid;gap:var(--space-2);padding-left:var(--space-4);border-left:2px solid var(--border);list-style:none;margin:0}.job-error-caused-by{display:block;font-size:var(--text-xs);text-transform:uppercase;letter-spacing:.04em}.job-details{margin-top:var(--space-3)}.job-details>summary{cursor:pointer;margin-bottom:var(--space-2);font-weight:600}.job-stacktraces{display:grid;gap:var(--space-3);list-style:none;margin:0;padding:0}.job-logs-controls{display:inline-flex;justify-content:flex-end;align-items:center;gap:var(--space-3);flex-wrap:wrap}.job-logs-clear{display:inline-flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}.job-logs-clear-reason{font-size:var(--text-xs)}.job-logs-order{display:inline-flex;align-items:center;gap:var(--space-2);font-size:var(--text-sm)}.job-logs-follow,.job-logs-total{margin:0 0 var(--space-2);font-size:var(--text-xs)}.job-flow-summary{margin-bottom:var(--space-3)}.job-ref code{font-family:var(--font-mono);overflow-wrap:anywhere}.job-form{display:grid;gap:var(--space-3)}.job-form-options,.job-states-picker{display:grid;gap:var(--space-3);padding:var(--space-3);border:1px solid var(--border);border-radius:var(--radius);margin:0}.job-states-picker{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:var(--space-2)}.job-form-options>legend,.job-states-picker>legend{padding:0 var(--space-1);font-weight:600;font-size:var(--text-sm)}.job-form-error{margin:0}@media (min-width:640px){.job-form-options{grid-template-columns:repeat(2,minmax(0,1fr))}.job-form-options>legend{grid-column:1/-1}}.job-note{padding:var(--space-2)var(--space-3);border-radius:var(--radius-sm);background:var(--surface-2);font-size:var(--text-sm);margin:0}.job-note-warning{background:var(--warning-bg);color:var(--warning-text)}.job-progress{display:inline-flex;align-items:center;gap:var(--space-2)}.job-progress-bar{display:inline-block;overflow:hidden;border-radius:var(--radius-sm);background:var(--surface-2);width:8rem;height:.5rem}.job-progress-fill{display:block;background:var(--accent);height:100%}.job-progress-value{font-variant-numeric:tabular-nums}.job-processed-by{display:inline-flex;align-items:baseline;gap:var(--space-1)var(--space-2);overflow-wrap:anywhere;flex-wrap:wrap}.flow-count{font-size:var(--text-sm);margin:0}.flow-tree{display:grid;gap:var(--space-3);list-style:none;margin:0;padding:0}.flow-children{margin-top:var(--space-3);padding-left:var(--space-4);border-left:2px solid var(--border)}.flow-node{display:grid;gap:var(--space-3);padding:var(--space-3);border:1px solid var(--border);border-radius:var(--radius);min-width:0;margin:0}.flow-node>legend{padding:0 var(--space-1);font-weight:600}.flow-node[data-refused]{border-color:var(--danger)}.flow-node-queue>p{margin:0}.flow-node-actions{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}.flow-node-blocked{flex-basis:100%;margin:0}.flow-result{display:grid;gap:var(--space-2)}.flow-result>p,.flow-result-list{margin:0}
@@ -0,0 +1,4 @@
1
+ import{C,v,T,r,n,e,t,f,i,m,y,a,_,s,E,dr,rt,d,Cn,Ve,R,o,h,l,M,S,w,I}from"./main-a250ffk7.js";import{Mn,Or,Ar,co,Rr,mo,Dr,At,Vt,fo,po}from"./main-4gte3eqq.js";import{he,mt,cn}from"./main-gngzht43.js";import{W}from"./main-3yj6bv90.js";import{Jo,Yo}from"./main-w93x1dzs.js";import{ae}from"./main-d6ge7w08.js";import"./main-5grjvsy7.js";var le={all:"Everything (all)",queues:"Every queue (queues)",queue:"One queue",job:"One job",runners:"Every runner (runners)",runner:"One runner",workers:"Every worker (workers)",queueWorkers:"One queue's workers"},U=new Set(["all","queues","runners","workers"]);function ie(u){return{scope:u.scope,queue:u.scope==="queue"||u.scope==="job"||u.scope==="queueWorkers"?u.queue:"",runner:u.scope==="runner"?u.runner:"",id:u.scope==="job"?u.id:""}}function X(u){switch(u.scope){case"all":case"queues":case"runners":case"workers":return{scope:u.scope};case"queueWorkers":return u.queue?{scope:"queueWorkers",queue:u.queue}:null;case"queue":return u.queue?{scope:"queue",queue:u.queue}:null;case"runner":return u.runner?{scope:"runner",runner:u.runner}:null;case"job":return u.queue&&u.id?{scope:"job",queue:u.queue,id:u.id}:null}}function V({label:u,value:c,names:g,onChange:N}){return e(l,{label:u,children:g&&g.length>0?e(S,{options:[{value:"",label:"Choose…"},...g.map((q)=>({value:q}))],value:g.includes(c)?c:"",onChange:N}):e(M,{value:c,onChange:N,maxLength:200,autoComplete:"off",spellCheck:!1})})}function ue({choice:u,onApply:c}){let g=i(),N=m(),q=y("queues.list"),A=y("runners.list"),[k,L]=r(()=>ie(u)),B=k.scope==="queue"||k.scope==="job"||k.scope==="queueWorkers",j=a({queryKey:_.queues(""),queryFn:({signal:p})=>g.listQueues("",p),enabled:B&&q}),O=a({queryKey:he.list(),queryFn:({signal:p})=>cn(g,p),enabled:k.scope==="runner"&&A}),F=X(k);return t("form",{className:"events-picker",onSubmit:(p)=>{if(p.preventDefault(),F)c(F)},"aria-label":"Channel",children:[e(l,{label:"Channel",children:e(S,{options:Rr(N.mode).map((p)=>({value:p,label:le[p]})),value:k.scope,onChange:(p)=>{let D={...k,scope:p};L(D);let x=U.has(p)?X(D):null;if(x)c(x)}})}),B&&e(V,{label:"Queue",value:k.queue,names:j.data?.items.map((p)=>p.name),onChange:(p)=>L({...k,queue:p})}),k.scope==="job"&&e(l,{label:"Job id",children:e(M,{value:k.id,onChange:(p)=>L({...k,id:p}),autoComplete:"off",spellCheck:!1})}),k.scope==="runner"&&e(V,{label:"Runner",value:k.runner,names:O.data?.items.map((p)=>p.id),onChange:(p)=>L({...k,runner:p})}),!U.has(k.scope)&&e(s,{type:"submit",variant:"primary",disabled:F===null,children:"Watch"})]})}function de({allowed:u,selected:c,onChange:g}){let N=(q,A)=>g(u.filter((k)=>k===q?A:c.includes(k)));return t("details",{className:"events-types",children:[t("summary",{"data-testid":"events-types-summary",children:["Types: ",c.length===0?"all":c.join(", ")]}),t("fieldset",{children:[e("legend",{className:"visually-hidden",children:"Event types"}),e("div",{className:"events-type-grid",children:u.map((q)=>e(w,{label:q,checked:c.includes(q),onChange:(A)=>N(q,A)},q))}),e(s,{size:"sm",variant:"ghost",onClick:()=>g([]),disabled:c.length===0,children:"All types"})]})]})}function ce({ignored:u,channel:c,showingAll:g}){if(u.length===0)return null;return t("p",{className:"events-types-ignored",role:"note","data-testid":"events-types-ignored",children:["Ignored in the link's types:"," ",u.map((N,q)=>t("span",{children:[q>0?"; ":"",e("code",{children:N.name})," ",N.reason==="unknown"?"(not an event type)":`(${c} does not carry it)`]},N.name)),g?". Showing every type.":"."]})}function Y(u){let c=new Date(u),g=(N,q=2)=>String(N).padStart(q,"0");return`${g(c.getHours())}:${g(c.getMinutes())}:${g(c.getSeconds())}.${g(c.getMilliseconds(),3)}`}function pe(u){switch(u.type){case"failed":case"dead":case"timeout":case"killed":return"danger";case"retrying":case"stalled":case"skipped":return"warning";case"completed":case"succeeded":return"success";default:return"neutral"}}function me({event:u}){if(u.id===void 0)return e("span",{className:"muted",children:"—"});if(u.kind==="queue")return e(E,{to:Cn(u.target,u.id),children:u.id});return e("code",{children:u.id})}var ge={queue:"info",runner:"accent",worker:"neutral"};function ye({row:u,event:c}){let g=new Date(c.at).toISOString();return t("tr",{"data-testid":"event-row","data-type":c.type,children:[e("td",{className:"events-time",children:e("time",{dateTime:g,title:g,children:Y(c.at)})}),t("td",{className:"events-kind",children:[e(f,{tone:ge[c.kind],children:c.kind})," ",e(f,{tone:pe(c),children:c.type})]}),e("td",{className:"events-target",children:e(E,{to:c.kind==="runner"?mt(c.target):Ve(c.target),children:c.target})}),e("td",{className:"events-id",children:e(me,{event:c})}),t("td",{className:"events-payload",children:[c.kind==="queue"&&c.type==="summon"&&Yo(c.payload)&&e("p",{className:"events-summary","data-testid":"event-summon-summary",children:Jo(c.payload)}),e(ae,{value:c.payload,label:`Payload of ${c.type} #${u.key}`,expandDepth:0,copyable:!1})]})]})}function fe({row:u,gap:c}){return t("tr",{"data-testid":"event-row","data-type":"gap",className:"events-gap",children:[e("td",{className:"events-time",children:Y(u.receivedAt)}),t("td",{colSpan:4,children:[t("strong",{children:["gap: ",c.reason]})," ",t("span",{className:"muted",children:[c.toSeq>0?`events ${c.fromSeq}–${c.toSeq} `:"events ","may be missing",c.channels?` on ${c.channels.join(", ")}`:""]})]})]})}function ve({status:u,channel:c}){if(u.publishing===!1)return e(d,{title:"Producers are not publishing events",description:"This API reports publishing: false. The queues and runners it manages emit no events, so nothing will arrive here; the screens refresh by polling instead."});if(u.events==="local")return e(d,{title:"Only this API process's own events",description:"This API reports events: local. It sees only the events of work done in its own process; jobs and runs handled by other processes will not appear here."});if(u.state==="off"||u.state==="refused")return e(d,{title:"Live updates are off",description:u.detail??"There is no socket to the API."});return e(d,{title:"Waiting for events",description:t(n,{children:["Nothing has arrived on ",e("code",{children:c})," yet."]})})}function be({rejected:u}){if(u.length===0)return null;return e("div",{className:"events-rejected",role:"alert","data-testid":"events-rejected",children:u.map((c)=>t("p",{children:["The server refused ",e("code",{children:c.channel}),":"," ",e("strong",{children:c.code}),c.detail?` (${c.detail})`:""]},`${c.channel}:${c.code}`))})}function xe(){let u=m(),c=dr(),[g,N]=W(),q=At(g.get("channel"),u.mode)??mo(u.mode),A=Dr(q),k=Vt(q),L=g.get("types"),B=fo(L,k),{types:j}=B;v(()=>{if(L!==null&&B.normalized!==L)N({types:B.normalized})},[L,B.normalized,N]);let[O,F]=r([]),[J,p]=r(!1),[D,x]=r({rows:[],dropped:0}),G=T(0),z=T(J);z.current=J;let H=T(j);H.current=j;let Q=T([]),K=C((b)=>{if(z.current)x((P)=>P.rows.length>=Or?{rows:P.rows,dropped:P.dropped+1}:{rows:[...P.rows,b],dropped:P.dropped});else F((P)=>Ar(P,[b]))},[]),Z=C((b)=>{if(!po(b,H.current))return;let P=co(Q.current,b);if(Q.current=P.seen,P.duplicate)return;K({key:G.current++,kind:"event",receivedAt:Date.now(),event:b})},[K]),ee=C((b)=>K({key:G.current++,kind:"gap",receivedAt:Date.now(),gap:b}),[K]),{rejected:ne}=rt({channels:[A],events:j.length===0?void 0:j,onEvent:Z,onGap:ee}),te=()=>{z.current=!0,p(!0)},se=()=>{z.current=!1,F((b)=>Ar(b,D.rows)),x({rows:[],dropped:0}),p(!1)},oe=()=>{F([]),x({rows:[],dropped:0})};return t("div",{className:"screen events-screen","data-testid":"events-screen",children:[e("h1",{className:"screen-title",children:"Events"}),t(R,{title:"Subscription",className:"events-controls",children:[e(ue,{choice:q,onApply:(b)=>{let P=Vt(b);N({channel:Dr(b),types:j.filter((re)=>P.includes(re)).join(",")||null})}},A),e(de,{allowed:k,selected:j,onChange:(b)=>N({types:b.join(",")||null})}),e(ce,{ignored:B.ignored,channel:A,showingAll:j.length===0}),t("p",{className:"muted events-channel",children:["Watching ",e("code",{"data-testid":"events-channel",children:A})]}),e(be,{rejected:ne})]}),e(R,{title:"Log",actions:t("div",{className:"events-actions",children:[t("span",{className:"muted","data-testid":"events-count",children:[h(O.length,"row")," (the latest ",o(Mn)," ","are kept)"]}),J&&t("span",{className:"events-held","data-testid":"events-held",children:[o(D.rows.length)," held",D.dropped>0?`, ${o(D.dropped)} dropped`:""]}),e(s,{size:"sm",onClick:J?se:te,children:J?"Resume":"Pause"}),e(s,{size:"sm",onClick:oe,disabled:O.length===0&&D.rows.length===0,children:"Clear"})]}),children:O.length===0?e(ve,{status:c,channel:A}):t(I,{label:"Events, newest first",className:"events-table",children:[e("thead",{children:t("tr",{children:[e("th",{scope:"col",children:"Time"}),e("th",{scope:"col",children:"Event"}),e("th",{scope:"col",children:"Target"}),e("th",{scope:"col",children:"Id"}),e("th",{scope:"col",children:"Payload"})]})}),e("tbody",{children:O.map((b)=>b.kind==="event"?e(ye,{row:b,event:b.event},b.key):e(fe,{row:b,gap:b.gap},b.key))})]})})]})}export{xe as EventsScreen};
2
+
3
+ //# debugId=E837A263E86CCE7764756E2164756E21
4
+ //# sourceMappingURL=index-47pxmyxn.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["app/jobs/screens/events/index.tsx"],
4
+ "sourcesContent": [
5
+ "/**\n * The Events console: a live tail of the API's socket. Routed from\n * `routes.tsx` at `/events` (lazily, see `../lazy.tsx`).\n */\nimport type { FormEvent } from \"react\";\nimport type {\n EventName,\n EventWire,\n JobsApiAckRejection,\n JobsApiGapMessage,\n} from \"../../api/types\";\nimport type { BadgeTone } from \"../../components/Badge\";\nimport type { LiveStatus } from \"../../live\";\nimport type {\n ChannelChoice,\n ChannelScope,\n IgnoredType,\n LogRow,\n} from \"./eventLog\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { queryKeys } from \"../../api/queryKeys\";\nimport { jobPath, queuePath } from \"../../api/queues\";\nimport { listRunners, runnerKeys, runnerPath } from \"../../api/runners\";\nimport { Badge } from \"../../components/Badge\";\nimport { Button } from \"../../components/Button\";\nimport { Card } from \"../../components/Card\";\nimport { EmptyState } from \"../../components/EmptyState\";\nimport { Field } from \"../../components/Field\";\nimport { Checkbox, Select, TextInput } from \"../../components/inputs\";\nimport { JsonView } from \"../../components/JsonView\";\nimport { Table } from \"../../components/Table\";\nimport { useApiClient } from \"../../context\";\nimport { formatNumber, plural } from \"../../format\";\nimport { useLiveStatus, useLiveSubscription } from \"../../live\";\nimport { useCan, useMeta } from \"../../meta/hooks\";\nimport { Link } from \"../../router\";\nimport { isSummonEvent, summonEventSummary } from \"../queues/panels/summonText\";\nimport { useUrlParams } from \"../queues/urlState\";\nimport {\n channelName,\n dedupeSummon,\n defaultChoice,\n matchesTypes,\n MAX_PAUSED,\n MAX_ROWS,\n parseChannel,\n prependRows,\n readTypes,\n scopesFor,\n typesFor,\n} from \"./eventLog\";\nimport \"./events.css\";\n\n/** How the scope select names each scope. */\nconst SCOPE_LABELS: Readonly<Record<ChannelScope, string>> = {\n all: \"Everything (all)\",\n queues: \"Every queue (queues)\",\n queue: \"One queue\",\n job: \"One job\",\n runners: \"Every runner (runners)\",\n runner: \"One runner\",\n workers: \"Every worker (workers)\",\n queueWorkers: \"One queue's workers\",\n};\n\n/** Scopes that name no target, applied as soon as they are picked. */\nconst BROAD_SCOPES: ReadonlySet<ChannelScope> = new Set<ChannelScope>([\n \"all\",\n \"queues\",\n \"runners\",\n \"workers\",\n]);\n\n/** What the picker is editing before it is applied. */\ninterface Draft {\n /** The scope. */\n scope: ChannelScope;\n /** The queue, for `queue` and `job`. */\n queue: string;\n /** The runner, for `runner`. */\n runner: string;\n /** The job id, for `job`. */\n id: string;\n}\n\n/** A draft from an applied choice. */\nfunction draftOf(choice: ChannelChoice): Draft {\n return {\n scope: choice.scope,\n queue:\n choice.scope === \"queue\" ||\n choice.scope === \"job\" ||\n choice.scope === \"queueWorkers\"\n ? choice.queue\n : \"\",\n runner: choice.scope === \"runner\" ? choice.runner : \"\",\n id: choice.scope === \"job\" ? choice.id : \"\",\n };\n}\n\n/** The choice a draft names, or `null` while a target is missing. */\nfunction choiceOf(draft: Draft): ChannelChoice | null {\n switch (draft.scope) {\n case \"all\":\n case \"queues\":\n case \"runners\":\n case \"workers\":\n return { scope: draft.scope };\n case \"queueWorkers\":\n return draft.queue ? { scope: \"queueWorkers\", queue: draft.queue } : null;\n case \"queue\":\n return draft.queue ? { scope: \"queue\", queue: draft.queue } : null;\n case \"runner\":\n return draft.runner ? { scope: \"runner\", runner: draft.runner } : null;\n case \"job\":\n return draft.queue && draft.id\n ? { scope: \"job\", queue: draft.queue, id: draft.id }\n : null;\n }\n}\n\n/** Props of {@link TargetInput}. */\ninterface TargetInputProps {\n /** The field's label. */\n label: string;\n /** The chosen name. */\n value: string;\n /** Names to choose from; `undefined` (not listable) or empty gives a text box. */\n names: readonly string[] | undefined;\n /** Sets the name. */\n onChange: (value: string) => void;\n}\n\n/** A target picker: a select over the listed names when there are some, else a text box. */\nfunction TargetInput({ label, value, names, onChange }: TargetInputProps) {\n return (\n <Field label={label}>\n {names && names.length > 0 ? (\n <Select\n options={[\n { value: \"\", label: \"Choose…\" },\n ...names.map((name) => ({ value: name })),\n ]}\n value={names.includes(value) ? value : \"\"}\n onChange={onChange}\n />\n ) : (\n <TextInput\n value={value}\n onChange={onChange}\n maxLength={200}\n autoComplete=\"off\"\n spellCheck={false}\n />\n )}\n </Field>\n );\n}\n\n/** Props of {@link ChannelPicker}. */\ninterface ChannelPickerProps {\n /** The applied choice. */\n choice: ChannelChoice;\n /** Applies a new choice. */\n onApply: (choice: ChannelChoice) => void;\n}\n\n/**\n * Picks the channel: a scope, then its queue (from the queue list), runner\n * (from the runner list) or job (a queue and an id). A broad scope applies\n * at once; a targeted one on \"Watch\".\n */\nfunction ChannelPicker({ choice, onApply }: ChannelPickerProps) {\n const api = useApiClient();\n const meta = useMeta();\n const canQueues = useCan(\"queues.list\");\n const canRunners = useCan(\"runners.list\");\n const [draft, setDraft] = useState<Draft>(() => draftOf(choice));\n const needsQueue =\n draft.scope === \"queue\" ||\n draft.scope === \"job\" ||\n draft.scope === \"queueWorkers\";\n const queues = useQuery({\n queryKey: queryKeys.queues(\"\"),\n queryFn: ({ signal }) => api.listQueues(\"\", signal),\n enabled: needsQueue && canQueues,\n });\n const runners = useQuery({\n queryKey: runnerKeys.list(),\n queryFn: ({ signal }) => listRunners(api, signal),\n enabled: draft.scope === \"runner\" && canRunners,\n });\n const next = choiceOf(draft);\n\n const onSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (next) {\n onApply(next);\n }\n };\n\n return (\n <form\n className=\"events-picker\"\n onSubmit={onSubmit}\n aria-label=\"Channel\"\n >\n <Field label=\"Channel\">\n <Select\n options={scopesFor(meta.mode).map((scope) => ({\n value: scope,\n label: SCOPE_LABELS[scope],\n }))}\n value={draft.scope}\n onChange={(scope) => {\n const updated = { ...draft, scope };\n setDraft(updated);\n const applied = BROAD_SCOPES.has(scope) ? choiceOf(updated) : null;\n if (applied) {\n onApply(applied);\n }\n }}\n />\n </Field>\n {needsQueue && (\n <TargetInput\n label=\"Queue\"\n value={draft.queue}\n names={queues.data?.items.map((queue) => queue.name)}\n onChange={(queue) => setDraft({ ...draft, queue })}\n />\n )}\n {draft.scope === \"job\" && (\n <Field label=\"Job id\">\n <TextInput\n value={draft.id}\n onChange={(id) => setDraft({ ...draft, id })}\n autoComplete=\"off\"\n spellCheck={false}\n />\n </Field>\n )}\n {draft.scope === \"runner\" && (\n <TargetInput\n label=\"Runner\"\n value={draft.runner}\n names={runners.data?.items.map((runner) => runner.id)}\n onChange={(runner) => setDraft({ ...draft, runner })}\n />\n )}\n {!BROAD_SCOPES.has(draft.scope) && (\n <Button\n type=\"submit\"\n variant=\"primary\"\n disabled={next === null}\n >\n Watch\n </Button>\n )}\n </form>\n );\n}\n\n/** Props of {@link TypeFilter}. */\ninterface TypeFilterProps {\n /** The types the channel can carry. */\n allowed: readonly EventName[];\n /** The chosen ones; empty means every type. */\n selected: readonly EventName[];\n /** Sets the filter. */\n onChange: (types: EventName[]) => void;\n}\n\n/** The event-type filter: a checkbox per type, under a summary of the choice. */\nfunction TypeFilter({ allowed, selected, onChange }: TypeFilterProps) {\n const toggle = (type: EventName, on: boolean) =>\n onChange(\n allowed.filter((candidate) =>\n candidate === type ? on : selected.includes(candidate),\n ),\n );\n return (\n <details className=\"events-types\">\n <summary data-testid=\"events-types-summary\">\n Types: {selected.length === 0 ? \"all\" : selected.join(\", \")}\n </summary>\n <fieldset>\n <legend className=\"visually-hidden\">Event types</legend>\n <div className=\"events-type-grid\">\n {allowed.map((type) => (\n <Checkbox\n key={type}\n label={type}\n checked={selected.includes(type)}\n onChange={(on) => toggle(type, on)}\n />\n ))}\n </div>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => onChange([])}\n disabled={selected.length === 0}\n >\n All types\n </Button>\n </fieldset>\n </details>\n );\n}\n\n/** Props of {@link IgnoredTypesNote}. */\ninterface IgnoredTypesNoteProps {\n /** The names the filter left out. */\n ignored: readonly IgnoredType[];\n /** The channel, for the reason. */\n channel: string;\n /** Whether nothing was left to filter on, so every type shows. */\n showingAll: boolean;\n}\n\n/** Says which names in the URL's `types` the filter ignores, so none is dropped silently. */\nfunction IgnoredTypesNote({\n ignored,\n channel,\n showingAll,\n}: IgnoredTypesNoteProps) {\n if (ignored.length === 0) {\n return null;\n }\n return (\n <p\n className=\"events-types-ignored\"\n role=\"note\"\n data-testid=\"events-types-ignored\"\n >\n Ignored in the link's types:{\" \"}\n {ignored.map((entry, index) => (\n <span key={entry.name}>\n {index > 0 ? \"; \" : \"\"}\n <code>{entry.name}</code>{\" \"}\n {entry.reason === \"unknown\"\n ? \"(not an event type)\"\n : `(${channel} does not carry it)`}\n </span>\n ))}\n {showingAll ? \". Showing every type.\" : \".\"}\n </p>\n );\n}\n\n/** `hh:mm:ss.mmm`, local time. */\nfunction clock(ms: number): string {\n const date = new Date(ms);\n const pad = (value: number, width = 2) => String(value).padStart(width, \"0\");\n return `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}.${pad(date.getMilliseconds(), 3)}`;\n}\n\n/** A colour per outcome: failures red, trouble amber, successes green. */\nfunction toneOf(event: EventWire): BadgeTone {\n switch (event.type) {\n case \"failed\":\n case \"dead\":\n case \"timeout\":\n case \"killed\":\n return \"danger\";\n case \"retrying\":\n case \"stalled\":\n case \"skipped\":\n return \"warning\";\n case \"completed\":\n case \"succeeded\":\n return \"success\";\n default:\n return \"neutral\";\n }\n}\n\n/** An event's id: a queue event's job, linked to its screen; a runner event's run or a worker event's worker incarnation, as text. */\nfunction EventId({ event }: { event: EventWire }) {\n if (event.id === undefined) {\n return <span className=\"muted\">—</span>;\n }\n if (event.kind === \"queue\") {\n return <Link to={jobPath(event.target, event.id)}>{event.id}</Link>;\n }\n return <code>{event.id}</code>;\n}\n\n/**\n * The kind badge's tone: one per kind, so a worker event does not pass for a\n * runner's. `neutral` for workers, because the type badge beside it gives\n * success, warning and danger their meaning.\n */\nconst KIND_TONE: Readonly<Record<EventWire[\"kind\"], BadgeTone>> = {\n queue: \"info\",\n runner: \"accent\",\n worker: \"neutral\",\n};\n\n/** One event row. */\nfunction EventRow({ row, event }: { row: LogRow; event: EventWire }) {\n const at = new Date(event.at).toISOString();\n return (\n <tr\n data-testid=\"event-row\"\n data-type={event.type}\n >\n <td className=\"events-time\">\n <time\n dateTime={at}\n title={at}\n >\n {clock(event.at)}\n </time>\n </td>\n <td className=\"events-kind\">\n <Badge tone={KIND_TONE[event.kind]}>{event.kind}</Badge>{\" \"}\n <Badge tone={toneOf(event)}>{event.type}</Badge>\n </td>\n <td className=\"events-target\">\n <Link\n to={\n // A worker event's target is the QUEUE the worker consumes.\n event.kind === \"runner\"\n ? runnerPath(event.target)\n : queuePath(event.target)\n }\n >\n {event.target}\n </Link>\n </td>\n <td className=\"events-id\">\n <EventId event={event} />\n </td>\n <td className=\"events-payload\">\n {event.kind === \"queue\" &&\n event.type === \"summon\" &&\n isSummonEvent(event.payload) && (\n // A summon attempt in words above its payload: the outcome, how\n // many workers, the summoner and why the check ran.\n <p\n className=\"events-summary\"\n data-testid=\"event-summon-summary\"\n >\n {summonEventSummary(event.payload)}\n </p>\n )}\n <JsonView\n value={event.payload}\n label={`Payload of ${event.type} #${row.key}`}\n expandDepth={0}\n copyable={false}\n />\n </td>\n </tr>\n );\n}\n\n/** A gap row: events in a range may have been lost. */\nfunction GapRow({ row, gap }: { row: LogRow; gap: JobsApiGapMessage }) {\n return (\n <tr\n data-testid=\"event-row\"\n data-type=\"gap\"\n className=\"events-gap\"\n >\n <td className=\"events-time\">{clock(row.receivedAt)}</td>\n <td colSpan={4}>\n <strong>gap: {gap.reason}</strong>{\" \"}\n <span className=\"muted\">\n {/*\n A gap on a connection that has carried no sequenced event yet\n (`queue-discovered` right after subscribing) is 0–0, which reads\n as a range of nothing; there the range is left out.\n */}\n {gap.toSeq > 0 ? `events ${gap.fromSeq}–${gap.toSeq} ` : \"events \"}\n may be missing\n {gap.channels ? ` on ${gap.channels.join(\", \")}` : \"\"}\n </span>\n </td>\n </tr>\n );\n}\n\n/** Why the log may stay empty, from the live status. */\nfunction EmptyLog({\n status,\n channel,\n}: {\n status: LiveStatus;\n channel: string;\n}) {\n if (status.publishing === false) {\n return (\n <EmptyState\n title=\"Producers are not publishing events\"\n description=\"This API reports publishing: false. The queues and runners it manages emit no events, so nothing will arrive here; the screens refresh by polling instead.\"\n />\n );\n }\n if (status.events === \"local\") {\n return (\n <EmptyState\n title=\"Only this API process's own events\"\n description=\"This API reports events: local. It sees only the events of work done in its own process; jobs and runs handled by other processes will not appear here.\"\n />\n );\n }\n if (status.state === \"off\" || status.state === \"refused\") {\n return (\n <EmptyState\n title=\"Live updates are off\"\n description={status.detail ?? \"There is no socket to the API.\"}\n />\n );\n }\n return (\n <EmptyState\n title=\"Waiting for events\"\n description={\n <>\n Nothing has arrived on <code>{channel}</code> yet.\n </>\n }\n />\n );\n}\n\n/** The channels the server refused, each with why. */\nfunction Rejections({\n rejected,\n}: {\n rejected: readonly JobsApiAckRejection[];\n}) {\n if (rejected.length === 0) {\n return null;\n }\n return (\n <div\n className=\"events-rejected\"\n role=\"alert\"\n data-testid=\"events-rejected\"\n >\n {rejected.map((rejection) => (\n <p key={`${rejection.channel}:${rejection.code}`}>\n The server refused <code>{rejection.channel}</code>:{\" \"}\n <strong>{rejection.code}</strong>\n {rejection.detail ? ` (${rejection.detail})` : \"\"}\n </p>\n ))}\n </div>\n );\n}\n\n/** What the paused display holds back. */\ninterface Held {\n /** Rows waiting, oldest first (at most {@link MAX_PAUSED}). */\n rows: LogRow[];\n /** Rows that arrived after the cap, dropped. */\n dropped: number;\n}\n\n/**\n * `/events`: the live event tail. The channel and type filter live in the\n * URL (`channel`, `types`); the log keeps the latest {@link MAX_ROWS} rows,\n * newest first, and pausing holds up to {@link MAX_PAUSED} more.\n */\nexport function EventsScreen() {\n const meta = useMeta();\n const status = useLiveStatus();\n const [params, update] = useUrlParams();\n const choice =\n parseChannel(params.get(\"channel\"), meta.mode) ?? defaultChoice(meta.mode);\n const channel = channelName(choice);\n const allowed = typesFor(choice);\n const rawTypes = params.get(\"types\");\n const typesParam = readTypes(rawTypes, allowed);\n const { types } = typesParam;\n\n // Prefixed names (`queue.completed`) are written back bare.\n useEffect(() => {\n if (rawTypes !== null && typesParam.normalized !== rawTypes) {\n update({ types: typesParam.normalized });\n }\n }, [rawTypes, typesParam.normalized, update]);\n\n const [rows, setRows] = useState<LogRow[]>([]);\n const [paused, setPaused] = useState(false);\n const [held, setHeld] = useState<Held>({ rows: [], dropped: 0 });\n const nextKeyRef = useRef(0);\n const pausedRef = useRef(paused);\n pausedRef.current = paused;\n const typesRef = useRef(types);\n typesRef.current = types;\n // The summon event ids heard, for `dedupeSummon`: kept across Clear and a\n // channel change, since a shared unit's copies may still be arriving.\n const seenRef = useRef<readonly string[]>([]);\n\n const add = useCallback((row: LogRow) => {\n if (pausedRef.current) {\n setHeld((current) =>\n current.rows.length >= MAX_PAUSED\n ? { rows: current.rows, dropped: current.dropped + 1 }\n : { rows: [...current.rows, row], dropped: current.dropped },\n );\n } else {\n setRows((current) => prependRows(current, [row]));\n }\n }, []);\n\n const onEvent = useCallback(\n (event: EventWire) => {\n // Another screen may hold this channel with a wider filter, and the\n // client merges filters per channel, so filter here too.\n if (!matchesTypes(event, typesRef.current)) {\n return;\n }\n // A shared summon unit's event arrives once per queue it serves: one\n // row. Checked after the filter, so only an id that was shown counts.\n const dedupe = dedupeSummon(seenRef.current, event);\n seenRef.current = dedupe.seen;\n if (dedupe.duplicate) {\n return;\n }\n add({\n key: nextKeyRef.current++,\n kind: \"event\",\n receivedAt: Date.now(),\n event,\n });\n },\n [add],\n );\n const onGap = useCallback(\n (gap: JobsApiGapMessage) =>\n add({\n key: nextKeyRef.current++,\n kind: \"gap\",\n receivedAt: Date.now(),\n gap,\n }),\n [add],\n );\n\n const { rejected } = useLiveSubscription({\n channels: [channel],\n events: types.length === 0 ? undefined : types,\n onEvent,\n onGap,\n });\n\n const pause = () => {\n pausedRef.current = true;\n setPaused(true);\n };\n const resume = () => {\n pausedRef.current = false;\n setRows((current) => prependRows(current, held.rows));\n setHeld({ rows: [], dropped: 0 });\n setPaused(false);\n };\n const clear = () => {\n setRows([]);\n setHeld({ rows: [], dropped: 0 });\n };\n\n const apply = (next: ChannelChoice) => {\n const nextAllowed = typesFor(next);\n update({\n channel: channelName(next),\n types:\n types.filter((type) => nextAllowed.includes(type)).join(\",\") || null,\n });\n };\n\n return (\n <div\n className=\"screen events-screen\"\n data-testid=\"events-screen\"\n >\n <h1 className=\"screen-title\">Events</h1>\n <Card\n title=\"Subscription\"\n className=\"events-controls\"\n >\n <ChannelPicker\n key={channel}\n choice={choice}\n onApply={apply}\n />\n <TypeFilter\n allowed={allowed}\n selected={types}\n onChange={(next) => update({ types: next.join(\",\") || null })}\n />\n <IgnoredTypesNote\n ignored={typesParam.ignored}\n channel={channel}\n showingAll={types.length === 0}\n />\n <p className=\"muted events-channel\">\n Watching <code data-testid=\"events-channel\">{channel}</code>\n </p>\n <Rejections rejected={rejected} />\n </Card>\n <Card\n title=\"Log\"\n actions={\n <div className=\"events-actions\">\n <span\n className=\"muted\"\n data-testid=\"events-count\"\n >\n {plural(rows.length, \"row\")} (the latest {formatNumber(MAX_ROWS)}{\" \"}\n are kept)\n </span>\n {paused && (\n <span\n className=\"events-held\"\n data-testid=\"events-held\"\n >\n {formatNumber(held.rows.length)} held\n {held.dropped > 0\n ? `, ${formatNumber(held.dropped)} dropped`\n : \"\"}\n </span>\n )}\n {/* The label says what a press does; an aria-pressed on top would\n contradict it (\"Resume, pressed\"). */}\n <Button\n size=\"sm\"\n onClick={paused ? resume : pause}\n >\n {paused ? \"Resume\" : \"Pause\"}\n </Button>\n <Button\n size=\"sm\"\n onClick={clear}\n disabled={rows.length === 0 && held.rows.length === 0}\n >\n Clear\n </Button>\n </div>\n }\n >\n {rows.length === 0 ? (\n <EmptyLog\n status={status}\n channel={channel}\n />\n ) : (\n <Table\n label=\"Events, newest first\"\n className=\"events-table\"\n >\n <thead>\n <tr>\n <th scope=\"col\">Time</th>\n <th scope=\"col\">Event</th>\n <th scope=\"col\">Target</th>\n <th scope=\"col\">Id</th>\n <th scope=\"col\">Payload</th>\n </tr>\n </thead>\n <tbody>\n {rows.map((row) =>\n row.kind === \"event\" ? (\n <EventRow\n key={row.key}\n row={row}\n event={row.event}\n />\n ) : (\n <GapRow\n key={row.key}\n row={row}\n gap={row.gap}\n />\n ),\n )}\n </tbody>\n </Table>\n )}\n </Card>\n </div>\n );\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "E837A263E86CCE7764756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,4 @@
1
+ import{v,T,N,n,e,t,f,i,m,y,a,Q,is,E,d,p,L,o,u,I}from"./main-a250ffk7.js";import{ke,wo,ko,xe,ft,Ze,Wn,Yn,jt,zn,Pr,Mo,Fo,Vo,Ur}from"./main-jxre7w93.js";import{vt,En}from"./main-w93x1dzs.js";import{Ie,A}from"./main-0jmeh6mq.js";import{pt}from"./main-9prgjhg4.js";import"./main-pegp0ygb.js";function R({refetchInterval:r}){let c=i(),l=is().get("group"),s=a({queryKey:ke.groups(c),queryFn:({signal:S})=>ko(c,S),refetchInterval:r}),h=T(null),b=T(null),g=s.data!==void 0;return v(()=>{if(!g||l===null||b.current===l)return;let S=h.current;if(S===null)return;if(b.current=l,typeof S.scrollIntoView==="function")S.scrollIntoView({block:"center"})},[g,l]),t("section",{className:"summon-groups","data-testid":"summon-groups","aria-labelledby":"summon-groups-heading",children:[e("h2",{id:"summon-groups-heading",className:"summon-groups-title",children:"Summon groups"}),s.isPending?e(p,{label:"Loading the summon groups",showLabel:!0}):s.isError?e(L,{error:s.error,title:"Could not load the summon groups",onRetry:()=>void s.refetch()}):s.data.groups.length===0?e("p",{className:"muted","data-testid":"summon-groups-empty",children:"No summon groups in this namespace."}):t(I,{label:"Summon groups",children:[e("thead",{children:t("tr",{children:[e("th",{scope:"col",children:"Group"}),e("th",{scope:"col",children:"Unit"}),e("th",{scope:"col",children:"Budget left"}),e("th",{scope:"col",children:"Shared circuit"}),e("th",{scope:"col",title:Fo,children:Mo})]})}),e("tbody",{children:s.data.groups.map((S)=>e(q,{group:S,current:S.name===l,rowRef:S.name===l?h:void 0},S.name))})]})]})}function q({group:r,current:c,rowRef:l}){let s=Wn(r),h=Yn(r,void 0),b=jt(r);return t("tr",{ref:l,id:`summon-group-${r.name}`,"data-testid":`summon-group-row-${r.name}`,"aria-current":c?"true":void 0,className:N(c&&"is-current"),children:[e("th",{scope:"row",children:r.name}),e("td",{children:b?e(f,{tone:"neutral",title:zn,testId:`summon-groups-unit-${r.name}`,children:Pr(r)}):e("span",{"data-testid":`summon-groups-unit-${r.name}`,children:Pr(r)})}),e("td",{children:e(Ze,{budget:r.budget,testId:`summon-groups-budget-${r.name}`})}),e("td",{children:h.length===0?e("span",{className:"muted",title:"The group shares no circuit, or none has counted a failure",children:"—"}):e("ul",{className:"summon-group-list",children:h.map((g)=>e("li",{children:e(Ur,{circuit:g,compact:!0,testId:`summon-groups-circuit-${r.name}-${g.kind??"this-summoner"}`})},g.kind??""))})}),t("td",{children:[s.length===0?e("span",{className:"muted",children:"None today"}):e("ul",{className:"summon-group-list",children:s.map((g)=>t("li",{"data-testid":`summon-groups-share-${r.name}-${g.queue}`,children:[e(E,{to:xe(g.queue),title:`The Summon tab of ${g.queue}`,children:g.queue})," ",e("span",{className:"summon-group-count",children:o(g.day)})]},g.queue))}),b&&s.length>0&&e("span",{className:"muted summon-group-note","data-testid":`summon-groups-note-${r.name}`,children:Vo})]})]})}var w=Q;function P(){let r=i(),c=y("queues.list"),l=m().features.summonStoredStatus===!0,s=a({queryKey:ke.list(r),queryFn:({signal:h})=>wo(r,h),refetchInterval:w,enabled:c});return t("div",{className:"screen","data-testid":"summoning-screen",children:[e("h1",{className:"screen-title",children:"Summoning"}),!c?e(d,{title:"Nothing to show",description:"You may not list queues on this API."}):s.isPending?e(p,{label:"Loading the summon controllers",showLabel:!0}):s.isError?e(L,{error:s.error,title:"Could not load the summon controllers",onRetry:()=>void s.refetch()}):s.data.controllers.length===0?e(d,{title:"No summon controllers here",description:l?"No queue summons here: none has a controller in the API's own process, or summon state in the store that you may read.":"Summon controllers run in the API's own process, from its BunJobs context's summon option or jobs.summonController(). None runs in this one, so there is nothing to list. A controller running in another process is not listed."}):t(I,{label:"Summon controllers",children:[e("thead",{children:t("tr",{children:[e("th",{scope:"col",children:"Queue"}),e("th",{scope:"col",children:"Summoner"}),e("th",{scope:"col",children:"Readiness"}),e("th",{scope:"col",children:"Last outcome"}),e("th",{scope:"col",children:"Budget left"})]})}),e("tbody",{children:s.data.controllers.map((h)=>e(C,{item:h},`${h.namespace}/${h.queue}`))})]}),c&&l&&e(R,{refetchInterval:w})]})}function k({queue:r,group:c,queues:l}){return t("span",{className:"muted summoning-unit","data-testid":`summoning-unit-${r}`,children:["Shared unit of ",u(c),":"," ",l.map((s,h)=>t("span",{children:[h>0&&", ",e(E,{to:xe(s),title:`The Summon tab of ${s}`,children:u(s)})]},s))]})}function C({item:r}){let c=Ie(),l=r.readiness===void 0?void 0:pt(r.readiness),s=r.last===void 0?void 0:vt(r.last.outcome);return t("tr",{"data-testid":`summoning-row-${r.queue}`,children:[t("th",{scope:"row",children:[e(E,{to:xe(r.queue),title:`The Summon tab of ${r.queue}`,children:r.queue}),r.group!==void 0&&e(k,{queue:r.queue,group:r.group,queues:r.queues??[r.queue]})]}),e("td",{children:r.kind===""?e("span",{className:"muted",title:"Not recorded yet: its controller runs in another process","data-testid":"summoning-kind-unknown",children:"—"}):e("code",{children:u(r.kind)})}),t("td",{children:[l===void 0?e("span",{className:"muted",title:"Its controller runs in another process",children:"Elsewhere"}):e(f,{tone:l.tone,title:l.hint,testId:"summoning-readiness",children:l.label}),r.inert&&t(n,{children:[" ",e(f,{tone:"neutral",title:En(r.inertReason),testId:"summoning-inert",children:"Inert"})]}),r.circuitOpenUntil!==void 0&&t(n,{children:[" ",e(f,{tone:"warning",title:`Circuit open until ${ft(r.circuitOpenUntil,c)}: after repeated failures nothing is summoned until then, apart from one trial attempt.`,testId:"summoning-circuit",children:"Circuit open"})]})]}),e("td",{"data-testid":"summoning-last",children:r.last===void 0||s===void 0?e("span",{className:"muted",children:"None yet"}):t(n,{children:[e(f,{tone:s.tone,title:s.hint,children:s.label})," ",e(A,{value:r.last.at}),r.last.detail!==void 0&&t("span",{className:"muted",children:[" — ",u(r.last.detail)]})]})}),e("td",{children:r.budget===void 0?e("span",{className:"muted","data-testid":`summoning-budget-${r.queue}`,children:"—"}):e(Ze,{budget:r.budget,testId:`summoning-budget-${r.queue}`})})]})}export{P as SummoningScreen};
2
+
3
+ //# debugId=74F8CB744D249C1D64756E2164756E21
4
+ //# sourceMappingURL=index-4e55z986.js.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["app/jobs/screens/summoning/SummonGroupsSection.tsx", "app/jobs/screens/summoning/SummoningScreen.tsx"],
4
+ "sourcesContent": [
5
+ "import type { RefObject } from \"react\";\nimport type { SummonGroupStatusDto } from \"../../api/types\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useEffect, useRef } from \"react\";\nimport { listSummonGroups, summonKeys } from \"../../api/summon\";\nimport { Badge } from \"../../components/Badge\";\nimport { cx } from \"../../components/classNames\";\nimport { ErrorView } from \"../../components/ErrorView\";\nimport { Spinner } from \"../../components/Spinner\";\nimport { Table } from \"../../components/Table\";\nimport { useApiClient } from \"../../context\";\nimport { formatNumber } from \"../../format\";\nimport { Link } from \"../../router\";\nimport { useSearchParams } from \"../../routing\";\nimport { SummonBudget } from \"../queues/panels/SummonBudget\";\nimport { CircuitState } from \"../queues/panels/SummonGroupCard\";\nimport {\n groupCircuits,\n groupIsShared,\n GROUPS_TODAY_HEADER,\n GROUPS_TODAY_TITLE,\n groupShares,\n groupUnitLabel,\n SHARED_UNIT_ROW_NOTE,\n SHARED_UNIT_TITLE,\n} from \"../queues/panels/summonGroupText\";\nimport { summonTabPath } from \"./paths\";\n\n/** Props of {@link SummonGroupsSection}. */\nexport interface SummonGroupsSectionProps {\n /** How often the groups are re-read, ms: the controllers list's interval. */\n refetchInterval: number;\n}\n\n/**\n * The Summoning screen's summon groups (`GET /summon/groups`): one row per\n * group with shared state in the namespace — whether it is one shared unit\n * or per-queue controllers, its budget, its shared circuit per provider\n * kind, and the member queues that charged it today, each linked to its\n * Summon tab. A shared unit's counts are the attempts that served each\n * queue, each attempt counted on every queue it served, so they do not add\n * up to the group's; the column's title says so.\n *\n * The screen renders it only where the API reads summon state from storage\n * (`features.summonStoredStatus`) and the caller may list queues\n * (`queues.list`, the route's action). Each group arrives redacted to the\n * member queues the caller may read, so a row never claims a member count.\n *\n * `?group=<name>` marks that group's row and scrolls it into view once, when\n * the groups arrive. A failed read is an error view inside the section, so\n * the controllers above it stay.\n */\nexport function SummonGroupsSection({\n refetchInterval,\n}: SummonGroupsSectionProps) {\n const api = useApiClient();\n const selected = useSearchParams().get(\"group\");\n const groups = useQuery({\n queryKey: summonKeys.groups(api),\n queryFn: ({ signal }) => listSummonGroups(api, signal),\n refetchInterval,\n });\n const selectedRowRef = useRef<HTMLTableRowElement | null>(null);\n // The group last scrolled to: once per `?group=`, not on every re-read.\n const scrolledToRef = useRef<string | null>(null);\n const loaded = groups.data !== undefined;\n useEffect(() => {\n if (!loaded || selected === null || scrolledToRef.current === selected) {\n return;\n }\n const row = selectedRowRef.current;\n if (row === null) {\n return;\n }\n scrolledToRef.current = selected;\n // happy-dom, and an old browser, may not have it.\n if (typeof row.scrollIntoView === \"function\") {\n row.scrollIntoView({ block: \"center\" });\n }\n }, [loaded, selected]);\n return (\n <section\n className=\"summon-groups\"\n data-testid=\"summon-groups\"\n aria-labelledby=\"summon-groups-heading\"\n >\n <h2\n id=\"summon-groups-heading\"\n className=\"summon-groups-title\"\n >\n Summon groups\n </h2>\n {groups.isPending ? (\n <Spinner\n label=\"Loading the summon groups\"\n showLabel\n />\n ) : groups.isError ? (\n <ErrorView\n error={groups.error}\n title=\"Could not load the summon groups\"\n onRetry={() => void groups.refetch()}\n />\n ) : groups.data.groups.length === 0 ? (\n <p\n className=\"muted\"\n data-testid=\"summon-groups-empty\"\n >\n No summon groups in this namespace.\n </p>\n ) : (\n <Table label=\"Summon groups\">\n <thead>\n <tr>\n <th scope=\"col\">Group</th>\n <th scope=\"col\">Unit</th>\n <th scope=\"col\">Budget left</th>\n <th scope=\"col\">Shared circuit</th>\n <th\n scope=\"col\"\n title={GROUPS_TODAY_TITLE}\n >\n {GROUPS_TODAY_HEADER}\n </th>\n </tr>\n </thead>\n <tbody>\n {groups.data.groups.map((group) => (\n <GroupRow\n key={group.name}\n group={group}\n current={group.name === selected}\n rowRef={group.name === selected ? selectedRowRef : undefined}\n />\n ))}\n </tbody>\n </Table>\n )}\n </section>\n );\n}\n\n/** Props of {@link GroupRow}. */\ninterface GroupRowProps {\n /** The group, as `GET /summon/groups` lists it. */\n group: SummonGroupStatusDto;\n /** Whether `?group=` names it: the row is marked. */\n current: boolean;\n /** Set to the row's element for the marked row, so it can be scrolled into view. */\n rowRef: RefObject<HTMLTableRowElement | null> | undefined;\n}\n\n/** One group. */\nfunction GroupRow({ group, current, rowRef }: GroupRowProps) {\n const shares = groupShares(group);\n // No answering controller here, so `circuit` alone has no kind to name.\n const circuits = groupCircuits(group, undefined);\n const shared = groupIsShared(group);\n return (\n <tr\n ref={rowRef}\n id={`summon-group-${group.name}`}\n data-testid={`summon-group-row-${group.name}`}\n aria-current={current ? \"true\" : undefined}\n className={cx(current && \"is-current\")}\n >\n <th scope=\"row\">{group.name}</th>\n <td>\n {shared ? (\n <Badge\n tone=\"neutral\"\n title={SHARED_UNIT_TITLE}\n testId={`summon-groups-unit-${group.name}`}\n >\n {groupUnitLabel(group)}\n </Badge>\n ) : (\n <span data-testid={`summon-groups-unit-${group.name}`}>\n {groupUnitLabel(group)}\n </span>\n )}\n </td>\n <td>\n <SummonBudget\n budget={group.budget}\n testId={`summon-groups-budget-${group.name}`}\n />\n </td>\n <td>\n {circuits.length === 0 ? (\n <span\n className=\"muted\"\n title=\"The group shares no circuit, or none has counted a failure\"\n >\n —\n </span>\n ) : (\n <ul className=\"summon-group-list\">\n {circuits.map((circuit) => (\n <li key={circuit.kind ?? \"\"}>\n <CircuitState\n circuit={circuit}\n compact\n testId={`summon-groups-circuit-${group.name}-${circuit.kind ?? \"this-summoner\"}`}\n />\n </li>\n ))}\n </ul>\n )}\n </td>\n <td>\n {shares.length === 0 ? (\n <span className=\"muted\">None today</span>\n ) : (\n <ul className=\"summon-group-list\">\n {shares.map((share) => (\n <li\n key={share.queue}\n data-testid={`summon-groups-share-${group.name}-${share.queue}`}\n >\n <Link\n to={summonTabPath(share.queue)}\n title={`The Summon tab of ${share.queue}`}\n >\n {share.queue}\n </Link>{\" \"}\n <span className=\"summon-group-count\">\n {formatNumber(share.day)}\n </span>\n </li>\n ))}\n </ul>\n )}\n {shared && shares.length > 0 && (\n <span\n className=\"muted summon-group-note\"\n data-testid={`summon-groups-note-${group.name}`}\n >\n {SHARED_UNIT_ROW_NOTE}\n </span>\n )}\n </td>\n </tr>\n );\n}\n",
6
+ "import type { SummonListItemDto } from \"../../api/types\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { listSummonControllers, summonKeys } from \"../../api/summon\";\nimport { Badge } from \"../../components/Badge\";\nimport { EmptyState } from \"../../components/EmptyState\";\nimport { ErrorView } from \"../../components/ErrorView\";\nimport { RelativeTime } from \"../../components/RelativeTime\";\nimport { Spinner } from \"../../components/Spinner\";\nimport { Table } from \"../../components/Table\";\nimport { useApiClient } from \"../../context\";\nimport { displayText } from \"../../format\";\nimport { useNow } from \"../../hooks/useNow\";\nimport { useCan, useMeta } from \"../../meta/hooks\";\nimport { POLL_INTERVAL_MS } from \"../../queryClient\";\nimport { Link } from \"../../router\";\nimport { providerReadiness } from \"../providers/providerText\";\nimport { utcResetLabel } from \"../queues/panels/budgetText\";\nimport { SummonBudget } from \"../queues/panels/SummonBudget\";\nimport { summonInert, summonOutcome } from \"../queues/panels/summonText\";\nimport { summonTabPath } from \"./paths\";\nimport { SummonGroupsSection } from \"./SummonGroupsSection\";\n// The group styles live with the Summon tab's; this chunk may load first.\nimport \"../queues/queues.css\";\n\n/**\n * How often the list is re-read: attempts and budgets move with the clock\n * and with summon checks, which no event this screen follows announces — so,\n * like the Summon panel, it polls at the base interval, live or not.\n */\nconst SUMMONING_REFRESH_MS = POLL_INTERVAL_MS;\n\n/**\n * `/summon`: every summon controller in the API's process (`GET /summon`),\n * and, where the API reads summon state from storage\n * (`features.summonStoredStatus`), every queue whose controller runs\n * elsewhere (`local: false`: \"Elsewhere\", no actions), one row each — its queue (linked to the queue's Summon tab), the\n * summoner's kind and readiness, the last outcome and when, and the budget\n * left in each UTC window with when it resets, and an open circuit.\n *\n * Under the controllers, where the API reads summon state from storage, the\n * summon groups of the namespace ({@link SummonGroupsSection}).\n *\n * Routed only where the API serves the list (`features.summonList`) and the\n * caller may list queues (`queues.list`, the route's action); the nav entry\n * follows the same rule. The API then lists a controller only where the\n * caller may read its queue (`queues.read` on that queue).\n */\nexport function SummoningScreen() {\n const api = useApiClient();\n // `queues.list` is also what routes the queue screen, so every row links.\n const canList = useCan(\"queues.list\");\n // Whether the API reads summon state from storage, and so also lists the\n // queues whose controller runs in another process.\n const stored = useMeta().features.summonStoredStatus === true;\n const list = useQuery({\n queryKey: summonKeys.list(api),\n queryFn: ({ signal }) => listSummonControllers(api, signal),\n refetchInterval: SUMMONING_REFRESH_MS,\n enabled: canList,\n });\n return (\n <div\n className=\"screen\"\n data-testid=\"summoning-screen\"\n >\n <h1 className=\"screen-title\">Summoning</h1>\n {!canList ? (\n <EmptyState\n title=\"Nothing to show\"\n description=\"You may not list queues on this API.\"\n />\n ) : list.isPending ? (\n <Spinner\n label=\"Loading the summon controllers\"\n showLabel\n />\n ) : list.isError ? (\n <ErrorView\n error={list.error}\n title=\"Could not load the summon controllers\"\n onRetry={() => void list.refetch()}\n />\n ) : list.data.controllers.length === 0 ? (\n <EmptyState\n title=\"No summon controllers here\"\n description={\n stored\n ? \"No queue summons here: none has a controller in the API's own process, or summon state in the store that you may read.\"\n : \"Summon controllers run in the API's own process, from its BunJobs context's summon option or jobs.summonController(). None runs in this one, so there is nothing to list. A controller running in another process is not listed.\"\n }\n />\n ) : (\n <Table label=\"Summon controllers\">\n <thead>\n <tr>\n <th scope=\"col\">Queue</th>\n <th scope=\"col\">Summoner</th>\n <th scope=\"col\">Readiness</th>\n <th scope=\"col\">Last outcome</th>\n <th scope=\"col\">Budget left</th>\n </tr>\n </thead>\n <tbody>\n {list.data.controllers.map((item) => (\n <ControllerRow\n key={`${item.namespace}/${item.queue}`}\n item={item}\n />\n ))}\n </tbody>\n </Table>\n )}\n {canList && stored && (\n <SummonGroupsSection refetchInterval={SUMMONING_REFRESH_MS} />\n )}\n </div>\n );\n}\n\n/** Props of {@link ControllerRow}. */\ninterface ControllerRowProps {\n /** The controller, as `GET /summon` lists it. */\n item: SummonListItemDto;\n}\n\n/** Props of {@link SharedUnitLine}. */\ninterface SharedUnitLineProps {\n /** The row's queue (`item.queue`), naming the line's test id. */\n queue: string;\n /** The summon group the unit is the unit of (`item.group`). */\n group: string;\n /** The unit's queues the caller may read (`item.queues`), the row's own first. */\n queues: readonly string[];\n}\n\n/**\n * Under a shared unit's queue: the group it is the unit of, and each of its\n * queues the caller may read, linked to its Summon tab. The row's own queue\n * is listed too, so the line reads as the whole visible unit; queues hidden\n * from the caller are not counted.\n */\nfunction SharedUnitLine({ queue, group, queues }: SharedUnitLineProps) {\n return (\n <span\n className=\"muted summoning-unit\"\n data-testid={`summoning-unit-${queue}`}\n >\n Shared unit of {displayText(group)}:{\" \"}\n {queues.map((member, index) => (\n <span key={member}>\n {index > 0 && \", \"}\n <Link\n to={summonTabPath(member)}\n title={`The Summon tab of ${member}`}\n >\n {displayText(member)}\n </Link>\n </span>\n ))}\n </span>\n );\n}\n\n/** One controller. */\nfunction ControllerRow({ item }: ControllerRowProps) {\n const now = useNow();\n // Absent for a queue read from storage (`local: false`): its controller,\n // and so its summoner, runs in another process.\n const readiness =\n item.readiness === undefined\n ? undefined\n : providerReadiness(item.readiness);\n const last =\n item.last === undefined ? undefined : summonOutcome(item.last.outcome);\n return (\n <tr data-testid={`summoning-row-${item.queue}`}>\n <th scope=\"row\">\n <Link\n to={summonTabPath(item.queue)}\n title={`The Summon tab of ${item.queue}`}\n >\n {item.queue}\n </Link>\n {item.group !== undefined && (\n <SharedUnitLine\n queue={item.queue}\n group={item.group}\n queues={item.queues ?? [item.queue]}\n />\n )}\n </th>\n <td>\n {item.kind === \"\" ? (\n // Read from storage before any claim recorded the summoner's kind.\n <span\n className=\"muted\"\n title=\"Not recorded yet: its controller runs in another process\"\n data-testid=\"summoning-kind-unknown\"\n >\n —\n </span>\n ) : (\n <code>{displayText(item.kind)}</code>\n )}\n </td>\n <td>\n {readiness === undefined ? (\n <span\n className=\"muted\"\n title=\"Its controller runs in another process\"\n >\n Elsewhere\n </span>\n ) : (\n <Badge\n tone={readiness.tone}\n title={readiness.hint}\n testId=\"summoning-readiness\"\n >\n {readiness.label}\n </Badge>\n )}\n {item.inert && (\n <>\n {\" \"}\n <Badge\n tone=\"neutral\"\n title={summonInert(item.inertReason)}\n testId=\"summoning-inert\"\n >\n Inert\n </Badge>\n </>\n )}\n {item.circuitOpenUntil !== undefined && (\n <>\n {\" \"}\n <Badge\n tone=\"warning\"\n title={`Circuit open until ${utcResetLabel(item.circuitOpenUntil, now)}: after repeated failures nothing is summoned until then, apart from one trial attempt.`}\n testId=\"summoning-circuit\"\n >\n Circuit open\n </Badge>\n </>\n )}\n </td>\n <td data-testid=\"summoning-last\">\n {item.last === undefined || last === undefined ? (\n <span className=\"muted\">None yet</span>\n ) : (\n <>\n <Badge\n tone={last.tone}\n title={last.hint}\n >\n {last.label}\n </Badge>{\" \"}\n <RelativeTime value={item.last.at} />\n {item.last.detail !== undefined && (\n <span className=\"muted\"> — {displayText(item.last.detail)}</span>\n )}\n </>\n )}\n </td>\n <td>\n {item.budget === undefined ? (\n // None for summon state a newer bun-jobs wrote: it is not read here.\n <span\n className=\"muted\"\n data-testid={`summoning-budget-${item.queue}`}\n >\n —\n </span>\n ) : (\n <SummonBudget\n budget={item.budget}\n testId={`summoning-budget-${item.queue}`}\n />\n )}\n </td>\n </tr>\n );\n}\n"
7
+ ],
8
+ "mappings": "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",
9
+ "debugId": "74F8CB744D249C1D64756E2164756E21",
10
+ "names": []
11
+ }
@@ -0,0 +1,4 @@
1
+ import{Me,c,r,Z,Tn,je,n,e,t,f,i,m,y,Fe,ie,Y,a,Q,s,de,E,ve,H,d,p,us,ee,Ve,Ln,R,L,o,z,Ut,h,u,l,S,I,ne,Is,gr,$r,qe,ws,$e,bt,st,xt,it,Nt,Se,at}from"./main-a250ffk7.js";import{Ye,Rt,De,Tr,vr,No,fn,Fn,Bt,qt,Vn,Bn,Oo,pn,Ao,qn,Jn,Sr,Hn,Ro,Do,Dt}from"./main-ts19j4n0.js";import{_e,ze,hn,To,Gn,vo,So,gn,Oe}from"./main-kwmqkjfx.js";import{k}from"./main-4g69fn3x.js";import{O}from"./main-4j1fcevh.js";import{W,me,Tt,we}from"./main-3yj6bv90.js";import{A}from"./main-0jmeh6mq.js";import"./main-jkvd92z9.js";import"./main-hm1ng3yg.js";import"./main-5grjvsy7.js";import{F}from"./main-pegp0ygb.js";function ce({queue:g,workerKey:b}){let v=i(),C=at("workers"),[T,x]=Nt("range"),{analytics:K,key:P,request:q}=it(T),_=H(Q),w=a({queryKey:qe.worker(g,b,P),queryFn:({signal:N})=>ws(v,g,b,q(),N),enabled:C,refetchInterval:_});if(!C)return null;return e(R,{title:"Throughput and busyness",className:"analytics-section",actions:e(xt,{range:T,onChange:x,label:"Range for this worker's numbers",maxSpan:K?.maxSpanMs}),children:e("div",{className:"worker-analytics","data-testid":"worker-analytics",children:w.isPending?e(p,{label:"Loading this worker's numbers",showLabel:!0}):w.isError?e(bt,{error:w.error,title:"Could not load this worker's numbers",onRetry:()=>void w.refetch(),testId:"worker-range-not-retained"}):t(n,{children:[t("section",{"aria-label":"Throughput",children:[e("h3",{className:"worker-analytics-title",children:"Throughput"}),e(st,{range:w.data.jobs.range,always:!0,testId:"worker-jobs-range-caption"}),t("div",{className:"analytics-headline",children:[t("dl",{className:"stat-grid","aria-label":"Throughput totals",children:[t("div",{className:"stat",children:[e("dt",{className:"stat-label",children:"Completed"}),e("dd",{className:"stat-value",children:o(w.data.jobs.totals.completed)})]}),t("div",{className:"stat",children:[e("dt",{className:"stat-label",children:"Failed"}),e("dd",{className:"stat-value",children:o(w.data.jobs.totals.failed)}),e("dd",{className:"stat-hint",children:"Attempts that failed."})]})]}),e("div",{className:"analytics-charts",children:e(Se,{values:w.data.jobs.buckets.map((N)=>N.completed),secondary:w.data.jobs.buckets.map((N)=>N.failed),label:`${b}: ${o(w.data.jobs.totals.completed)} completed, ${o(w.data.jobs.totals.failed)} failed, ${$e(w.data.jobs.range)}`,width:240})})]})]}),w.data.busyness?t("section",{"aria-label":"Busyness",children:[e("h3",{className:"worker-analytics-title",children:"Busyness"}),e(st,{range:w.data.busyness.range,always:!0,testId:"worker-busyness-range-caption"}),w.data.busyness.totals.samples===0?e("p",{className:"muted","data-testid":"worker-busyness-no-samples",children:"No heartbeat landed in this range, so nothing was sampled — the worker was not reporting, which is not the same as idle."}):t("div",{className:"analytics-headline",children:[t("dl",{className:"stat-grid","aria-label":"Busyness totals",children:[t("div",{className:"stat",children:[e("dt",{className:"stat-label",children:"Mean in flight"}),t("dd",{className:"stat-value",children:[w.data.busyness.totals.activeMean.toFixed(1)," /"," ",o(w.data.busyness.totals.concurrency)]}),e("dd",{className:"stat-hint",children:"Against the concurrency of the last sample."})]}),t("div",{className:"stat",children:[e("dt",{className:"stat-label",children:"Most in flight"}),e("dd",{className:"stat-value",children:o(w.data.busyness.totals.activeMax)})]}),t("div",{className:"stat",children:[e("dt",{className:"stat-label",children:"Samples"}),e("dd",{className:"stat-value",children:o(w.data.busyness.totals.samples)}),e("dd",{className:"stat-hint",children:"Heartbeats in the range."})]})]}),e("div",{className:"analytics-charts",children:e(Se,{values:w.data.busyness.buckets.map((N)=>N.activeMean),secondary:w.data.busyness.buckets.map((N)=>N.concurrency),label:`${b}: mean jobs in flight against its concurrency, ${$e(w.data.busyness.range)}`,width:240})})]})]}):e("p",{className:"muted","data-testid":"worker-busyness-absent",children:"This backend records no busyness for workers."})]})})})}var Ke=new Set(["concurrency","maxStalledCount"]);function ue(g,b){return Ke.has(g)?o(b):`${o(b)} ms`}function xe(g,b){return je.every((v)=>g.config?.effective[v]===b.config?.effective[v])}function Ne({queue:g,workerKey:b,instances:v,stored:C}){let T=qt(),[x,K]=r(!1),P=v.find((j)=>j.config!==void 0);if(v.length===0)return e(R,{title:"Configuration",children:e(Je,{queue:g,workerKey:b,stored:C,canReset:T("workers.configure")})});let q=P?.config,_=v.some((j)=>j.control?.pending===!0),w=P!==void 0&&Bt(P,T).configure,N=P!==void 0&&v.some((j)=>j.config!==void 0&&!xe(j,P));return t(R,{title:"Configuration",actions:t(n,{children:[_&&e(f,{tone:"accent",title:"A change was recorded and an instance has not taken it up yet. It applies within seconds.",children:"Change pending"}),w&&e(s,{size:"sm",onClick:()=>K(!0),children:"Edit settings…"})]}),children:[e("div",{"data-testid":"worker-config",children:q===void 0?e("p",{className:"muted",children:"No instance of this key reports its settings (it predates remote configuration, or the backend keeps no config), so there is nothing to show."}):t(n,{children:[e("p",{className:"muted worker-config-summary","data-testid":"worker-config-summary",children:q.overridden.length===0?"No override is stored: every value is what the code asks for.":t(n,{children:["An override (version ",q.seq,q.updatedAt!==void 0&&t(n,{children:[", written ",e(A,{value:q.updatedAt})]}),") replaces ",q.overridden.length," of the"," ",je.length," settings, for every instance of this key."]})}),N&&t("p",{className:"notice",role:"note","data-testid":"worker-config-differs",children:["Not every instance runs with these values (they are"," ",e("code",{children:P.id}),"’s): a change is still being taken up, or the instances’ code differs. Each instance’s Settings… shows its own."]}),t(I,{label:`Settings of ${b}`,children:[e("thead",{children:t("tr",{children:[e("th",{scope:"col",children:"Setting"}),e("th",{scope:"col",className:"num",children:"Running with"}),e("th",{scope:"col",className:"num",children:"Code asks for"}),e("th",{scope:"col",children:"Source"})]})}),e("tbody",{children:je.map((j)=>{let B=q.overridden.includes(j),J=q.derived?.includes(j)===!0;return t("tr",{"data-testid":`worker-setting-${j}`,children:[e("th",{scope:"row",title:Vn[j],children:e("code",{children:j})}),e("td",{className:"num",children:ue(j,q.effective[j])}),t("td",{className:"num",children:[ue(j,q.code[j]),J&&t("span",{className:"muted",title:"Derived rather than given: a third of lockDuration.",children:[" ","(derived)"]})]}),e("td",{children:B?e(f,{tone:"accent",title:"Replaced by the override stored for this key.",children:"Overridden"}):e("span",{className:"muted",children:"Code"})})]},j)})})]})]})}),x&&P!==void 0&&e(Bn,{worker:P,onClose:()=>K(!1)})]})}function Je({queue:g,workerKey:b,stored:v,canReset:C}){let T=i(),[x,K]=r(!1),P=O({mutationFn:()=>gn(T,g,b),invalidate:ze(g),successMessage:`Reset ${b} to the values in its code`,toastErrors:!1}),q=v?je.flatMap((w)=>{let N=v.values[w];return N===void 0?[]:[{setting:w,value:N}]}):[],_=C&&v!==null;return t("div",{"data-testid":"worker-config-offline",children:[e("p",{className:"muted",children:"No instance of this key is live, so its configuration cannot be shown until one reports: the values a worker runs with and the ones its code asks for come from the running worker."}),v===null?e("p",{"data-testid":"worker-config-none-stored",children:"No override is stored for this key."}):v!==void 0?t(n,{children:[t("p",{"data-testid":"worker-config-stored",children:["An override is stored for this key (version ",v.seq,", written"," ",e(A,{value:v.updatedAt}),"). The next instance to start takes it up."]}),q.length>0&&e(F,{items:q.map(({setting:w,value:N})=>({key:w,label:e("code",{children:w}),value:ue(w,N)}))})]}):null,_&&e(s,{size:"sm",variant:"danger",onClick:()=>K(!0),children:"Reset to code values…"}),e(k,{open:x,onClose:()=>K(!1),title:`Reset ${b}?`,description:"Drops the override stored for this key, so every instance started from now on runs with what its code asks for.",confirmLabel:"Reset",pendingLabel:"Resetting…",variant:"danger",onConfirm:()=>P.mutateAsync()})]})}var D={state:"jobState",name:"jobName",search:"jobSearch",order:"jobOrder",offset:"jobOffset",limit:"jobLimit",finished:"finished"},G={kind:"preset",seconds:86400},Be=new Set(["completed","dead"]);function pe(g){return g===De||Be.has(g)}function Ce(g){if(g.kind==="preset")return g.seconds===G.seconds?null:`${g.seconds}s`;return`${g.from}-${g.to}`}function fe(g){if(g===null||g==="")return G;let b=/^(\d+)-(\d+)$/.exec(g);if(b){let v=Number(b[1]),C=Number(b[2]);return Number.isSafeInteger(v)&&Number.isSafeInteger(C)&&C>v?{kind:"custom",from:v,to:C}:G}if(/^\d+s$/.test(g)){let v=gr(g);return v.kind==="preset"&&g===`${v.seconds}s`?v:G}return G}function Qe(g){return g.kind==="preset"?{kind:"last",ms:g.seconds*1000}:{kind:"between",from:g.from,to:g.to}}function We(g,b,v,C){let T=fe(g.get(D.finished));return{state:b===De?null:b,offset:me(g,D.offset,0),limit:we(me(g,D.limit,C.defaultPageSize),C.maxPageSize),order:g.get(D.order)==="asc"?"asc":"desc",names:Tt(g.get(D.name)??""),search:g.get(D.search)??"",total:!1,attribution:{workerKeys:[v],workerIds:[],finished:pe(b)?Qe(T):null}}}var Ge="Jobs whose last attempt this key ran",He=[D.offset],Te=[{value:De,label:"All"},...Z.map((g)=>({value:g,label:z[g],title:Ut[g]}))];function he({queue:g,workerKey:b}){let v=ie("jobAttribution"),C=y("jobs.list");return e(R,{title:Ge,children:e("div",{"data-testid":"worker-jobs",children:!v?e("div",{"data-testid":"worker-jobs-unrecorded",children:e(d,{title:"Not recorded by this backend",description:"This backend does not record which worker ran a job, so a worker's jobs cannot be listed."})}):!C?e("div",{"data-testid":"worker-jobs-hidden",children:e(d,{title:"Jobs hidden",description:"You may not list this queue's jobs."})}):!us(b)?e("div",{"data-testid":"worker-jobs-unfilterable",children:e(d,{title:"Cannot be filtered to this key",description:"The API splits every filter value at commas, and this key contains one, so the job list cannot be filtered to it."})}):e(Ue,{queue:g,workerKey:b})})})}function Ue({queue:g,workerKey:b}){let v=i(),C=m(),T=Fe()("queues.list"),[x,K]=W(),P=Ye(D.state,Te,De),q=We(x,P,b,C.limits),_=fe(x.get(D.finished)),w=pe(P),N=a({queryKey:ee.jobs(g,q),queryFn:({signal:J})=>Ln(v,g,q,J,{attribution:C.features.jobAttribution,createdOrder:C.features.addedByState}),refetchInterval:Is("jobs"),placeholderData:Y}),j=(J)=>K({[D.finished]:Ce(J),[D.offset]:null}),B=JSON.stringify([q.state,q.order,q.names,q.search,w?x.get(D.finished):null]);return t("section",{className:"jobs-section","aria-label":"Jobs this key ran",children:[e("p",{className:"muted","data-testid":"worker-jobs-last-attempt",children:"Only a job's last attempt is recorded: a job that failed on another worker and then ran here is listed on this page alone."}),e(Rt,{tabs:Te,param:D.state,defaultValue:De,resetParams:He,label:"Job states"}),w?t("div",{"data-testid":"worker-jobs-range",children:[e(xt,{range:_,onChange:j,label:"Range these jobs finished in",maxSpan:null}),e("p",{className:"muted",children:P===De?`Finished in: ${$r(_)}. Only a completed or dead job has a finish time, so a range lists those alone; choose Active for the jobs this key is running now.`:`Finished in: ${$r(_)}.`})]}):t("p",{className:"muted","data-testid":"worker-jobs-no-range",children:[q.state===null?"These":z[q.state]," jobs have not finished, so no date range applies to them: this lists every one whose last attempt this key ran, whenever that was."]}),e(Tr,{filters:q,searchIndexed:C.features.search,onApply:(J)=>K({[D.name]:J.name,[D.search]:J.search,[D.offset]:null}),onOrder:(J)=>K({[D.order]:J==="asc"?"asc":null,[D.offset]:null})},`${x.get(D.name)??""}|${q.search}`),N.isPending?e(p,{label:"Loading this key's jobs",showLabel:!0}):N.isError?e(L,{error:N.error,title:"Could not load this key's jobs",onRetry:()=>void N.refetch()}):t(n,{children:[e(vr,{queue:g,items:N.data.items,label:`Jobs whose last attempt ${b} ran`,linkJobs:T,processedBy:!1,empty:e("div",{"data-testid":"worker-jobs-empty",children:e(d,{title:"No jobs",description:"No job whose last attempt this key ran matches the state, range and filters. Which worker ran a job is kept only as long as the job itself: jobs removed on completion are not listed."})})},B),e(ne,{label:"Pages of this key's jobs",offset:q.offset,limit:q.limit,itemCount:N.data.items.length,hasMore:N.data.page.hasMore,maxPageSize:C.limits.maxPageSize,disabled:N.isFetching&&N.isPlaceholderData,onChange:(J)=>K({[D.offset]:J.offset>0?String(J.offset):null,[D.limit]:String(J.limit)})})]})]})}function Re({workerKey:g,instances:b}){let v=[];for(let w of b)if(w.summon!==void 0)v.push({id:w.id,summon:w.summon});if(v.length===0)return null;let C=b.length-v.length,T=v.some(({summon:w})=>w.kind!==void 0),x=v.some(({summon:w})=>w.group!==void 0),K=v.some(({summon:w})=>w.resolvedMode!==void 0),P=v.some(({summon:w})=>w.mode!==void 0),q=v.some(({summon:w})=>w.deadlineAt!==void 0),_=v.some(({summon:w})=>w.handle!==void 0);return e(R,{title:"Summoned",children:t("div",{"data-testid":"worker-summon",children:[e("p",{className:"muted worker-target-note",children:Oo}),t(I,{label:`Summoned instances of ${g}`,children:[e("thead",{children:t("tr",{children:[e("th",{scope:"col",children:"Instance"}),e("th",{scope:"col",children:"Summon"}),T&&e("th",{scope:"col",children:"Summoner"}),x&&e("th",{scope:"col",children:"Unit of"}),K&&e("th",{scope:"col",children:"Runs as"}),P&&e("th",{scope:"col",children:"Requested mode"}),q&&e("th",{scope:"col",children:"Requested deadline"}),_&&e("th",{scope:"col",children:"Handle"})]})}),e("tbody",{children:v.map(({id:w,summon:N})=>t("tr",{"data-testid":`worker-summon-row-${w}`,children:[e("th",{scope:"row",children:e("code",{children:w})}),e("td",{children:e("code",{children:u(N.id)})}),T&&e("td",{children:N.kind!==void 0&&u(N.kind)}),x&&e("td",{title:N.group===void 0?void 0:qn(N.group),children:N.group===void 0?"—":u(N.group)}),K&&e("td",{title:N.resolvedMode===void 0?void 0:"The mode it actually runs in: its own option, else the requested mode, else exit when idle.",children:N.resolvedMode!==void 0&&pn(N.resolvedMode)}),P&&e("td",{title:N.mode===void 0?void 0:Ao(N.mode),children:N.mode!==void 0&&pn(N.mode)}),q&&e("td",{children:N.deadlineAt!==void 0&&e(A,{value:N.deadlineAt,hint:"As requested by the summoner."})}),_&&e("td",{children:N.handle!==void 0&&e("code",{className:"worker-target-file",children:u(N.handle)})})]},w))})]}),C>0&&t("p",{className:"muted","data-testid":"worker-summon-others",children:[h(C,"other instance")," of this key"," ",C===1?"reports":"report"," no summon."]})]})})}var Ze=5,Xe="This worker predates target reporting, so it does not say where its attempts run.";function ke({testId:g}){return e("span",{className:"muted",title:"Not reported: this worker predates target reporting.","data-testid":g,children:"—"})}function et({target:g}){if(g===void 0)return e(F,{items:[{label:"Runs in",value:e(ke,{testId:"worker-target-kind"}),hint:e("span",{"data-testid":"worker-target-predates",children:Xe})}]});return e(F,{items:[{label:"Runs in",value:e("span",{"data-testid":"worker-target-kind",children:Jn(g.kind)}),hint:Hn(g.kind)},{label:"Processor",value:e("span",{"data-testid":"worker-target-processor",children:Sr(g.processor)})},g.name!==void 0&&{label:"Name",value:e("code",{"data-testid":"worker-target-name",children:u(g.name)})},g.file!==void 0&&{label:"File",value:e("code",{className:"worker-target-file","data-testid":"worker-target-file",children:u(g.file)})}]})}function tt({ids:g}){let b=g.slice(0,Ze),v=g.length-b.length;return t(n,{children:[h(g.length,"instance"),":"," ",b.map((C,T)=>t("span",{children:[T>0&&", ",e("code",{children:C})]},C)),v>0&&` and ${h(v,"more","more")}`]})}function rt({workerKey:g,groups:b}){let v=b.some((T)=>T.target?.name!==void 0),C=b.some((T)=>T.target?.file!==void 0);return t(n,{children:[e("p",{className:"notice",role:"note","data-testid":"worker-target-differs",children:"Not every instance of this key runs the same way: a redeploy is still rolling out, or the instances were built from different code. Each row is one way, with the instances that report it."}),t(I,{label:`Targets of ${g}`,children:[e("thead",{children:t("tr",{children:[e("th",{scope:"col",children:"Runs in"}),e("th",{scope:"col",children:"Processor"}),v&&e("th",{scope:"col",children:"Name"}),C&&e("th",{scope:"col",children:"File"}),e("th",{scope:"col",children:"Instances"})]})}),e("tbody",{children:b.map(({target:T,ids:x})=>t("tr",{"data-testid":"worker-target-group",children:[e("th",{scope:"row",title:T===void 0?void 0:Hn(T.kind),children:T===void 0?e(ke,{}):Jn(T.kind)}),e("td",{children:T===void 0?e(ke,{}):Sr(T.processor)}),v&&e("td",{children:T?.name!==void 0&&e("code",{children:u(T.name)})}),C&&e("td",{children:T?.file!==void 0&&e("code",{className:"worker-target-file",children:u(T.file)})}),e("td",{children:e(tt,{ids:x})})]},x[0]))})]})]})}function Ae({workerKey:g,instances:b}){let v=Do(b);return e(R,{title:"Target",children:e("div",{"data-testid":"worker-target",children:v.length===0?e("p",{className:"muted",children:"Where this key's attempts run is known once an instance reports."}):t(n,{children:[e("p",{className:"muted worker-target-note",children:Ro}),v.length===1?e(et,{target:v[0].target}):e(rt,{workerKey:g,groups:v})]})})})}var ot=10;function nt(g){return g!==void 0&&Object.values(g.values).some((b)=>b!==void 0)?g:null}function dt(){let{queue:g="",key:b=""}=de(),v=i(),C=y("workers.list"),T=Fe()("queues.list"),x=Fn();fn(g,y("queues.read")&&C);let K=a({queryKey:_e.ofKey(g,b),queryFn:({signal:j})=>hn(v,{queue:[g],key:[b],includeOffline:!0},j),refetchInterval:x,enabled:C});if(!C)return t("div",{className:"screen",children:[e("h1",{className:"screen-title",children:b}),e(d,{title:"Instances hidden",description:"You may not list workers on this queue, so its instances and configuration are not shown."}),e(ce,{queue:g,workerKey:b}),e(he,{queue:g,workerKey:b})]});let P=K.data?.items??[],q=K.data?.offline,_=q===void 0?void 0:nt(q.find((j)=>j.queue===g&&j.key===b)),w=P.find((j)=>j.service!==void 0)?.service,N=P.some((j)=>j.host!==void 0||j.pid!==void 0);return t("div",{className:"screen","data-testid":"worker-screen",children:[t("div",{className:"worker-header",children:[t("h1",{className:"screen-title",children:[e("span",{className:"visually-hidden",children:"Worker "}),b]}),e(F,{className:"worker-header-facts",items:[{label:"Queue",value:T?e(E,{to:Ve(g),children:g}):g},{label:"Service",value:P.length===0?null:w??e("span",{className:"muted",children:"None named"}),hint:P.length===0?"Known once an instance reports.":void 0}]})]}),K.isPending?e(p,{label:"Loading this worker",showLabel:!0}):K.isError?e(L,{error:K.error,title:"Could not load this worker",onRetry:()=>void K.refetch()}):t(n,{children:[e(R,{title:"Instances",actions:e("span",{className:"muted",children:h(P.length,"live instance")}),children:e("div",{"data-testid":"worker-instances",children:P.length===0?e(d,{title:"No live instance",description:"No worker carrying this key is reporting now. One appears here when a process starts it; a stopped worker that lapsed is not listed."}):e(Dt,{workers:P,label:`Instances of ${b}`,showQueue:!1,showHost:N,showMemory:!0,pageSize:ot})})}),e(Ae,{workerKey:b,instances:P}),e(Re,{workerKey:b,instances:P}),e(Ne,{queue:g,workerKey:b,instances:P,stored:_})]}),e(ce,{queue:g,workerKey:b}),e(he,{queue:g,workerKey:b})]})}var ge=["queue","service","host","state"];function lt(g){return Tn.includes(g)}function Ee(g){let b=g.get("state")?.trim()??"";return{queue:g.get("queue")?.trim()??"",service:g.get("service")?.trim()??"",host:g.get("host")?.trim()??"",state:lt(b)?b:""}}function Pe(g){return ge.some((b)=>g[b]!=="")}function Ie(g,b){let v={};if(g.queue)v.queue=[g.queue];if(g.service)v.service=[g.service];if(g.host&&b)v.host=[g.host];if(g.state)v.state=[g.state];return v}var ct=25;function mt(g){if(g.host===null&&g.pid===null)return"Hosts hidden by the API";return`${g.host??"unknown host"} · pid ${g.pid??"?"}`}function ut({server:g,linkQueues:b,linkKeys:v}){let C=mt(g);return t("section",{className:"worker-server","data-testid":`worker-server-${g.key}`,children:[t("h3",{className:"worker-server-title",children:[C," ",e("span",{className:"muted",children:h(g.workers.length,"worker")})]}),e(Dt,{workers:g.workers,label:`Workers on ${C}`,linkQueues:b,linkKeys:v,showMemory:!0,pageSize:ct})]})}function pt({group:g,linkQueues:b,linkKeys:v}){return e(R,{title:g.service??"No service named",actions:e("span",{className:"muted",children:h(g.count,"worker")}),children:t("div",{"data-testid":`worker-service-${g.service??"none"}`,children:[g.service===null&&t("p",{className:"muted worker-service-note",children:["These processes set no ",e("code",{children:"service"})," on their BunJobs context, so they are grouped by host and pid alone."]}),g.servers.map((C)=>e(ut,{server:C,linkQueues:b,linkKeys:v},C.key))]})})}var ft={running:"Running",paused:"Paused",stopping:"Stopping",stopped:"Stopped",restarting:"Restarting"};function re({label:g,any:b,value:v,choices:C,onChange:T,labelOf:x}){let K=v!==""&&!C.includes(v)?[v,...C]:C;return e(l,{label:g,children:e(S,{options:[{value:"",label:b},...K.map((P)=>({value:P,label:x?x(P):P}))],value:v,onChange:T})})}function ht(){let g=i(),b=y("workers.list"),v=y("queues.list"),C=Oe(),[T,x]=W(),K=c(),P=T.get("search")??"",q=Me(P),_=Ee(T),w=Fn();No(b);let N=a({queryKey:_e.list(),queryFn:({signal:M})=>hn(g,{},M),refetchInterval:w,enabled:b}),j=N.isSuccess?To(N.data.items)??!1:N.isError,B=N.isSuccess||N.isError,J=Ie(_,j),V=a({queryKey:_e.list(J),queryFn:({signal:M})=>hn(g,J,M),refetchInterval:w,enabled:b&&(_.host===""||B)});if(!b)return t("div",{className:"screen",children:[e("h1",{className:"screen-title",children:"Workers"}),e(d,{title:"Nothing to show",description:"You may not list workers on this API."})]});let U=N.data?.items??[],ye=Pe(_),X=V.data?.items??[],oe=X.filter((M)=>So(M,q)),se=vo(oe),Le=se.reduce((M,le)=>M+le.servers.length,0),ae=N.data?U.length:X.length,te=(M)=>(le)=>x({[M]:le}),be=()=>x(Object.fromEntries(ge.map((M)=>[M,null])));return t("div",{className:"screen","data-testid":"workers-list",children:[e("h1",{className:"screen-title",children:"Workers"}),t("div",{className:"worker-filters",role:"search","aria-label":"Filter workers","data-testid":"worker-filters",children:[t("div",{className:"search",children:[e("label",{htmlFor:K,className:"visually-hidden",children:"Filter workers by id, queue or host"}),e("input",{id:K,type:"search",className:"input",placeholder:"Filter workers",...ve,value:P,maxLength:200,onChange:(M)=>x({search:M.target.value})})]}),e(re,{label:"Queue",any:"Any queue",value:_.queue,choices:Gn(U,"queue"),onChange:te("queue")}),e(re,{label:"Service",any:"Any service",value:_.service,choices:Gn(U,"service"),onChange:te("service")}),j&&e(re,{label:"Host",any:"Any host",value:_.host,choices:Gn(U,"host"),onChange:te("host")}),e(re,{label:"State",any:"Any state",value:_.state,choices:Tn,onChange:te("state"),labelOf:(M)=>ft[M]}),ye&&e(s,{size:"sm",onClick:be,children:"Clear filters"})]}),_.host!==""&&B&&!j&&t("p",{className:"notice",role:"note","data-testid":"workers-host-ignored",children:["This API hides worker hosts, so the host filter in this link (",e("code",{children:_.host}),") is ignored."]}),V.isPending?e(p,{label:"Loading workers",showLabel:!0}):V.isError?e(L,{error:V.error,title:"Could not load workers",onRetry:()=>void V.refetch()}):X.length===0&&(!ye||ae===0)?e(d,{title:"No live workers",description:"Workers appear here once a process runs one and it reports."}):X.length===0?e(d,{title:"No workers match these filters",description:"No live worker has every value chosen above.",action:e(s,{size:"sm",onClick:be,children:"Clear filters"})}):se.length===0?e(d,{title:"No workers match",description:`No worker id, queue or host contains “${q.trim()}”.`}):t(n,{children:[t("p",{className:"muted","data-testid":"workers-count",children:[h(oe.length,"worker")," on ",h(Le,"server"),oe.length<ae&&` (of ${ae})`]}),se.map((M)=>e(pt,{group:M,linkQueues:v,linkKeys:C},M.service??""))]})]})}export{dt as WorkerScreen,ht as WorkersListScreen};
2
+
3
+ //# debugId=AC0C8BC200BBDE9064756E2164756E21
4
+ //# sourceMappingURL=index-5c933424.js.map