@apisurf/wireui 0.1.2 → 0.1.3

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 (51) hide show
  1. package/README.md +42 -26
  2. package/bin/wireui.mjs +1 -1
  3. package/dist/nitro.json +1 -1
  4. package/dist/public/assets/environments-299O-03t.js +1 -0
  5. package/dist/public/assets/feed-B8L4GK9D.js +1 -0
  6. package/dist/public/assets/globals-k1eOASJT.css +1 -0
  7. package/dist/public/assets/history-EqPRzguE.js +1 -0
  8. package/dist/public/assets/index-D3MuiLlr.js +11 -0
  9. package/dist/public/assets/kv-table-Dv6o68aD.js +2 -0
  10. package/dist/public/assets/preload-helper-CIs162tl.js +3 -0
  11. package/dist/public/assets/query-DE41dcUO.js +19 -0
  12. package/dist/public/assets/requests._requestId-DSbe2mSh.js +1 -0
  13. package/dist/public/assets/rolldown-runtime-CbXtAM7H.js +1 -0
  14. package/dist/public/assets/routes-CRl6TZP9.js +1 -0
  15. package/dist/public/assets/runs._runId-BGRrB0cL.js +1 -0
  16. package/dist/public/assets/scoped-DoOxDjHI.js +1 -0
  17. package/dist/public/assets/session-header-wONyPgx_.js +1 -0
  18. package/dist/public/assets/sessions-CqjoUG4A.js +1 -0
  19. package/dist/public/assets/split-Ddiw3mOT.js +1 -0
  20. package/dist/public/assets/tabs-C1EijW_Z.js +2 -0
  21. package/dist/server/_ssr/{api-Dw1Zb_PK.mjs → api-DUem3i24.mjs} +28 -17
  22. package/dist/server/_ssr/environments-BFBtf7iL.mjs +146 -0
  23. package/dist/server/_ssr/feed-BgweoqQ4.mjs +108 -0
  24. package/dist/server/_ssr/history-CbfbTHg9.mjs +195 -0
  25. package/dist/server/_ssr/{kv-table-DQUkoItO.mjs → kv-table-BONnSOLb.mjs} +2 -2
  26. package/dist/server/_ssr/{router-CPcgc_kh.mjs → prefs-iPvYd_Vz.mjs} +246 -1551
  27. package/dist/server/_ssr/{query-D4so9xiY.mjs → query-DBNlR5hk.mjs} +7 -6
  28. package/dist/server/_ssr/{requests._requestId-BFukRwqL.mjs → requests._requestId-DX2svRx4.mjs} +7 -23
  29. package/dist/server/_ssr/router-BpH2DFcQ.mjs +1068 -0
  30. package/dist/server/_ssr/{routes-DaV9vGHn.mjs → routes-DGIQrvhg.mjs} +18 -8
  31. package/dist/server/_ssr/runs._runId-DZ-DQirQ.mjs +850 -0
  32. package/dist/server/_ssr/{scoped-CnQ56K8h.mjs → scoped-CNX8KOhL.mjs} +2 -2
  33. package/dist/server/_ssr/session-header-CH-Pbd1E.mjs +153 -0
  34. package/dist/server/_ssr/{collections-CqidTQpw.mjs → sessions-D3LBcKOI.mjs} +35 -72
  35. package/dist/server/_ssr/{split-DWrMIs7K.mjs → split-qGbYHKc9.mjs} +2 -2
  36. package/dist/server/_ssr/ssr.mjs +10 -14
  37. package/dist/server/_tanstack-start-manifest_v-B2rWFyf7.mjs +79 -0
  38. package/dist/server/index.mjs +100 -51
  39. package/package.json +3 -3
  40. package/dist/public/assets/collections-CLHcfRfi.js +0 -1
  41. package/dist/public/assets/globals-CZiNFGaK.css +0 -1
  42. package/dist/public/assets/index-D5VFd_3H.js +0 -14
  43. package/dist/public/assets/kv-table-oB5gcq0i.js +0 -2
  44. package/dist/public/assets/query-BKAhHNIi.js +0 -19
  45. package/dist/public/assets/requests._requestId-Bu7E2eoI.js +0 -1
  46. package/dist/public/assets/routes-DDY2CfzA.js +0 -1
  47. package/dist/public/assets/runs._runId-CzwtVjYq.js +0 -1
  48. package/dist/public/assets/scoped-DB8raIWx.js +0 -1
  49. package/dist/public/assets/split-Br1RX2I4.js +0 -1
  50. package/dist/server/_ssr/runs._runId-Df_LmPHa.mjs +0 -836
  51. package/dist/server/_tanstack-start-manifest_v-CARKjHfs.mjs +0 -50
