@dudousxd/nestjs-telescope-ui 1.0.0

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 (179) hide show
  1. package/CHANGELOG.md +349 -0
  2. package/LICENSE +21 -0
  3. package/README.md +51 -0
  4. package/dist/client/index.d.ts +4 -0
  5. package/dist/client/index.d.ts.map +1 -0
  6. package/dist/client/index.js +2 -0
  7. package/dist/client/index.js.map +1 -0
  8. package/dist/client/telescope-client.d.ts +63 -0
  9. package/dist/client/telescope-client.d.ts.map +1 -0
  10. package/dist/client/telescope-client.js +87 -0
  11. package/dist/client/telescope-client.js.map +1 -0
  12. package/dist/client/types.d.ts +267 -0
  13. package/dist/client/types.d.ts.map +1 -0
  14. package/dist/client/types.js +2 -0
  15. package/dist/client/types.js.map +1 -0
  16. package/dist/react/components/batch-timeline.d.ts +7 -0
  17. package/dist/react/components/batch-timeline.d.ts.map +1 -0
  18. package/dist/react/components/batch-timeline.js +10 -0
  19. package/dist/react/components/batch-timeline.js.map +1 -0
  20. package/dist/react/components/cache-badge.d.ts +20 -0
  21. package/dist/react/components/cache-badge.d.ts.map +1 -0
  22. package/dist/react/components/cache-badge.js +42 -0
  23. package/dist/react/components/cache-badge.js.map +1 -0
  24. package/dist/react/components/charts/area-chart-card.d.ts +16 -0
  25. package/dist/react/components/charts/area-chart-card.d.ts.map +1 -0
  26. package/dist/react/components/charts/area-chart-card.js +12 -0
  27. package/dist/react/components/charts/area-chart-card.js.map +1 -0
  28. package/dist/react/components/charts/bar-chart-card.d.ts +26 -0
  29. package/dist/react/components/charts/bar-chart-card.d.ts.map +1 -0
  30. package/dist/react/components/charts/bar-chart-card.js +27 -0
  31. package/dist/react/components/charts/bar-chart-card.js.map +1 -0
  32. package/dist/react/components/charts/chart-card.d.ts +11 -0
  33. package/dist/react/components/charts/chart-card.d.ts.map +1 -0
  34. package/dist/react/components/charts/chart-card.js +9 -0
  35. package/dist/react/components/charts/chart-card.js.map +1 -0
  36. package/dist/react/components/charts/chart-theme.d.ts +41 -0
  37. package/dist/react/components/charts/chart-theme.d.ts.map +1 -0
  38. package/dist/react/components/charts/chart-theme.js +53 -0
  39. package/dist/react/components/charts/chart-theme.js.map +1 -0
  40. package/dist/react/components/charts/index.d.ts +6 -0
  41. package/dist/react/components/charts/index.d.ts.map +1 -0
  42. package/dist/react/components/charts/index.js +6 -0
  43. package/dist/react/components/charts/index.js.map +1 -0
  44. package/dist/react/components/charts/stacked-area-chart-card.d.ts +14 -0
  45. package/dist/react/components/charts/stacked-area-chart-card.d.ts.map +1 -0
  46. package/dist/react/components/charts/stacked-area-chart-card.js +13 -0
  47. package/dist/react/components/charts/stacked-area-chart-card.js.map +1 -0
  48. package/dist/react/components/entries-table.d.ts +11 -0
  49. package/dist/react/components/entries-table.d.ts.map +1 -0
  50. package/dist/react/components/entries-table.js +68 -0
  51. package/dist/react/components/entries-table.js.map +1 -0
  52. package/dist/react/components/entry-detail.d.ts +6 -0
  53. package/dist/react/components/entry-detail.d.ts.map +1 -0
  54. package/dist/react/components/entry-detail.js +110 -0
  55. package/dist/react/components/entry-detail.js.map +1 -0
  56. package/dist/react/components/entry-insights.d.ts +5 -0
  57. package/dist/react/components/entry-insights.d.ts.map +1 -0
  58. package/dist/react/components/entry-insights.js +107 -0
  59. package/dist/react/components/entry-insights.js.map +1 -0
  60. package/dist/react/components/entry-types.d.ts +40 -0
  61. package/dist/react/components/entry-types.d.ts.map +1 -0
  62. package/dist/react/components/entry-types.js +44 -0
  63. package/dist/react/components/entry-types.js.map +1 -0
  64. package/dist/react/components/export-json-toolbar.d.ts +9 -0
  65. package/dist/react/components/export-json-toolbar.d.ts.map +1 -0
  66. package/dist/react/components/export-json-toolbar.js +21 -0
  67. package/dist/react/components/export-json-toolbar.js.map +1 -0
  68. package/dist/react/components/export-json.d.ts +14 -0
  69. package/dist/react/components/export-json.d.ts.map +1 -0
  70. package/dist/react/components/export-json.js +44 -0
  71. package/dist/react/components/export-json.js.map +1 -0
  72. package/dist/react/components/pulse-panel.d.ts +9 -0
  73. package/dist/react/components/pulse-panel.d.ts.map +1 -0
  74. package/dist/react/components/pulse-panel.js +20 -0
  75. package/dist/react/components/pulse-panel.js.map +1 -0
  76. package/dist/react/components/queue-sparkline.d.ts +5 -0
  77. package/dist/react/components/queue-sparkline.d.ts.map +1 -0
  78. package/dist/react/components/queue-sparkline.js +8 -0
  79. package/dist/react/components/queue-sparkline.js.map +1 -0
  80. package/dist/react/components/queues/EnqueueJobForm.d.ts +14 -0
  81. package/dist/react/components/queues/EnqueueJobForm.d.ts.map +1 -0
  82. package/dist/react/components/queues/EnqueueJobForm.js +61 -0
  83. package/dist/react/components/queues/EnqueueJobForm.js.map +1 -0
  84. package/dist/react/components/queues/JobActions.d.ts +38 -0
  85. package/dist/react/components/queues/JobActions.d.ts.map +1 -0
  86. package/dist/react/components/queues/JobActions.js +106 -0
  87. package/dist/react/components/queues/JobActions.js.map +1 -0
  88. package/dist/react/components/queues/JobDetailDrawer.d.ts +11 -0
  89. package/dist/react/components/queues/JobDetailDrawer.d.ts.map +1 -0
  90. package/dist/react/components/queues/JobDetailDrawer.js +45 -0
  91. package/dist/react/components/queues/JobDetailDrawer.js.map +1 -0
  92. package/dist/react/components/queues/JobTable.d.ts +13 -0
  93. package/dist/react/components/queues/JobTable.d.ts.map +1 -0
  94. package/dist/react/components/queues/JobTable.js +0 -0
  95. package/dist/react/components/queues/JobTable.js.map +1 -0
  96. package/dist/react/components/queues/QueueList.d.ts +8 -0
  97. package/dist/react/components/queues/QueueList.d.ts.map +1 -0
  98. package/dist/react/components/queues/QueueList.js +27 -0
  99. package/dist/react/components/queues/QueueList.js.map +1 -0
  100. package/dist/react/components/queues/QueueStateTabs.d.ts +7 -0
  101. package/dist/react/components/queues/QueueStateTabs.d.ts.map +1 -0
  102. package/dist/react/components/queues/QueueStateTabs.js +12 -0
  103. package/dist/react/components/queues/QueueStateTabs.js.map +1 -0
  104. package/dist/react/components/queues/index.d.ts +8 -0
  105. package/dist/react/components/queues/index.d.ts.map +1 -0
  106. package/dist/react/components/queues/index.js +8 -0
  107. package/dist/react/components/queues/index.js.map +1 -0
  108. package/dist/react/components/queues/queue-format.d.ts +8 -0
  109. package/dist/react/components/queues/queue-format.d.ts.map +1 -0
  110. package/dist/react/components/queues/queue-format.js +51 -0
  111. package/dist/react/components/queues/queue-format.js.map +1 -0
  112. package/dist/react/components/queues-panel.d.ts +6 -0
  113. package/dist/react/components/queues-panel.d.ts.map +1 -0
  114. package/dist/react/components/queues-panel.js +8 -0
  115. package/dist/react/components/queues-panel.js.map +1 -0
  116. package/dist/react/components/request-timeline.d.ts +14 -0
  117. package/dist/react/components/request-timeline.d.ts.map +1 -0
  118. package/dist/react/components/request-timeline.js +30 -0
  119. package/dist/react/components/request-timeline.js.map +1 -0
  120. package/dist/react/components/retention-indicator.d.ts +10 -0
  121. package/dist/react/components/retention-indicator.d.ts.map +1 -0
  122. package/dist/react/components/retention-indicator.js +38 -0
  123. package/dist/react/components/retention-indicator.js.map +1 -0
  124. package/dist/react/components/sparkline.d.ts +7 -0
  125. package/dist/react/components/sparkline.d.ts.map +1 -0
  126. package/dist/react/components/sparkline.js +20 -0
  127. package/dist/react/components/sparkline.js.map +1 -0
  128. package/dist/react/components/stacked-bars.d.ts +21 -0
  129. package/dist/react/components/stacked-bars.d.ts.map +1 -0
  130. package/dist/react/components/stacked-bars.js +51 -0
  131. package/dist/react/components/stacked-bars.js.map +1 -0
  132. package/dist/react/components/tag-autocomplete.d.ts +12 -0
  133. package/dist/react/components/tag-autocomplete.d.ts.map +1 -0
  134. package/dist/react/components/tag-autocomplete.js +90 -0
  135. package/dist/react/components/tag-autocomplete.js.map +1 -0
  136. package/dist/react/components/trace-link.d.ts +6 -0
  137. package/dist/react/components/trace-link.d.ts.map +1 -0
  138. package/dist/react/components/trace-link.js +10 -0
  139. package/dist/react/components/trace-link.js.map +1 -0
  140. package/dist/react/components/type-tabs.d.ts +5 -0
  141. package/dist/react/components/type-tabs.d.ts.map +1 -0
  142. package/dist/react/components/type-tabs.js +8 -0
  143. package/dist/react/components/type-tabs.js.map +1 -0
  144. package/dist/react/components/window-select.d.ts +5 -0
  145. package/dist/react/components/window-select.d.ts.map +1 -0
  146. package/dist/react/components/window-select.js +6 -0
  147. package/dist/react/components/window-select.js.map +1 -0
  148. package/dist/react/index.d.ts +23 -0
  149. package/dist/react/index.d.ts.map +1 -0
  150. package/dist/react/index.js +23 -0
  151. package/dist/react/index.js.map +1 -0
  152. package/dist/react/telescope-context.d.ts +14 -0
  153. package/dist/react/telescope-context.d.ts.map +1 -0
  154. package/dist/react/telescope-context.js +27 -0
  155. package/dist/react/telescope-context.js.map +1 -0
  156. package/dist/react/use-telescope-queries.d.ts +244 -0
  157. package/dist/react/use-telescope-queries.d.ts.map +1 -0
  158. package/dist/react/use-telescope-queries.js +216 -0
  159. package/dist/react/use-telescope-queries.js.map +1 -0
  160. package/dist/server/index.d.ts +3 -0
  161. package/dist/server/index.d.ts.map +1 -0
  162. package/dist/server/index.js +2 -0
  163. package/dist/server/index.js.map +1 -0
  164. package/dist/server/telescope-ui.controller.d.ts +10 -0
  165. package/dist/server/telescope-ui.controller.d.ts.map +1 -0
  166. package/dist/server/telescope-ui.controller.js +105 -0
  167. package/dist/server/telescope-ui.controller.js.map +1 -0
  168. package/dist/server/telescope-ui.module.d.ts +6 -0
  169. package/dist/server/telescope-ui.module.d.ts.map +1 -0
  170. package/dist/server/telescope-ui.module.js +26 -0
  171. package/dist/server/telescope-ui.module.js.map +1 -0
  172. package/dist/server/telescope-ui.options.d.ts +12 -0
  173. package/dist/server/telescope-ui.options.d.ts.map +1 -0
  174. package/dist/server/telescope-ui.options.js +2 -0
  175. package/dist/server/telescope-ui.options.js.map +1 -0
  176. package/dist/spa/assets/index-BHS361H_.js +135 -0
  177. package/dist/spa/assets/index-DsBEgxHC.css +1 -0
  178. package/dist/spa/index.html +13 -0
  179. package/package.json +97 -0
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Pure JSON-export helpers shared by the entry-detail and trace export toolbars.
3
+ * Kept framework-free (no React) so they can be unit-tested in isolation.
4
+ */
5
+ /** Pretty-print any value with 2-space indent, falling back to String() if not serializable. */
6
+ export declare function toPrettyJson(value: unknown): string;
7
+ /**
8
+ * Copy a value as pretty JSON to the clipboard. Resolves to `true` on success,
9
+ * `false` when the Clipboard API is unavailable (or the write rejects) — never throws.
10
+ */
11
+ export declare function copyJson(value: unknown): Promise<boolean>;
12
+ /** Trigger a browser download of a value serialized as pretty JSON under `filename`. */
13
+ export declare function downloadJson(filename: string, value: unknown): void;
14
+ //# sourceMappingURL=export-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-json.d.ts","sourceRoot":"","sources":["../../../src/react/components/export-json.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,gGAAgG;AAChG,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMnD;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAU/D;AAED,wFAAwF;AACxF,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAWnE"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Pure JSON-export helpers shared by the entry-detail and trace export toolbars.
3
+ * Kept framework-free (no React) so they can be unit-tested in isolation.
4
+ */
5
+ /** Pretty-print any value with 2-space indent, falling back to String() if not serializable. */
6
+ export function toPrettyJson(value) {
7
+ try {
8
+ return JSON.stringify(value, null, 2) ?? String(value);
9
+ }
10
+ catch {
11
+ return String(value);
12
+ }
13
+ }
14
+ /**
15
+ * Copy a value as pretty JSON to the clipboard. Resolves to `true` on success,
16
+ * `false` when the Clipboard API is unavailable (or the write rejects) — never throws.
17
+ */
18
+ export async function copyJson(value) {
19
+ const text = toPrettyJson(value);
20
+ const clipboard = globalThis.navigator?.clipboard;
21
+ if (!clipboard?.writeText)
22
+ return false;
23
+ try {
24
+ await clipboard.writeText(text);
25
+ return true;
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ }
31
+ /** Trigger a browser download of a value serialized as pretty JSON under `filename`. */
32
+ export function downloadJson(filename, value) {
33
+ const text = toPrettyJson(value);
34
+ const blob = new Blob([text], { type: 'application/json' });
35
+ const url = URL.createObjectURL(blob);
36
+ const anchor = document.createElement('a');
37
+ anchor.href = url;
38
+ anchor.download = filename;
39
+ document.body.appendChild(anchor);
40
+ anchor.click();
41
+ anchor.remove();
42
+ URL.revokeObjectURL(url);
43
+ }
44
+ //# sourceMappingURL=export-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-json.js","sourceRoot":"","sources":["../../../src/react/components/export-json.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,gGAAgG;AAChG,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAc;IAC3C,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC;IAClD,IAAI,CAAC,SAAS,EAAE,SAAS;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,KAAc;IAC3D,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC;IAClB,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,MAAM,CAAC,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { PulseReport } from '../../client/index.js';
2
+ export declare function PulsePanel({ report, onSelectEntry, onSelectFamily, onSelectRoute, onSelectOutgoing, }: {
3
+ report: PulseReport;
4
+ onSelectEntry?: (id: string) => void;
5
+ onSelectFamily?: (familyHash: string) => void;
6
+ onSelectRoute?: (route: string) => void;
7
+ onSelectOutgoing?: (route: string) => void;
8
+ }): JSX.Element;
9
+ //# sourceMappingURL=pulse-panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pulse-panel.d.ts","sourceRoot":"","sources":["../../../src/react/components/pulse-panel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAWzD,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,aAAa,EACb,cAAc,EACd,aAAa,EACb,gBAAgB,GACjB,EAAE;IACD,MAAM,EAAE,WAAW,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C,GAAG,GAAG,CAAC,OAAO,CAmKd"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ function Section({ title, children }) {
3
+ return (_jsxs("section", { className: "mb-6", children: [_jsx("h3", { className: "mb-2 text-xs uppercase tracking-wide text-zinc-500", children: title }), children] }));
4
+ }
5
+ export function PulsePanel({ report, onSelectEntry, onSelectFamily, onSelectRoute, onSelectOutgoing, }) {
6
+ return (_jsxs("div", { className: "text-xs", children: [report.truncated && (_jsxs("p", { className: "mb-4 text-amber-500", children: ["Scan truncated at ", report.scanned, " entries \u2014 widen the window with care."] })), _jsx(Section, { title: "Entries by type", children: _jsxs("div", { className: "flex flex-wrap gap-3", children: [Object.entries(report.counts).map(([type, count]) => (_jsxs("span", { className: "rounded bg-zinc-900 px-2 py-1", children: [_jsx("span", { className: "text-emerald-400", children: type }), ' ', _jsx("span", { className: "text-zinc-300", children: count })] }, type))), Object.keys(report.counts).length === 0 && (_jsx("span", { className: "text-zinc-600", children: "No entries in window." }))] }) }), _jsx(Section, { title: "Slowest", children: _jsx("table", { className: "w-full text-left", children: _jsxs("tbody", { children: [report.slowest.map((slow) => (_jsxs("tr", { tabIndex: 0, onClick: () => onSelectEntry?.(slow.id), onKeyDown: (event) => {
7
+ if (event.key === 'Enter' || event.key === ' ')
8
+ onSelectEntry?.(slow.id);
9
+ }, className: "cursor-pointer border-t border-zinc-900 hover:bg-zinc-900", children: [_jsx("td", { className: "py-1 text-emerald-400", children: slow.type }), _jsx("td", { className: "max-w-md truncate text-zinc-300", children: slow.label }), _jsxs("td", { className: "text-right text-zinc-400", children: [slow.durationMs, "ms"] })] }, slow.id))), report.slowest.length === 0 && (_jsx("tr", { children: _jsx("td", { className: "py-1 text-zinc-600", children: "\u2014" }) }))] }) }) }), _jsx(Section, { title: "Top exceptions", children: _jsx("table", { className: "w-full text-left", children: _jsxs("tbody", { children: [report.topExceptions.map((group) => (_jsxs("tr", { className: "border-t border-zinc-900", children: [_jsx("td", { className: "py-1 text-red-400", children: group.class }), _jsx("td", { className: "max-w-md truncate text-zinc-300", children: group.message }), _jsxs("td", { className: "text-right text-zinc-400", children: ["\u00D7", group.count] })] }, group.familyHash))), report.topExceptions.length === 0 && (_jsx("tr", { children: _jsx("td", { className: "py-1 text-zinc-600", children: "No exceptions \uD83C\uDF89" }) }))] }) }) }), _jsx(Section, { title: "N+1 query hotspots", children: _jsx("table", { className: "w-full text-left", children: _jsxs("tbody", { children: [report.nPlusOne.map((hotspot) => (_jsxs("tr", { tabIndex: 0, onClick: () => onSelectFamily?.(hotspot.familyHash), onKeyDown: (event) => {
10
+ if (event.key === 'Enter' || event.key === ' ')
11
+ onSelectFamily?.(hotspot.familyHash);
12
+ }, className: "cursor-pointer border-t border-zinc-900 hover:bg-zinc-900", children: [_jsxs("td", { className: "whitespace-nowrap py-1 text-amber-400", children: ["\u00D7", hotspot.perRequest, _jsx("span", { className: "text-zinc-500", children: " per request" })] }), _jsx("td", { className: "max-w-md truncate text-zinc-300", children: hotspot.sql }), _jsxs("td", { className: "whitespace-nowrap text-right text-zinc-500", children: [hotspot.requests, " requests \u00B7 ", hotspot.total, " total"] })] }, hotspot.familyHash))), report.nPlusOne.length === 0 && (_jsx("tr", { children: _jsx("td", { className: "py-1 text-zinc-600", children: "None detected" }) }))] }) }) }), _jsx(Section, { title: "Slow request hotspots", children: _jsx("table", { className: "w-full text-left", children: _jsxs("tbody", { children: [report.slowRoutes.map((route) => (_jsxs("tr", { tabIndex: 0, onClick: () => onSelectRoute?.(route.route), onKeyDown: (event) => {
13
+ if (event.key === 'Enter' || event.key === ' ')
14
+ onSelectRoute?.(route.route);
15
+ }, className: "cursor-pointer border-t border-zinc-900 hover:bg-zinc-900", children: [_jsx("td", { className: "max-w-md truncate py-1 font-mono text-zinc-300", children: route.route }), _jsxs("td", { className: "whitespace-nowrap text-right text-amber-400", children: [route.p99, "ms", _jsx("span", { className: "text-zinc-500", children: " p99" })] }), _jsxs("td", { className: "whitespace-nowrap text-right text-zinc-500", children: ["\u00D7", route.count] })] }, route.route))), report.slowRoutes.length === 0 && (_jsx("tr", { children: _jsx("td", { className: "py-1 text-zinc-600", children: "None detected" }) }))] }) }) }), _jsx(Section, { title: "Slow outgoing HTTP", children: _jsx("table", { className: "w-full text-left", children: _jsxs("tbody", { children: [report.slowOutgoing.map((target) => (_jsxs("tr", { tabIndex: 0, onClick: () => onSelectOutgoing?.(target.route), onKeyDown: (event) => {
16
+ if (event.key === 'Enter' || event.key === ' ')
17
+ onSelectOutgoing?.(target.route);
18
+ }, className: "cursor-pointer border-t border-zinc-900 hover:bg-zinc-900", children: [_jsx("td", { className: "max-w-md truncate py-1 font-mono text-zinc-300", children: target.route }), _jsxs("td", { className: "whitespace-nowrap text-right text-amber-400", children: [target.p99, "ms", _jsx("span", { className: "text-zinc-500", children: " p99" })] }), _jsxs("td", { className: "whitespace-nowrap text-right text-zinc-500", children: ["\u00D7", target.count] })] }, target.route))), report.slowOutgoing.length === 0 && (_jsx("tr", { children: _jsx("td", { className: "py-1 text-zinc-600", children: "None detected" }) }))] }) }) })] }));
19
+ }
20
+ //# sourceMappingURL=pulse-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pulse-panel.js","sourceRoot":"","sources":["../../../src/react/components/pulse-panel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function QueueSparkline({ queue, window }: {
2
+ queue: string;
3
+ window: string;
4
+ }): JSX.Element;
5
+ //# sourceMappingURL=queue-sparkline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-sparkline.d.ts","sourceRoot":"","sources":["../../../src/react/components/queue-sparkline.tsx"],"names":[],"mappings":"AAGA,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,GAAG,CAAC,OAAO,CAShG"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useTimeseries } from '../use-telescope-queries.js';
3
+ import { Sparkline } from './sparkline.js';
4
+ export function QueueSparkline({ queue, window }) {
5
+ const { data } = useTimeseries({ window, tag: `queue:${queue}`, buckets: 24 });
6
+ return (_jsx(Sparkline, { values: (data?.buckets ?? []).map((bucket) => bucket.total), width: 120, height: 20 }));
7
+ }
8
+ //# sourceMappingURL=queue-sparkline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-sparkline.js","sourceRoot":"","sources":["../../../src/react/components/queue-sparkline.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,UAAU,cAAc,CAAC,EAAE,KAAK,EAAE,MAAM,EAAqC;IACjF,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;IAC/E,OAAO,CACL,KAAC,SAAS,IACR,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAC3D,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,EAAE,GACV,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { QueueCapabilities } from '../../../client/index.js';
2
+ /**
3
+ * "Send message" form for enqueueing a new job onto the selected queue. Shown
4
+ * only when the driver advertises the `'enqueue'` capability AND mutations are
5
+ * enabled (default-deny gate on the server). The payload is parsed as JSON;
6
+ * invalid JSON surfaces inline without calling the API. A 403 surfaces inline
7
+ * as "Not authorized".
8
+ */
9
+ export declare function EnqueueJobForm({ capabilities, driver, queue, }: {
10
+ capabilities: QueueCapabilities | undefined;
11
+ driver: string;
12
+ queue: string;
13
+ }): JSX.Element | null;
14
+ //# sourceMappingURL=EnqueueJobForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EnqueueJobForm.d.ts","sourceRoot":"","sources":["../../../../src/react/components/queues/EnqueueJobForm.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAmBlE;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAC7B,YAAY,EACZ,MAAM,EACN,KAAK,GACN,EAAE;IACD,YAAY,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAsErB"}
@@ -0,0 +1,61 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { useQueueEnqueue } from '../../use-telescope-queries.js';
4
+ import { supportsAction } from './JobActions.js';
5
+ function isForbidden(error) {
6
+ return error instanceof Error && /\b403\b/.test(error.message);
7
+ }
8
+ /** Parse the JSON payload; returns either the value or a message describing why it failed. */
9
+ function parsePayload(raw) {
10
+ const trimmed = raw.trim();
11
+ if (trimmed === '')
12
+ return { ok: false, message: 'Payload is required.' };
13
+ try {
14
+ return { ok: true, value: JSON.parse(trimmed) };
15
+ }
16
+ catch {
17
+ return { ok: false, message: 'Payload must be valid JSON.' };
18
+ }
19
+ }
20
+ /**
21
+ * "Send message" form for enqueueing a new job onto the selected queue. Shown
22
+ * only when the driver advertises the `'enqueue'` capability AND mutations are
23
+ * enabled (default-deny gate on the server). The payload is parsed as JSON;
24
+ * invalid JSON surfaces inline without calling the API. A 403 surfaces inline
25
+ * as "Not authorized".
26
+ */
27
+ export function EnqueueJobForm({ capabilities, driver, queue, }) {
28
+ const mutation = useQueueEnqueue();
29
+ const [name, setName] = useState('');
30
+ const [payload, setPayload] = useState('');
31
+ const [jsonError, setJsonError] = useState(null);
32
+ const [sentId, setSentId] = useState(undefined);
33
+ if (!supportsAction(capabilities, driver, 'enqueue'))
34
+ return null;
35
+ const forbidden = isForbidden(mutation.error);
36
+ async function submit(event) {
37
+ event.preventDefault();
38
+ setSentId(undefined);
39
+ const parsed = parsePayload(payload);
40
+ if (!parsed.ok) {
41
+ setJsonError(parsed.message);
42
+ return;
43
+ }
44
+ setJsonError(null);
45
+ try {
46
+ const result = await mutation.mutateAsync({
47
+ driver,
48
+ queue,
49
+ ...(name.trim() !== '' ? { name: name.trim() } : {}),
50
+ payload: parsed.value,
51
+ });
52
+ setSentId(result.id);
53
+ setPayload('');
54
+ }
55
+ catch {
56
+ // surfaced inline via mutation.error
57
+ }
58
+ }
59
+ return (_jsxs("form", { onSubmit: submit, className: "space-y-2 rounded-lg border border-zinc-800 p-3", children: [_jsx("h3", { className: "text-[10px] uppercase tracking-wide text-zinc-500", children: "Send message" }), _jsx("input", { type: "text", value: name, onChange: (event) => setName(event.target.value), placeholder: "Job name (optional)", "aria-label": "Job name", className: "w-full rounded border border-zinc-800 bg-zinc-950 px-2 py-1 text-xs text-zinc-200 placeholder:text-zinc-600" }), _jsx("textarea", { value: payload, onChange: (event) => setPayload(event.target.value), placeholder: '{"to": "a@b.c"}', "aria-label": "Payload (JSON)", rows: 4, className: "w-full rounded border border-zinc-800 bg-zinc-950 px-2 py-1 font-mono text-xs text-zinc-200 placeholder:text-zinc-600" }), jsonError && _jsx("p", { className: "text-[10px] text-red-400", children: jsonError }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "submit", disabled: mutation.isPending, className: "rounded border border-emerald-500/40 px-2.5 py-1 text-[11px] text-emerald-300 transition-colors hover:bg-emerald-500/10 disabled:opacity-50", children: mutation.isPending ? 'Sending…' : 'Send message' }), forbidden && _jsx("span", { className: "text-[10px] text-red-400", children: "Not authorized" }), sentId !== undefined && !forbidden && (_jsx("span", { className: "text-[10px] text-emerald-400", children: sentId ? `Enqueued job ${sentId}` : 'Message enqueued' }))] })] }));
60
+ }
61
+ //# sourceMappingURL=EnqueueJobForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EnqueueJobForm.js","sourceRoot":"","sources":["../../../../src/react/components/queues/EnqueueJobForm.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { JobActionName, QueueActionName, QueueCapabilities, QueueState } from '../../../client/index.js';
2
+ /** Does the driver advertise this action AND are mutations enabled at all? */
3
+ export declare function supportsAction(capabilities: QueueCapabilities | undefined, driver: string, action: QueueActionName): boolean;
4
+ /**
5
+ * Which per-job actions are valid for a job in the given state.
6
+ * - promote only for a delayed job
7
+ * - retry only for failed/completed jobs
8
+ * - remove whenever supported
9
+ */
10
+ export declare function jobActionAllowedForState(action: JobActionName, state: QueueState): boolean;
11
+ /** Per-job action buttons, gated by capabilities + job state. */
12
+ export declare function JobActions({ capabilities, driver, queue, id, state, onDone, }: {
13
+ capabilities: QueueCapabilities | undefined;
14
+ driver: string;
15
+ queue: string;
16
+ id: string;
17
+ state: QueueState;
18
+ onDone?: () => void;
19
+ }): JSX.Element | null;
20
+ /** "Retry all failed" bulk action, gated by capabilities; shown on the failed tab. */
21
+ export declare function RetryAllFailedButton({ capabilities, driver, queue, }: {
22
+ capabilities: QueueCapabilities | undefined;
23
+ driver: string;
24
+ queue: string;
25
+ }): JSX.Element | null;
26
+ /**
27
+ * "Redrive DLQ" action for SQS-style drivers (moves dead-lettered messages back
28
+ * to the source queue via the native message-move task). Shown on the failed tab,
29
+ * gated by capabilities — only when the driver advertises `'redrive'` and
30
+ * mutations are enabled. Confirms before firing (it moves messages); a 403
31
+ * surfaces inline as "Not authorized".
32
+ */
33
+ export declare function RedriveDlqButton({ capabilities, driver, queue, }: {
34
+ capabilities: QueueCapabilities | undefined;
35
+ driver: string;
36
+ queue: string;
37
+ }): JSX.Element | null;
38
+ //# sourceMappingURL=JobActions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobActions.d.ts","sourceRoot":"","sources":["../../../../src/react/components/queues/JobActions.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,UAAU,EACX,MAAM,0BAA0B,CAAC;AAGlC,8EAA8E;AAC9E,wBAAgB,cAAc,CAC5B,YAAY,EAAE,iBAAiB,GAAG,SAAS,EAC3C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,eAAe,GACtB,OAAO,CAGT;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAW1F;AA6ED,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,EACzB,YAAY,EACZ,MAAM,EACN,KAAK,EACL,EAAE,EACF,KAAK,EACL,MAAM,GACP,EAAE;IACD,YAAY,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAoBrB;AAED,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,EACnC,YAAY,EACZ,MAAM,EACN,KAAK,GACN,EAAE;IACD,YAAY,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CA0BrB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,YAAY,EACZ,MAAM,EACN,KAAK,GACN,EAAE;IACD,YAAY,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAkDrB"}
@@ -0,0 +1,106 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { useQueueAction, useQueueJobAction } from '../../use-telescope-queries.js';
4
+ /** Does the driver advertise this action AND are mutations enabled at all? */
5
+ export function supportsAction(capabilities, driver, action) {
6
+ if (!capabilities?.mutationsEnabled)
7
+ return false;
8
+ return (capabilities.actionsByDriver[driver] ?? []).includes(action);
9
+ }
10
+ /**
11
+ * Which per-job actions are valid for a job in the given state.
12
+ * - promote only for a delayed job
13
+ * - retry only for failed/completed jobs
14
+ * - remove whenever supported
15
+ */
16
+ export function jobActionAllowedForState(action, state) {
17
+ switch (action) {
18
+ case 'promote':
19
+ return state === 'delayed';
20
+ case 'retry':
21
+ return state === 'failed' || state === 'completed';
22
+ case 'remove':
23
+ return true;
24
+ default:
25
+ return false;
26
+ }
27
+ }
28
+ function isForbidden(error) {
29
+ return error instanceof Error && /\b403\b/.test(error.message);
30
+ }
31
+ const ACTION_STYLE = {
32
+ retry: 'border-emerald-500/40 text-emerald-300 hover:bg-emerald-500/10',
33
+ promote: 'border-amber-500/40 text-amber-300 hover:bg-amber-500/10',
34
+ remove: 'border-red-500/40 text-red-300 hover:bg-red-500/10',
35
+ };
36
+ function JobActionButton({ driver, queue, id, action, onDone, }) {
37
+ const mutation = useQueueJobAction();
38
+ const [confirming, setConfirming] = useState(false);
39
+ const pending = mutation.isPending;
40
+ const forbidden = isForbidden(mutation.error);
41
+ async function fire() {
42
+ setConfirming(false);
43
+ try {
44
+ await mutation.mutateAsync({ driver, queue, id, action });
45
+ onDone?.();
46
+ }
47
+ catch {
48
+ // surfaced inline via mutation.error
49
+ }
50
+ }
51
+ if (action === 'remove' && confirming) {
52
+ return (_jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx("button", { type: "button", disabled: pending, onClick: fire, className: "rounded border border-red-500/50 bg-red-500/10 px-2 py-1 text-[11px] text-red-200 disabled:opacity-50", children: pending ? 'Removing…' : 'Confirm remove' }), _jsx("button", { type: "button", onClick: () => setConfirming(false), className: "rounded border border-zinc-700 px-2 py-1 text-[11px] text-zinc-400 hover:text-zinc-200", children: "Cancel" })] }));
53
+ }
54
+ return (_jsxs("span", { className: "inline-flex flex-col", children: [_jsx("button", { type: "button", disabled: pending, onClick: action === 'remove' ? () => setConfirming(true) : fire, className: `rounded border px-2 py-1 text-[11px] capitalize transition-colors disabled:opacity-50 ${ACTION_STYLE[action]}`, children: pending ? `${action}…` : action }), forbidden && _jsx("span", { className: "mt-0.5 text-[10px] text-red-400", children: "Not authorized" })] }));
55
+ }
56
+ /** Per-job action buttons, gated by capabilities + job state. */
57
+ export function JobActions({ capabilities, driver, queue, id, state, onDone, }) {
58
+ const actions = ['retry', 'promote', 'remove'].filter((action) => supportsAction(capabilities, driver, action) && jobActionAllowedForState(action, state));
59
+ if (actions.length === 0)
60
+ return null;
61
+ return (_jsx("div", { className: "flex flex-wrap items-start gap-1.5", children: actions.map((action) => (_jsx(JobActionButton, { driver: driver, queue: queue, id: id, action: action, onDone: onDone }, action))) }));
62
+ }
63
+ /** "Retry all failed" bulk action, gated by capabilities; shown on the failed tab. */
64
+ export function RetryAllFailedButton({ capabilities, driver, queue, }) {
65
+ const mutation = useQueueAction();
66
+ if (!supportsAction(capabilities, driver, 'retry-all'))
67
+ return null;
68
+ const forbidden = isForbidden(mutation.error);
69
+ async function fire() {
70
+ try {
71
+ await mutation.mutateAsync({ driver, queue, action: 'retry-all', state: 'failed' });
72
+ }
73
+ catch {
74
+ // surfaced inline via mutation.error
75
+ }
76
+ }
77
+ return (_jsxs("span", { className: "inline-flex items-center gap-2", children: [_jsx("button", { type: "button", disabled: mutation.isPending, onClick: fire, className: "rounded border border-emerald-500/40 px-2.5 py-1 text-[11px] text-emerald-300 transition-colors hover:bg-emerald-500/10 disabled:opacity-50", children: mutation.isPending ? 'Retrying all…' : 'Retry all failed' }), forbidden && _jsx("span", { className: "text-[10px] text-red-400", children: "Not authorized" })] }));
78
+ }
79
+ /**
80
+ * "Redrive DLQ" action for SQS-style drivers (moves dead-lettered messages back
81
+ * to the source queue via the native message-move task). Shown on the failed tab,
82
+ * gated by capabilities — only when the driver advertises `'redrive'` and
83
+ * mutations are enabled. Confirms before firing (it moves messages); a 403
84
+ * surfaces inline as "Not authorized".
85
+ */
86
+ export function RedriveDlqButton({ capabilities, driver, queue, }) {
87
+ const mutation = useQueueAction();
88
+ const [confirming, setConfirming] = useState(false);
89
+ if (!supportsAction(capabilities, driver, 'redrive'))
90
+ return null;
91
+ const forbidden = isForbidden(mutation.error);
92
+ async function fire() {
93
+ setConfirming(false);
94
+ try {
95
+ await mutation.mutateAsync({ driver, queue, action: 'redrive' });
96
+ }
97
+ catch {
98
+ // surfaced inline via mutation.error
99
+ }
100
+ }
101
+ if (confirming) {
102
+ return (_jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx("button", { type: "button", disabled: mutation.isPending, onClick: fire, className: "rounded border border-amber-500/50 bg-amber-500/10 px-2.5 py-1 text-[11px] text-amber-200 disabled:opacity-50", children: mutation.isPending ? 'Redriving…' : 'Confirm redrive' }), _jsx("button", { type: "button", onClick: () => setConfirming(false), className: "rounded border border-zinc-700 px-2 py-1 text-[11px] text-zinc-400 hover:text-zinc-200", children: "Cancel" })] }));
103
+ }
104
+ return (_jsxs("span", { className: "inline-flex items-center gap-2", children: [_jsx("button", { type: "button", disabled: mutation.isPending, onClick: () => setConfirming(true), className: "rounded border border-amber-500/40 px-2.5 py-1 text-[11px] text-amber-300 transition-colors hover:bg-amber-500/10 disabled:opacity-50", children: "Redrive DLQ" }), forbidden && _jsx("span", { className: "text-[10px] text-red-400", children: "Not authorized" })] }));
105
+ }
106
+ //# sourceMappingURL=JobActions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobActions.js","sourceRoot":"","sources":["../../../../src/react/components/queues/JobActions.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { QueueCapabilities, QueueState } from '../../../client/index.js';
2
+ /** Right slide-over showing a single job's full detail + actions. */
3
+ export declare function JobDetailDrawer({ driver, queue, jobId, state, capabilities, onClose, }: {
4
+ driver: string;
5
+ queue: string;
6
+ jobId: string;
7
+ state: QueueState;
8
+ capabilities: QueueCapabilities | undefined;
9
+ onClose: () => void;
10
+ }): JSX.Element;
11
+ //# sourceMappingURL=JobDetailDrawer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobDetailDrawer.d.ts","sourceRoot":"","sources":["../../../../src/react/components/queues/JobDetailDrawer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAkB,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAqH9F,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,KAAK,EACL,KAAK,EACL,KAAK,EACL,YAAY,EACZ,OAAO,GACR,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC5C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,GAAG,GAAG,CAAC,OAAO,CAmDd"}
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect } from 'react';
3
+ import { useQueueJob } from '../../use-telescope-queries.js';
4
+ import { JobActions } from './JobActions.js';
5
+ import { relativeTime } from './queue-format.js';
6
+ function prettyJson(value) {
7
+ if (value === undefined)
8
+ return '—';
9
+ try {
10
+ return JSON.stringify(value, null, 2);
11
+ }
12
+ catch {
13
+ return String(value);
14
+ }
15
+ }
16
+ function JsonBlock({ label, value }) {
17
+ return (_jsxs("section", { children: [_jsx("h4", { className: "mb-1 text-[10px] uppercase tracking-wide text-zinc-500", children: label }), _jsx("pre", { className: "overflow-auto rounded bg-zinc-950 p-2.5 text-[11px] leading-relaxed text-zinc-300 ring-1 ring-zinc-800", children: prettyJson(value) })] }));
18
+ }
19
+ function MetaRow({ label, value }) {
20
+ return (_jsxs("div", { className: "flex items-baseline justify-between gap-3 border-t border-zinc-900 py-1 first:border-0", children: [_jsx("span", { className: "text-[10px] uppercase tracking-wide text-zinc-500", children: label }), _jsx("span", { className: "tabular-nums text-zinc-300", children: value })] }));
21
+ }
22
+ function timestampLabel(value) {
23
+ if (value == null)
24
+ return '—';
25
+ return `${new Date(value).toLocaleString()} (${relativeTime(value)})`;
26
+ }
27
+ function DetailBody({ detail, capabilities, driver, queue, state, onClose, }) {
28
+ return (_jsxs("div", { className: "space-y-4", children: [_jsxs("header", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm font-medium text-emerald-400", children: detail.name || 'job' }), _jsx("span", { className: "rounded bg-zinc-800 px-1.5 py-0.5 text-[10px] capitalize text-zinc-300", children: detail.state })] }), _jsx("div", { className: "font-mono text-[11px] text-zinc-500", children: detail.id })] }), _jsx(JobActions, { capabilities: capabilities, driver: driver, queue: queue, id: detail.id, state: state, onDone: onClose }), _jsxs("div", { className: "rounded-lg border border-zinc-800 bg-zinc-900/40 px-3 py-2 text-xs", children: [_jsx(MetaRow, { label: "Attempts", value: detail.maxAttempts != null
29
+ ? `${detail.attemptsMade}/${detail.maxAttempts}`
30
+ : `${detail.attemptsMade}` }), _jsx(MetaRow, { label: "Progress", value: detail.progress != null ? `${detail.progress}` : '—' }), _jsx(MetaRow, { label: "Created", value: timestampLabel(detail.timestamp) }), _jsx(MetaRow, { label: "Processed", value: timestampLabel(detail.processedOn) }), _jsx(MetaRow, { label: "Finished", value: timestampLabel(detail.finishedOn) })] }), detail.failedReason && (_jsxs("section", { children: [_jsx("h4", { className: "mb-1 text-[10px] uppercase tracking-wide text-red-400", children: "Failed reason" }), _jsx("p", { className: "rounded bg-red-500/5 px-2.5 py-2 text-[11px] text-red-300 ring-1 ring-red-500/20", children: detail.failedReason })] })), _jsx(JsonBlock, { label: "Payload (data)", value: detail.data }), _jsx(JsonBlock, { label: "Options (opts)", value: detail.opts }), detail.returnValue !== undefined && detail.returnValue !== null && (_jsx(JsonBlock, { label: "Return value", value: detail.returnValue })), detail.stacktrace && detail.stacktrace.length > 0 && (_jsxs("section", { children: [_jsx("h4", { className: "mb-1 text-[10px] uppercase tracking-wide text-zinc-500", children: "Stacktrace" }), _jsx("pre", { className: "overflow-auto rounded bg-zinc-950 p-2.5 text-[11px] leading-relaxed text-red-300/80 ring-1 ring-zinc-800", children: detail.stacktrace.join('\n') })] }))] }));
31
+ }
32
+ /** Right slide-over showing a single job's full detail + actions. */
33
+ export function JobDetailDrawer({ driver, queue, jobId, state, capabilities, onClose, }) {
34
+ const { data, isLoading, isError } = useQueueJob(driver, queue, jobId);
35
+ useEffect(() => {
36
+ function onKey(event) {
37
+ if (event.key === 'Escape')
38
+ onClose();
39
+ }
40
+ window.addEventListener('keydown', onKey);
41
+ return () => window.removeEventListener('keydown', onKey);
42
+ }, [onClose]);
43
+ return (_jsxs("div", { className: "fixed inset-0 z-40 flex justify-end", children: [_jsx("button", { type: "button", "aria-label": "Close job detail", onClick: onClose, className: "absolute inset-0 bg-black/50" }), _jsxs("aside", { className: "relative z-10 flex h-full w-full max-w-md flex-col border-l border-zinc-800 bg-zinc-950 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-800 px-4 py-2.5", children: [_jsx("span", { className: "text-xs uppercase tracking-wide text-zinc-500", children: "Job detail" }), _jsx("button", { type: "button", onClick: onClose, className: "rounded px-2 py-0.5 text-zinc-500 hover:bg-zinc-900 hover:text-zinc-200", children: "\u2715" })] }), _jsx("div", { className: "flex-1 overflow-auto p-4", children: isLoading ? (_jsx("p", { className: "text-xs text-zinc-600", children: "Loading job\u2026" })) : isError ? (_jsx("p", { className: "text-xs text-red-400", children: "Failed to load job." })) : !data ? (_jsx("p", { className: "text-xs text-zinc-600", children: "Job not found (it may have been removed)." })) : (_jsx(DetailBody, { detail: data, capabilities: capabilities, driver: driver, queue: queue, state: state, onClose: onClose })) })] })] }));
44
+ }
45
+ //# sourceMappingURL=JobDetailDrawer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobDetailDrawer.js","sourceRoot":"","sources":["../../../../src/react/components/queues/JobDetailDrawer.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { QueueState } from '../../../client/index.js';
2
+ /**
3
+ * Job table for the selected queue + state. The active (last-requested) cursor
4
+ * drives the live polling query; "Load more" advances the cursor and the new
5
+ * page is merged into the accumulated list. Switching queue/state resets.
6
+ */
7
+ export declare function JobTable({ driver, queue, state, onOpen, }: {
8
+ driver: string;
9
+ queue: string;
10
+ state: QueueState;
11
+ onOpen: (id: string) => void;
12
+ }): JSX.Element;
13
+ //# sourceMappingURL=JobTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobTable.d.ts","sourceRoot":"","sources":["../../../../src/react/components/queues/JobTable.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAY,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAgDrE;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,EACvB,MAAM,EACN,KAAK,EACL,KAAK,EACL,MAAM,GACP,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B,GAAG,GAAG,CAAC,OAAO,CA6Ed"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobTable.js","sourceRoot":"","sources":["../../../../src/react/components/queues/JobTable.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare function QueueList({ selected, onSelect, }: {
2
+ selected?: {
3
+ driver: string;
4
+ queue: string;
5
+ };
6
+ onSelect: (driver: string, queue: string) => void;
7
+ }): JSX.Element;
8
+ //# sourceMappingURL=QueueList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueueList.d.ts","sourceRoot":"","sources":["../../../../src/react/components/queues/QueueList.tsx"],"names":[],"mappings":"AAkEA,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EACR,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnD,GAAG,GAAG,CAAC,OAAO,CA8Bd"}
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useLiveQueues } from '../../use-telescope-queries.js';
3
+ import { QUEUE_STATE_ORDER, STATE_ACCENT } from './queue-format.js';
4
+ function CountBadge({ state, value, }) {
5
+ const emphasize = state === 'failed' && value > 0;
6
+ return (_jsxs("span", { className: `flex items-baseline gap-1 rounded px-1.5 py-0.5 ${emphasize ? 'bg-red-500/10' : 'bg-zinc-800/60'}`, title: `${value} ${state}`, children: [_jsx("span", { className: "text-[9px] uppercase tracking-wide text-zinc-500", children: state.slice(0, 4) }), _jsx("span", { className: `tabular-nums ${value > 0 ? STATE_ACCENT[state] : 'text-zinc-600'}`, children: value })] }));
7
+ }
8
+ function QueueRow({ summary, active, onSelect, }) {
9
+ return (_jsxs("button", { type: "button", onClick: () => onSelect(summary.driver, summary.queue), className: `w-full rounded-lg border px-3 py-2.5 text-left transition-colors ${active
10
+ ? 'border-emerald-500/40 bg-emerald-500/5'
11
+ : 'border-zinc-800 bg-zinc-900/40 hover:border-zinc-700 hover:bg-zinc-900'}`, children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("span", { className: "min-w-0 truncate font-medium text-zinc-100", children: summary.queue }), summary.isPaused && (_jsx("span", { className: "shrink-0 rounded bg-violet-500/15 px-1.5 py-0.5 text-[9px] uppercase tracking-wide text-violet-300", children: "paused" }))] }), _jsx("div", { className: "mt-0.5 text-[10px] uppercase tracking-wide text-zinc-600", children: summary.driver }), _jsx("div", { className: "mt-2 flex flex-wrap gap-1 text-[10px]", children: QUEUE_STATE_ORDER.map((state) => (_jsx(CountBadge, { state: state, value: summary.counts[state] }, state))) })] }));
12
+ }
13
+ export function QueueList({ selected, onSelect, }) {
14
+ const { data, isLoading, isError } = useLiveQueues();
15
+ if (isLoading) {
16
+ return _jsx("p", { className: "px-1 py-2 text-xs text-zinc-600", children: "Loading queues\u2026" });
17
+ }
18
+ if (isError) {
19
+ return _jsx("p", { className: "px-1 py-2 text-xs text-red-400", children: "Failed to load queues." });
20
+ }
21
+ const queues = data?.queues ?? [];
22
+ if (queues.length === 0) {
23
+ return (_jsx("div", { className: "rounded-lg border border-dashed border-zinc-800 px-3 py-6 text-center text-xs text-zinc-600", children: "No live queues detected." }));
24
+ }
25
+ return (_jsx("div", { className: "space-y-2", children: queues.map((summary) => (_jsx(QueueRow, { summary: summary, active: selected?.driver === summary.driver && selected?.queue === summary.queue, onSelect: onSelect }, `${summary.driver}:${summary.queue}`))) }));
26
+ }
27
+ //# sourceMappingURL=QueueList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueueList.js","sourceRoot":"","sources":["../../../../src/react/components/queues/QueueList.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEpE,SAAS,UAAU,CAAC,EAClB,KAAK,EACL,KAAK,GAIN;IACC,MAAM,SAAS,GAAG,KAAK,KAAK,QAAQ,IAAI,KAAK,GAAG,CAAC,CAAC;IAClD,OAAO,CACL,gBACE,SAAS,EAAE,mDACT,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,gBAChC,EAAE,EACF,KAAK,EAAE,GAAG,KAAK,IAAI,KAAK,EAAE,aAE1B,eAAM,SAAS,EAAC,kDAAkD,YAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAQ,EAC7F,eAAM,SAAS,EAAE,gBAAgB,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,EAAE,YACjF,KAAK,GACD,IACF,CACR,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,EAChB,OAAO,EACP,MAAM,EACN,QAAQ,GAKT;IACC,OAAO,CACL,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,EACtD,SAAS,EAAE,oEACT,MAAM;YACJ,CAAC,CAAC,wCAAwC;YAC1C,CAAC,CAAC,wEACN,EAAE,aAEF,eAAK,SAAS,EAAC,yCAAyC,aACtD,eAAM,SAAS,EAAC,4CAA4C,YAAE,OAAO,CAAC,KAAK,GAAQ,EAClF,OAAO,CAAC,QAAQ,IAAI,CACnB,eAAM,SAAS,EAAC,oGAAoG,uBAE7G,CACR,IACG,EACN,cAAK,SAAS,EAAC,0DAA0D,YACtE,OAAO,CAAC,MAAM,GACX,EACN,cAAK,SAAS,EAAC,uCAAuC,YACnD,iBAAiB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAChC,KAAC,UAAU,IAAa,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAjD,KAAK,CAAgD,CACvE,CAAC,GACE,IACC,CACV,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EACxB,QAAQ,EACR,QAAQ,GAIT;IACC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;IAErD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,YAAG,SAAS,EAAC,iCAAiC,qCAAoB,CAAC;IAC5E,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,YAAG,SAAS,EAAC,gCAAgC,uCAA2B,CAAC;IAClF,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC;IAClC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CACL,cAAK,SAAS,EAAC,6FAA6F,yCAEtG,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,cAAK,SAAS,EAAC,WAAW,YACvB,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CACvB,KAAC,QAAQ,IAEP,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,IAAI,QAAQ,EAAE,KAAK,KAAK,OAAO,CAAC,KAAK,EAChF,QAAQ,EAAE,QAAQ,IAHb,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,KAAK,EAAE,CAIzC,CACH,CAAC,GACE,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { QueueCounts, QueueState } from '../../../client/index.js';
2
+ export declare function QueueStateTabs({ counts, state, onState, }: {
3
+ counts: QueueCounts | undefined;
4
+ state: QueueState;
5
+ onState: (state: QueueState) => void;
6
+ }): JSX.Element;
7
+ //# sourceMappingURL=QueueStateTabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueueStateTabs.d.ts","sourceRoot":"","sources":["../../../../src/react/components/queues/QueueStateTabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGxE,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,KAAK,EACL,OAAO,GACR,EAAE;IACD,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;IAChC,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACtC,GAAG,GAAG,CAAC,OAAO,CA8Bd"}
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { QUEUE_STATE_ORDER, STATE_ACCENT } from './queue-format.js';
3
+ export function QueueStateTabs({ counts, state, onState, }) {
4
+ return (_jsx("div", { className: "flex flex-wrap gap-1 border-b border-zinc-800 pb-2", children: QUEUE_STATE_ORDER.map((candidate) => {
5
+ const active = candidate === state;
6
+ const value = counts?.[candidate] ?? 0;
7
+ return (_jsxs("button", { type: "button", onClick: () => onState(candidate), className: `flex items-baseline gap-1.5 rounded-md px-2.5 py-1 text-xs transition-colors ${active
8
+ ? 'bg-zinc-800 text-zinc-100'
9
+ : 'text-zinc-500 hover:bg-zinc-900 hover:text-zinc-300'}`, children: [_jsx("span", { className: "capitalize", children: candidate }), _jsx("span", { className: `tabular-nums text-[11px] ${active ? STATE_ACCENT[candidate] : 'text-zinc-600'}`, children: value })] }, candidate));
10
+ }) }));
11
+ }
12
+ //# sourceMappingURL=QueueStateTabs.js.map