@@ -1,836 +0,0 @@
1
- import { __toESM } from "../_runtime.mjs";
2
- import { Link, require_jsx_runtime, require_react, useNavigate } from "../_libs/@tanstack/react-router+[...].mjs";
3
- import { Callout, Card, Dot, Empty, FilterInput, IconAlert, IconButton, IconCheckCircle, IconChevronLeft, IconChevronRight, IconCollections, IconXCircle, MethodBadge, Pill, Route, SectionTitle, Segmented, Stat, StatGrid, StatusBadge, TabList, css, cx, formatBytes, formatCount, formatDateTime, formatMs, formatOffset, isFailure, mono, pagePad, plural, runTone, runVerdict, scrollPane, statusTone, tabKey, table, toneText, truncate, useNow, useTab, useUnreadable } from "./router-CPcgc_kh.mjs";
4
- import { Code, KvTable } from "./kv-table-DQUkoItO.mjs";
5
- //#region node_modules/.nitro/vite/services/ssr/assets/runs._runId-Df_LmPHa.js
6
- var import_react = /* @__PURE__ */ __toESM(require_react());
7
- var import_jsx_runtime = require_jsx_runtime();
8
- function RunPage() {
9
- const { run, tags, requests, checks, analytics, neighbours } = Route.useLoaderData();
10
- const { tab = "requests" } = Route.useSearch();
11
- const navigate = useNavigate({ from: Route.fullPath });
12
- const unreadable = useUnreadable();
13
- const tone = runTone(run);
14
- useTab({
15
- key: tabKey.run(run.id),
16
- title: `${run.file} #${run.id}`,
17
- icon: "run",
18
- failed: tone === "bad"
19
- });
20
- if (unreadable) return unreadable;
21
- const failedChecks = checks.filter((c) => c.status === "fail").length;
22
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
23
- className: css({
24
- display: "flex",
25
- flexDir: "column",
26
- h: "full",
27
- minH: "0"
28
- }),
29
- children: [
30
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunHeader, {
31
- run,
32
- neighbours
33
- }),
34
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TabList, {
35
- items: [
36
- {
37
- id: "requests",
38
- label: "Requests",
39
- count: requests.length
40
- },
41
- {
42
- id: "checks",
43
- label: "Checks",
44
- count: checks.length ? `${checks.length - failedChecks}/${checks.length}` : 0,
45
- tone: failedChecks ? "bad" : checks.length ? "ok" : void 0
46
- },
47
- {
48
- id: "insights",
49
- label: "Insights"
50
- },
51
- {
52
- id: "details",
53
- label: "Details",
54
- count: tags.length || void 0
55
- }
56
- ],
57
- value: tab,
58
- onSelect: (next) => void navigate({ search: { tab: next === "requests" ? void 0 : next } })
59
- }),
60
- tab === "requests" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequestsTab, {
61
- run,
62
- requests,
63
- checks
64
- }) : null,
65
- tab === "checks" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChecksTab, {
66
- run,
67
- checks
68
- }) : null,
69
- tab === "insights" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsTab, {
70
- run,
71
- analytics
72
- }) : null,
73
- tab === "details" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DetailsTab, {
74
- run,
75
- tags
76
- }) : null
77
- ]
78
- });
79
- }
80
- function RunHeader({ run, neighbours }) {
81
- const navigate = useNavigate();
82
- const now = useNow(Date.now(), 6e4);
83
- const tone = runTone(run);
84
- const wall = run.finished_at ? run.finished_at - run.started_at : null;
85
- const httpCount = run.request_count - run.connection_count;
86
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
87
- className: css({
88
- px: "5",
89
- pt: "4",
90
- pb: "3",
91
- display: "flex",
92
- flexDir: "column",
93
- gap: "3",
94
- flexShrink: 0
95
- }),
96
- children: [
97
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
98
- className: css({
99
- display: "flex",
100
- alignItems: "flex-start",
101
- gap: "3"
102
- }),
103
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
104
- className: css({
105
- minW: "0",
106
- flex: "1"
107
- }),
108
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
109
- className: css({
110
- display: "flex",
111
- alignItems: "center",
112
- gap: "2"
113
- }),
114
- children: [
115
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Dot, { tone }),
116
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
117
- className: cx(truncate, css({
118
- fontSize: "18px",
119
- fontWeight: "600",
120
- m: "0"
121
- })),
122
- children: run.file
123
- }),
124
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
125
- className: cx(mono, css({
126
- color: "faint",
127
- fontSize: "13px"
128
- })),
129
- children: ["#", run.id]
130
- }),
131
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pill, {
132
- tone,
133
- children: runVerdict(run)
134
- }),
135
- run.env ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pill, { children: run.env }) : null
136
- ]
137
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
138
- className: css({
139
- display: "flex",
140
- gap: "2",
141
- mt: "1",
142
- color: "muted",
143
- flexWrap: "wrap",
144
- fontSize: "12px"
145
- }),
146
- children: [
147
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
148
- to: "/collections",
149
- search: { entry: run.entry },
150
- className: cx(mono, css({
151
- color: "muted",
152
- display: "inline-flex",
153
- gap: "1",
154
- alignItems: "center",
155
- _hover: { color: "accent" }
156
- })),
157
- title: run.entry,
158
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconCollections, { size: 12 }), run.rel]
159
- }),
160
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "·" }),
161
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: formatDateTime(now, run.started_at) }),
162
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "·" }),
163
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: ["node ", run.node_version] }),
164
- run.label && run.label !== run.file ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "·" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: run.label })] }) : null
165
- ]
166
- })]
167
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
168
- className: css({
169
- display: "flex",
170
- gap: "1",
171
- flexShrink: 0
172
- }),
173
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconButton, {
174
- label: "Older run of this script",
175
- disabled: neighbours.prev == null,
176
- onClick: () => neighbours.prev && void navigate({
177
- to: "/runs/$runId",
178
- params: { runId: String(neighbours.prev) }
179
- }),
180
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconChevronLeft, {})
181
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconButton, {
182
- label: "Newer run of this script",
183
- disabled: neighbours.next == null,
184
- onClick: () => neighbours.next && void navigate({
185
- to: "/runs/$runId",
186
- params: { runId: String(neighbours.next) }
187
- }),
188
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconChevronRight, {})
189
- })]
190
- })]
191
- }),
192
- run.exit_status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Callout, {
193
- tone: "bad",
194
- icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconAlert, { size: 15 }),
195
- title: run.error_name ?? "The script threw",
196
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
197
- className: mono,
198
- children: run.error_message
199
- })
200
- }) : null,
201
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(StatGrid, { children: [
202
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stat, {
203
- label: "Wall time",
204
- value: formatMs(wall),
205
- sub: run.finished_at ? "start to finish" : "never finished"
206
- }),
207
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stat, {
208
- label: "Requests",
209
- value: formatCount(httpCount),
210
- sub: run.connection_count ? `+ ${plural(run.connection_count, "connection")}` : `${formatMs(run.total_duration_ms)} in flight`
211
- }),
212
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stat, {
213
- label: "Failed requests",
214
- value: formatCount(run.error_count),
215
- tone: run.error_count ? "warn" : "ok",
216
- sub: "errors and ≥ 400"
217
- }),
218
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stat, {
219
- label: "Checks",
220
- value: run.check_count ? `${run.check_count - run.failed_check_count}/${run.check_count}` : "—",
221
- tone: run.failed_check_count ? "bad" : run.check_count ? "ok" : void 0,
222
- sub: run.check_count ? run.failed_check_count ? `${run.failed_check_count} failed` : "all passed" : "none recorded"
223
- }),
224
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stat, {
225
- label: "Data",
226
- value: formatBytes(run.total_bytes),
227
- sub: "sent + received"
228
- })
229
- ] })
230
- ]
231
- });
232
- }
233
- var BAR = {
234
- ok: css({ bg: "ok" }),
235
- info: css({ bg: "info" }),
236
- warn: css({ bg: "warn" }),
237
- bad: css({ bg: "bad" }),
238
- neutral: css({ bg: "faint" })
239
- };
240
- function RequestsTab({ run, requests, checks }) {
241
- const navigate = useNavigate();
242
- const [filter, setFilter] = import_react.useState("");
243
- const [show, setShow] = import_react.useState("all");
244
- const [withChecks, setWithChecks] = import_react.useState(true);
245
- const needle = filter.trim().toLowerCase();
246
- const visible = requests.filter((r) => (show === "all" || isFailure(r)) && (!needle || `${r.method} ${r.host}${r.path} ${r.status ?? ""}`.toLowerCase().includes(needle)));
247
- const rows = import_react.useMemo(() => {
248
- const merged = visible.map((row) => ({
249
- type: "request",
250
- row
251
- }));
252
- if (!withChecks || needle || show === "failed") return merged;
253
- for (const check of checks) merged.push({
254
- type: "check",
255
- row: check
256
- });
257
- return merged.toSorted((a, b) => a.row.ts - b.row.ts);
258
- }, [
259
- visible,
260
- checks,
261
- withChecks,
262
- needle,
263
- show
264
- ]);
265
- const start = run.started_at;
266
- const span = Math.max(run.finished_at ?? 0, ...requests.map((r) => r.ts + r.duration_ms), ...checks.map((c) => c.ts), start + 1) - start;
267
- const failures = requests.filter(isFailure).length;
268
- if (requests.length === 0 && checks.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, { title: "This run made no requests" });
269
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
270
- className: css({
271
- display: "flex",
272
- flexDir: "column",
273
- flex: "1",
274
- minH: "0"
275
- }),
276
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
277
- className: css({
278
- display: "flex",
279
- gap: "2",
280
- px: "5",
281
- py: "2",
282
- alignItems: "center",
283
- flexShrink: 0,
284
- flexWrap: "wrap"
285
- }),
286
- children: [
287
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FilterInput, {
288
- className: css({ w: "280px" }),
289
- placeholder: "Filter by method, path or status",
290
- value: filter,
291
- onChange: (e) => setFilter(e.target.value)
292
- }),
293
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Segmented, {
294
- items: [{
295
- id: "all",
296
- label: `All ${requests.length}`
297
- }, {
298
- id: "failed",
299
- label: `Failed ${failures}`
300
- }],
301
- value: show,
302
- onSelect: setShow
303
- }),
304
- checks.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", {
305
- className: css({
306
- display: "inline-flex",
307
- alignItems: "center",
308
- gap: "1.5",
309
- color: "muted",
310
- fontSize: "12px",
311
- cursor: "pointer"
312
- }),
313
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", {
314
- type: "checkbox",
315
- checked: withChecks,
316
- onChange: (e) => setWithChecks(e.target.checked)
317
- }), "Show checks inline"]
318
- }) : null,
319
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
320
- className: css({
321
- ml: "auto",
322
- color: "faint",
323
- fontSize: "12px"
324
- }),
325
- children: ["Timeline spans ", formatMs(span)]
326
- })
327
- ]
328
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
329
- className: scrollPane,
330
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", {
331
- className: table,
332
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
333
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
334
- className: "num",
335
- style: { width: 40 },
336
- children: "#"
337
- }),
338
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "Request" }),
339
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "Status" }),
340
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
341
- className: "num",
342
- children: "Time"
343
- }),
344
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
345
- className: "num",
346
- children: "Size"
347
- }),
348
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
349
- style: { width: "32%" },
350
- children: "Timeline"
351
- })
352
- ] }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tbody", { children: [rows.map((item) => item.type === "check" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CheckLine, {
353
- check: item.row,
354
- start,
355
- span
356
- }, `c${item.row.id}`) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", {
357
- "data-link": true,
358
- onClick: () => void navigate({
359
- to: "/requests/$requestId",
360
- params: { requestId: String(item.row.id) }
361
- }),
362
- children: [
363
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
364
- className: cx("num", mono, css({ color: "faint" })),
365
- children: item.row.seq + 1
366
- }),
367
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
368
- className: css({
369
- maxW: "0",
370
- w: "full"
371
- }),
372
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
373
- className: css({
374
- display: "flex",
375
- alignItems: "center",
376
- gap: "2",
377
- minW: "0"
378
- }),
379
- children: [
380
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MethodBadge, {
381
- method: item.row.method,
382
- kind: item.row.kind,
383
- width: "list"
384
- }),
385
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
386
- className: cx(truncate, mono),
387
- title: `${item.row.host}${item.row.path}`,
388
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
389
- className: css({ color: "faint" }),
390
- children: item.row.host
391
- }), item.row.path]
392
- }),
393
- item.row.kind !== "http" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
394
- className: css({
395
- color: "faint",
396
- fontSize: "11px",
397
- whiteSpace: "nowrap"
398
- }),
399
- children: plural(item.row.message_count, "message")
400
- }) : null
401
- ]
402
- })
403
- }),
404
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBadge, {
405
- status: item.row.status,
406
- error: item.row.error_name
407
- }) }),
408
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
409
- className: cx("num", mono),
410
- children: formatMs(item.row.duration_ms)
411
- }),
412
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
413
- className: cx("num", mono, css({ color: "muted" })),
414
- children: formatBytes(item.row.response_bytes)
415
- }),
416
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
417
- className: css({
418
- position: "relative",
419
- h: "8px"
420
- }),
421
- title: `${formatOffset(item.row.ts - start)} · ${formatMs(item.row.duration_ms)}`,
422
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
423
- className: cx(css({
424
- position: "absolute",
425
- top: "0",
426
- bottom: "0",
427
- rounded: "full",
428
- minW: "2px"
429
- }), BAR[statusTone(item.row.status, item.row.error_name)]),
430
- style: {
431
- left: `${(item.row.ts - start) / span * 100}%`,
432
- width: `${item.row.duration_ms / span * 100}%`,
433
- opacity: item.row.kind === "http" ? 1 : .5
434
- }
435
- })
436
- }) })
437
- ]
438
- }, item.row.id)), rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
439
- colSpan: 6,
440
- className: css({
441
- textAlign: "center",
442
- color: "faint",
443
- py: "6"
444
- }),
445
- children: "No requests match."
446
- }) }) : null] })]
447
- })
448
- })]
449
- });
450
- }
451
- function CheckLine({ check, start, span }) {
452
- const pass = check.status === "pass";
453
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
454
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {}),
455
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
456
- colSpan: 4,
457
- className: css({ maxW: "0" }),
458
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
459
- className: css({
460
- display: "flex",
461
- alignItems: "center",
462
- gap: "2",
463
- minW: "0",
464
- fontSize: "12px"
465
- }),
466
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
467
- className: cx(css({
468
- display: "inline-flex",
469
- w: "46px",
470
- justifyContent: "center"
471
- }), toneText(pass ? "ok" : "bad")),
472
- children: pass ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconCheckCircle, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconXCircle, { size: 14 })
473
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
474
- className: cx(truncate, pass ? css({ color: "muted" }) : css({
475
- color: "bad",
476
- fontWeight: "500"
477
- })),
478
- children: [check.name, !pass && check.message ? ` — ${check.message}` : ""]
479
- })]
480
- })
481
- }),
482
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
483
- className: css({
484
- position: "relative",
485
- h: "8px"
486
- }),
487
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
488
- className: cx(css({
489
- position: "absolute",
490
- top: "-1px",
491
- w: "2px",
492
- h: "10px",
493
- rounded: "full"
494
- }), pass ? BAR.ok : BAR.bad),
495
- style: { left: `${(check.ts - start) / span * 100}%` }
496
- })
497
- }) })
498
- ] });
499
- }
500
- function ChecksTab({ run, checks }) {
501
- if (checks.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Empty, {
502
- title: "No checks in this run",
503
- icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconCheckCircle, { size: 22 }),
504
- children: [
505
- "A script records expectations with ",
506
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: "check()" }),
507
- " and ",
508
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: "assert()" }),
509
- " from",
510
- " ",
511
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: "@apisurf/wire/kit" }),
512
- "."
513
- ]
514
- });
515
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
516
- className: scrollPane,
517
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
518
- className: pagePad,
519
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { children: checks.map((check) => {
520
- const pass = check.status === "pass";
521
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
522
- className: css({
523
- display: "flex",
524
- gap: "2.5",
525
- px: "3",
526
- py: "2",
527
- borderBottom: "1px solid",
528
- borderColor: "line",
529
- _last: { borderBottom: "none" }
530
- }),
531
- children: [
532
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
533
- className: cx(css({ pt: "1px" }), toneText(pass ? "ok" : "bad")),
534
- children: pass ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconCheckCircle, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconXCircle, { size: 16 })
535
- }),
536
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
537
- className: css({
538
- flex: "1",
539
- minW: "0"
540
- }),
541
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
542
- className: css({
543
- display: "flex",
544
- gap: "2",
545
- alignItems: "center"
546
- }),
547
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
548
- className: css({ fontWeight: "500" }),
549
- children: check.name
550
- }), check.mode === "assert" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pill, {
551
- tone: pass ? "neutral" : "bad",
552
- children: "assert"
553
- }) : null]
554
- }), !pass && check.message ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
555
- className: cx(mono, css({
556
- color: "bad",
557
- mt: "0.5",
558
- wordBreak: "break-word"
559
- })),
560
- children: check.message
561
- }) : null]
562
- }),
563
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
564
- className: cx(mono, css({
565
- color: "faint",
566
- whiteSpace: "nowrap"
567
- })),
568
- children: formatOffset(check.ts - run.started_at)
569
- })
570
- ]
571
- }, check.id);
572
- }) })
573
- })
574
- });
575
- }
576
- var MIX_TONE = {
577
- "1xx": "info",
578
- "2xx": "ok",
579
- "3xx": "info",
580
- "4xx": "warn",
581
- "5xx": "bad",
582
- error: "bad"
583
- };
584
- function InsightsTab({ run, analytics }) {
585
- const navigate = useNavigate();
586
- if (analytics.total === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, { title: "Nothing to analyse — this run made no requests" });
587
- const maxHost = Math.max(...analytics.byHost.map((h) => h.count), 1);
588
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
589
- className: scrollPane,
590
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
591
- className: pagePad,
592
- children: [
593
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(StatGrid, { children: [
594
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stat, {
595
- label: "p50 latency",
596
- value: formatMs(analytics.p50),
597
- sub: `over ${plural(analytics.latencySamples, "HTTP request")}`
598
- }),
599
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stat, {
600
- label: "p95 latency",
601
- value: formatMs(analytics.p95)
602
- }),
603
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stat, {
604
- label: "p99 latency",
605
- value: formatMs(analytics.p99)
606
- }),
607
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stat, {
608
- label: "Hosts",
609
- value: formatCount(analytics.byHost.length),
610
- sub: analytics.byHost[0]?.host
611
- })
612
- ] }),
613
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionTitle, { children: "Status mix" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, {
614
- className: css({ p: "3" }),
615
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
616
- className: css({
617
- display: "flex",
618
- gap: "2px",
619
- h: "14px"
620
- }),
621
- children: analytics.statusMix.map((mix) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
622
- title: `${mix.status_class}: ${mix.count}`,
623
- className: cx(css({
624
- rounded: "sm",
625
- minW: "4px"
626
- }), BAR[MIX_TONE[mix.status_class] ?? "neutral"]),
627
- style: { flexGrow: mix.count }
628
- }, mix.status_class))
629
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
630
- className: css({
631
- display: "flex",
632
- gap: "4",
633
- mt: "2.5",
634
- flexWrap: "wrap"
635
- }),
636
- children: analytics.statusMix.map((mix) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
637
- className: css({
638
- display: "inline-flex",
639
- alignItems: "center",
640
- gap: "1.5"
641
- }),
642
- children: [
643
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: cx(css({
644
- w: "8px",
645
- h: "8px",
646
- rounded: "xs"
647
- }), BAR[MIX_TONE[mix.status_class] ?? "neutral"]) }),
648
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
649
- className: mono,
650
- children: mix.status_class
651
- }),
652
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
653
- className: css({ color: "muted" }),
654
- children: [
655
- mix.count,
656
- " · ",
657
- Math.round(mix.count / analytics.total * 100),
658
- "%"
659
- ]
660
- })
661
- ]
662
- }, mix.status_class))
663
- })]
664
- })] }),
665
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
666
- className: css({
667
- display: "grid",
668
- gridTemplateColumns: {
669
- base: "1fr",
670
- lg: "1fr 1fr"
671
- },
672
- gap: "5"
673
- }),
674
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionTitle, { children: "By host" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", {
675
- className: table,
676
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
677
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { children: "Host" }),
678
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
679
- className: "num",
680
- children: "Calls"
681
- }),
682
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
683
- className: "num",
684
- children: "Errors"
685
- }),
686
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
687
- className: "num",
688
- children: "p95"
689
- })
690
- ] }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: analytics.byHost.map((host) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
691
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
692
- className: cx(mono, truncate),
693
- children: host.host
694
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
695
- className: css({
696
- h: "3px",
697
- mt: "1",
698
- bg: "accent",
699
- rounded: "full",
700
- opacity: .6
701
- }),
702
- style: { width: `${host.count / maxHost * 100}%` }
703
- })] }),
704
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
705
- className: "num",
706
- children: host.count
707
- }),
708
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
709
- className: cx("num", host.errors ? css({ color: "warn" }) : void 0),
710
- children: host.errors
711
- }),
712
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
713
- className: cx("num", mono),
714
- children: formatMs(host.p95)
715
- })
716
- ] }, host.host)) })]
717
- }) })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionTitle, { children: "Slowest requests" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", {
718
- className: table,
719
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: analytics.slowest.map((row) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", {
720
- "data-link": true,
721
- onClick: () => void navigate({
722
- to: "/requests/$requestId",
723
- params: { requestId: String(row.id) }
724
- }),
725
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
726
- className: css({
727
- maxW: "0",
728
- w: "full"
729
- }),
730
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
731
- className: css({
732
- display: "flex",
733
- gap: "2",
734
- alignItems: "center",
735
- minW: "0"
736
- }),
737
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MethodBadge, {
738
- method: row.method,
739
- width: "list"
740
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
741
- className: cx(mono, truncate),
742
- children: row.path
743
- })]
744
- })
745
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
746
- className: cx("num", mono),
747
- children: formatMs(row.duration_ms)
748
- })]
749
- }, row.id)) })
750
- }) })] })]
751
- }),
752
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
753
- className: css({
754
- color: "faint",
755
- fontSize: "12px",
756
- m: "0"
757
- }),
758
- children: ["Latency covers HTTP requests only; a WebSocket or SSE connection's duration is how long it stayed open.", run.connection_count ? ` This run opened ${plural(run.connection_count, "connection")}.` : ""]
759
- })
760
- ]
761
- })
762
- });
763
- }
764
- function DetailsTab({ run, tags }) {
765
- const now = useNow(Date.now(), 6e4);
766
- const rows = [
767
- {
768
- name: "id",
769
- value: String(run.id)
770
- },
771
- {
772
- name: "uid",
773
- value: run.uid
774
- },
775
- {
776
- name: "label",
777
- value: run.label ?? "—"
778
- },
779
- {
780
- name: "entry",
781
- value: run.entry
782
- },
783
- {
784
- name: "cwd",
785
- value: run.cwd
786
- },
787
- {
788
- name: "env",
789
- value: run.env ?? "—"
790
- },
791
- {
792
- name: "node",
793
- value: run.node_version
794
- },
795
- {
796
- name: "started",
797
- value: formatDateTime(now, run.started_at)
798
- },
799
- {
800
- name: "finished",
801
- value: run.finished_at ? formatDateTime(now, run.finished_at) : "—"
802
- },
803
- {
804
- name: "exit status",
805
- value: run.exit_status ?? "—"
806
- }
807
- ];
808
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
809
- className: scrollPane,
810
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
811
- className: pagePad,
812
- children: [
813
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionTitle, { children: "Run" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(KvTable, {
814
- rows,
815
- empty: "",
816
- filterable: false,
817
- nameLabel: "Field"
818
- }) })] }),
819
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionTitle, { children: "Tags" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(KvTable, {
820
- rows: tags.map((t) => ({
821
- name: t.key,
822
- value: t.value
823
- })),
824
- empty: "No tags — add them with wire execute --tag key=value",
825
- filterable: false
826
- }) })] }),
827
- run.entry_source ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SectionTitle, { children: "Inline source" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Card, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
828
- className: css({ bg: "well" }),
829
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Code, { text: run.entry_source })
830
- }) })] }) : null
831
- ]
832
- })
833
- });
834
- }
835
- //#endregion
836
- export { RunPage as component };